28

Putting on Debian 8.3

stty werase '^H'

or on Arch Linux 2/2016

stty werase '^?'

in .bashrc (for example) makes Ctrl-Backspace delete the last word in the terminal. Still it's not the same behavior as in modern GUI applications (e.g. Firefox): It deletes the last whitespace-separated word, and not the last word separated by whitespace or characters like . : , ; " ' & / ( ).

Is it possible to make Ctrl-Backspace behave in the terminal similar to modern GUI applications? Also, is there any way to make Ctrl-Delete delete the word immediately before the cursor?

wittich
  • 155
viuser
  • 2,614

4 Answers4

53

There are two line editors at play here: the basic line editor provided by the kernel (canonical mode tty line editor), and bash's line editor (implemented via the readline library). Both of these have an erase-to-previous-word command which is bound to Ctrl+W by default. The key can be configured for the canonical mode tty line editor through stty werase; bash imitates the key binding that it finds in the tty setting unless overridden in its own configuration.

The werase action in tty line editor cannot be configured. It always erases (ASCII) whitespace-delimited words. It's rare to interact with the tty line editor — it's what you get e.g. when you type cat with no argument. If you want fancy key bindings there, you can run the command under a tool like rlwrap which uses readline.

Bash provides two commands to delete the previous word: unix-word-rubout (Ctrl+w or as set through stty werase), and backward-kill-word (M-DEL, i.e. Esc Backspace) which treats a word as a sequence of alphanumeric characters in the current locale and _. If you want Ctrl+Backspace to erase the previous sequence of alphanumeric characters, don't set stty werase, and instead put the following line in your .inputrc:

"\C-h": backward-kill-word

Note that this assumes that your terminal sends the Ctrl+H character for Ctrl+Backspace. Unfortunately it's one of those keys with no standard binding (and Backspace in particular is a mess for historical reasons).

There's also a symmetric command kill-word which is bound to M-d (Alt+D) by default. To bind it to Ctrl+Delete, you first need to figure out what escape sequence your terminal sends, then add a corresponding line in your .inputrc. Type Ctrl+V then Ctrl+Delete; this will insert something like ^[[3;5~ where the initial ^[ is a visual representation of the escape character. Then the binding is

"\e[3;5~": kill-word

If you aren't happy with either definition of a word, you can provide your own in bash: see confusing behavior of emacs-style keybindings in bash

  • 4
    excellent explanation ! The Ctrl+Del worked well. However, I cannot get Ctrl+Backspace to work. For Ctrl+v, Ctrl+Backspace my terminal says ^?. What should I put in the .inputrc ? Thank you – Ciprian Tomoiagă Mar 19 '17 at 12:16
  • 4
    @CiprianTomoiaga "\C-?": backward-kill-word or whatever readline function you want. But you can only define a binding for Ctrl+Backspace that's different from the binding for Backspace if they send different characters. If your terminal sends ^? for both Backspace and Ctrl+Backspace, then the application running in the terminal has no way to distinguish them. Some terminals can be configured (e.g. xterm, urxvt), others (e.g. VTE-based terminal emulators) can't. – Gilles 'SO- stop being evil' Mar 19 '17 at 21:57
  • 6
    it's important to note that defining ~/.inputrc disables the default /etc/inputrc. to fix this you have to include that file: $include /etc/inputrc (from here) – Ciprian Tomoiagă Mar 31 '17 at 22:26
  • Wow. I've spent the last 10 years hating not having ctrl+del/ctrl+backspace in the terminal and the fix was a 2' config. – Pepe Mandioca Mar 15 '21 at 20:46
  • Using \C-h for both kill-word and backward-kill-word worked for me on Raspbian ‍♀️ – Vimes Mar 02 '23 at 23:22
16

Try

alt+backspace

In elementary OS it works like the way you want it (just like ctrl+backspace)

wjandrea
  • 658
1

The behaviour of the WERASE character in cooked mode terminal processing is hardcoded, at least in Linux:

           if (kill_type == WERASE) {
                   /* Equivalent to BSD's ALTWERASE. */
                   if (isalnum(c) || c == '_')
                           seen_alnums++;
                   else if (seen_alnums)
                           break;
           }

So words are letters, digits, and underscore. This is the way it will be at all times in a terminal on Linux when an application that does its own cooked mode processing is not running.

readline's version (used by bash and others) seems to be a little different than the kernel's version, but it also seems to be hardcoded:

Words are composed of letters and digits.

But this doesn't seem to match what bash actually does for me: foo+bar^W erases everything, not just bar. There is more information about that here.

wjandrea
  • 658
Celada
  • 44,132