Delete last word (Ctrl-W): Make bash shell behave like vim command line
Among the many useful keyboard shortcuts available in the bash shell, there is Ctrl-W to delete the word to the left of the cursor. Let's suppose my command line looks like the following:
cp some-file /foo/bar/baz/copy
Now I'd expect to be able to press Ctrl-W and end up with the following:
cp some-file /foo/bar/baz/
In Vim's command line it actually works this way: Only alphanumeric characters are treated as "word", whereas special characters (like /
) serve as delimiters marking the start of a new "word".
But unfortunately it doesn't work like that in all shells I've used so far. Only spaces will delimit a "word", so pressing the shortcut with the command line shown above will give me:
cp some-file
Is there a way to make Bash behave like Vim? Some configuration I can put into my .bashrc
?
This has nothing to do with Vim, all editors behave that way (including emacs), they treat non-word characters as delimiters. Anyway, the behavior you are talking about is controlled by readline
and its manual lists quite a few commands you can assign shortcuts to. I am pasting a few relevant ones here but I recommend you read man readline
for more info:
backward-word (M-b)
Move back to the start of the current or previous word. Words
are composed of alphanumeric characters (letters and digits).
kill-line (C-k)
Kill the text from point to the end of the line.
kill-word (M-d)
Kill from point the end of the current word, or if between
words, to the end of the next word. Word boundaries are the
same as those used by forward-word.
backward-kill-word (M-Rubout)
Kill the word behind point. Word boundaries are the same as
those used by backward-word.
unix-word-rubout (C-w)
Kill the word behind point, using white space as a word bound‐
ary. The killed text is saved on the kill-ring.
unix-filename-rubout
Kill the word behind point, using white space and the slash
character as the word boundaries. The killed text is saved on
the kill-ring.
So, the one you want is backward-kill-word
, which uses non alphanumeric characters as word boundaries. By default, it is assigned to Alt+Backspace but you can change that by using either the global /etc/inputrc
if you want them to apply to all users or (better) your own local $HOME/.inputrc
.
As far as I can tell, Ctrl+W seems to be reserved and you can't use that one but you can choose another shortcut, Ctrl+J for example. Create a $HOME/.inputrc
file if it doesn't exist and add this line to it:
Control-J: backward-kill-word
That should be enough for most modern terminal emulators. However, some older terminals use different codes. If you're using xterm
, for example, the line above should be written as:
C-J: backward-kill-word
You can enable readline's (and thus bash's) so called "vi mode" by putting the following lines in ~/.inputrc
and starting a new shell:
set editing-mode vi
set keymap vi-command
But you will notice that <C-w>
works the same as with the default Emacs mode: words are space-delimited. You can do dT/
or similar commands, though. It's still an emulation, not the real deal. The available mappings are listed in readline's manual:
$ man readline
/VI
See also this page on the Vim wiki.
But I don't think readline's vi mode is that useful, if you often find yourself in need of seriously editing your command line… why not use Vim for real?
<C-x><C-e>
There are two options that I know of, though neither directly does what you ask.
- set bash to use vi mode, where the prompt then behaves like a line in vi. The command is
set -o vi
. Ref: BASH Help - A Bash Tutorial - Add vi key maps to your current shell prompt. Ref: StackOverflow: What does set key map vi do?