1

I'm a new user to Fish. I use vi command line bindings. I understand from various places (like here and the issue comments here, for instance) that history search and recall can lack certain bindings and functionality that people like myself may have become accustomed to in bash or other shells.

That being the case, I want to understand how best to do search in vi mode in fish. Judging from the following post from a main contributor to the project: https://github.com/fish-shell/fish-shell/issues/2271#issuecomment-127585955

These bindings should do something:

bind u history-search-backward
bind \cr history-search-forward
bind '[' history-token-search-backward
bind ']' history-token-search-forward
bind -M insert \cp history-search-backward
bind -M insert \cn history-search-forward

Can someone explain to me how any of those work in vi mode? How do you search backward for a term using u, for instance? And how does [ work to search for a token backwards?

I'm struggling to understand the docs. Take this for example: https://fishshell.com/docs/current/interactive.html#command-mode

[ and ] search the command history for the previous/next token 
containing the token under the cursor before the search was 
started. See the history section for more information on history
searching.

OK. So in insert mode, I enter a substring to search on. Then in command mode I try [ and ], but they seem to do nothing. Can someone help me understand what I am missing?

4
  • Thanks for prompting me to take a look - at least some of the documentation is wrong due to a change in 2020 that capitalised a heap of stuff that probably shouldn't have been.
    – Zanchey
    Commented Jul 21, 2022 at 14:12
  • @Zanchey: Understood. Thank you for working on fish. I'm a new user and pretty excited about what it offers. I might suggest adding something in the documentation about the ability to extend history search functionality with external tools, such as fzf. I'm glad someone posted an example configuration for that (see my answer, FWIW). Regardless, thank you again for your hard work on fish.
    – firebush
    Commented Jul 21, 2022 at 14:20
  • One of the problems is that the Vi key bindings are used by a small fraction of users, so they don't get a lot of attention. I'd encourage you to look at the shared bindings section; history doesn't work exactly the way it does in bash but is just as powerful.
    – Zanchey
    Commented Jul 21, 2022 at 14:42
  • 1
    Thank you for the feedback, @Zanchey. I called fish's history functionality "anemic" which isn't really fair. I updated the question accordingly.
    – firebush
    Commented Jul 21, 2022 at 15:10

3 Answers 3

1

I'm not sure how to use those documented history commands in vi command mode.

However, in answer to the intention of my question, I stumbled upon this very helpful comment that makes searching through history in fish quite convenient via fzf: https://github.com/fish-shell/fish-shell/issues/2271#issuecomment-352210807

Pasting the config here:

fish_vi_key_bindings

# Enable command history search via fzf.                                    
function reverse_history_search                                    
  history | fzf --no-sort | read -l command                                    
  if test $command                                    
    commandline -rb $command                                    
  end                                    
end                                    
                                    
function fish_user_key_bindings                                    
  bind -M default / reverse_history_search                                    
end                                    

Some notes:

  • This makes use of fzf, so you'll need to install that on your system (e.g., brew install fzf for MacOS via brew).
  • With the above configuration, press escape to enter command mode followed by / to search your history via the fzf tool.
  • Simply start typing substrings that you are interested in from your history.
  • ctrl+n and ctrl+p navigates up and down through the options.
  • Once you have the option you desire, simply press enter and you will come back to your prompt with that selection.

If you are using fish and want a powerful way to search through history, then I strongly suggest trying this out. I see many comments from people online say that they liked a lot about fish, but felt they had to give it up because of its weak native ability to search through history and recall previous commands. I came close to giving up on it myself. I think this solution may enable many to stick with fish, which is in other ways an outstanding shell.

1
  • In normal mode "/" seems to trigger the search by default. While the script above works, in insert mode, it makes it impossible to enter paths. Commented Apr 1 at 8:54
1

Here's what these mean:

bind u history-search-backward

this means pressing "u" searches the history backwards, with the current commandline as the search string. Because no -M/--mode argument is given, this binding concerns the default mode, which is vi's normal mode.

Note: This particular binding is outdated, "u" in normal mode is bound to undo since fish 3.3.0, released a year ago.

bind \cr history-search-forward

Pressing ctrl+r will search history forwards, with the current search string. Again in default mode.

bind '[' history-token-search-backward
bind ']' history-token-search-forward

Pressing "["/"]" does the same, except with the current token as the search string. So if you have echo foo with the cursor on the "foo", it will look for any token in history that matches "foo", and insert it, resulting in e.g. echo "foobar" if you had run set var "foobar" before.

bind -M insert \cp history-search-backward
bind -M insert \cn history-search-forward

Pressing ctrl+p/ctrl+n searches full commandlines back/forwards in insert mode.

0

I'm using fish for the first time and since I'm used to vi, I immediately set it to that stumbling right into this issue. So I'm leaving this here for anyone stumbling on this page:

There is no need for special configuration for basic search, it's just not very clear in the docs how to get there:

To use the fish search go into "command mode" (aka "normal mode" displaying "[N]" in the cursor) and then start a search with "/" - just start typing - you can select options with your arrow keys.

In "insert mode" ("[I]") you can also search out of the box by simply entering a string and then use up/down arrows to browse through the history that matches that string.

These two things work out of the box (fish 3.7.1) - no need to change any settings other than starting vi mode. (You can persist vi mode by adding fish_vi_key_bindings to .config/fish/config.fish.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .