I have already discussed how one can
leverage ugrep
and consult-xref
to make a completing-read
variant of
project-find-regexp
.
However, today I would like to go a bit further and show how easily Consult can
be extended to include a command that behaves like consult-grep
,
consult-git-grep
, and consult-ripgrep
, but with ugrep
as its engine. True,
something along these lines has been
around for a while. And yet I have
no need for an external package when Consult has everything in place in order to
devise a custom command.
By inspecting the code behind consult-git-grep
and consult-ripgrep
the
pattern is pretty clear:
- a
defcustom
with the command (e.g.,git grep
) and its arguments - a builder function to create the actual command to be invoked (e.g.,
consult--git-grep-make-builder
) - a wrapper around
consult--grep
(e.g.,consult-git-grep
)
Therefore, the solution is simple:
(defvar mu-consult-ugrep-args (string-join '("ugrep"
"--color=never"
"--exclude-dir=.git/"
"--hidden"
"--ignore-binary"
"--ignore-case"
"--line-buffered"
"--line-number"
"--null"
"--recursive")
" "))
(defun mu-consult-ugrep-make-builder (paths)
"Create ugrep command line builder given PATHS."
(let ((cmd (consult--build-args mu-consult-ugrep-args)))
(lambda (input)
(pcase-let* ((`(,arg . ,opts) (consult--command-split input))
(`(,re . ,hl)
(funcall consult--regexp-compiler arg 'extended t)))
(when re
(cons (append cmd
(cdr (mapcan (lambda (x) (list "--and" "-e" x)) re))
opts paths)
hl))))))
(defun mu-consult-ugrep (&optional dir initial)
"Search with `ugrep' for files in DIR with INITIAL input."
(interactive "P")
(require 'consult)
(consult--grep "Ugrep" #'mu-consult-ugrep-make-builder dir initial))
Since I am always using the same ugrep
options, my builder function is a bit
simpler than consult--git-grep-make-builder
or
consult--ripgrep-make-builder
. Other than that, it’s only a matter of
understanding the right options for ugrep
.
Building on top of Consult is great. Much like consult-git-grep
and
consult-ripgrep
, the integration with Embark is around the corner. And now
that the power of the minibuffer is available during my searches I have no use
for mu-recursive-grep any more.