Delete key doesn't work on command line

34,015

Solution 1

For Googlers:

Whew. For something that should be so simple, this was hard.

The short solution is use the following to set the delete key (in kshrc or wherever),

bind '^[[3'=prefix-2
bind '^[[3~'=delete-char-forward

And set your PuTTy terminal settings to rxvt instead of Standard.

PuTTy settings

This thing that really helped me get this working was: http://www.mail-archive.com/[email protected]/msg81796.html

ksh does silly things with the home and end keys. Basically, I couldn't make it tell the difference between Home, End, and Delete at the same time. Whatever was last bound, all three keys would do. Changing what PuTTy sent for these keys helped immensely.

Note: Some folks suggest if you want to see what code the shell is getting when you press a key, type cat, press enter, then push the key. For my shell, this didn't work. I got ~ for all the control keys. What I did instead was press Esc once, then press the key. The control code would show then show up. Use that control code in bind and you're all set.

Solution 2

If shell is running inside a gnome terminal window, then menu into: Edit | Preferences | Profiles and select a profile, then select the Compatibility tab, and change the Delete key generates to Automatic. (Or if this fails try the other choices there.)


Also, you can enter ^v Del and ^v Backspace, (i.e. Control-v followed by the delete key, and Control-v followed by the backspace key), to find the returned 'terminal' sequence codes.


And for inspection use the showkey command as showkey -s, showkey -k, and/or showkey -a (i.e. the three layers) and then press the Del and Backspace keys for:

I) raw output from a keyboard
II) output from tty driver
III) character strings given to a (ansi) terminal


From this I noticed that when using stty (e.g. stty1) that my shell behavior was different from when using xterm (from within a Graphical X terminal). Del deleted correctly forwards (right) in stty1, but backwards (left) in my xterm.

Solution 3

The existing two answers did not work for me going from Linux (Ubuntu 18.10) bash, via SSH to Solaris 11.3 bash, using gnome terminal.

I found I needed to use the bind command, but with a work-around, as I could not get a native Delete to function.

So the work-around is that when Delete is pressed, to simulate a delete by mapping the delete keypress to and Backspace.

bind '"^[[3~":"^[[C^?"'

To type that, use the key-presses:

CTRL-vDelete for the first part
and CTRL-vCTRL-vBackspace for the second.
(or use \e for the escape instead, e.g.: "\e[3~")

It's not perfect, if you Delete at end-of-line, it still backspaces. But it saves me having to backspace-out the ~ character umpteen times a day.

Solution 4

According to man ksh on my Debian 10 system, prefix-1 "introduces a 2-character command sequence" and prefix-2 "introduces a multi-character command sequence". Essentially, they tell the shell "don't process this yet, there's supposed to be a longer sequence of characters - wait for the complete sequence."

Modern Unix/Linux terminal sessions generally run on terminal emulators: they essentially emulate (an extended version of) some type of computer terminal connected over a serial port. With many terminals, the mapping between keyboard keys and characters sent to the computer was not strictly one-to-one: because there were no standardized ASCII control characters for all the various non-character keys of the keyboard, some keys will send multi-character sequences. The function keys, arrow keys, Home, End, Insert, Delete, PgUp and PgDn belong to this group.

The Esc key is represented as ^[, in other words Control+[. And when you look at an ASCII code table, you'll see that the Control key essentially subtracts 64 (i.e. flips one bit) from the value of the regular character combined with it. So ^[ is just a single ASCII control character that has the special name "ESC".

Your bind | grep prefix output indicates ^[ is already recognized as prefix-1, and ^[[ as prefix-2.

The Delete key actually sends a sequence that would be the equivalent of Esc [ 3 ~.

So the shell must parse it one character/byte at a time, like this:

  1. received Esc: also known as ^[, matches prefix-1, so wait for at least one more character and combine this with it
  2. received [: combined with the previous prefix character it's ^[[ which matches prefix-2, so wait for more still and keep combining the characters.
  3. received 3: combined with the previous prefixes it's ^[[3 which is prefix-2 again, so keep waiting and combining.
  4. received ~: now the resulting combination is ^[[3~ which now matches the binding for delete-char-forward.
Share:
34,015

Related videos on Youtube

user3330406
Author by

user3330406

Updated on September 18, 2022

Comments

  • user3330406
    user3330406 almost 2 years

    **Note: I asked this same question on SuperUser, but didn't get any response. I now realize this is a more appropriate forum for this particular question.*

    In a ksh shell, the Delete key doesn't work appropriately on the command line. I get a ~ when I press Delete.

    How do I:

    1. bind the functionality of "Delete the character at the cursor" to the Delete keyboard button? (Control-D behaves like I expect the delete button to work and my attempts at using an alias were unsuccessful and likely naive.)
    2. bind the functionality of "Move to the first of the line" to the Home keyboard button? (Control A does this now, but I want Home to do it.)
    3. bind the functionality of "Move to the end of the line" to the End keyboard button? (Control E does this now, but I want end to do it.)

    Final(?) Update

    I stumbled across something that works, but I don't understand quite why. This works:

    bind '^[[3'=prefix-2
    bind '^[[3~'=delete-char-forward
    

    According to http://www.qnx.com/developers/docs/6.3.2/neutrino/utilities/k/ksh.html#bind,

    prefix-2
    Key binding: ^X, ^[[
    Introduces a 2-character command sequence.
    

    So my updated question is why do I need to use prefix-2 for this? Please translate for me so I can understand so I don't have to bug everyone again about this.

    OLD STUFF FOLLOWS

    UPDATE

    It turns out that ESC in QNX is ^[. Using the command bind '^[[3~'='delete-char-backward' I am able to get the cursor to overwrite the character under the cursor with a ~. This is some progress at least--I now know how to spell Delete Key for the shell. Most things I have seen on the web say that the delete key is ^?, but that doesn't seem to work for me. Also, I should mention I am accessing this via PuTTy.

    I don't understand because Control D does what I want the delete key to do. I tried binding it to eot-or-delete again to no avail.

    This should be simple, right?

    UPDATE 2:

     bind | grep prefix
    ^X = prefix-2
    ^[ = prefix-1
    ÿ = prefix-3
    ^[O = prefix-2
    ^[[ = prefix-2
    
    
    bind | grep '[^ -~]'
    ÿ = prefix-3
    à  = beginning-of-line
    à¡ = up-history
    ठ= backward-char
    ঠ= forward-char
    ਠ= end-of-line
    à© = down-history
    ଠ= delete-char-forward
    à´ = backward-word
    ච= forward-word
    

    UPDATE 3: More of my settings

    ENV setting

     echo $ENV
    /etc/kshrc
    

    BIND Complete Output

    bind
    ^A = beginning-of-line
    ^B = backward-char
    ^C = abort
    ^D = eot-or-delete
    ^E = end-of-line
    ^F = forward-char
    ^G = abort
    ^H = delete-char-backward
    ^I = complete
    ^J = newline
    ^K = kill-to-eol
    ^L = redraw
    ^M = newline
    ^N = down-history
    ^O = newline-and-next
    ^P = up-history
    ^R = search-history
    ^T = transpose-chars
    ^U = kill-line
    ^V = version
    ^W = kill-region
    ^X = prefix-2
    ^Y = yank
    ^[ = prefix-1
    ^\ = no-op
    ^] = search-character-forward
    ^^ = quote
    ^_ = eot
    ^? = delete-char-backward
    ÿ = prefix-3
    ^[^H = delete-word-backward
    ^[^X = complete-file
    ^[^[ = complete
    ^[^] = search-character-backward
    ^[  = set-mark-command
    ^[# = comment
    ^[* = expand-file
    ^[. = prev-hist-word
    ^[0 = set-arg
    ^[1 = set-arg
    ^[2 = set-arg
    ^[3 = set-arg
    ^[4 = set-arg
    ^[5 = set-arg
    ^[6 = set-arg
    ^[7 = set-arg
    ^[8 = set-arg
    ^[9 = set-arg
    ^[< = beginning-of-history
    ^[= = complete-list
    ^[> = end-of-history
    ^[? = list
    ^[C = capitalize-word
    ^[L = downcase-word
    ^[O = prefix-2
    ^[U = upcase-word
    ^[[ = prefix-2
    ^[_ = prev-hist-word
    ^[b = backward-word
    ^[c = capitalize-word
    ^[d = delete-word-forward
    ^[f = forward-word
    ^[g = goto-history
    ^[h = delete-word-backward
    ^[l = downcase-word
    ^[u = upcase-word
    ^[y = yank-pop
    ^[^? = delete-word-backward
    ^X^X = exchange-point-and-mark
    ^X^Y = list-file
    ^X^[ = complete-command
    ^X? = list-command
    ^XA = up-history
    ^XB = down-history
    ^XC = forward-char
    ^XD = backward-char
    ^XH = beginning-of-line
    ^XP = delete-char-forward
    ^XY = end-of-line
    ^Xc = forward-word
    ^Xd = backward-word
    ^Xw = end-of-line
    à  = beginning-of-line
    à¡ = up-history
    ठ= backward-char
    ঠ= forward-char
    ਠ= end-of-line
    à© = down-history
    ଠ= delete-char-forward
    à´ = backward-word
    ච= forward-word
    

    /etc/kshrc

    /etc # cat kshrc
    case $- in
    *i*)
        export SHELL_COLOR_BLUE="print -n \\033[0;34m"
        export SHELL_COLOR_GREEN="print -n \\033[0;32m"
        export SHELL_COLOR_RED="print -n \\033[0;31m"
        export SHELL_COLOR_LIGHTGRAY="print -n \\033[0;37m"
        export SHELL_COLOR_YELLOW="print -n \\033[1;33m"
    
        export COLOR_BLACK="\\033[0;30m"
        export COLOR_BLUE="\\033[0;34m"
        export COLOR_GREEN="\\033[0;32m"
        export COLOR_CYAN="\\033[0;36m"
        export COLOR_RED="\\033[0;31m"
        export COLOR_PURPLE="\\033[0;35m"
        export COLOR_BROWN="\\033[0;33m"
        export COLOR_LIGHTGRAY="\\033[0;37m"
        export COLOR_DARKGRAY="\\033[1;30m"
        export COLOR_LIGHTBLUE="\\033[1;34m"
        export COLOR_LIGHTGREEN="\\033[1;32m"
        export COLOR_LIGHTCYAN="\\033[1;36m"
        export COLOR_LIGHTRED="\\033[1;31m"
        export COLOR_LIGHTPURPLE="\\033[1;35m"
        export COLOR_YELLOW="\\033[1;33m"
        export COLOR_WHITE="\\033[1;37m"
    
        if [[ `id -u` -eq 0 ]]; then
            export PS1=`$SHELL_COLOR_RED`'$(hostname -s):'`$SHELL_COLOR_YELLOW`'$(pwd) # '`$SHELL_COLOR_LIGHTGRAY`
        else
            export PS1=`$SHELL_COLOR_BLUE`'$(hostname -s):'`$SHELL_COLOR_GREEN`'$(pwd) $ '`$SHELL_COLOR_LIGHTGRAY`
        fi
    
    esac
    

    PuTTy settings:

    enter image description here

    Notes that may or may not matter, but could provide background:

    The shell is "PD KSH v5.2.14 99/07/13.2". Yes, I have no option to upgrade... it's an embedded system. "Get a modern shell" is not a viable answer. The operating system is QNX Neutrino 6.4.1.

    bind shows the following:

     bind | grep del
    ^D = eot-or-delete
    ^H = delete-char-backward
    ^? = delete-char-backward
    ^[^H = delete-word-backward
    ^[d = delete-word-forward
    ^[h = delete-word-backward
    ^[^? = delete-word-backward
    ^XP = delete-char-forward
    ଠ= delete-char-forward
    

    infocmp shows the following:

    infocmp  #      Reconstructed via infocmp from file:
    /usr/lib/terminfo/x/xterm xterm|vs100|xterm terminal emulator,
            am, km, mir, msgr, xenl, xon,
            cols#80, it#8, lines#65, vt@,
            acsc=Oa``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
            bel=^G, blink=@, bold=\E[1m, clear=\E[H\E[2J, cr=^M,
            csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
            cud=\E[%p1%dB, cud1=\E[B, cuf=\E[%p1%dC, cuf1=\E[C,
            cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
            dch=\E[%p1%dP, dch1=\E[P, dl=\E[%p1%dM, dl1=\E[M, ed=\E[J,
            el=\E[K, el1=\E[1K$<3>, enacs=\E(B\E)0, home=\E[H, ht=^I,
            hts=\EH, ich=\E[%p1%d@, ich1=\E[2~, il=\E[%p1%dL, il1=\E[L,
            ind=^J, is1=\E=\E[?1l, kBEG=\ENn, kCPY=\ENs, kCRT=\ENt,
            kDL=\ENv, kEXT=\ENw, kFND=\ENx, kHLP=\ENy, kOPT=\ENz,
            ka3=\EOs, kb2=\EOr, kbs=^H, kc1=\EOq, kcan=\EOm, kclo=\ENc,
            kclr=\ENa, kcmd=\EOu, kcub1=\E[D, kcud1=\E[B, kcuf1=\E[C,
            kcuu1=\E[A, kdch1=\E[P, kend=\E[9, kf1=\E[11~, kf10=\E[21~,
            kf11=\E[23~, kf12=\E[24~, kf2=\E[12~, kf3=\E[13~,
            kf4=\E[14~, kf5=\E[15~, kf6=\E[17~, kf7=\E[18~, kf8=\E[19~,
            kf9=\E[20~, kfnd=\ENf, khlp=\ENh, khome=\E[8, khts=\ENb,
            kich1=\E[2~, kmov=\ENi, kmrk=\ENm, kmsg=\ENe, knp=\E[6~,
            kopn=\ENo, kopt=\ENk, kpp=\E[5~, kref=\ENl, kres=\ENp,
            krfr=\ENg, krpl=\ENr, krst=\ENj, ksav=\ENq, kslt=\EOM,
            ktbc=\ENd, kund=\ENu, rc=\E8, rev=\E[7m, ri=\EM, rmacs=^O,
            rmam=\E[?7l, rmkx=\E>, rmso=\E[m,
            rs1=\E>\E[1;3;4;5;6l\E[?7h\E[m\E[r\E[2J\E[H, rs2=@,
            sc=\E7,
            setb=\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
            setf=\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m,
            sgr=\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m,
            sgr0=\E[m, smacs=^N, smam=\E[?7h, smkx=\E=, smso=\E[7m,
            tbc=\E[3g,
    

    stty shows the following:

    stty Name:  /dev/ttyp0 Type:  pseudo Opens: 2
    +edit +echok +echonl
    +osflow  intr=^C  quit=^\ erase=^?  kill=^U   eof=^D start=^Q  stop=^S  susp=^Z lnext=^V   min=01  time=00   pr1=^[   pr2=5B  left=44 right=43
    up=41  down=42   ins=40   del=50  home=48   end=59
    
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' over 11 years
    • user3330406
      user3330406 over 11 years
      I have actually already seen both of those links, and I have tried to modify kshrc to no avail. I get sh: /etc/kshrc[21]: trap: bad signal KEYBD I don't have another shell option unfortunately. I don't know if this is a problem with the PDKSH or with QNX or both. I do know what key combinations will cause what I want. I just need to know the syntax to map them to the appropriate keys.
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' over 11 years
      The Delete key works for me with Pdksh (same version, it hasn't been maintained since the last century) under Linux. What does bind | grep prefix show for you? And bind | grep '[^ -~]'?
    • user3330406
      user3330406 over 11 years
      @Gilles I updated with the results of your bind commands. Could it be my PuTTy settings? I appreciate your help. :-)
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' over 11 years
      AFAIK bind '^[[3~'='delete-char-forward' should have worked. I don't understand where those non-ASCII characters are coming from (they're not ESC+foo sequences with the 8th bit set, nor latin1/utf8 confusions thereof). Does `bind '^X3~=delete-char-forward' work?
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' over 11 years
      Mmmm, overwrite the character under the cursor with a ~? That's weird. Please post the complete output from bind. Is there a ~/.kshrc or a $ENV?
    • user3330406
      user3330406 over 11 years
      New output is attached as Update 3. Also bind '^X3~=delete-char-forward' does not work.
    • Kingsley
      Kingsley over 5 years
      With linux <-> solaris, it's delete-char (no -forward), e.g.: bind '"\e[3~": delete-char'
  • Janac Meena
    Janac Meena over 6 years
    I can confirm that this works in Conemu + Cygwin as well.
  • Milk
    Milk over 4 years
    Article is a dead link
  • a_girl
    a_girl almost 3 years
    Do you know how to make ssh use this "rxvt" option?