Bash uses readline to do its line editing and history search functionality, which works pretty well in the past for me. To enable this, just put these 2 lines of configurations in your ~/.inputrc (the config for your readline):
After restart your terminal or shell, you can now use Up Arrow and Down Arrow to navigate your bash history, the beauty of this is it will match the thing you typed between the prompt and the cursor (if typed nothing, it will just use your last command of the history).
This solution works so well that it increases a lot of my productivity and efficiency in the past and now it becomes a must-have for my shell features. Once I switched to Zsh, I was looking for a similar solution since the first day of using Zsh.
Turns out oh-my-zsh includes a default history search functionality already (up-line-or-beginning-search, down-line-or-beginning-search), which works well for a lot of people, but unfortunately not for me.
The issue for this command is it only matches the command, not the entire thing before your cursor, for example, if I typed:
Then do a tab, it will only match the command starts from “cd”, not the entire “cd code”. You may still call this a history search functionality, but for me, it’s not working as I expected since I come from the bash/readline world.
Then I found one solution in the Arch Linux (My fav linux distribution) forum, which works well for me for at least 2 months since I migrated until I noticed subtle differences (issues).
bindkey '^[[A' history-beginning-search-backward
bindkey '^[[B' history-beginning-search-forward
The configurations above simulate everything in the bash history search except only one thing: the cursor position. In bash when you do a history search the cursor will always be put at the end of the line once search finished and line edited; but here, in Zsh, the cursor will remain its position during search, so it will leave your cursor in the middle of the line once finished matching. If your next action is just to hit Enter, everything is still fine. But you may found you’re in an awkward position if you want to somehow tweak your command a little bit after search completed.
I noticed this differences in the first place, I thought it won’t be a big deal until I realize I’m wrong. Turns out I can’t stand for this so-called small subtle differences at all. Perfectionist? I don’t know, maybe, I prefer to call it the habit, or muscle memory.
So today I started another round of google search for a better solution. Now I finally found it and I think it’s good to share. Turns out there is a user contribution widget in Zsh, which called xxx-search-end, the -end looks so promising when I saw it in the manual page.
After I little bit of research and try-out, here is what I got:
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey '^[[A' history-beginning-search-backward-end
bindkey '^[[B' history-beginning-search-forward-end
Put it in your ~/.zshrc or your zsh configuration file and restart the terminal or shell to enable it.
Noticed that we only add a “-end” to the previous version, but since it’s somehow can’t be found and this command defines 2 widgets in 1 command, the usage becomes slightly different. That’s why we add the autoload and map 2 widgets to the same command. Do “man zshcontrib” and “man zshzle” in your terminal for more details.
One more thing (since we’re all perfectionists:)), if you use Ctrl+U to delete from your cursor to the beginning of the line, you will notice another issue in zsh: it deletes the whole line instead of the desired behavior described above, this can be considered a bug/defect since Ctrl+K works (delete from your cursor to the end of the line). To solve this, put this config along with your history search configurations:
bindkey \^U backward-kill-line
That’s it, enjoy!
- [2012-12-18] Finally we can code