I used to use the function below to call ack as a fast, recursive grep, but for whatever reason it stopped working. More precisely it returns no result. It probably happened when I updated Emacs or macOS, hard to say.
The ack is working from terminal without any issues.
Does anyone have any idea how to fix it? I also considering alternatives, but hopefully not too slow for big folders.
(defun my/rgrep ()
(interactive)
(if (executable-find "ack")
(let* ((regexp (grep-read-regexp))
(dir (read-directory-name "Base directory: " nil default-directory t))
(command (concat "ack '" regexp "' " dir)))
(unless (file-accessible-directory-p dir)
(error (concat "directory: '" dir "' is not accessible.")))
(compilation-start command 'grep-mode))
))
EDIT:
Sadly even rgrep doesn't work when evaluated as (progn (grep-compute-defaults) (rgrep "foo" "*.txt" "/Volumes/RAM_Disk/test"))
where that folder has only one txt file with text "foo" it returns no matches. The generated find command below:
find . -type d \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path \*/MCVS -o -path \*/.src -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path \*/.bzr -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{arch\} \) -prune -o \! -type d \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name \*.bin -o -name \*.lbin -o -name \*.so -o -name \*.a -o -name \*.ln -o -name \*.blg -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name \*.glo -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem -o -name \*.x86f -o -name \*.sparcf -o -name \*.dfsl -o -name \*.pfsl -o -name \*.d64fsl -o -name \*.p64fsl -o -name \*.lx64fsl -o -name \*.lx32fsl -o -name \*.dx64fsl -o -name \*.dx32fsl -o -name \*.fx64fsl -o -name \*.fx32fsl -o -name \*.sx64fsl -o -name \*.sx32fsl -o -name \*.wx64fsl -o -name \*.wx32fsl -o -name \*.fasl -o -name \*.ufsl -o -name \*.fsl -o -name \*.dxl -o -name \*.lo -o -name \*.la -o -name \*.gmo -o -name \*.mo -o -name \*.toc -o -name \*.aux -o -name \*.cp -o -name \*.fn -o -name \*.ky -o -name \*.pg -o -name \*.tp -o -name \*.vr -o -name \*.cps -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name \*.tps -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) -prune -o -type f \( -iregex \*.txt \) -exec grep -i -nH --null -e foo \{\} +
After more pondering on this, I found that there is also a problem with running rgrep or any alternative in tramp.
I think of making a universal my/rgrep function that will use default strategy like ack, and fallback to another strategy like ag and find/grep if the previous one wasn't found. Also making it work with tramp.
Because I already have defined config for ack that works well from the terminal I would put ack on the front of that list, but it shouldn't matter which one we put first.
Does anyone of you have this problem solved already, or at least have configured tramp to work well with rgrep?
(elisp)Edebug
to learn what's happening. Note that(concat "ack '" regexp "' " dir)
is buggy. Compilation commands are run via a shell, so useC-h f shell-quote-argument
. Currently you're assuming that single-quoting will be fine, so I imagine your command will just break if REGEXP contained a single quote, and DIR isn't escaped at all.rgrep
?(progn (grep-compute-defaults) (rgrep "<regex>" "<file-glob>" "<directory>"))
. Remember to add the(grep-compute-defaults)
if you callrgrep
programmatically.find
command uses-iregex \*.txt
which is wrong (even in my side), mine use-name \*.txt
and it works. Maybe you can fix the issue by passing a regex at the second argument (e.g..*.txt
), but it's not the expected behaviour ofrgrep
. I'll take a look on the source code.