Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to change tab completion behavior in fish shell?

Update: This complaint relates to an old version of fish -- see the below comment from one of the fish developers describing the awesome improvements to the fish pager behavior which nullified this complaint.

The fish shell is pretty cool -- however I hate one of the features of tab-completion.

I frequently -- almost like a nervous tick -- will hit {tab}{tab} while typing a path when changing directories. This lets me use {tab} to examine the contents of some path while simultaneously solving however much of the path disambiguation problem my current keystrokes allow to be solved. This gives a great way to quickly discover the quickest key combination to get to a certain place in the filesystem without a lot of thought or necessarily having to know the contents of the various directories in advance.

Fish on the other hand interprets {tab} {tab} in what I consider to be an incredibly annoying way. The first {tab} lists the possible completions, that's great. The next tab is pressed fish selects the first completion in the list and replaces the last portion of the path currently entered on the line with the full first completion -- regardless of disambiguation status. Subsequent tabs cycle through the next possibilities. Its similar to what the windows command shell does.

This is far worse than the normal bash behavior ...

Consider a deeply nested directory structure foo/bar/baz/a/b/c/

Where some of foo, bar, baz, are empty directories. Bash tab completion lets me type cd foo/{tab}{tab}{tab}{tab}{tab}{tab} -- without having to think about how many times I'm hitting tab, without having to think through the effects in advance of hitting tab on the current state of my command line entry.

The normal case all these directories won't be empty -- but the above still works to very quickly discover the fewest number of characters I need to enter to make it to some deeply nested path.

With bash behavior: cd some/unknown/dir/{tab}{tab} guarantees that

(1) I see the contents of the directory dir/ (2) as much of what can unambiguously be expressed from my command so far is completed, but no more.

After hitting the two tabs above I might see contents like this:

abc123 bar123 baz123 bcd123 mnop123

the following actions are possible:

a{TAB}{TAB} (gives me abc123 and if this is a directory lists its contents)

m{tab}{tab} (gives me mnop123 and if its a directory lists its contents)

Suppose I want to get to the path bcd123: b -- shows me that I was too fast in my typing, with only 3 options now shown I easily conclude I need only hit 'c' to disambiguate to my goal

b{tab}{tab}c{tab}{tab} (gets me the path I want, lists bcd123's contents if its a directory)

fish's model is much worse. b{tab}{tab} would've completed to bar123, and I have to hit tab an unknown number of times to get the value I wanted, furthermore I have no way of getting the entry context back to only the letters that I've actually typed up to this point (other than hitting backspace a whole bunch of times). What if there happen to be a whole bunch of things that start with ba in this directory -- I'm totally screwed is what happens ...

In general fish's model is worse:

  • it does not allow using tab to complete nested paths -- to do this with fish you need to '/' at the correct time within the command sequence -- which requires mental feedback
  • much more difficult to discover disambiguation sequences when in large directories
  • in general requires you to 'be careful' before you hit tab which makes you hit it less often and decreases its utility ...

Somone please tell me there's a way to change fish's behavior here to be more like bash ... fish is cool but this behavior is unusable -- I'll have to go back to bash if there's not a way to change this ...

like image 849
Ben Avatar asked Jan 28 '15 23:01

Ben


People also ask

What is Shell tab completion?

Command-line completion (also tab completion) is a common feature of command-line interpreters, in which the program automatically fills in partially typed commands.

Which shells support command completion with Tab key?

All of the modern shells have command and filename completion via the <TAB> key. Bourne shell and csh do not, but ksh, bash, tcsh, and zsh all have tab completion to varying degrees.

How do you paste in fish shells?

Shift + D deletes text after the current cursor position and moves it to the Copy and paste (Kill Ring). P pastes text from the Copy and paste (Kill Ring).


1 Answers

I commend you for writing up this detailed and thoughtful post, and it deserves an equally detailed and thoughtful response!

The tab completion behavior has been rewritten in fish top-of-tree (not yet released), and is referred to as the "new pager." You can see the design goals and discussion here. I put a note at the bottom of this reply for how to get it.

Shells are personal, and like anything personal, rationalizations and justifications aren't worth anything: you either like it, or you don't, and we may not even be conscious of the factors influencing our feelings. So all I can really say is try it, see how you feel, and (please) report back.

I put up a short little screencast of the new pager on YouTube. Things to notice: 1. the menu is dismissed just by typing more, 2. it "unfurls" progressively (requires a few tabs to become fully visible), never modally takes over your screen even when there's a huge number of completions, and is easily searchable and navigable, and 3. escape will always dismiss it and put your command line back to just what you typed.

Let me go through your concerns individually:

"I have to hit tab an unknown number of times to get the value I wanted". With the new pager, the selected item is highlighted in the menu. This sounds minor, but personally I believe this makes a huge difference: the number of additional times to hit tab becomes known, and since your finger is over tab, it's often easier to just hit it a few more times than to type additional letters. You can also use the arrow keys to navigate.

"I have no way of getting the entry context back to only the letters that I've actually typed up to this point". With the new pager, the escape key does exactly that. It's easy to press since escape is right above tab, where your finger is.

"What if there happen to be a whole bunch of things that start with ba in this directory -- I'm totally screwed is what happens". Neither bash nor old-pager-fish handles large numbers of completions well. fish would drop you into this modal paging environment, while bash breaks your flow with the modal "Display all 1002 possibilities? (y or n)" dialog that forces you to stop what you're doing and hit 'n'.

I think you'll love how the new pager handles this. Initially you get a short menu, that fills a maximum of five lines below your prompt (not above, and not replacing). This menu is non-modal, and is dismissed by typing more or hitting escape. If you hit tab again, the menu grows to show more completions, but is still non-modal. There's never a jarring transition.

"it does not allow using tab to complete nested paths" Sorry, I'm not sure what you mean by this. Both bash and fish append a / when tab completing a directory.

"much more difficult to discover disambiguation sequences when in large directories" With the new pager, you can hit escape, type some more, and then tab again. Or you can search the menu: put the focus in the menu and type something, and it's filtered. See the screencast above.

"in general requires you to 'be careful' before you hit tab which makes you hit it less often and decreases its utility" A very valid point, which the new pager addresses in a few ways. First of all, it uses a notion of progressive disclosure, which means that it takes "work" to output a lot of data. Second, it never "takes over your screen" like the old modal pager. And lastly, you can hit escape to get back to just what you typed, and since the pager appears below the prompt, it won't leave little turds in your scrollback like bash does.

If you're using homebrew, you can install from master via brew install fish --HEAD. There's also nightly builds for Linux. And lastly, feel free to open an issue at https://github.com/fish-shell/fish-shell/issues with any ideas for improvements you have.

like image 69
ridiculous_fish Avatar answered Oct 20 '22 00:10

ridiculous_fish