3

I am trying to understand how terminal works by doing different tricks, like writing from one tty to another, changing settings tty1 from tty2, etc. Also, I am trying to change a color by sending escape sequence from keyboard, directly. That is, not by echo -e '\e[0;31m' command, but by direct keyboard input. It doesn’t work.

I do this steps:

  1. Open tty1 and tty2
  2. In the tty2 put bash into the sleep mode, by sleep 10m. Type word 'one'.

enter image description here

  1. Go to tty1, do echo -n ^[[0;31m > /dev/tty2. The first character ^[ is typed by this way Ctrl + v Esc
  2. Return to tty2, type word 'two'. Yes - the color has been changed to red by command from another tty.

enter image description here

  1. Repeat steps 3,4, but with green color and word 'three'

enter image description here

  1. And finally, I am trying to send the escape sequence not by another tty, but from keyboard directly - by typing ^[[0;37m in tty2. I do everything the same way - Esc (Ctrl + v doesn't needed, because readline is sleeping), then [0;37m, but get this:

enter image description here

Question: Why does it work this way? All characters the same, terminal state the same, but in one case terminal get escape sequence, and in another case don't.


Edit

The question was answered here: Echoed escape sequences doesn't interpreted in Linux tty.

MiniMax
  • 4,123
  • The terminal state may or may not be the same; use stty to inspect the terminal file. Otherwise one difference is that sleep is not doing anything with the input, while the output from echo or external data is written to the terminal. – thrig Jun 07 '17 at 23:06
  • Very hard to read, People don't know what you've done by ^[, do you press the ESC key or two separate keys? Why is Ctrl+V mentioned? – 炸鱼薯条德里克 Sep 12 '19 at 21:48
  • @炸鱼薯条德里克 I fixed some grammatical mistakes, hope the text is more understandable now. Ctrl+v is needed to "add the next character typed to the line verbatim. This is how to insert characters like C-q, for example." Quote from man bash. So, if I want to insert Esc code verbatim, I do Ctrl+v, then press Esc button. – MiniMax Sep 12 '19 at 23:32

2 Answers2

5

When you run echo, you're sending output to the terminal. The terminal interprets escape sequences such as the one to change colors in the output that is sent to it. These escape sequences are meant to be sent by applications, this is why they are recognized in the output that comes from the application running in the terminal. Usually the application running in the terminal is the one started by the terminal emulator (your shell) and the ones started by this in turn, but if you run echo … >/dev/tty2 then echo is effectively “running in the terminal” (in the sense that its output is going to the terminal, which is what matters here).

When you press Esc [ etc., you're sending input to the terminal. The terminal does not interpret escape sequences such as the one to change colors in the input that it receives. The terminal does interpret escape sequences in input, but for a completely different purpose: they're a way to encode function key presses.

How do keyboard input and text output work? has some relevant background.

  • As it turned out, the reason of this behavior was different. I did investigation here and found out the following information: "The Linux virtual console emulates a (sort of) VT102 terminal in ON-LINE mode connected to a Linux (serial) tty device. The Linux tty driver doesn't normally echo back the escape control character, and instead echos ^[. If you don't want the tty driver to do this, then use stty -ctlecho." So, I executed stty -ctlecho and got expected behavior. – MiniMax May 11 '19 at 11:32
  • @gilles do you not want to adapt your explanations to the new facts? (the answer has been unaccepted). –  Sep 18 '19 at 08:24
  • @S.P. This is a two year-old question and I have no memory of it. The answer looks correct to me. What new facts are you talking about? – Gilles 'SO- stop being evil' Sep 18 '19 at 08:35
  • After stty -echoctl and sleep, you can send escape sequences directly, without echo. Minimax had added in a comment. I have tested. Everything there, no need to strain your brain. –  Sep 18 '19 at 08:40
  • @S.P. Ah, I see what you mean. After stty -echoctl, the escape sequences that you type are echoed. That's an interesting complement, but I still can't see anything wrong in my answer, and it does answer the core question (why this doesn't work out of the box). – Gilles 'SO- stop being evil' Sep 18 '19 at 09:49
  • "-echoctl" (as opposed to default echoctl) rather stops the "echoing" - the "reflex echo" we see as "^[" also after "read" command, when typing esc or using arrow keys etc.. I just think it has more to do with "line discipline" than with input / output. With "echo" command (how confusing, actually) you force shell to output the sequence. When you type it directly (ctrl-[ or esc, then "[", then some more), shell only checks for it's own bindings, then gives up and of course does not try to send that sequence - you have echo builtin for that. –  Sep 18 '19 at 10:09
  • @S.P. No, -echoctl doesn't stop the echoing. What it does is change from echoing an escape character as caret-bracket to echoing it as an actual escape character. If you disabled echo, then the setting of echoctl would have no impact, and pressing Escape would not have any effect on the display. – Gilles 'SO- stop being evil' Sep 18 '19 at 10:22
  • but "^[" is escape, if it is one char. This is the "hat notation" stty mentions: "echo control characters in hat notation" for +echoctl. Thus, -echoctl means: "do not echo" (((but let it pass even if shell is sleeping))) –  Sep 18 '19 at 10:52
  • @S.P. No. With -echo, nothing is echoed. With echo -echoctl, every character is echoed (i.e. the kernel forwards input on the terminal to the output). With echo echoctl (the default), printable characters are echoed (i.e. the kernel forwards non-control characters from the input to the output, and responds to a control character in the input by outputting a ^ and the corresponding printable character, e.g. an output of ^[ for an escape character on the input). – Gilles 'SO- stop being evil' Sep 18 '19 at 11:22
  • You are just talking, and not testing, are you not? -echoctl is a stty option. Nobody went "echo echoctl". –  Sep 18 '19 at 11:30
  • @S.P. I'm not talking about running the echo command, if that's what you're implying. I'm discussing stty settings. By “with echo -echoctl”, I mean if you set these stty settings, which you can do with the command stty echo -echoctl. – Gilles 'SO- stop being evil' Sep 18 '19 at 11:41
  • "With echo -echoctl, every character is echoed [to output]". But in your answer you say: "if you press Esc [ etc., you send input, and the terminal does not interpret sequences in input." Well it does, if it gets it after -echoctl. You even say "as the ones to change color". So which other sequences does it interpret, even with default echoctl ? –  Sep 18 '19 at 11:51
  • @S.P. The terminal interprets escape sequences in its output. With -echoctl, the kernel forwards the escape sequences from the input to the output, and the terminal sees the escape sequences in the output and interprets them there. – Gilles 'SO- stop being evil' Sep 18 '19 at 12:00
  • I can live with that, thanks. –  Sep 18 '19 at 12:03
1

This works even in xterm in xorg:

stty -echoctl
sleep <a bit>

Then, on the "dead" terminal, you can directly press Escape and then

[32m

and the next keys you press is already green! If you kill sleep with ctrl-C your prompt stays clean...

enter image description here

The Question is a very special case -- a way of sneaking an escape sequence from keyboard to the screen, while readline/bash is in a coma.

WITH normal echoctl/ctlecho, after sleep the shell does echo keypresses (input), but also echoes the escape key directly as ^[ on the screen (output). Special meaning as 'control sequence introducer (CSI) is lost.

So isn't the (accepted) answer wrong?


Here I press ctrl-C with the cursor on the "l" of "line", as if I decide to abort and not continue editing the line:

$  weird -cmd ^Cne
$  stty -echoctl
$  weird -cmd line
$  # nice but now it looks like it got exec'd

This seems to be the main effect of this stty echoctl option.

I just realized, an Escape press is just short for control-[ aka ^[. So it is logical for tty to just ECHO the ^[ char immediately and not wait for a sequence. After a sleep with normal echoctl on, the Home key generates ^[[H. Without echoctl i.e. after stty -echoctl, the Home key...puts the cursor top left of my xterm screen!

(When bash is awake, the Home key works: beginning of line.)

these two bind -p lines are builtin/terminfo xterm:

"\eOH": beginning-of-line
"\e[H": beginning-of-line
  • Yes, the accepted answer is wrong. I should to reject the acceptance. Did you read my comment to it? It has the link to my investigation on this topic as well as the answer to this question: Echoed escape sequences doesn't interpreted in Linux tty – MiniMax Sep 12 '19 at 13:57
  • Of course I read your comment/solution! I overflew your new Q before...I also will do some investigations. I think realine/bash is more active than we knew... your trick provides RAW access to the tty. Funny thing: it's the ESCAPE that does not "pass" when echoctl is on...it's not "stty blockesc". –  Sep 12 '19 at 15:30