replacing ag with rg and fd
I really, really liked ag. Then I noticed that my installed version of
the silver searcher, 2.2.0, was
also the latest one. It shipped in
August 2018. The last
commit landed in December 2020. Nothing broke. My favorite code search tool was
just never going to get better.
Turns out I only ever used three ag flags, and they do not map to three rg
flags. One of them was never really a search feature at all:
$ ag -g package.json # print filenames matching a regex$ ag -G '\.tsx$' useQuery # search only in matching files$ ag -u secret # search ignored, hidden, binary files too
ripgrep covers the last two. Searching file names is a job it refuses to take. There is no flag for it, and the author’s answer when asked is a pipeline:
No. ripgrep doesn’t even expose a way to search file paths with a regex at all. The only way to match on file paths is with globs. If you want regexes, you need to use pipelines, e.g.,
rg --files | rg 'foo\w+'.
I cannot be bothered to type that. Finding files by name is
fd’s whole job, and it kept the syntax ag -g
had:
$ fd package.json # was: ag -g package.json$ rg -g '*.tsx' useQuery # was: ag -G '\.tsx$' useQuery$ rg -uuu secret # was: ag -u secret
Two gotchas in there. rg -g takes a glob, not a regex, and it filters files
like ag -G did instead of listing them like ag -g. Same letter, different
job. And the third flag, the one I had to look up every single time because ag
split it across -u and -U: rg just counts the us.
-usearches ignored files-uuadds hidden files-uuuadds binary files
fd uses the same idiom. I will never look that one up again.
The switch itself:
$ brew install ripgrep fd$ brew uninstall the_silver_searcher
Installing a better tool does not switch you to it. Muscle memory keeps the old one alive.
Now, to fight muscle memory, I added a fish abbreviation:
# in ~/.config/fish/config.fishabbr -a -- ag 'rg -S'
An alias would have hidden the rename forever. An
abbreviation expands in the
buffer before it runs. I type ag, hit space, and watch it become rg -S.
Every invocation is a flashcard. One day I will catch myself typing rg
unprompted and delete the abbr. The -S is smart case, which ag did by
default and rg does not. Silently finding fewer results is the worst kind of
different. I added the same abbreviation to
my PowerShell profile on
Windows.
ag, space, and the buffer says rg -S
down the rabbit hole
The project behind ag is called the silver searcher, and ag is the
chemical symbol for silver. The README also brags that “the command name is 33%
shorter than ack, and all keys are on the home row!” I never used ack, nor
pt, the platinum
searcher that followed. Still, I was sad to see the pun go.
So I went digging through the successors’ docs, and found the jokes better
maintained than the code. fd’s README claims a command name “50% shorter than
find”, and the asterisk on that claim links to ag’s repo.
And the ripgrep FAQ swears the “rip” meant “to rip through your text”. The “grep, rest in peace” reading only surfaced after the release, pointed out by someone else, and the author admits he might have picked a different name had he seen it coming.
So my mnemonic for the new pair: rg rips through file contents, and fd is
find with the “in” ripped out. Learning is being alive.