Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building blocks of interactive terminal applications

Tags:

terminal

I've been struggling to find the words that would help me surface the information I need. I want to create a terminal application that "takes over" the terminal and can be interacted with - like man, less, top etc

If my first goal was to create an application that when run in the terminal displays some static output based on different key presses, then exits back to the command prompt on 'q' press - what kind of libraries / frameworks do I need to be looking at?

I know my way around a shell script and terminal but haven't an idea how the aforementioned applications achieve what they do in terms of their "interactiveness" in the terminal.

Apologies for the vagueness - like I say, I'm struggling to find the words I need to find the information I need, just need a push in the right direction.

like image 626
markdsievers Avatar asked Sep 02 '16 13:09

markdsievers


1 Answers

You are seeking to write a textual user interface application that presents a full-screen user interface as opposed to a simple scrolling glass teletypewriter one. These applications switch the terminal into cursor addressing mode, from scrolling mode, and use terminal control sequences to move the cursor around the display and set attributes and colours.

These control sequences vary by terminal type and there are a terminfo database or a termcap database on your system that takes the terminal type, as specified in your TERM environment variable, and maps it to a record that contains a set of terminal capabilities. Terminal capabilities describe how the terminal behaves, including things like whether it has automatic margins and background colour erase, and describe to applications what set graphic rendition control sequences are used to perform various abstract operations like "enter standout mode" and "exit standout mode".

On top of this are built things like the ncursesw library, which is a function library accessible to compiled programs written in programming languages like C or C++. This library has an application programming interface that comprises various abstract concepts like windows and panes. It also provides an abstraction for keyboard input that works in terms of keyboard codes. Internally, it uses termcap/terminfo in order to determine how to render the abstractions in terms of actual character sequences sent to the terminal device.

The ncursesw keyboard input is layered over the top of switching the terminal from canonical input mode into non-canonical input mode (known before the POSIX standard as cooked input mode and raw input mode, respectively). In non-canonical input mode, the terminal line discipline does not do all of the line editing stuff that it does in canonical input mode. The special characters are not treated specially and the read() system call does not wait for a newline or other line delimiter character to be received by the line discipline.

Ironically, you'll see a lot of doco on the World Wide Web that tells you all about canonical input mode as if it is the norm. In fact, if your world involves full-screen TUI applications and modern shells with command line editing capabilities (built with libraries such as ZLE, libedit, or readline) your line discipline is almost never in canonical mode nowadays. Canonical mode is not the norm but rather the exception, that largely (and ironically) applies when you are running non-interactive programs.

Keys that don't map directly to alphanumeric characters, punctuation, or control characters are sent down the wire by the terminal as control sequences. Terminal capabilities in the termcap/terminfo databases describe how applications reading these control sequences should map them onto the function key or extended key that triggered sending them in the first place. Because there's an ambiguity between a person pressing the escape key and an actual control sequence, there is a slightly complex dance that programs have to perform with timed reading of its input. This is done for you in the aforementioned libraries.

Further reading

  • https://superuser.com/a/711019/38062
  • https://unix.stackexchange.com/a/243320/5132
  • https://superuser.com/a/715563/38062
  • https://en.wikipedia.org/wiki/POSIX_terminal_interface
  • https://unix.stackexchange.com/a/333922/5132
like image 160
JdeBP Avatar answered Sep 26 '22 19:09

JdeBP