0

I am writing simple terminal so I am trying to understand some basic things about control symbols, escape sequences and how all that is related to terminfo and termios.

What I find awkward is that according to the input I have from tty and according to tput left key is mapped to Backspace code (ASCII code 8)

tput cub1 | od -tx1
0000000    08                                                            
0000001

while I would expect it to be \033[D because

$ tput cuf1 | od -tx1
0000000    1b  5b  43                                                    
0000003

which is \033[C code that is right key indeed according to various documents about terminal codes.

So the absence of symmetry here is quite confusing to me. Is there a specific reason behind it?

The second question: is there way to change it?

I have created example of raw terminal which demonstrates this behaviour: RawTerminal.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Stanislav Pankevich
  • 11,044
  • 8
  • 69
  • 129

1 Answers1

2

The cub1 capability is not left arrow, but instead a cursor movement capability. Referring to terminfo(5), you may find

   cursor_left               cub1   le   move left one space

which is named similarly to the key marked "left-arrow":

   key_left                  kcub1  kl   left-arrow key

The cursor-movement capabilities do just that: move the cursor around on the screen. In some cases, the similarly-named cursor-movement and cursor-keys have the same string, just because (long ago) it was useful to have keys which one could setup to echo locally (rather than send to a host application).

In this particular case, the two are different because the main use of these terminal descriptions is for curses applications, which minimize the number of characters sent to the screen (as well as minimizing the time spent sending the characters). Making cub1 send an ASCII backspace is fewer characters than the escape sequence.

While there is no requirement, longstanding convention tells you that terminfo capabilities which begin with "k" are probably for the keyboard.

bash uses readline for reading keys and updating the line which you are typing on. Checking its source-code, e.g., from bash-4.2 I am looking at lib/readline/terminal.c, it has a table of the termcap strings that it may use:

    static const struct _tc_string tc_strings[] =
    {
      { "@7", &_rl_term_at7 },
      { "DC", &_rl_term_DC },
      { "IC", &_rl_term_IC },
      { "ce", &_rl_term_clreol },
      { "cl", &_rl_term_clrpag },
      { "cr", &_rl_term_cr },
      { "dc", &_rl_term_dc },
      { "ei", &_rl_term_ei },
      { "ic", &_rl_term_ic },
      { "im", &_rl_term_im },
      { "kD", &_rl_term_kD },        /* delete */
      { "kH", &_rl_term_kH },        /* home down ?? */
      { "kI", &_rl_term_kI },        /* insert */
      { "kd", &_rl_term_kd },
      { "ke", &_rl_term_ke },        /* end keypad mode */
      { "kh", &_rl_term_kh },        /* home */
      { "kl", &_rl_term_kl },
      { "kr", &_rl_term_kr },
      { "ks", &_rl_term_ks },        /* start keypad mode */
      { "ku", &_rl_term_ku },
      { "le", &_rl_term_backspace },
      { "mm", &_rl_term_mm },
      { "mo", &_rl_term_mo },
      { "nd", &_rl_term_forward_char },
      { "pc", &_rl_term_pc },
      { "up", &_rl_term_up },
      { "vb", &_rl_visible_bell },
      { "vs", &_rl_term_vs },
      { "ve", &_rl_term_ve },
    };

Using "infocmp -Cr xterm", I can see this:

xterm|xterm terminal emulator (X Window System):\
        :am:bs:km:mi:msn:\
        :co#80:it#8:li#24:\
        :AL=\E[%dLC=\E[%dPL=\E[%dMO=\E[%dB:IC=\E[%d@:\
        :K2=\EOE:LE=\E[%dD:RI=\E[%dC:SF=\E[%dS:SR=\E[%dT:\
        :UP=\E[%dA:ae=\E(B:al=\E[L:as=\E(0:bl=^G:bt=\E[Z:cd=\E[J:\
        :ce=\E[K:cl=\E[H\E[2J:cm=\E[%i%d;%dH:cr=^M:\
        :cs=\E[%i%d;%dr:ct=\E[3gc=\E[Pl=\E[Mo=^J:ec=\E[%dX:\
        :ei=\E[4l:ho=\E[H:im=\E[4h:is=\E[!p\E[?3;4l\E[4l\E>:\
        :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[15~:k6=\E[17~:\
        :k7=\E[18~:k8=\E[19~:k9=\E[20~:kD=\E[3~:kI=\E[2~:kN=\E[6~:\
        :kP=\E[5~:kb=\177:kd=\EOB:ke=\E[?1l\E>:kh=\EOH:kl=\EOD:\
        :kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:\
        :me=\E[0m:mh=\E[2m:mm=\E[?1034h:mo=\E[?1034l:mr=\E[7m:\
        :nd=\E[C:rc=\E8:sc=\E7:se=\E[27m:sf=^J:so=\E[7m:sr=\EM:\
        :st=\EH:ta=^I:te=\E[?1049l:ti=\E[?1049h:ue=\E[24m:up=\E[A:\
        :us=\E[4m:vb=\E[?5h\E[?5l:ve=\E[?12l\E[?25h:vi=\E[?25l:\
        :vs=\E[?12;25h:

or with "infocmp -Cr nsterm":

nsterm|Apple_Terminal|AppKit Terminal.app:\
        :am:hs:mi:msno:\
        :co#80:it#8:li#24:ws#50:\
        :AL=\E[%dLC=\E[%dPL=\E[%dMO=\E[%dB:IC=\E[%d@:\
        :K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:LE=\E[%dD:\
        :RI=\E[%dC:UP=\E[%dA:ae=^O:al=\E[L:as=^N:bl=^G:cd=\E[J:\
        :ce=\E[K:cl=\E[H\E[J:cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:\
        :ct=\E[3gc=\E[Pl=\E[Mo=^Js=\E]2;\007:ei=\E[4l:\
        :fs=^G:ho=\E[H:ic=\E[@:im=\E[4h:k1=\EOP:k2=\EOQ:k3=\EOR:\
        :k4=\EOS:k5=\E[15~:k6=\E[17~:k7=\E[18~:k8=\E[19~:\
        :k9=\E[20~:kD=\E[3~:kN=\E[6~:kP=\E[5~:kb=\177:kd=\EOB:\
        :ke=\E[?1l\E>:kh=\EOH:kl=\EOD:kr=\EOC:ks=\E[?1h\E=:\
        :ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:me=\E[0m:mh=\E[2m:\
        :mr=\E[7m:nd=\E[C:rc=\E8:\
        :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:sc=\E7:se=\E[m:\
        :sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:te=\E[2J\E[?47l\E8:\
        :ti=\E7\E[?47h:ts=\E]2;:ue=\E[m:up=\E[A:us=\E[4m:\
        :vb=\E[?5h\E[?5l:ve=\E[?25h:vi=\E[?25l:

The ":le=^H:" part is what you are seeing.

From (ncurses) terminfo(5):

   cursor_left                   cub1       le        move left one space

if you made a termcap (for "xterm") setting that to \e[D, then bash should echo back \e[D rather than ^H. But ncurses uses ^H to reduce the number of characters from from 3 (\e[D) to 1 (^H)

Rather than modify the terminal description, you should modify your program, e.g., to read the termcap strings and handle those.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • I have just realized that I got answer from author of xterm and so many other things! Sorry about this newbie question: I did read your answer but I didn't get why on my raw terminal left arrow produces backspace (i.e. deletes symbols) whereas for example in xterm which I have just checked (X11 on OSX) it does work as expected - just moves a curson to the left. Do you treat that backspace code as "move left one space" (undestructive) given left arrow key on keyboard was pressed? I hope my question is clear. Thanks. – Stanislav Pankevich Dec 16 '15 at 22:32
  • My keyboard has a group of 4 cursor-keys, which all send escape sequences. There is also a back-arrow key (labeled "Backspace"), which sends an ASCII DEL (`^?`). – Thomas Dickey Dec 16 '15 at 22:38
  • My left key does send escape sequence: \033[D but in response I get Backspace, whilte for right key that I press, for code: \033[C I do get \033[C back and that's asymmetry that I'm confused about. Additional information: I use openpty to create my terminal connection. – Stanislav Pankevich Dec 16 '15 at 22:45
  • 1
    That sounds like an application doing the translation. I used `cat -v` and `^V` before characters to see what was actually sent. – Thomas Dickey Dec 16 '15 at 22:56
  • Yes, I am doing the same: cat -v and ^V reveal: `^[[D` to me for left key, and `^[[C` for right key but in response I get Backspace for left arrow key and `\e[C` for right and I can't spot why this happens. That's why I somehow found tput and noticed that it outputs the same asymmetry for cub1 and cuf1. At this step I just want to make left key work like right key works :) – Stanislav Pankevich Dec 16 '15 at 23:01
  • If you are typing into bash, its command-line editing feature will read the arrow key and translate it into a suitable screen-update (which can be a backspace). I just tried a simple case, typing "datte" and using the arrow-key to move back and then delete one of the "t' characters. – Thomas Dickey Dec 16 '15 at 23:06
  • Yes! I am typing into bash: if I type "datte" and then press left arrow I get ASCII code 8 in response, if I then press enter I do see "datte: command not found". But if my lexer does not differentiate between this "strange" backspace and regular backspace (which should delete symbols) I actually delete this letter "e" from screen (though terminal state is cursor moved to the left without deleting it). SO is saying the discussion is becoming "extended", I'll try to write you an email if you don't mind. – Stanislav Pankevich Dec 16 '15 at 23:22
  • ok (I think I answered the question as given; this is all background stuff) – Thomas Dickey Dec 17 '15 at 00:11