Possible to change tab completion behavior in fish shell? - bash

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 ...

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.

Related

how to prevent emacs from changing cursor position when scrolling the page

there is this annoying behavior in emacs which I don't know how to get rid of it.
lets say the current cursor position is on line 10 column 15.
now I need to quickly look up something far down the same buffer, I scroll down to that location and as I scroll down (or up) the cursor keeps moving and it loses its original location.
many people suggest to set a marker before scrolling but that is not a good solution, because you have to be always mindful of this fact before scrolling (which is impossible)
I know there should be a simple solution but I have not found it yet.
I'll appreciate your suggestions
As far as I know, Emacs doesn't allow you to scroll in such a way that your point disappears. I just took a quick look at xdisp.c and it looks like this is a fundamental assumption in the C code. This is different from some more recent editors (Sublime Text, VSCode etc).
However, the "many people" you mention actually have a reasonable point. If you're moving through the file by searching (C-s the-thing-im-looking-for) then Emacs will set a marker for you automatically.
I guess you could try adding a hook that set a marker at point whenever you scrolled? It wouldn't be trivial because you'd have to cope with things like not setting a load of markers through the file as your scroll dragged the cursor down. But my recommendation is probably to alter your workflow to match how Emacs wants to do things. In this case, it's probably a better approach than the modern editors it sounds like you're used to.
An option that might or might not be useful is scroll-preserve-screen-position. The description is somewhat hard to understand, but a net result is that if you mainly scroll using C-v/M-v, the point will visually stay at the same place on the screen (so if you do e.g. C-v C-v M-v M-v, the point will come back to its original position.
However, note that many commands do push a mark before they jump: isearch, end-of-buffer, imenu, xref-find-definition ... In all those cases, you can then press C-u C-SPC (the same command that you use to set the mark but called with a prefix argument) to pop the mark (concretely, jump to the last mark). If you need to jump back more than once, you can set the variable set-mark-command-repeat-pop to t, so that you only need to do C-u once and then repeatedly press C-SPC to pop more and more marks from the mark ring.
In general, there are better ways to navigate a buffer than scrolling in the wild; the cases where you do need to scroll, starting from "your current" point are (or should/could be ...) sufficiently rare that you know beforehand that you will be spending a possibly long time "looking around" in the buffer. It is then quite fast to set a mark, do your stuff somewhere else, and C-u <mash C-SPC as often as needed> until you get back to your initial point.

Cursive navigate forward/back word within a comment line

Alt-left & Alt-right (the emacs key-bindings that work across many apps in Mac OS, including as I type now into chrome), instead of doing forward and back word, go forward and back form (i.e. lisp form).
This is a much higher level navigation, frustrating at first, but actually turns out quite usable because you can just bump one char into a form if you don't want to jump over it, then you can navigate by word within it just fine.
This is fine except within a comment line. There, the usual forward and back word break completely, simply jumping you back to the previous form (comment lines are ignored) or on to the next.
It would be great to be able to make cursive/intellij respect forward/back word within a comment line if possible but I have no idea how to modify this particular behaviour. It seems deeper than just modifying a key binding, if I'm correct.
It turns out these keys in cursive/intellij are bound by default as follows (note Alt-right is by default bound to both of the below):
and
The second was overriding the first, the one wanted here.
So by removing the alt binding to make it look like:
Plus the same for back, it now works as desired :)

Some questions related the autocompletion of the fish shell

When typing the beginning of a command in the fish shell the most recent (or frequently?) possible completion of the command is visible in dark grey.
Say I type:
fish
in dark grey: _config is appended.
at this time it is not yet evident, what I'm about to do. So the TAB key shows me all possible completions of 'fish'
I can keep on typing characters, until it's clear what I want. E.g: _con
Now there is only one option to which this could be completed. So I can hit the tab key to see fish_config. However: this was not indicated somehow. In other words: After typing fish_con nothing really tells me that I don't have to keep on typing. Is this the case? Wouldn't this be extremely helpful?
Second question: What is the actual sense of the grey characters? I'd only understand their purpose if there was a way to accept this propose. After typing f, I'd expect a key combination that immediately fully completes to the propose in grey: fish_config.
Even better would be the option let the grey letters cycle through all options, or possible completions based on the history.
The characters to the right of the cursor are called the autosuggestion. They are gray to indicate that they are not actually part of the command, just a suggested completion of what you've typed so far.
So I can hit the tab key to see fish_config. However: this was not indicated somehow. In other words: After typing fish_con nothing really tells me that I don't have to keep on typing
This sounds like you have an idea for an indication when the partial command is a unique prefix of another command. I am not sure what UI you have in mind - what would the indication look like? Please feel welcome to open an issue with your UI ideas.
However if your command is unique, the autosuggestion will always contain it.
Second question: What is the actual sense of the grey characters? I'd only understand their purpose if there was a way to accept this propose. After typing f, I'd expect a key combination that immediately fully completes to the propose in grey: fish_config.
You can accept the autosuggestion by hitting right arrow or control-F. Tab shows you all possible completions, and up arrow lets you cycle through matching history.
You may want to read the fish tutorial, which covers autosuggestions here: http://fishshell.com/docs/current/tutorial.html#tut_autosuggestions

Three-way-merge - different philosophies?

I've been a user of UltraCompare Pro since it first came out, and I think it's a very full-featured compare and merge tool. However, since I have been looking more closely into DVCS, I found that it handles three-way merges differently than (most?) other tools out there. So I wonder why that is, and whether I'm missing something because of it.
In UltraCompare, there are three merge panels (let's call them base, local and other). All the merge action happens within these panels. In practice, this means that I do my work on the middle pane (local), merging changes from the right (other) or maybe from the common ancestor on the left (base). The middle pane is modified during the session and then saved - and committed as the result of the merge. The fourth pane (Output window) only contains information about the diff result.
(source: ultraedit.com)
In other tools, it appears that the three panes only exist in a read-only state, and that the fourth, bottom pane (output) is the place where all the merging happens. What are the reasons to have an extra merge window? Is it easier to keep track of all the changes? Or is it just like that because everybody has always been doing it this way, so we're copying that behavior? What's your opinion on this?
(source: hginit.com)
I'm not sure whether there exists a best or correct answer, so I haven't yet made this question CW, but I'll defer to your opinion here as well.
Seems straightforward to me, you might very well want to keep an unchanged ‘local’ version visible when you are making your changes.
original local other merged
bar= foo+1 bar= foo+2 bof= foo+2
zot= foo+1
... ... ... ...
print foo print bar print foo+1 print bar??
Both local and other have introduced a new variable bar. Merge the first change to bof/zot, go for a cup of tea, come back and try to merge the print. Wait, what was bar in local? If the original local isn't there, that information's gone, and you're scrabbling about with another text editor to work out what's happened.
This is a contrived example but this sort of thing can easily happen for any set of changes you can't keep all in your head and do in one go. In general, a 3WM always has two variable elements, change A and change B. To reproduce all the information in that, you need four views for all the possible permutations of: 0 (the original), A, B, and AB (the merge).
Project: Merge is a comparison and merge tool I've written for XML. I looked at the standard 4-pane approach and almost instantly discarded it as being a very wasteful way of displaying data. A point amply proven in the screenshots above where nearly all panes are showing exactly the same data multiple times.
I therefore developed a single pane approach for displaying all input files and showing which of them contributes to the output. (Or where the differences are when comparing files.) While I haven't allowed completely free form editing of text (mostly due to how the XML nodes are managed and referenced) some parts of the merge output can be edited more or less as you would in a regular text editor. (My editor keyboard shortcuts closely follow those of Visual Studio as far as navigation is concerned.) Most notably character data, comments, and attribute values. You can also cut and paste XML nodes in their entirety. (But obviously only as text to external applications.)
The following screenshot shows a three-way merge with most changes appearing in the 'left' file, and an unresolved conflict below the selected change:
Personally, I like the free perforce merge tool (p4merge). It also has 4 windows - top middle for the original (before branching), left for destination branch, right for source branch and the bottom part is editable.
I like this better than your option 1, as all 3 original files may have important information that can influence the merge.
There are basically two ways to display differences between two files:
Two panels side by side
One panel
Graphically:
aaa aaa
bbb ···
··· ccc
ddd ddd
and
aaa
-bbb
+ccc
ddd
Some program use the first one (e.g. WinMerge) and some programs allow to choose (e.g. TortoiseMerge or Google Project Hosting). It's probably a matter of taste but I find the second one more intuitive when you want to track changes. However, you need two panels when you want to edit changes.
When doing three-way merges, the different layouts come from this. Ultra compare uses the single panel approach to display changes so you get two panels plus a third panel to edit. Other programs use the two panel approach to display changes so you get three panels plus a fourth one for edits.
Again, I believe it's just a matter of taste.

What's the point of viEmu plugin for Visual Studio?

This may sound a bit provocative but it actually is a real question. Feel free to edit if you don't like the tone.
Now, as much as I understand vi from my short experience with it like 10 years ago, it's a primitive text editor with one editable line at the bottom of the screen created before the scrollbars were invented, with some crazy shortcuts to overcome this limitation.
Can somebody explain me how one can be more productive with it than with, say normal VS.NET editor? Moreover, why would anybody want to use viEmu which supposedly turns your VS.NET into an ancient vi?
I'm willing to give it a try but I need some motivation to overcome the learning curve.
It honestly sounds like you have never seen someone use Vi who is truly proficient in it. When you normally use Visual Studio you frequently will move your hand over to your mouse, click through options, dialogs, classes, etc.
With ViEmu your hand never leaves the keyboard. You are compiling, switching files, highlighting groups of text, fixing indentation, performing complex motions on your code and running regular expression searches in seconds. For people who are fast typists it allows you to achieve a speed for tasks you would not be able to otherwise.
Many people will counter this by saying things like, "Most of my development time is spent thinking. The extra speed I gain from using tools like these is negligible.".
That is a non-argument in my opinion. It is true, for most large programming tasks you spend far more time planning and thinking then you do actually slinging code. But that doesn't mean that being able to express yourself through your IDE 2x faster doesn't have an impact on your productivity as a programmer.
The viEmu page itself has a pretty good article that might help to answer your question: Why, oh WHY, do those #?#! nutheads use vi?
I've spent the last couple months trying to teach myself to use vim "properly" and now I can hardly stand using other editors because they seem underpowered and clunky. For a random example, imagine you have a line of code that looks like this:
$welcomeMessage = "Welcome to SiteName!"; // shows at the top of homepage
In a normal editor, how would you change the string? You'd probably have to reach over and grab your mouse and carefully select it, or you'd move your cursor inside the first quotation mark, and hold down Shift and the right-arrow until you got to the closing quotation mark.
In vim, with my cursor anywhere in-between the quotes, I type ci" and it erases everything inside the quotation marks and puts me into insert-mode so I can type the new value I want. My hands didn't even have to move from my normal typing position.
There are so many things like this, I think you really have to spend a while using the editor to understand how powerful it is. It's very slow and hard to use at first, that's why a lot of people try it for a short time and think "this is dumb, everything is way harder", but after a while you start thinking in terms of the motions, it all starts to become automatic and it's much, much faster than using a "normal" editor. As I said, I can't go back now.
I've also had trouble understanding why people choose vim as their editor, even though I was using it from time to time, until I've finally "got it". I think most explanations of "why?" fails, because they fail to show couple crucial points. To explain those points, first you need to understand that in vim you are manipulating text primarily being in command mode. Ie by default your key presses are commands, and do not usually insert any text, unless those commands (like append, insert, change) switch to insert mode. This lets you navigate and edit your text easily without ever touching your mouse or moving your hands away from "editing pose".
Now the crucial points are:
Vim commands are divided into nouns, verbs and modifiers.
Editing is performed by combining them.
And this is what gives vim the power. To ilustrate the point, here are some most used commands:
Nouns: word, sentence, block, quotes and braces.
Verbs: cchange, insert, visual, delete
Modifiers: inside, around, till
And to ilustrate how you can mix them:
Want to change a word? cw
Same, but cursor in the middle of the word? caw
Change text inside quotes? ci", also change quotes? ca"
Delete function body? di{
Delete up till first comma? dt,
Delete up till second comma? d2t,
Jump to first comma? t,
Select word? viw
Also notice how all commands nicely translate into natural language:
delete word
change inside {
In vim if you learn a new verb, noun or modifier, you can easily mix and match with what you already know. So basically learning just one thing, you learn how to do a lot of different things.
Another great thing is that vim remembers what commands you have used, and you can repeat the sequence just by pressing .. For this post I've had to surround a lot of letters with <kbd> tag. But I've did that only once, and then just went over each letter and pressed ..
And that's basically the thing you "need to get" to understand the power of vim and become advanced user overnight.
P.S. if you don't like vim because it's console based and want a modern text editor, then I suggest looking into Sublime Text editor, which is a great editor and also supports vim mode.
P.S.2. I also recommend to map Esc key to jj and kk, which makes things a lot easier.
You are wrong about "one editable line at the bottom of the screen." All the text in the window is editable. And it does scroll (all versions) and in the case of gvim, has scrollbars.
Maybe you inadvertently put it in "ex mode". This is easily done and can be confusing.
Another answer got me thinking that watching some skilled editing using vim would be pretty revealing so I dug up this video showing basic and more advance motions while coding. This person could get even a bit efficient using some marks, etc but it gives an idea.
http://www.youtube.com/watch?v=FcpQ7koECgk&feature=related
If you need inspiration or want to see someone who really knows what they are doing with Vim, check out Gary Bernhardt's String Calculator Kata In Python, look at him go! http://vimeo.com/8569257
I think they have a long and acceptable answer for your question on the viEmu hompage:
One other even more powerful example: let's take the 'ce' command, which is composed of 'c' and 'e'. The 'c'hange command deletes the range specified by the next motion command, and also enters insert mode. It's the same as 'd', but with the distinction that it enters insert mode, instead of staying in normal mode. The boon is that the text you type in the next (short) input session is also part of the command. So if you do 'ceHello>', what you do is replace from the cursor to the end of the word by 'Hello', and the '.' command afterwards will work exactly like that: replace up to the end of the word with 'Hello'.
From:
http://www.viemu.com/a-why-vi-vim.html
I have viEmu installed ~half year ago. But I have to say (maybe without strong linux experiences) I've never used it. Too alien, too far, too complex.
So IMHO viEmu it's a great technical&historical challenge but no more for the 95% of the developers.
Basically with Vi (or ViM) you get faster because you don't need to touch the mouse and the key-map is improved (this represent learning curve cost but worth the effort) for do any text manipulation in a very easy way once that the fundamentals are learned.
Top 10 things Vi user need to know about Vim
I have not experience with VS.Net but I guess it has the same features that any other IDE has.
I have found that learning the all the key commands of the editor in my IDE was a sufficient replacement for Vi. Things like renaming, indenting, formatting, moving lines and that kind of stuff.
So I guess the major win would be for someone who already know Vi to be productive without having to learn VS.Net.
But then again, Vi has some truly esoteric but powerful features that probably can't be matched by you standard IDE editor.
I think you really should give Vim a try.
If you quickly tried Vi ten years ago, I may understand you didn't appreciate it. It's not really user-friendly at first sight. Actually its real power is revealed when you start feeling comfortable with the movements and start making it your own with customisation.
Once Vim is familiar to you you may understand why it deserves to be learnt.
I actually use VS only for debugging these days. Coding with vim (real vim, not viemu) is just a better experience.
Now, I am not going to claim that using one over another makes any difference in productivity - after all I spend most of my time trying to figure out how to solve a problem - entering the code is the easy part.

Resources