When I described how I use Ugrep in Emacs I forgot to mention something. It’s true that I rely on project-find-regexp (C-x p g ) for searches, but there is a specific use-case where this command is not as handy as it usually is: project-wide navigation.

To be more precise, in my daily workflows it can happen that all I need to do is jump to a different file where the thing at point is used. The power of project-find-regexp is too much here, because I don’t need the *xref* buffer with all the results and the ability to replace them. I just want a quick a way to hit RET on the candidate I am looking for and move to the desired file.

With xref-search-program set to 'ugrep1 the solution is trivial.

(defun mu-project-find-regexp ()
  "Use `project-find-regexp' with completion."
  (interactive)
  (defvar xref-show-xrefs-function)
  (let ((xref-show-xrefs-function #'xref-show-definitions-completing-read))
    (if-let ((tap (thing-at-point 'symbol)))
        (project-find-regexp tap)
      (call-interactively #'project-find-regexp))))

The trick is temporarily setting xref-show-xrefs-function to xref-show-definitions-completing-read, which according to its documentation does exactly what I am looking for.

Let the user choose the target definition with completion.

When there is more than one definition, let the user choose between them by typing in the minibuffer with completion.

I then bind mu-project-find-regexp to M-? and all is set. Needless to say, the heavy work is still done by project-find-regexp. Such an awesome tool.

Note that I am overriding the default M-? on purpose, because the original xref-find-references does not take things like .gitignore into account, something absolutely necessary in large projects where I want to avoid having useless candidates spam the ever precious minibuffer.

Finally, be aware that a better version of mu-project-find-regexp can be found here.


  1. Once again, refer to Using ugrep with Emacs for the configuration details. ↩︎