linenoise.c revision 192a28831520dee50410a17953d87280d0fd8996
17fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich/* linenoise.c -- guerrilla line editing library against the idea that a
27fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * line editing lib needs to be 20,000 lines of C code.
37fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
47fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * You can find the latest source code at:
57fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
67fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *   http://github.com/antirez/linenoise
77fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
87fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * Does a number of crazy assumptions that happen to be true in 99.9999% of
97fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * the 2010 UNIX computers around.
107fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
117fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
127fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * All rights reserved.
137fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
147fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * Redistribution and use in source and binary forms, with or without
157fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * modification, are permitted provided that the following conditions are met:
167fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
177fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *   * Redistributions of source code must retain the above copyright notice,
187fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *     this list of conditions and the following disclaimer.
197fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *   * Redistributions in binary form must reproduce the above copyright
207fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *     notice, this list of conditions and the following disclaimer in the
217fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *     documentation and/or other materials provided with the distribution.
227fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *   * Neither the name of Redis nor the names of its contributors may be used
237fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *     to endorse or promote products derived from this software without
247fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *     specific prior written permission.
257fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
267fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
277fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
307fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
367fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * POSSIBILITY OF SUCH DAMAGE.
377fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
387fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * References:
397fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
407fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
417fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
427fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * Todo list:
437fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - Switch to gets() if $TERM is something we can't support.
447fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - Filter bogus Ctrl+<char> combinations.
457fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - Win32 support
467fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
477fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * Bloat:
487fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - Completion?
497fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * - History search like Ctrl+r in readline?
507fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
517fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * List of escape sequences used by this program, we do everything just
527fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * with three sequences. In order to be so cheap we may have some
537fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * flickering effect with some slow terminal, but the lesser sequences
547fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * the more compatible.
557fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
567fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * CHA (Cursor Horizontal Absolute)
577fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Sequence: ESC [ n G
587fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Effect: moves cursor to column n
597fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
607fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * EL (Erase Line)
617fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Sequence: ESC [ n K
627fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Effect: if n is 0 or missing, clear from cursor to end of line
637fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Effect: if n is 1, clear from beginning of line to cursor
647fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Effect: if n is 2, clear entire line
657fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
667fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich * CUF (CUrsor Forward)
677fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Sequence: ESC [ n C
687fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *    Effect: moves cursor forward of n chars
697fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich *
707fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich */
717fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
727fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <termios.h>
737fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <unistd.h>
747fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <stdlib.h>
757fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <stdio.h>
767fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <errno.h>
777fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <string.h>
787fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <stdlib.h>
797fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <sys/types.h>
807fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <sys/ioctl.h>
817fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#include <unistd.h>
827fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
837fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich#define LINENOISE_MAX_LINE 4096
847fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic char *unsupported_term[] = {"dumb","cons25",NULL};
857fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
867fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic struct termios orig_termios; /* in order to restore at exit */
877fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int rawmode = 0; /* for atexit() function to check if restore is needed*/
887fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int atexit_registered = 0; /* register atexit just 1 time */
897fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int history_max_len = 100;
907fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int history_len = 0;
917fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichchar **history = NULL;
927fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
937fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic void linenoiseAtExit(void);
947fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichint linenoiseHistoryAdd(const char *line);
957fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
967fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int isUnsupportedTerm(void) {
977fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    char *term = getenv("TERM");
987fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    int j;
997fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1007fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (term == NULL) return 0;
1017fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    for (j = 0; unsupported_term[j]; j++)
1027fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (!strcasecmp(term,unsupported_term[j])) return 1;
1037fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return 0;
1047fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
1057fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1067fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic void freeHistory(void) {
1077fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (history) {
1087fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        int j;
1097fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1107fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        for (j = 0; j < history_len; j++)
1117fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            free(history[j]);
1127fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        free(history);
1137fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
1147fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
1157fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1167fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int enableRawMode(int fd) {
1177fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    struct termios raw;
1187fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1197fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (!isatty(STDIN_FILENO)) goto fatal;
1207fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (!atexit_registered) {
1217fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        atexit(linenoiseAtExit);
1227fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        atexit_registered = 1;
1237fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
1247fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
1257fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1267fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    raw = orig_termios;  /* modify the original mode */
1277fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* input modes: no break, no CR to NL, no parity check, no strip char,
1287fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich     * no start/stop output control. */
1297fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
1307fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* output modes - disable post processing */
1317fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    raw.c_oflag &= ~(OPOST);
1327fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* control modes - set 8 bit chars */
1337fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    raw.c_cflag |= (CS8);
1347fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* local modes - choing off, canonical off, no extended functions,
1357fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich     * no signal chars (^Z,^C) */
1367fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
1377fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* control chars - set return condition: min number of bytes and timer.
1387fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich     * We want read to return every single byte, without timeout. */
1397fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
1407fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
141192a28831520dee50410a17953d87280d0fd8996Jack Palevich    /* put terminal in raw mode */
142192a28831520dee50410a17953d87280d0fd8996Jack Palevich    if (tcsetattr(fd,TCSADRAIN,&raw) < 0) goto fatal;
1437fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    rawmode = 1;
1447fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return 0;
1457fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1467fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichfatal:
1477fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    errno = ENOTTY;
1487fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return -1;
1497fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
1507fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1517fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic void disableRawMode(int fd) {
1527fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* Don't even check the return value as it's too late. */
153192a28831520dee50410a17953d87280d0fd8996Jack Palevich    if (rawmode && tcsetattr(fd,TCSADRAIN,&orig_termios) != -1)
1547fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        rawmode = 0;
1557fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
1567fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1577fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich/* At exit we'll try to fix the terminal to the initial conditions. */
1587fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic void linenoiseAtExit(void) {
1597fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    disableRawMode(STDIN_FILENO);
1607fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    freeHistory();
1617fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
1627fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1637fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int getColumns(void) {
1647fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    struct winsize ws;
1657fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
166192a28831520dee50410a17953d87280d0fd8996Jack Palevich    if (ioctl(1, TIOCGWINSZ, &ws) == -1) return 4096;
1677fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (ws.ws_col == 0) {
168192a28831520dee50410a17953d87280d0fd8996Jack Palevich        return 4096;
1697fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
1707fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return ws.ws_col;
1717fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
1727fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
173192a28831520dee50410a17953d87280d0fd8996Jack Palevichstatic int effectiveLen(const char* prompt) {
174192a28831520dee50410a17953d87280d0fd8996Jack Palevich    int col = 0;
175192a28831520dee50410a17953d87280d0fd8996Jack Palevich    char c;
176192a28831520dee50410a17953d87280d0fd8996Jack Palevich    // TODO: Handle escape sequences.
177192a28831520dee50410a17953d87280d0fd8996Jack Palevich    while ( (c = *prompt++) != 0 ) {
178192a28831520dee50410a17953d87280d0fd8996Jack Palevich        if (c == '\n') {
179192a28831520dee50410a17953d87280d0fd8996Jack Palevich            col = 0;
180192a28831520dee50410a17953d87280d0fd8996Jack Palevich        } else {
181192a28831520dee50410a17953d87280d0fd8996Jack Palevich            col++;
182192a28831520dee50410a17953d87280d0fd8996Jack Palevich        }
183192a28831520dee50410a17953d87280d0fd8996Jack Palevich    }
184192a28831520dee50410a17953d87280d0fd8996Jack Palevich    return col;
185192a28831520dee50410a17953d87280d0fd8996Jack Palevich}
186192a28831520dee50410a17953d87280d0fd8996Jack Palevich
1877fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
1887fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    char seq[64];
189192a28831520dee50410a17953d87280d0fd8996Jack Palevich    size_t plen = effectiveLen(prompt);
1907fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
1917fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    while((plen+pos) >= cols) {
1927fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        buf++;
1937fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        len--;
1947fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        pos--;
1957fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
1967fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    while (plen+len > cols) {
1977fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        len--;
1987fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
1997fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
2007fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* Cursor to left edge */
2017fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    snprintf(seq,64,"\x1b[0G");
2027fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (write(fd,seq,strlen(seq)) == -1) return;
2037fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* Write the prompt and the current buffer content */
2047fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (write(fd,prompt,strlen(prompt)) == -1) return;
2057fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (write(fd,buf,len) == -1) return;
2067fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* Erase to right */
2077fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    snprintf(seq,64,"\x1b[0K");
2087fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (write(fd,seq,strlen(seq)) == -1) return;
2097fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* Move cursor to original position. */
2107fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    snprintf(seq,64,"\x1b[0G\x1b[%dC", (int)(pos+plen));
2117fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (write(fd,seq,strlen(seq)) == -1) return;
2127fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
2137fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
2147fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) {
2157fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    size_t plen = strlen(prompt);
2167fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    size_t pos = 0;
2177fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    size_t len = 0;
2187fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    size_t cols = getColumns();
2197fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    int history_index = 0;
2207fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
2217fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    buf[0] = '\0';
2227fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    buflen--; /* Make sure there is always space for the nulterm */
2237fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
2247fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    /* The latest history entry is always our current buffer, that
2257fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich     * initially is just an empty string. */
2267fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    linenoiseHistoryAdd("");
2277fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
2287fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (write(fd,prompt,plen) == -1) return -1;
2297fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    while(1) {
2307fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        char c;
2317fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        int nread;
2327fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        char seq[2];
2337fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
2347fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        nread = read(fd,&c,1);
2357fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (nread <= 0) return len;
2367fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        switch(c) {
2377fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 10:    /* line feed. */
2387fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 13:    /* enter */
2397fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            history_len--;
2407fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            return len;
2417fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 4:     /* ctrl-d */
2427fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            history_len--;
2437fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            return (len == 0) ? -1 : (int)len;
2447fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 3:     /* ctrl-c */
2457fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            errno = EAGAIN;
2467fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            return -1;
2477fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 127:   /* backspace */
2487fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 8:     /* ctrl-h */
2497fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            if (pos > 0 && len > 0) {
2507fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                memmove(buf+pos-1,buf+pos,len-pos);
2517fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                pos--;
2527fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                len--;
2537fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                buf[len] = '\0';
2547fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                refreshLine(fd,prompt,buf,len,pos,cols);
2557fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            }
2567fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
2577fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 20:    /* ctrl-t */
2587fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            if (pos > 0 && pos < len) {
2597fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                int aux = buf[pos-1];
2607fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                buf[pos-1] = buf[pos];
2617fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                buf[pos] = aux;
2627fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                if (pos != len-1) pos++;
2637fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                refreshLine(fd,prompt,buf,len,pos,cols);
2647fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            }
2657fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
2667fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 2:     /* ctrl-b */
2677fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            goto left_arrow;
2687fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 6:     /* ctrl-f */
2697fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            goto right_arrow;
2707fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 16:    /* ctrl-p */
2717fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            seq[1] = 65;
2727fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            goto up_down_arrow;
2737fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 14:    /* ctrl-n */
2747fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            seq[1] = 66;
2757fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            goto up_down_arrow;
2767fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
2777fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 27:    /* escape sequence */
2787fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            if (read(fd,seq,2) == -1) break;
2797fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            if (seq[0] == 91 && seq[1] == 68) {
2807fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichleft_arrow:
2817fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                /* left arrow */
2827fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                if (pos > 0) {
2837fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    pos--;
2847fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    refreshLine(fd,prompt,buf,len,pos,cols);
2857fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                }
2867fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            } else if (seq[0] == 91 && seq[1] == 67) {
2877fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichright_arrow:
2887fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                /* right arrow */
2897fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                if (pos != len) {
2907fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    pos++;
2917fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    refreshLine(fd,prompt,buf,len,pos,cols);
2927fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                }
2937fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            } else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
2947fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichup_down_arrow:
2957fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                /* up and down arrow: history */
2967fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                if (history_len > 1) {
2977fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    /* Update the current history entry before to
2987fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                     * overwrite it with tne next one. */
2997fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    free(history[history_len-1-history_index]);
3007fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    history[history_len-1-history_index] = strdup(buf);
3017fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    /* Show the new entry */
3027fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    history_index += (seq[1] == 65) ? 1 : -1;
3037fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    if (history_index < 0) {
3047fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        history_index = 0;
3057fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        break;
3067fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    } else if (history_index >= history_len) {
3077fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        history_index = history_len-1;
3087fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        break;
3097fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    }
3107fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    strncpy(buf,history[history_len-1-history_index],buflen);
3117fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    buf[buflen] = '\0';
3127fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    len = pos = strlen(buf);
3137fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    refreshLine(fd,prompt,buf,len,pos,cols);
3147fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                }
3157fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            }
3167fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
3177fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        default:
3187fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            if (len < buflen) {
3197fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                if (len == pos) {
3207fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    buf[pos] = c;
3217fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    pos++;
3227fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    len++;
3237fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    buf[len] = '\0';
3247fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    if (plen+len < cols) {
3257fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        /* Avoid a full update of the line in the
3267fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                         * trivial case. */
3277fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        if (write(fd,&c,1) == -1) return -1;
3287fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    } else {
3297fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                        refreshLine(fd,prompt,buf,len,pos,cols);
3307fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    }
3317fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                } else {
3327fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    memmove(buf+pos+1,buf+pos,len-pos);
3337fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    buf[pos] = c;
3347fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    len++;
3357fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    pos++;
3367fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    buf[len] = '\0';
3377fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                    refreshLine(fd,prompt,buf,len,pos,cols);
3387fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich                }
3397fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            }
3407fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
3417fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 21: /* Ctrl+u, delete the whole line. */
3427fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            buf[0] = '\0';
3437fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            pos = len = 0;
3447fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            refreshLine(fd,prompt,buf,len,pos,cols);
3457fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
3467fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 11: /* Ctrl+k, delete from current to end of line. */
3477fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            buf[pos] = '\0';
3487fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            len = pos;
3497fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            refreshLine(fd,prompt,buf,len,pos,cols);
3507fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
3517fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 1: /* Ctrl+a, go to the start of the line */
3527fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            pos = 0;
3537fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            refreshLine(fd,prompt,buf,len,pos,cols);
3547fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
3557fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        case 5: /* ctrl+e, go to the end of the line */
3567fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            pos = len;
3577fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            refreshLine(fd,prompt,buf,len,pos,cols);
3587fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            break;
3597fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        }
3607fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
3617fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return len;
3627fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
3637fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
3647fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichstatic int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
3657fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    int fd = STDIN_FILENO;
3667fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    int count;
3677fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
3687fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (buflen == 0) {
3697fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        errno = EINVAL;
3707fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        return -1;
3717fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
3727fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (!isatty(STDIN_FILENO)) {
3737fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (fgets(buf, buflen, stdin) == NULL) return -1;
3747fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        count = strlen(buf);
3757fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (count && buf[count-1] == '\n') {
3767fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            count--;
3777fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            buf[count] = '\0';
3787fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        }
3797fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    } else {
3807fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (enableRawMode(fd) == -1) return -1;
3817fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        count = linenoisePrompt(fd, buf, buflen, prompt);
3827fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        disableRawMode(fd);
3837fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
3847fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return count;
3857fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
3867fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
3877fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichchar *linenoise(const char *prompt) {
3887fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    char buf[LINENOISE_MAX_LINE];
3897fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    int count;
3907fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
3917fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (isUnsupportedTerm()) {
3927fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        size_t len;
3937fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
3947fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        printf("%s",prompt);
3957fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        fflush(stdout);
3967fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
3977fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        len = strlen(buf);
3987fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
3997fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            len--;
4007fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich            buf[len] = '\0';
4017fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        }
4027fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        return strdup(buf);
4037fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    } else {
4047fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
4057fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (count == -1) return NULL;
4067fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        return strdup(buf);
4077fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
4087fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
4097fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
4107fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich/* Using a circular buffer is smarter, but a bit more complex to handle. */
4117fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichint linenoiseHistoryAdd(const char *line) {
4127fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    char *linecopy;
4137fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
4147fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (history_max_len == 0) return 0;
4157fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (history == 0) {
4167fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        history = malloc(sizeof(char*)*history_max_len);
4177fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (history == NULL) return 0;
4187fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        memset(history,0,(sizeof(char*)*history_max_len));
4197fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
4207fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    linecopy = strdup(line);
4217fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (!linecopy) return 0;
4227fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (history_len == history_max_len) {
4237fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        memmove(history,history+1,sizeof(char*)*(history_max_len-1));
4247fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        history_len--;
4257fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
4267fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    history[history_len] = linecopy;
4277fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    history_len++;
4287fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return 1;
4297fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
4307fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
4317fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevichint linenoiseHistorySetMaxLen(int len) {
4327fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    char **new;
4337fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
4347fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (len < 1) return 0;
4357fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (history) {
4367fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        int tocopy = history_len;
4377fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich
4387fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        new = malloc(sizeof(char*)*len);
4397fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (new == NULL) return 0;
4407fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        if (len < tocopy) tocopy = len;
4417fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy);
4427fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        free(history);
4437fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        history = new;
4447fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    }
4457fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    history_max_len = len;
4467fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    if (history_len > history_max_len)
4477fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich        history_len = history_max_len;
4487fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich    return 1;
4497fe202f160ca1926bc0277e3c276ad7b3f9b9aebJack Palevich}
450