views:

283

answers:

2

I'm writing a script to navigate a text-based menu system, using python's telnetlib to access a serial connection.

I can happily press the F-keys, using the escape codes. e.g. F9 = "\033OX", where "\033" is the escape sequence.

How do I encode the "esc" keyboard key? I would have expected just "\033", but that doesn't seem to work.

+3  A: 

Put a small delay, say 1.5s, after sending the escape so that the other side realizes that it's an isolated escape and not part of a longer sequence.

Ignacio Vazquez-Abrams
Thanks. You pointed me in the right direction. A delay didn't work, but what did was sending a " " (space) after the escape sequence. This prompted the menu system to accept the "standalone" escape key.
JLB
+2  A: 

There is no such thing as an "escape sequence" for the ESC key on a VT-100 (or other terminals that used escape sequences).

The escape character, ASCII 27, was used to indicate that the following sequences of characters had special meaning. This usually put the terminal into a simple state machine. In general the rule was to swallow the incoming characters until an alphabetic or symbolic character was seen, inclusively, although some special cases such as symbols which might grab one additional character, e.g. ESC # 6 to double-width characters.

For instance on a H-19 / VT-52 terminal, ESC H meant home, ESC E meant clear screen and home, ESC J meant clear to end of screen, etc. The VT-100 series used ESC [ H for home, and ESC [ 2 J for clear to end of screen.

What was really going on was that the open square bracket (there was no close bracket) said that a list of arguments, usually numeric, was coming. The '2' in the ESC [ 2 J meant both from the cursor to the top (zero), and from the cursor to the end (one). Switch the J to a K, and now it would clear the line, rather than the screen, the same way. They weren't arbitrary. Even ESC [ row ; col H would take a numerical row/col, e.g. ESC [ 12; 34 H would go to row 12, column 34. Not providing them took default values.

In theory the server should never throw you a meaningless orphaned ESC character as the terminal would sit there and wait for a sequence.

When you pressed a function key, the terminal would send an ESC character followed by some pre-canned sequence for a function key, arrow, or action. For instance ESC [ 21 ~ was F10.

This then left the very real problem of how to send a literal orphaned ESC. There were two ways.

One, send the ESC and then delay for some amount. The host would have the responsibility of watching not just what came in, but when. And, working under the assumption that a terminal would send a block of characters in its buffer immediately, it would internally time out and take ESC to mean just ESC. The delay did not have to be long.

Two, require the user to press ESC twice for every literal ESC desired. As no escape sequence ever consisted of a double escape character, it signaled a special condition. It exactly the same thing we do when quoting backslash characters in strings, a "\" really means a "\" because we have to satisfy the compiler's lexical phase. In this case, it's the host server. Remember, in the days of serial ports, which was when these terminals were in use, when a character was pressed, it was sent immediately. Only years later did we start emulating terminals and thus rose the need to emulate their escape sequences rather than taking the behaviors out of the content stream.

Of course, an 'invalid' ESC sequence meant the ESC was literal, but this required seeing what the following bytes were before you could act on them (hence the timeout solution). The problem is sometimes those characters caused side effects to an application, nasty ones, and interesting cases could arrive where trying to naively fake out the system could get you into trouble. e.g., use ESC Space to force the escape through, the ESC cancels one prompt, but the space unintendedly acknowledges the next.

The third solution to the problem was to simply have the host ignore special function keys altogether and take the incoming byte stream as literal. For instance, the TECO editor would display a dollar sign to the user each time the ESC was pressed, as it used this for a command separator the same way one might use a semicolon in coding today.

Walt Stoneburner