A fuzzy cd command for Fish
This is not a Christmas post. I kind of forgot it was Christmas Eve until my mom called just now. So I edited this post to start with “Merry Christmas.” I hope that brings cheer to your life.
I’m constantly playing with ways to make navigating in Terminal easier. I’ve been doing it for years. Tools like z
, fasd
, jump
, bashmarks
, cdargs
, and dozens more always appeal to me. My latest experiment has been creating an all-purpose cd command that combines some of my favorite navigation methods.
Fair warning, this only applies to the Fish shell. I’m sure you could duplicate it in any shell, but I haven’t the time.
This trick comprises several of my other tools, including a custom version of jump, and my own fuzzy directory search. Add fasd and mix in some fzf for good measure.
If you’re not familiar with jump
(originally by Joroen Janssen), it’s basically a port of Bashmarks, which was probably a port of something else… it allows you to create shortcuts to your frequently used directories. You type m abbr
to bookmark the current directory, then jump abbr
to return to it. So I can just type jump bunch
to change to the repository folder for Bunch. It’s actually aliased to g
, so it’s just g bunch
. I expanded this to allow additional arguments which are fuzzy searched within the target directory. So I can type g doing lib compl
and get to ~/Code/doing/lib/completion
. I also made it fuzzy match the bookmark name itself, so g do
would jump to the doing
mark if there was no better match.
If you don’t want to use jump
, you can just create the folder ~/.marks
and this fuzzy cd function should still work.
I also make frequent use of autojump
, which relies on fasd
to allow you to jump to recently-used directories with fuzzy name matching. I have it aliased to z
, so assuming at some point I had been in the ~/Code/doing/lib/completion
directory, I can just type z complet
to get back there (or to the recent directory that ranks highest for the search terms).
My goal was to combine all of this into one command so I could just use cd
and it would figure it out. Here’s what it does:
- If there’s only one argument and it matches a subdirectory of the current path, just cd to it. Path completion still works.
- If the first argument contains no non-alphanumeric characters (
/
,.
, etc.) and fuzzy matches a jump mark, use that as the base, otherwise use the current directory as the base - Do a fuzzy directory search using any additional parameters. Arguments are separated by spaces, but if an argument contains
/
it will be split into multiple search terms - If no results are found below the current directory or the base jump mark, switch to fasd and find matches for the search string
- if there’s more than one match returned by any of the above, use fzf to allow quick selection
I played with adding tab completion for this, but Fish completion is finicky if you try to modify the command line while completing, and the way this trick works means multiple arguments result in a single path, so just replacing the last token results in a broken command. So I gave up on that.
Anyway, if you’re using Fish and want to see if you can benefit from my hacking, the files you need are all in my Fish files repo on GitHub. You’ll need a couple of things first.
Prerequisites
You’ll definitely need to install fasd
. This is easiest with Homebrew, just brew install fasd
.
To make use of the jump marks, you’ll want to install this particular jump plugin (via omf install jump
, probably). The __fuzzy_cd
function doesn’t actually use it for jumping, but my replacement for the jump
function does not include any functions for adding or listing marks. This version of jump creates symlinks in ~/.marks
, which is what fuzzy cd is set up to read.
Installation
Updated: I’ll leave the below instructions in place in case you want to set this up manually, but you can now install this command using fisher:
fisher install ttscoff/fuzzy_cd
Once installed, your cd
command will be updated and function as a fuzzy cd command. You can revert at any time using fisher remove ttscoff/fuzzy_cd
.
Manual Installation
Clone the github repo and pick out the files you need/(want). You’ll need the following installed to matching folders in ~/.config/fish
:
- conf.d/fuzzy_cd.fish (shadows the default cd function)
- conf.d/common.fish (utility functions)
- functions/__fuzzy_cd.fish (the main fuzzy cd function)
- functions/ffmark.fish (fuzzy matches jump marks)
- functions/jump.fish (my replacement for the jump function)
- functions/ffdir.fish (fuzzy search subdirectories)
- functions/__f_dir_regex.fish (utility function)
- functions/shortest.fish (utility function)
I’m hoping that’s all. My “system” for organizing functions has morphed over time and is currently a bit chaotic. It doesn’t seem that way until I try to share something I’ve been working on, but here we are.
Once those files are in place, open a new terminal to load the functions. The conf.d files should automatically shadow the cd command for you, and the rest of the functions are autoloaded. Just type cd search string
to see if it works (or cd mark_name subdirectory
).
If you try it and hate it, uninstalling is as simple as removing the conf.d/fuzzy_cd.fish
file. The rest of the files can stay or go, depending on whether you want any of the utility functions they provide for other purposes.
If you test this out, let me know how it goes! It seems to be working well for me so far… there’s a bunch of new stuff in the GitHub repo since the last time I mentioned it, feel free to explore.