4

In bash, pressing Tab invokes the programmable completion feature and either (a) expands to a unique path or command matching what's typed or (b) a list of possible options.

Is it possible to undo the entire expansion made by pressing Tab?

Example:

  1. My current command is ls application/views/.
  2. There are two possible expansions on that command: helpers/ and scripts/.
  3. I type heTab, which expands to helpers/.
  4. I realize I meant the other one scripts.
  5. Now I have to delete the entire expansion "helpers/".

I usually just backspace over the entire path (helpers/ in this case), because I find striking readline undo Control+_ tedious. What I'd like is a single key sequence that deletes the full match of the expansion, regardless of any characters I initially typed and any spaces or slashes added to the end.


Running list of key sequences suggested by comments or my own read of the GNU reference. None of these accomplish the goal:

  • Meta+b -- Moves back to the previous / or , but doesn't delete.
  • Meta+Del -- Deletes one character, not the entire word.
  • Meta+Backspace -- Moves back one character without deleting.
  • Control+W -- Deletes the entire path, not just the expansion. So in my example, after pressing Tab, bash expands that to ls application/views/helpers, then when I press Control+W, bash deletes application/views/helpers.

If relevant, I'm using the vi editing mode on a Gentoo Linux box. I've checked my configuration and I've not remapped any characters.

  • You can delete back one word with M-b (<alt>+b). – jordanm Nov 11 '15 at 14:45
  • @jordanm That just jumps my cursor back, not deleting. Thoughts? – bishop Nov 11 '15 at 14:47
  • 1
    Words are usually deleted via <ctl>W – schily Nov 11 '15 at 14:49
  • @schily That just blasts the entire path, not the expanded component. – bishop Nov 11 '15 at 14:49
  • 1
    @bishop sorry, that should be M-<backspace>. M-b is move back one word. M-d is delete one word forward. – jordanm Nov 11 '15 at 15:16
8

You're giving the keystrokes, but not the readline bindings, this can explain differences in observed behaviour (try bind -p).

The only way I can think of to do exactly what you ask is to use a custom completion function that saves the buffer state, and a separate key binding which invokes a companion shell function to restore it.

In addition to @Mark Plotnick's excellent suggestion to use menu-complete, other readline/bash options are:

  • shell-backward-kill-word this removes a "shell word" which in the case of an expanded file or path will be the complete file or path name
  • backward-kill-word this removes a "readline word", which in the case of a file or path will be a file or directory name component, including the trailing /
  • undo which undoes each change atomically, but this almost certainly requires several attempts to fully remove a complete expansion, this is almost certainly the function you have bound to to ctrl-_ (bash default)
  • set-mark and kill-region are lesser used readline features, set-mark marks the current cursor position, and kill-region deletes from the mark to the cursor. This requires you to invoke set-mark (default meta-space) in advance so that you can later use kill-region to delete back to it (no default binding)
  • possible-completions (bound to meta-=) which lists the completions without modifying the command buffer

You could also write your own function to modify the input buffer, and bind it to a function (here's one I made earlier) but I don't see how that would be very much better than backward-kill-word in this case.

You can test bindings on the fly without using .inputrc using bash's bind command, e.g.:

bind "\C-o: backward-kill-word"
bind "\C-o: shell-backward-kill-word"

backward-kill-word is the best fit, default binding is metactrl-h. set-mark/kill-region would be better, but I can't think of a neat way to automate the use of this though.

  • Perfect, thanks! bind -p showed that backward-kill-word was unbound. I rigged it up to my Shift+Tab with "\e[Z": backward-kill-word and now it does exactly what I want. – bishop Nov 11 '15 at 19:22
  • zsh's undo can actually undo a completion in one step! – SilverWolf Nov 3 '18 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.