Skip to content

afl5c/read_line

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 

Repository files navigation

read_line

A small libreadline replacement. Inspired by antirez/linenoise except read_line is even smaller (<200 LOC) and simpler.

Problem

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.

Solution

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.

Technical Details

Entering Raw Mode

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.

Other Code Savings

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.

Navigation Support

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.

About

A better smaller alternative to libreadline.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages