Replacing deadgrep with consult-ripgrep

[James Dyer] : Mar 08, 2023 : 473 words
emacs linux 🏷️ ripgrep grep emacs elisp 2023

I have been evolving my way through many differing ways of grepping recently from standard built-in greps to a few ripgrep front ends until I finally settled on deadgrep

I am currently an ivy user but as everyone seems to be talking about vertico and the associated completion stack I thought I would give it a try and therefore consult-ripgrep to see it can improve on my deadgrep setup.

Previously I have created a couple of wrappers around deadgrep:

(defun my/deadgrep ()
 (interactive)
 (if (equal major-mode 'dired-mode)
  (setq search-term
 (read-from-minibuffer "Search : "))
  (setq search-term
 (read-from-minibuffer "Search : " (thing-at-point 'symbol)))
  )
 (deadgrep search-term home-dir)
 )

(defun my/grep ()
 (interactive)
 (if (equal major-mode 'dired-mode)
  (setq search-term
 (read-from-minibuffer "Search : "))
  (setq search-term
 (read-from-minibuffer "Search : " (thing-at-point 'symbol)))
  )
 (deadgrep search-term)
 )

As a universal argument was passed to deadgrep which had a side effect of initially pausing the search, this meant I split my grepping between S-f12 and M-f12 one for a project grep and one for a local directory grep.

As part of trying out consult-ripgrep I think I would like to rewrite the functions above and I would want a quick and simple method to revert back to using deadgrep.

I settled on the following:

(defun my/project-root ()
 (interactive)
 "Guess the project root of the given FILE-PATH."
 (let ((root default-directory)
     (project (project-current)))
  (when project
 (cond ((fboundp 'project-root)
        (setq root (project-root project)))))))

(defun my/grep (arg)
 (interactive "p")
 (if (equal major-mode 'dired-mode)
  (setq search-term
 (read-from-minibuffer "Search : "))
  (setq search-term
 (read-from-minibuffer "Search : " (thing-at-point 'symbol)))
  )
 (if (> arg 1) ;; if C-u has been activated
  (consult-ripgrep default-directory search-term)
  (consult-ripgrep (my/project-root) search-term)))
;;   (progn
;;     (setq current-prefix-arg nil)
;;     (deadgrep search-term default-directory)
;;     )
;; (deadgrep search-term (my/project-root))))

To switch between deadgrep / consult-ripgrep I just need to uncomment / comment in and out the relevant bits and then re-evaluate.

As you can see I created a local function to find the project root directory if one exists and to then pass the result to the deadgrep / consult-ripgrep command meaning that they will both perform identically from a search directory perspective.

Note how I overcame the pass-through of the universal argument to deadgrep by just resetting the current-prefix-arg after I had already used the universal argument logic within the function.

I can now free up my original M-f12 binding which searched from the local default-directory as I can C-u to the S-f12 binding.

I’m not too sure about consult-ripgrep yet but the setup above gives me the following benefits:

  1. A common local find project root function that might become useful for future functions
  2. Flexibility with the universal argument meaning I could pass in multiple universal arguments or maybe even a numeric argument for enhanced functionality
  3. Able to quickly switch between ripgrep implementations by commenting / un-commenting
  4. Frees up a keybinding