
FZF and RipGrep – Navigate with bash faster than ever before - Midasx
http://owen.cymru/fzf-ripgrep-navigate-with-bash-faster-than-ever-before/
======
cryptonector
For dev work, I still prefer cscope for searching for things, at least in all
supported languages. cscope is _fantastic_. Combined with a $CSCOPE_EDITOR
that does the right thing (for me: open $EDITOR in the background in a new
tmux window titled after the file being edited, returning control to cscope
for additional searches / opens).

What's really good about cscope is this:

\- multiple search types such as: where is this symbol assigned to, what
functions call this function, where is this defined, where is this referenced,
and so on

\- curses and CLI interface

\- the curses interface is very nice

\- the CLI interface is very useful for integration into your $EDITOR,
whatever it might be

The only downside is that cscope only supports C-like languages and a few
others like yacc. So this works for C, C++, and Java (to a lesser extent), but
does not work at all for languages like, say, Python.

------
guitarbill
These look awesome! If you're willing to put in that much effort to learn new
tools though, could also try zsh or fish. The built-in autocomplete of both
over bash is on another level.

~~~
nerdponx
There are good reasons to use Zsh beyond its autocomplete system. Zsh
parameter expansions are a beautiful thing. When I write CLI scripts, I don't
write Bash scripts, I write Zsh scripts.

Documentation, however, is lacking. It's not quite as bad as Vim, but there
are massive swaths of the program, entire subsystems, that are more or less
completely undocumented. It's very user unfriendly.

Also, the ad-hoc "plugin" ecosystem is in a strange and fragmented state. It's
a shame that more people don't write actual modules in C (yes, Zsh has a
native module system), but then again, is the API even documented?

The thing about Fish vs Zsh is that Zsh, with all those pre-command hooks
running in Zsh scripts to replicate out-of-the-box Fish functionality, it's
slow. I haven't tried compiling my plugin files (yes, Zsh also has a byte
compiler), so maybe that would help. But I've occasionally found myself poring
over logs from zsh -x to see diagose my 200ms delay.

One more thing about Zsh: it has emacs syndrome. Do your really need an FTP
client and calendar built into your shell?

~~~
okdana
> There are good reasons to use Zsh beyond its autocomplete system...

zsh also performs much better in practice than bash. Not only does it run the
same code faster, it subsumes a great deal of functionality that normally
requires external utility calls (which are very slow) into the shell itself.

For example:

* zsh has native floating-point arithmetic, so no need for `awk` or whatever. It can even format (digit-group) the numbers

* Regular-expression matching with =~ can be replaced by extended globs (which offer similar functionality but are significantly faster in most cases)

* `basename`, `dirname`, `readlink -m`, and `readlink -f` can be replaced by parameter-expansion modifiers

* `sort` can be replaced by parameter-expansion flags

* `grep` can be replaced by parameter-expansion flags and extended globs

* `find` (including its `-type` and `-exec` features) can be replaced by globs

* `date` can be replaced by prompt expansion or the `zsh/datetime` module

* `cp`, `mkdir`, `rm`, and so on can be replaced by the `zsh/files` module

* `stat` can be replaced by the `zsh/stat` module

* `column` can be replaced by `print -c` or `print -C`

> there are massive swaths of the program, entire subsystems, that are more or
> less completely undocumented

Like what? I'm not sure i'd noticed that myself. Sometimes the documentation
is _vague_ , maybe hard to find (e.g., the completion system's documentation
is a bit overwhelming), but it's always been there when i went looking for it.

> Also, the ad-hoc "plugin" ecosystem is in a strange and fragmented state.

The plug-in ecosystem (i assume you mean OMZ, zplug, and stuff like that) is
entirely unofficial and most of the zsh developers don't seem to care for any
of it because it tends to be slow, error-prone, and often just unnecessary.
It's also a major support burden for the people on IRC and in the mailing
list, which doesn't endear them to it. Might be cool to have something
official though.

> It's a shame that more people don't write actual modules in C (yes, Zsh has
> a native module system), but then again, is the API even documented?

I don't think it is, there's just an example module you can build. bash also
supports loadable modules and it's the same way AFAIK.

> One more thing about Zsh: it has emacs syndrome. Do your really need an FTP
> client and calendar built into your shell?

Most of the weird stuff like the FTP client and calendar and Tetris game are
optional modules or even just regular shell scripts. None of them are enabled
by default and packagers can omit them (and they often do, especially with
static builds).

~~~
nerdponx
> zsh also performs much better in practice than bash. Not only does it run
> the same code faster, it subsumes a great deal of functionality that
> normally requires external utility calls (which are very slow) into the
> shell itself.

For the uninitiated: Zsh parameters expansions and globbing (called "filename
generation" in the docs) are beautiful. As I said above, I don't write Bash
scripts, I write Zsh scripts, and this kind of thing is why:

    
    
        % cd /tmp
        % mkdir example
        % cd example
        % touch foo
        % touch bar
        % mkdir "my documents"
        % touch "my documents/baz"
    
        % tree -N
        .
        ├── bar
        ├── foo
        └── my documents
            └── baz
    
        1 directory, 3 files
    
        % for f in **/*(.);
        >   do echo File ${f:t} lives in ${f:A:h}
        > done
        File bar lives in /tmp/example
        File foo lives in /tmp/example
        File baz lives in /tmp/example/my documents
    

> Like what? I'm not sure i'd noticed that myself. Sometimes the documentation
> is vague, maybe hard to find (e.g., the completion system's documentation is
> a bit overwhelming), but it's always been there when i went looking for it.

Fair enough. Although IMO "vague and disorganized" is just as good as
"nonexistent". Just try reading the docs for `autoload`/`typeset`/`local`, or
`zstyle` [0], or `zmodload`. The whole thing badly needs to be tagged and
reverse-indexed by functionality ("how do I accomplish X"), not by flag ("what
does foo -q mean?"). I wrote a long comment about this kind of documentation
recently [1].

> The plug-in ecosystem (i assume you mean OMZ, zplug, and stuff like that) is
> entirely unofficial and most of the zsh developers don't seem to care for
> any of it because it tends to be slow, error-prone, and often just
> unnecessary. It's also a major support burden for the people on IRC and in
> the mailing list, which doesn't endear them to it. Might be cool to have
> something official though.

Yes, this. It seems like everyone and their mother at one point decided to try
to write a "package manager" for Zsh.

But I think the problem with these unofficial plugins is mainly that sourcing
thousands of lines of shell script on every terminal load, and running
potentially dozens of functions before every command, is just plain slow. Zsh
might be faster than Bash, but it's still really really slow. Just looping
over 1..1000000 takes well over a second in Zsh, but less than 1/2 second in
Python (which is already considered a slow language).

What I haven't tried is zcompile-ing all my startup scripts. Would that help?

And of course, actually documenting the C API and build process would be a
good first step for the maintainers and devs. The example module is easy
enough to follow, but actually writing a module is another matter entirely.
This is especially frustrating because AFAICT Zsh builtins are themselves
implemented as a statically-linked module called "zsh/main", so it must be a
powerful system.

[0]:
[https://unix.stackexchange.com/q/214657](https://unix.stackexchange.com/q/214657)

[1]:
[https://news.ycombinator.com/item?id=15479273](https://news.ycombinator.com/item?id=15479273)

------
mason55
I added ctrl-P bind to open with vim. But if I realize I didn't want to do
that and want to cancel then hitting ESC or ctrl-c just drops me into vim with
no file. Any ideas on how to change that bind so that I can cancel back to the
command line?

Edit: actually it's even worse, it seems like rg keeps running in the
background even after I ctrl-c, which if I'm starting in some directory at the
top of my directory tree means it runs for a long time.

Edit 2: Looks like the problem in my edit is a known issue with ripgrep:
[https://github.com/BurntSushi/ripgrep/issues/200](https://github.com/BurntSushi/ripgrep/issues/200)

~~~
Midasx
Sorry, I should update the article with the better solution, it's just a few
more lines:

[https://github.com/bag-
man/dotfiles/blob/master/bashrc#L116-...](https://github.com/bag-
man/dotfiles/blob/master/bashrc#L116-L120)

~~~
chewz
It is also cool to add preview

[https://gist.github.com/chew-z/db310b0e3184ae335e24d2ec7087a...](https://gist.github.com/chew-z/db310b0e3184ae335e24d2ec7087a123)

------
corpMaverick
I am using ag. Is it worth changing to RipGrep ?

The other unix command line tool that I love is autojump.

I am thinking on trying fish and probably fzf.

~~~
kuwze
FZF and fish don't play well if I remember correctly (I hope I'm mistaken
though.)

~~~
perryprog
Fish user here! FZF works beautifully with fish, no plugin manager needed.
`brew install fzf` gives you the option to install scripts for fish if it's
your shell (IIRC).

------
graffitici
I love the combination of these! Really opens up a world of possibilities. The
one command I'm still trying to replace is `cd` itself. For instance, can
anyone suggest a way to add bookmarks, so that I can move around faster? I
found a few, but was never happy with them.

~~~
Midasx
It isn't super clear in the article, but I now use bfs & fzf for replacing cd.

[https://github.com/bag-
man/dotfiles/blob/master/bashrc#L73](https://github.com/bag-
man/dotfiles/blob/master/bashrc#L73)

Lets you change directory with alt+c, although I have tweaked it so you always
search from your root folder. Which isn't for everyone. Otherwise fzf alt+c
doesn't let you go back up directories which gets frustrating.

~~~
HurrdurrHodor
I've just tried this and in my case it leads to "cd \~[...]" which obviously
does not work.

~~~
Midasx
That's strange. Maybe just change it to:

    
    
        export FZF_ALT_C_COMMAND="bfs -type d -nohidden"
    

(and install bfs of course)

It won't let you go back up the tree, but if you are clever you can use `cd -`
to jump back to your previous location.

------
pmoriarty
If you like fzf you might be interested in fzy:

[https://github.com/jhawthorn/fzy](https://github.com/jhawthorn/fzy)

------
paule89
The second post i read today about fzf. And also again i see ripgrep. I think
it is time to make these tools a default in linux distros. Maybe a small you
could use ripgrep instead of grep, just before the first use of these tools
would be interesting.

~~~
burntsushi
Hope you don't mind some brief clarifications.

Work on adding ripgrep to Linux distros is being tracked here[1]. We've made
good progress so far, but AFAIK it's still missing in Ubuntu and Debian. I'm
not caught up with what's required to get ripgrep into those repos.

With respect to making it a literal default---as in replacing GNU grep---I
don't really expect that to ever happen. There is a _ton_ of intersection
between the tools, right down to the names and functionality of flags, but
there's also many subtle details in the differences. For example, normal grep
invocations will use BREs by default, which have different escaping rules than
EREs, where EREs are closer to what ripgrep uses. There's also the difference
where ripgrep respects things like .gitignore and ignores hidden files _by
default_ , which means there's likely a non-zero number of shell scripts out
there where swapping grep for ripgrep will break. Folks won't (and shouldn't)
take too kindly to that. :-)

To a first approximation, ripgrep is optimized for end user experience in a
terminal. This leads to different design decisions. Offering a compatibility
mode with grep has been suggested, but is significant work.

[1] -
[https://github.com/BurntSushi/ripgrep/issues/10](https://github.com/BurntSushi/ripgrep/issues/10)

~~~
kaushalmodi
Have you set up a Hackernews/Reddit crawler that pings you each time someone
mentions "ripgrep"? Seriously, I'd be interested in knowing what solution you
use.

~~~
burntsushi
I just saw it on the front page, which I check embarrassingly frequently. :-)
(But I do have a Google Alert setup for it, sure.)

------
Tycho
How does fzf actually work? What string matching techniques are behind it?

~~~
fernandotakai
their docs explain a lot on how it works, all the options and etc
[https://github.com/junegunn/fzf](https://github.com/junegunn/fzf)

