Terminal History Auto Suggestions As You Type With Oh My Zsh
14 April 2019
Oh-My-Zsh is a framework for Zsh, the Z shell. It is an efficiency boom for anyone that works in the terminal. There are a few auto suggest libraries that when combined can give you a fantastic suggestion to what you want to type to save you time and increase your efficiency tenfold. In our instagram post we had some questions about how to get autocomplete like we show in the screencast:
Well…let’s find out!
Our favorite resources
This is what we’re aiming for. As seen below the suggestions show up in a light blue color and those suggestions are based on commands previously typed in that directory. If there are no matches to what has been previously typed in that directory, it then suggests commands that have been previously typed on this computer at any point in any directory.
As a bonus, we also have the commmands “show_local_history” with a number to show the last number of X commands used in this directory. “search_local_history” will then use all the commands typed in this present working directory (PWD) to search based on the string we’re looking for.
What is this based on?
This leverages a few excellent libraries which are very useful just by themselves. zsh-autosuggestions provide us with “Fish like autosuggestions for zsh” based on the command history. It accepts a suggestion strategy that you can specify to guide it how to exactly suggest what to autocomplete with. What we’re doing is overriding the strategy and providing our own custom strategy.
Extending the suggestions
To be able to just use the present working directories history we have to track that in a different way. To do that, we leverage zsh-histdb which provides us with a SQLite database to track our commands and store them in the database. If we were to look at the schema zsh-histdb provides we would see that it has three tables:
- commands: which provides us with an argv column
- places: which provides us with a host (computer host) and a dir which is the present working directory that command was used in
- history: which provides us with a session id, a command_id which links with the commands table, a place_id which links with the places table, an exit_status, a start_time, and a duration
With some SQL querying to we can use all of that data to accomplish directory specific suggestions with a fallback to all directory suggestions. Ok, let’s roll up our sleeves and get some things installed.
Installing Zsh & Oh My Zsh
First, we need to install Zsh since oh my zsh is a framework that sits on top of Zsh. We’re going to use homebrew which you can install by running this in your terminal
Once that finishes, we’ll install zsh using homebrew
And finally, let’s install oh my zsh
If you get an error that says:
You need to install xcode’s devleoper tools before you can install oh-my-zsh. Run this in your terminal:
Let’s make sure zsh is our default shell:
Installing Autosuggestions & histdb
Next, we need to install zsh-autosuggestions. We’re going to follow their official guide
Next, we need to list that as a plugin in our .zshrc. So we’ll need to edit our .zshrc
Let’s add it as a plugin by adding or editing this line. If you have more than one plugin
they need to be separated by a space. Be sure to check your
.zshrc file as there
might already be a plugins line there. If so, just add
zsh-autosuggestions to the plugins
with a space separating any other ones there already.
One thing I like to do since I use a lot of plugins is to have all the plugins listed in a file and just include that file, like so
The contents of zshes/plugins.txt is like this:
Next we need to install sqlite3 since zsh-histdb has that as a dependency. Homebrew to the rescue
We’re now going to follow this guide for the install.
We then need to edit our .zshrc again and add this to it:
Restart your terminal and you should now see auto suggestions working!
We now have auto suggestions and zsh-histdb working, but we still want to customize it so that we get suggestions specific to our directory. To do that we need to tell zsh-autosuggestions to use our history sqlite database instead of the regular zsh history. To do that we can take advantage of the ZSH_AUTOSUGGEST_STRATEGY hook and provide a query and list of suggestions to pass along to zsh-autosuggestions.
Somewhere in your .zshrc file you can copy the below to edit how zsh-autosuggestions sends back suggestions. zsh-histdb has some queries you can use.
This will find the most frequently issued command issued exactly in this directory, or if there are no matches it will find the most frequently issued command in any directory.
This query is fine, however, the issue I have is that it doesn’t order the results by the most recently used. So I have added another to use query so that it orders by what was also most recently used in that directory:
Experiment with both and see what fits your needs best! I’m open to any suggestions to improve the above query as well.
Let’s add in a command to show the local history only. So once again we’ll edit our .zshrc:
This command defaults to showing 10 commands, but we could also pass in a number to get a desired number of results:
We also want to be able to search that history. I personally use ack but you can also use grep for this. We’ll build on our search local history command pass a limit of 100 and come out with this: