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