Linenoise is a C line editing library, readline replacement.

linenoise — a tiny readline replacement

Linenoise is a small self-contained line editing library written in C by Salvatore Sanfilippo of Redis fame, aimed at replacing the monster readline and libedit libraries. It is used in Redis, MongoDB, and Android.

Line editing libraries

Currently, the most popular line editing library is GNU Readline. Since its initial release in 1989 it has collected a lot of cruft, supporting many different legacy terminals, hence it has more than 20000 lines of C code. Readline is GPL-licensed, thus many more liberally licensed projects can’t include it with their distribution, and instead have a config script which enables fancy (or should I say, useful) text line editing only if readline is present on the target system.

There is also a BSD-licensed libedit, which is a bit smaller at 14K of C LOC, but it’s still pretty complex, containing the total of 72 files.

Why use linenoise

Linenoise is BSD-licensed alternative to readline or libedit, which has around 800 lines of code (measured by cloc) and consists of only two files: linenoise.c and linenoise.h. You can drop them into your project, distributing them along with program, and have a nice line editing available for your console app.

Remember: smaller code means fewer bugs and security issues. Linenoise is so small in part because it doesn’t support lots of old stuff. To quote the author:

Apparently almost every terminal you can happen to use today has some kind of support for basic VT100 escape sequences. So I tried to write a lib using just very basic VT100 features. The resulting library appears to work everywhere I tried to use it, and now can work even on ANSI.SYS compatible terminals, since no VT220 specific sequences are used anymore.

It has been tested to work properly on Linux, Mac OS X, FreeBSD, OpenBSD, AIX.

Linenoise supports single and multiline editing modes with compatible keybindings, provides completion and editing history.

Using linenoise

There is an example.c file in the repository that shows how to use the library. Here’s an extract (edited for clarity):

/* Now this is the main loop of the typical linenoise-
 * based application. The call to linenoise() will block
 * as long as the user types somethingand presses enter.
 *
 * The typed string is returned as a malloc() allocated
 * string by linenoise, so the user needs to free() it.
 */
while((line = linenoise("hello> ")) != NULL) {

    /* Do something with the string. */
    if (line[0] != '' && line[0] != '/') {
        printf("echo: '%s'n", line);

        /* Add this line to history */
        linenoiseHistoryAdd(line);

        /* Save history on disk. */
        linenoiseHistorySave("history.txt");

    } else if (!strncmp(line,"/historylen",11)) {
        /* 
           "/historylen" command will change
           the length of history.
        */
        int len = atoi(line+11);
        linenoiseHistorySetMaxLen(len);

    } else if (line[0] == '/') {

        printf("Unreconized command: %sn", line);

    }
    free(line);
}

Conclusion

Don’t leave your application without good terminal line editing — include linenoise into it! Even if you check for readline when building, it’s good if uses linenoise as a fallback in case readline or libedit are not available.

Source code

GitHub: https://github.com/antirez/linenoise
Authors: Salvatore Sanfilippo and Pieter Noordhuis
License: 2-clause BSD

There are also third-party Go and Lua bindings available.

Image credit: By Autopilot (Own work) CC BY-SA 3.0, via Wikimedia Commons, modified.

Leave a Reply

Your email address will not be published. Required fields are marked *