15

**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
8
  • 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. – kmort Feb 28 '13 at 21:39
  • 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 '[^ -~]'? – Gilles 'SO- stop being evil' Feb 28 '13 at 22:44
  • @Gilles I updated with the results of your bind commands. Could it be my PuTTy settings? I appreciate your help. :-) – kmort Feb 28 '13 at 22:54
  • 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' Feb 28 '13 at 23:12
9

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/misc@openbsd.org/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.

1
  • I can confirm that this works in Conemu + Cygwin as well. – Janac Meena Oct 18 '17 at 19:13
4

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.

1
  • Article is a dead link – Milk Nov 20 '19 at 19:39
2

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.

0

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.

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.