A small libreadline replacement. Inspired by antirez/linenoise except read_line is even smaller (<200 LOC) and simpler.
The library libreadline is famously large and annoying to link. For example, on Linux you have to install libreadline, libncurses, and libtinfo just to link it. All this just for the ability to read a line with history and navigation.
This implements a single function, read_line(), which reads a line while automatically handling history and navigation using VT100 escape codes.
Also I hereby put this in the public domain, so you can use this for whatever.
For some reason, linenoise sets flags explicitly. Most other examples are derived from linenoise, so they do the same thing. However, this is totally unecessary because there is a function called cfmakeraw() that will set the flags for you.
However, even that seems like an oversight because if you read the docs, most of the flags are for canonical-mode-style behavior, so simply zeroing the termios struct should suffice. So that's what I do here.
Linenoise supports various rare terminals. I do not; I've just tested this on some Linuxes, MacOS, and Raspberry Pi. (Note that Windows' console supports history and navigation natively).
Linenoise and other libraries set an atexit() handler to reset the tty attributes in case of an interrupt. In my testing, this doesn't seem to be necessary, so I don't do it.
I use C++ which provides <string> and <vector>, so I don't have to manually implement string or array manipulation. This also allows for unlimited lengths (in theory) so I don't have to set MAX_LINE/MAX_HISTORY constants. I store the history as a static variable, so I don't need a global history variable either.
Linenoise supports other stuff like completions and suggestions. I do not.
The following navigation keys are supported
- ↑ - Go up in history
- ↓ - Go down in history
- → - Go right
- ← - Go left
- ctrl-a / home - Go to start
- ctrl-e / end - Go to end
- ctlr-l - Clear screen (in case multiline input overflows terminal)
- double-press esc - Erase line
The exact history behavior is slighly different than libreadline. The first history entry is a blank line and over-navigation will just rotate instead of sounding a bell. Also, duplicate consecutive history items are not saved.
A double escape clears the line, which makes it consistent with Windows-style console behavior.
For these reasons, I would actually argue that the navigation scheme here is actually better than libreadline.