Skip to content

0xEAF/linenoise89

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

linenoise89

A single-file, C89-compatible amalgamation of the linenoise line-editing library, extended with Win32 console support, full UTF-8 handling, and Unicode 15.0 width/case tables.

Compile once with your project — no configure scripts, no dependencies, no separate build step.

Built on top of the linenoise-win32 fork made for JimTcl, which itself was made on top of linenoise.

WARNING

Everything (except this tiny message) was written by AI (Claude Sonnet 4.6), because I'm not a C expert nor a terminal expert and I just wanted it C89 compatible and easy to use. Normally it should be working fine though.

LICENSE

For a few months I released this code without respecting the original author's licensing conditions. I would like to apologise and have changed the license to the BSD 2-Clause License. Legally, it was only needed for the original license to be kept in every copy and fork of the project. However to keep the freedom of the code and respect the original author's choice of liberty, I decided to change the code from being licensed under the MIT License to being licensed under the BSD 2-Clause License.

Pratically, this does not change anything, as the BSD 2-Clause License is no more restrictive than the MIT License. Please note that this applies to all versions of the code, even previous ones.

Files

File Purpose
linenoise89.c The entire library — compile this alongside your source files
linenoise89.h Public API header — #include this in your code
_unicode_mapping.c Auto-generated Unicode 15.0 tables — #included by linenoise89.c, not a separate compile unit
gen_unicode_tables.py Python script to regenerate _unicode_mapping.c from a newer Unicode version

All four files must be in the same directory.


Using in a C program

Include the header in any source file that calls linenoise functions:

#include "linenoise89.h"

A minimal interactive loop:

#include <stdio.h>
#include <stdlib.h>
#include "linenoise89.h"

int main(void) {
    char *line;

    linenoiseHistoryLoad("history.txt");

    while ((line = linenoise("» ")) != NULL) {
        if (line[0] != '\0') {
            printf("you typed: %s\n", line);
            linenoiseHistoryAdd(line);
            linenoiseHistorySave("history.txt");
        }
        free(line);
    }
    return 0;
}

linenoise() returns a malloc-allocated string. You must free() it. It returns NULL on EOF (Ctrl-D on Unix, Ctrl-Z on Windows) or unrecoverable error.

Tab completion

#include "linenoise89.h"

void my_completion(const char *buf, linenoiseCompletions *lc, void *userdata) {
    (void)userdata;
    if (buf[0] == 'h') {
        linenoiseAddCompletion(lc, "help");
        linenoiseAddCompletion(lc, "history");
    }
}

/* call before your input loop */
linenoiseSetCompletionCallback(my_completion, NULL);

Hints (inline right-hand suggestions)

char *my_hints(const char *buf, int *color, int *bold, void *userdata) {
    (void)userdata;
    if (!strcasecmp(buf, "git")) {
        *color = 35;  /* magenta */
        *bold  = 0;
        return " commit -m \"...\"";
    }
    return NULL;
}

linenoiseSetHintsCallback(my_hints, NULL);

Starting with pre-filled text

/* second argument is the initial text placed in the edit buffer */
char *line = linenoiseWithInitial("» ", "default text");

Other options

linenoiseSetMultiLine(1);          /* enable multi-line editing */
linenoiseHistorySetMaxLen(200);    /* default is LINENOISE_DEFAULT_HISTORY_MAX_LEN */
linenoiseHistoryLoad("hist.txt");
linenoiseHistorySave("hist.txt");

Compiling

linenoise89.c is a separate translation unit — compile it alongside your own sources and let the linker combine them. Never #include the .c file directly.

GCC / Clang — Linux, macOS, MinGW

# With full UTF-8 support (recommended)
gcc -DUSE_UTF8 -o myapp myapp.c linenoise89.c

# Without UTF-8 (ASCII-only, slightly smaller binary)
gcc -o myapp myapp.c linenoise89.c

# Strict C89 mode
gcc -std=c89 -DUSE_UTF8 -o myapp myapp.c linenoise89.c

# Without tab-completion and hints (reduces binary size further)
gcc -DUSE_UTF8 -DNO_COMPLETION -o myapp myapp.c linenoise89.c

MSVC — Windows (x64 Native Tools Command Prompt)

rem With UTF-8 support
cl /DUSE_UTF8 myapp.c linenoise89.c

rem Without UTF-8
cl myapp.c linenoise89.c

rem Without completion/hints
cl /DUSE_UTF8 /DNO_COMPLETION myapp.c linenoise89.c

MSVC does not require a C standard flag — it compiles as C89/C90 compatible by default.

CMake

add_executable(myapp myapp.c linenoise89.c)
target_compile_definitions(myapp PRIVATE USE_UTF8)
target_include_directories(myapp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

Preprocessor flags

Flag Effect
USE_UTF8 Enable UTF-8 input, Unicode width/combining tables, and utf8_upper / utf8_lower. Strongly recommended.
NO_COMPLETION Remove tab-completion and hints callbacks. Saves code size on constrained targets.

Platform notes

On Linux/macOS, the library uses termios and poll() for raw terminal input.

On Windows (including MinGW and MSVC), it uses the Win32 Console API (ReadConsoleInputW / WriteConsoleW) and works correctly in both cmd.exe and Windows Terminal. The _stricmp / _strnicmp compatibility shims for strcasecmp / strncasecmp are provided automatically when linenoise89.h is included under MSVC.


Regenerating the Unicode tables

_unicode_mapping.c is pre-generated from Unicode 15.0. To update to a newer version, run:

python3 gen_unicode_tables.py

Requires Python 3.9+ (uses the built-in unicodedata module — no downloads or extra packages needed). The Unicode version used matches the Python installation's bundled unicodedata:

python3 -c "import unicodedata; print(unicodedata.unidata_version)"

Key bindings

Key Action
/ Move cursor left / right
Home / Ctrl-A Move to start of line
End / Ctrl-E Move to end of line
/ Previous / next history entry
Ctrl-R Reverse history search
Ctrl-U Delete from cursor to start of line
Ctrl-K Delete from cursor to end of line
Ctrl-W Delete previous word
Backspace / Ctrl-H Delete previous character
Del / Ctrl-D Delete character under cursor (or EOF if line empty)
Tab Trigger completion callback (if registered)
Ctrl-C Interrupt (sends SIGINT on Unix; clears line on Windows)
Ctrl-L Clear screen
Enter Submit line

About

Single-file LineNoise amalgamation in C89, compatible with Win32 - compilable using GCC, Clang or MSVC [Made by AI]

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors