[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6652":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":29,"discoverSource":30},6652,"linenoise","antirez\u002Flinenoise","antirez","A small self-contained alternative to readline and libedit","",null,"C",4296,735,99,69,0,2,41,1,65.7,"BSD 2-Clause \"Simplified\" License",false,"master",true,[],"2026-06-12 04:00:29","# Linenoise\n\nA minimal, zero-config, BSD licensed, readline replacement used in Redis,\nMongoDB, Android and many other projects.\n\n* Single and multi line editing mode with the usual key bindings implemented.\n* History handling.\n* Completion.\n* Hints (suggestions at the right of the prompt as you type).\n* Multiplexing mode, with prompt hiding\u002Frestoring for asynchronous output.\n* Bracketed paste support, with large or multi line pastes folded on screen.\n* UTF-8 support for multi-byte characters and emoji.\n* About ~1600 lines (comments and spaces excluded) of BSD license source code.\n* Only uses a subset of VT100 escapes (ANSI.SYS compatible).\n\n## Can a line editing library be 20k lines of code?\n\nLine editing with some support for history is a really important feature for command line utilities. Instead of retyping almost the same stuff again and again it's just much better to hit the up arrow and edit on syntax errors, or in order to try a slightly different command. But apparently code dealing with terminals is some sort of Black Magic: readline is 30k lines of code, libedit 20k. Is it reasonable to link small utilities to huge libraries just to get a minimal support for line editing?\n\nSo what usually happens is either:\n\n * Large programs with configure scripts disabling line editing if readline is not present in the system, or not supporting it at all since readline is GPL licensed and libedit (the BSD clone) is not as known and available as readline is (real world example of this problem: Tclsh).\n * Smaller programs not using a configure script not supporting line editing at all (A problem we had with `redis-cli`, for instance).\n \nThe result is a pollution of binaries without line editing support.\n\nSo I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporting line editing out of the box. Larger programs may use this little library or just checking with configure if readline\u002Flibedit is available and resorting to Linenoise if not.\n\n## Terminals, in 2010.\n\nApparently 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\nVT220 specific sequences are used anymore.\n\nThe library is currently about 1600 lines of code, excluding comments and empty lines. In order to use it in your project just look at the *example.c* file in the source distribution, it is pretty straightforward. The library supports both a blocking mode and a multiplexing mode, see the API documentation later in this file for more information.\n\nLinenoise is BSD-licensed code, so you can use both in free software and commercial software.\n\n## Tested with...\n\n * Linux text only console ($TERM = linux)\n * Linux KDE terminal application ($TERM = xterm)\n * Linux xterm ($TERM = xterm)\n * Linux Buildroot ($TERM = vt100)\n * Mac OS X iTerm ($TERM = xterm)\n * Mac OS X default Terminal.app ($TERM = xterm)\n * OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen)\n * IBM AIX 6.1\n * FreeBSD xterm ($TERM = xterm)\n * ANSI.SYS\n * Emacs comint mode ($TERM = dumb)\n\nPlease test it everywhere you can and report back!\n\n## Let's push this forward!\n\nPatches should be provided in the respect of Linenoise sensibility for small\neasy to understand code.\n\nSend feedbacks to antirez at gmail\n\n# The API\n\nLinenoise is very easy to use, and reading the example shipped with the\nlibrary should get you up to speed ASAP. Here is a list of API calls\nand how to use them. Let's start with the simple blocking mode:\n\n    char *linenoise(const char *prompt);\n\nThis is the main Linenoise call: it shows the user a prompt with line editing\nand history capabilities. The prompt you specify is used as a prompt, that is,\nit will be printed to the left of the cursor. The library returns a buffer\nwith the line composed by the user, or NULL on end of file or when there\nis an out of memory condition.\n\nWhen a tty is detected (the user is actually typing into a terminal session)\nthe maximum editable line length is `LINENOISE_MAX_LINE`. When instead the\nstandard input is not a tty, which happens every time you redirect a file\nto a program, or use it in an Unix pipeline, there are no limits to the\nlength of the line that can be returned.\n\nIn tty mode large pastes are accepted up to the same `LINENOISE_MAX_LINE`\nlimit. When the terminal supports bracketed paste, multi line pastes and\nvery long single line pastes are shown in a folded form on screen. However\nthe string returned by `linenoise()` is still the real text pasted by the\nuser.\n\nThe returned line should be freed with the `free()` standard system call.\nHowever sometimes it could happen that your program uses a different dynamic\nallocation library, so you may also used `linenoiseFree` to make sure the\nline is freed with the same allocator it was created.\n\nThe canonical loop used by a program using Linenoise will be something like\nthis:\n\n    while((line = linenoise(\"hello> \")) != NULL) {\n        printf(\"You wrote: %s\\n\", line);\n        linenoiseFree(line); \u002F* Or just free(line) if you use libc malloc. *\u002F\n    }\n\n## Single line VS multi line editing\n\nBy default, Linenoise uses single line editing, that is, a single row on the\nscreen will be used, and as the user types more, the text will scroll towards\nleft to make room. This works if your program is one where the user is\nunlikely to write a lot of text, otherwise multi line editing, where multiple\nscreens rows are used, can be a lot more comfortable.\n\nIn order to enable multi line editing use the following API call:\n\n    linenoiseSetMultiLine(1);\n\nYou can disable it using `0` as argument.\n\n## History\n\nLinenoise supporst history, so that the user does not have to retype\nagain and again the same things, but can use the down and up arrows in order\nto search and re-edit already inserted lines of text.\n\nThe followings are the history API calls:\n\n    int linenoiseHistoryAdd(const char *line);\n    int linenoiseHistorySetMaxLen(int len);\n    int linenoiseHistorySave(const char *filename);\n    int linenoiseHistoryLoad(const char *filename);\n\nUse `linenoiseHistoryAdd` every time you want to add a new element\nto the top of the history (it will be the first the user will see when\nusing the up arrow).\n\nNote that for history to work, you have to set a length for the history\n(which is zero by default, so history will be disabled if you don't set\na proper one). This is accomplished using the `linenoiseHistorySetMaxLen`\nfunction.\n\nLinenoise has direct support for persisting the history into an history\nfile. The functions `linenoiseHistorySave` and `linenoiseHistoryLoad` do\njust that. Both functions return -1 on error and 0 on success.\n\nThe history file is newline separated. If an history entry contains embedded\nnewlines, they are stored as CR characters and converted back when the history\nis loaded again. When multi line or very long entries are recalled with the\nup arrow, linenoise folds them again on screen, while keeping the real entry\navailable for editing.\n\n## Mask mode\n\nSometimes it is useful to allow the user to type passwords or other\nsecrets that should not be displayed. For such situations linenoise supports\na \"mask mode\" that will just replace the characters the user is typing \nwith `*` characters, like in the following example:\n\n    $ .\u002Flinenoise_example\n    hello> get mykey\n    echo: 'get mykey'\n    hello> \u002Fmask\n    hello> *********\n\nYou can enable and disable mask mode using the following two functions:\n\n    void linenoiseMaskModeEnable(void);\n    void linenoiseMaskModeDisable(void);\n\n## Completion\n\nLinenoise supports completion, which is the ability to complete the user\ninput when she or he presses the `\u003CTAB>` key.\n\nIn order to use completion, you need to register a completion callback, which\nis called every time the user presses `\u003CTAB>`. Your callback will return a\nlist of items that are completions for the current string.\n\nThe following is an example of registering a completion callback:\n\n    linenoiseSetCompletionCallback(completion);\n\nThe completion must be a function returning `void` and getting as input\na `const char` pointer, which is the line the user has typed so far, and\na `linenoiseCompletions` object pointer, which is used as argument of\n`linenoiseAddCompletion` in order to add completions inside the callback.\nAn example will make it more clear:\n\n    void completion(const char *buf, linenoiseCompletions *lc) {\n        if (buf[0] == 'h') {\n            linenoiseAddCompletion(lc,\"hello\");\n            linenoiseAddCompletion(lc,\"hello there\");\n        }\n    }\n\nBasically in your completion callback, you inspect the input, and return\na list of items that are good completions by using `linenoiseAddCompletion`.\n\nIf you want to test the completion feature, compile the example program\nwith `make`, run it, type `h` and press `\u003CTAB>`.\n\n## Hints\n\nLinenoise has a feature called *hints* which is very useful when you\nuse Linenoise in order to implement a REPL (Read Eval Print Loop) for\na program that accepts commands and arguments, but may also be useful in\nother conditions.\n\nThe feature shows, on the right of the cursor, as the user types, hints that\nmay be useful. The hints can be displayed using a different color compared\nto the color the user is typing, and can also be bold.\n\nFor example as the user starts to type `\"git remote add\"`, with hints it's\npossible to show on the right of the prompt a string `\u003Cname> \u003Curl>`.\n\nThe feature works similarly to the history feature, using a callback.\nTo register the callback we use:\n\n    linenoiseSetHintsCallback(hints);\n\nThe callback itself is implemented like this:\n\n    char *hints(const char *buf, int *color, int *bold) {\n        if (!strcasecmp(buf,\"git remote add\")) {\n            *color = 35;\n            *bold = 0;\n            return \" \u003Cname> \u003Curl>\";\n        }\n        return NULL;\n    }\n\nThe callback function returns the string that should be displayed or NULL\nif no hint is available for the text the user currently typed. The returned\nstring will be trimmed as needed depending on the number of columns available\non the screen.\n\nIt is possible to return a string allocated in dynamic way, by also registering\na function to deallocate the hint string once used:\n\n    void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);\n\nThe free hint callback will just receive the pointer and free the string\nas needed (depending on how the hits callback allocated it).\n\nAs you can see in the example above, a `color` (in xterm color terminal codes)\ncan be provided together with a `bold` attribute. If no color is set, the\ncurrent terminal foreground color is used. If no bold attribute is set,\nnon-bold text is printed.\n\nColor codes are:\n\n    red = 31\n    green = 32\n    yellow = 33\n    blue = 34\n    magenta = 35\n    cyan = 36\n    white = 37;\n\n## Screen handling\n\nSometimes you may want to clear the screen as a result of something the\nuser typed. You can do this by calling the following function:\n\n    void linenoiseClearScreen(void);\n\n## Asyncrhronous API\n\nSometimes you want to read from the keyboard but also from sockets or other\nexternal events, and at the same time there could be input to display to the\nuser *while* the user is typing something. Let's call this the \"IRC problem\",\nsince if you want to write an IRC client with linenoise, without using\nsome fully featured libcurses approach, you will surely end having such an\nissue.\n\nFortunately now a multiplexing friendly API exists, and it is just what the\nblocking calls internally use. To start, we need to initialize a linenoise\ncontext like this:\n\n    struct linenoiseState ls;\n    char buf[1024];\n    linenoiseEditStart(&ls,-1,-1,buf,sizeof(buf),\"some prompt> \");\n\nThe two -1 and -1 arguments are the stdin\u002Fout descriptors. If they are\nset to -1, linenoise will just use the default stdin\u002Fout file descriptors.\nThe asynchronous API uses the buffer provided by the caller, so pasted input\nis limited by the size passed to `linenoiseEditStart()`. Bracketed paste\nfolding works in this mode too, but if you want to accept large pastes you\nneed to provide a large enough buffer.\n\nNow as soon as we have data from stdin (and we know it via select(2) or\nsome other way), we can ask linenoise to read the next character with:\n\n    linenoiseEditFeed(&ls);\n\nThe function returns a `char` pointer: if the user didn't yet press enter\nto provide a line to the program, it will return `linenoiseEditMore`, that\nmeans we need to call `linenoiseEditFeed()` again when more data is\navailable. If the function returns non NULL, then this is a heap allocated\ndata (to be freed with `linenoiseFree()`) representing the user input.\nWhen the function returns NULL, than the user pressed CTRL-C or CTRL-D\nwith an empty line, to quit the program, or there was some I\u002FO error.\n\nAfter each line is received (or if you want to quit the program, and exit raw mode), the following function needs to be called:\n\n    linenoiseEditStop(&ls);\n\nTo start reading the next line, a new linenoiseEditStart() must\nbe called, in order to reset the state, and so forth, so a typical event\nhandler called when the standard input is readable, will work similarly\nto the example below:\n\n``` c\nvoid stdinHasSomeData(void) {\n    char *line = linenoiseEditFeed(&LineNoiseState);\n    if (line == linenoiseEditMore) return;\n    linenoiseEditStop(&LineNoiseState);\n    if (line == NULL) exit(0);\n\n    printf(\"line: %s\\n\", line);\n    linenoiseFree(line);\n    linenoiseEditStart(&LineNoiseState,-1,-1,LineNoiseBuffer,sizeof(LineNoiseBuffer),\"serial> \");\n}\n```\n\nNow that we have a way to avoid blocking in the user input, we can use\ntwo calls to hide\u002Fshow the edited line, so that it is possible to also\nshow some input that we received (from socekts, bluetooth, whatever) on\nscreen:\n\n    linenoiseHide(&ls);\n    printf(\"some data...\\n\");\n    linenoiseShow(&ls);\n\nTo the API calls, the linenoise example C file implements a multiplexing\nexample using select(2) and the asynchronous API:\n\n```c\n    struct linenoiseState ls;\n    char buf[1024];\n    linenoiseEditStart(&ls,-1,-1,buf,sizeof(buf),\"hello> \");\n\n    while(1) {\n        \u002F\u002F Select(2) setup code removed...\n        retval = select(ls.ifd+1, &readfds, NULL, NULL, &tv);\n        if (retval == -1) {\n            perror(\"select()\");\n            exit(1);\n        } else if (retval) {\n            line = linenoiseEditFeed(&ls);\n            \u002F* A NULL return means: line editing is continuing.\n             * Otherwise the user hit enter or stopped editing\n             * (CTRL+C\u002FD). *\u002F\n            if (line != linenoiseEditMore) break;\n        } else {\n            \u002F\u002F Timeout occurred\n            static int counter = 0;\n            linenoiseHide(&ls);\n            printf(\"Async output %d.\\n\", counter++);\n            linenoiseShow(&ls);\n        }\n    }\n    linenoiseEditStop(&ls);\n    if (line == NULL) exit(0); \u002F* Ctrl+D\u002FC. *\u002F\n```\n\nYou can test the example by running the example program with the `--async` option.\n\n## Running the tests\n\nTo run the test suite:\n\n    make test\n\nThe tests will display a virtual terminal showing linenoise output in real-time, making it easy to see what's being tested and debug any failures.\n\n### What the tests cover\n\nThe test suite verifies:\n\n* Basic typing and cursor movement (left, right, home, end)\n* Backspace and delete operations\n* UTF-8 multi-byte characters (accented letters, CJK)\n* Emoji and grapheme clusters (skin tones, ZWJ sequences like flags)\n* Horizontal scrolling for long lines\n* Multiline mode editing and navigation\n* History navigation in multiline mode\n* Word and line deletion (Ctrl-W, Ctrl-U)\n* Bracketed paste folding and large paste handling\n\n### How the test harness works\n\nThe test program (`linenoise-test.c`) implements a VT100 terminal emulator that captures and verifies linenoise output:\n\n1. **Fork and pipes**: The test harness forks `linenoise-example`, connecting to it via pipes. The child process sees `LINENOISE_ASSUME_TTY=1` to enable terminal mode despite not having a real TTY.\n2. **VT100 emulator**: A minimal VT100 emulator parses escape sequences (cursor movement, screen clearing, etc.) and maintains a virtual screen buffer. Each cell stores a complete UTF-8 grapheme cluster and its display width.\n3. **Visual rendering**: After each operation, the virtual screen is rendered to your real terminal with a border, so you can watch the test execute and see exactly what linenoise is displaying.\n4. **Assertions**: Tests verify screen contents and cursor position against expected values.\n\nThis approach tests linenoise as users actually experience it, catching rendering bugs that unit tests would miss.\n\n## Related projects\n\n* [Linenoise NG](https:\u002F\u002Fgithub.com\u002Farangodb\u002Flinenoise-ng) is a fork of Linenoise that aims to add more advanced features like Windows support and other features. Uses C++ instead of C as development language.\n* [Linenoise-swift](https:\u002F\u002Fgithub.com\u002Fandybest\u002Flinenoise-swift) is a reimplementation of Linenoise written in Swift.\n","Linenoise是一个轻量级的、零配置的readline替代品，适用于C语言项目。其核心功能包括单行和多行编辑模式、历史记录管理、自动补全、提示建议以及异步输出时的提示隐藏与恢复等。技术特点上，Linenoise仅依赖于VT100转义序列的一个子集，并且支持UTF-8编码，使得它在不同终端环境下的兼容性更强。该项目特别适合那些需要命令行交互但又不想引入庞大依赖（如readline或libedit）的小型至中型程序使用。由于其简洁的设计（约1600行代码），Linenoise易于集成到现有项目中，同时提供了足够的功能来改善用户体验。","2026-06-11 03:08:05","top_language"]