8

I am confused about how Ctrl-key combinations work in terminal. In bash man page, there are various combinations such as:

  • C-e - go to end of the line
  • C-f - go one character forward

etc.

But then there are some undocumented shortcuts such as:

  • C-j (OR C-m) for return key.
  • C-h for backspace
  • C-i for tab etc.

Are these shortcuts just forgotten to be documented? Or, because

  • C-j is LF
  • C-m is CR
  • C-i is Tab

in ASCII, is this somehow a "default" behavior? In other words, is the behavior for C-j, C-m and C-i not implemented by bash but by something else?

Another question is, when I press C-v and left arrow key, ^[[D appears on screen. I.e, ESC-[-d. But when I press ESC-[-d, the cursor does not move left. What is the reason for this?

EDIT:

Initially, I have thought that when I press C-j, the keyboard directly sends 00001010 to kernel. But then I decided that this is not the case, because using programs such as xev or evtest, I have observed that key presses to Control and j appear as different events. So when I press C-j, the keyboard does not send 00001010, but probably multiple bytes. Then where the conversion of these multiple bytes to 00001010 is done?

2 Answers 2

3

The behavior of C-m, C-i, etc. is implemented by bash, but the fact that they're the same thing as Return, Tab, etc. is due to the behavior of the terminal. All terminals behave like this because all terminals have always behaved like this and it's what applications expect. The interface between a terminal and an application is based on characters (in fact, bytes), not on keys, so keys that don't send printable characters and key combinations have to be encoded somehow. See How do keyboard input and text output work? for more on this topic. See also https://emacs.stackexchange.com/questions/1020/problems-with-keybindings-when-using-terminal

TAB is the tab character in ASCII, and that's the same thing as the Ctrl+I character in ASCII. Likewise for the other keys. Terminals send that character both when the user presses Tab and when the user presses Ctrl+I. Ditto for RET (CR) and C-m, for LFD and C-j (which most keyboards don't have), and for ESC and C-[. There's also BackSpace which sends either C-h or C-?, that's an issue of its own.

The configuration of the terminal (stty settings) can additionally come into play, and this affects some of bash's settings (e.g. after stty erase @, bash will treat pressing @ as BackSpace), but not C-m and C-j to submit the current line.

^[[D is Esc [ D, but with a capital D. If you press Esc [ D, bash sees the Left key, due to the declaration of cursor key escape sequences in the termcap or terminfo database. There's no default binding for Esc [ d (it isn't an escape sequence that common terminals send).

3
  • I was going to leave a comment but made an edit to make it more clear :-)
    – Utku
    Commented May 15, 2016 at 15:24
  • @Utku My first link should answer your added question. Commented May 15, 2016 at 15:29
  • I'd also point to Eric S. Raymond's Things Every Hacker Once Knew for an explanation of the historical, technical reasons that Ctrl+... combinations work the way they do.
    – ssokolow
    Commented Nov 2, 2019 at 8:03
0

Two questions, two points:

  • control/J, control/M and control/I are common ASCII controls which most programs assume. bash simply makes it easy to rebind those in readline.

  • most programs which accept special keys such as left-arrow provide a way to recognize the escape key distinguished from those special keys by timing. You probably cannot type fast enough to enter the characters (except for special cases such as emacs, which does not pay attention to timing).

    Since you don't type that fast, the program sees the separate characters, which won't move the cursor. The separate characters may do something interesting.

Regardless of that (noting a comment about a typo which I overlooked in the question), ESC[d is a standard control sequence, which if sent to a terminal would move the cursor to the top line of the screen:

CSI Pm d  Line Position Absolute  [row] (default = [1,column]) (VPA).

Since xterm implements this, anything which pretends to be just like xterm will do the same, of course. Linux console does that, too. However, bash generally doesn't echo control sequences: the behavior you observe would be whatever bash does with escapes which it doesn't recognize.

Regarding form-feeds (a comment assumes they are part of the question): bash's use of form-feed (for input) to clear the screen confuses some people (including PuTTY's developers) into supposing that terminals should interpret a form-feed. That feature actually comes from line-printers and originally was rarely found in terminals, even the printing variety. For some related discussion, see my notes on a repaginator and followups to reuse the feature.

2
  • What do you mean by most programs assume? I mean, combinations like C-f are definetely due to Readline (because it is in documentation) but are combinations like C-j and C-i due to Readline as well?
    – Utku
    Commented May 15, 2016 at 12:30
  • ASCII form-feed predates bash (as well as most of the readers of this site). Commented May 15, 2016 at 15:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .