1 /* linenoise.c -- guerrilla line editing library against the idea that a
2 * line editing lib needs to be 20,000 lines of C code.
4 * You can find the latest source code at:
6 * http://github.com/antirez/linenoise
8 * Does a number of crazy assumptions that happen to be true in 99.9999% of
9 * the 2010 UNIX computers around.
11 * ------------------------------------------------------------------------
13 * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
14 * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * ------------------------------------------------------------------------
44 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
45 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
49 * - Save and load history containing newlines
54 * List of escape sequences used by this program, we do everything just
55 * a few sequences. In order to be so cheap we may have some
56 * flickering effect with some slow terminal, but the lesser sequences
57 * the more compatible.
59 * CHA (Cursor Horizontal Absolute)
61 * Effect: moves cursor to column n
65 * Effect: if n is 0 or missing, clear from cursor to end of line
66 * Effect: if n is 1, clear from beginning of line to cursor
67 * Effect: if n is 2, clear entire line
69 * CUF (CUrsor Forward)
71 * Effect: moves cursor forward of n chars
73 * The following are used to clear the screen: ESC [ H ESC [ 2 J
74 * This is actually composed of two sequences:
78 * Effect: moves the cursor to upper left corner
80 * ED2 (Clear entire screen)
82 * Effect: clear the whole screen
84 * == For highlighting control characters, we also use the following two ==
87 * Effect: Uses some standout mode such as reverse video
91 * Effect: Exit standout mode
93 * == Only used if TIOCGWINSZ fails ==
94 * DSR/CPR (Report cursor position)
96 * Effect: reports current cursor position as ESC [ NNN ; MMM R
107 #include <sys/types.h>
108 #include <sys/ioctl.h>
109 #include <sys/poll.h>
111 #include "linenoise.h"
113 #include "jim-config.h"
119 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
120 #define LINENOISE_MAX_LINE 4096
121 static char *unsupported_term
[] = {"dumb","cons25",NULL
};
123 static struct termios orig_termios
; /* in order to restore at exit */
124 static int rawmode
= 0; /* for atexit() function to check if restore is needed*/
125 static int atexit_registered
= 0; /* register atexit just 1 time */
126 static int history_max_len
= LINENOISE_DEFAULT_HISTORY_MAX_LEN
;
127 static int history_len
= 0;
128 static char **history
= NULL
;
130 static void linenoiseAtExit(void);
131 static int fd_read(int fd
);
132 static void getColumns(int fd
, int *cols
);
134 static int isUnsupportedTerm(void) {
135 char *term
= getenv("TERM");
138 if (term
== NULL
) return 0;
139 for (j
= 0; unsupported_term
[j
]; j
++)
140 if (!strcasecmp(term
,unsupported_term
[j
])) return 1;
144 static void freeHistory(void) {
148 for (j
= 0; j
< history_len
; j
++)
155 static int enableRawMode(int fd
) {
158 if (!isatty(STDIN_FILENO
)) goto fatal
;
159 if (!atexit_registered
) {
160 atexit(linenoiseAtExit
);
161 atexit_registered
= 1;
163 if (tcgetattr(fd
,&orig_termios
) == -1) goto fatal
;
165 raw
= orig_termios
; /* modify the original mode */
166 /* input modes: no break, no CR to NL, no parity check, no strip char,
167 * no start/stop output control. */
168 raw
.c_iflag
&= ~(BRKINT
| ICRNL
| INPCK
| ISTRIP
| IXON
);
169 /* output modes - disable post processing */
170 raw
.c_oflag
&= ~(OPOST
);
171 /* control modes - set 8 bit chars */
172 raw
.c_cflag
|= (CS8
);
173 /* local modes - choing off, canonical off, no extended functions,
174 * no signal chars (^Z,^C) */
175 raw
.c_lflag
&= ~(ECHO
| ICANON
| IEXTEN
| ISIG
);
176 /* control chars - set return condition: min number of bytes and timer.
177 * We want read to return every single byte, without timeout. */
178 raw
.c_cc
[VMIN
] = 1; raw
.c_cc
[VTIME
] = 0; /* 1 byte, no timer */
180 /* put terminal in raw mode after flushing */
181 if (tcsetattr(fd
,TCSADRAIN
,&raw
) < 0) goto fatal
;
190 static void disableRawMode(int fd
) {
191 /* Don't even check the return value as it's too late. */
192 if (rawmode
&& tcsetattr(fd
,TCSADRAIN
,&orig_termios
) != -1)
196 /* At exit we'll try to fix the terminal to the initial conditions. */
197 static void linenoiseAtExit(void) {
198 disableRawMode(STDIN_FILENO
);
202 /* Structure to contain the status of the current (being edited) line */
204 int fd
; /* Terminal fd */
205 char *buf
; /* Current buffer. Always null terminated */
206 int bufmax
; /* Size of the buffer, including space for the null termination */
207 int len
; /* Number of bytes in 'buf' */
208 int chars
; /* Number of chars in 'buf' (utf-8 chars) */
209 int pos
; /* Cursor position, measured in chars */
210 int cols
; /* Size of the window, in chars */
214 /* gcc/glibc insists that we care about the return code of write! */
215 #if defined(__GNUC__) && !defined(__clang__)
216 #define IGNORE_RC(EXPR) ((EXPR) < 0 ? -1 : 0)
218 #define IGNORE_RC(EXPR) EXPR
221 /* This is fd_printf() on some systems, but use a different
222 * name to avoid conflicts
224 static void fd_printf(int fd
, const char *format
, ...)
230 va_start(args
, format
);
231 n
= vsnprintf(buf
, sizeof(buf
), format
, args
);
233 IGNORE_RC(write(fd
, buf
, n
));
236 static int utf8_getchars(char *buf
, int c
)
239 return utf8_fromunicode(buf
, c
);
247 * Returns the unicode character at the given offset,
250 static int get_char(struct current
*current
, int pos
)
252 if (pos
>= 0 && pos
< current
->chars
) {
254 int i
= utf8_index(current
->buf
, pos
);
255 (void)utf8_tounicode(current
->buf
+ i
, &c
);
261 static void refreshLine(const char *prompt
, struct current
*current
) {
266 const char *buf
= current
->buf
;
267 int chars
= current
->chars
;
268 int pos
= current
->pos
;
273 /* Should intercept SIGWINCH. For now, just get the size every time */
274 getColumns(current
->fd
, ¤t
->cols
);
276 plen
= strlen(prompt
);
277 pchars
= utf8_strlen(prompt
, plen
);
279 /* Account for a line which is too long to fit in the window.
280 * Note that control chars require an extra column
283 /* How many cols are required to the left of 'pos'?
284 * The prompt, plus one extra for each control char
286 n
= pchars
+ utf8_strlen(buf
, current
->len
);
288 for (i
= 0; i
< pos
; i
++) {
289 b
+= utf8_tounicode(buf
+ b
, &ch
);
295 /* If too many are need, strip chars off the front of 'buf'
296 * until it fits. Note that if the current char is a control character,
297 * we need one extra col.
299 if (current
->pos
< current
->chars
&& get_char(current
, current
->pos
) < ' ') {
303 while (n
>= current
->cols
) {
304 b
= utf8_tounicode(buf
, &ch
);
314 /* Cursor to left edge, then the prompt */
315 fd_printf(current
->fd
, "\x1b[0G");
316 IGNORE_RC(write(current
->fd
, prompt
, plen
));
318 /* Now the current buffer content */
320 /* Need special handling for control characters.
321 * If we hit 'cols', stop.
323 b
= 0; /* unwritted bytes */
324 n
= 0; /* How many control chars were written */
325 for (i
= 0; i
< chars
; i
++) {
327 int w
= utf8_tounicode(buf
+ b
, &ch
);
331 if (pchars
+ i
+ n
>= current
->cols
) {
335 /* A control character, so write the buffer so far */
336 IGNORE_RC(write(current
->fd
, buf
, b
));
339 fd_printf(current
->fd
, "\033[7m^%c\033[0m", ch
+ '@');
348 IGNORE_RC(write(current
->fd
, buf
, b
));
350 /* Erase to right, move cursor to original position */
351 fd_printf(current
->fd
, "\x1b[0K" "\x1b[0G\x1b[%dC", pos
+ pchars
+ backup
);
354 static void set_current(struct current
*current
, const char *str
)
356 strncpy(current
->buf
, str
, current
->bufmax
);
357 current
->buf
[current
->bufmax
- 1] = 0;
358 current
->len
= strlen(current
->buf
);
359 current
->pos
= current
->chars
= utf8_strlen(current
->buf
, current
->len
);
362 static int has_room(struct current
*current
, int bytes
)
364 return current
->len
+ bytes
< current
->bufmax
- 1;
368 * Removes the char at 'pos'.
370 * Returns 1 if the line needs to be refreshed, 2 if not
371 * and 0 if nothing was removed
373 static int remove_char(struct current
*current
, int pos
)
375 if (pos
>= 0 && pos
< current
->chars
) {
378 p1
= utf8_index(current
->buf
, pos
);
379 p2
= p1
+ utf8_index(current
->buf
+ p1
, 1);
381 /* optimise remove char in the case of removing the last char */
382 if (current
->pos
== pos
+ 1 && current
->pos
== current
->chars
) {
383 if (current
->buf
[pos
] >= ' ' && utf8_strlen(current
->prompt
, -1) + utf8_strlen(current
->buf
, current
->len
) < current
->cols
- 1) {
385 fd_printf(current
->fd
, "\b \b");
389 /* Move the null char too */
390 memmove(current
->buf
+ p1
, current
->buf
+ p2
, current
->len
- p2
+ 1);
391 current
->len
-= (p2
- p1
);
394 if (current
->pos
> pos
) {
403 * Insert 'ch' at position 'pos'
405 * Returns 1 if the line needs to be refreshed, 2 if not
406 * and 0 if nothing was inserted (no room)
408 static int insert_char(struct current
*current
, int pos
, int ch
)
411 int n
= utf8_getchars(buf
, ch
);
413 if (has_room(current
, n
) && pos
>= 0 && pos
<= current
->chars
) {
416 p1
= utf8_index(current
->buf
, pos
);
419 /* optimise the case where adding a single char to the end and no scrolling is needed */
420 if (current
->pos
== pos
&& current
->chars
== pos
) {
421 if (ch
>= ' ' && utf8_strlen(current
->prompt
, -1) + utf8_strlen(current
->buf
, current
->len
) < current
->cols
- 1) {
422 IGNORE_RC(write(current
->fd
, buf
, n
));
427 memmove(current
->buf
+ p2
, current
->buf
+ p1
, current
->len
- p1
);
428 memcpy(current
->buf
+ p1
, buf
, n
);
432 if (current
->pos
>= pos
) {
440 #ifndef NO_COMPLETION
441 static linenoiseCompletionCallback
*completionCallback
= NULL
;
444 fprintf(stderr
, "\x7");
448 static void freeCompletions(linenoiseCompletions
*lc
) {
450 for (i
= 0; i
< lc
->len
; i
++)
455 static int completeLine(struct current
*current
) {
456 linenoiseCompletions lc
= { 0, NULL
};
459 completionCallback(current
->buf
,&lc
);
463 size_t stop
= 0, i
= 0;
466 /* Show completion or original buffer */
468 struct current tmp
= *current
;
469 tmp
.buf
= lc
.cvec
[i
];
470 tmp
.pos
= tmp
.len
= strlen(tmp
.buf
);
471 tmp
.chars
= utf8_strlen(tmp
.buf
, tmp
.len
);
472 refreshLine(current
->prompt
, &tmp
);
474 refreshLine(current
->prompt
, current
);
477 c
= fd_read(current
->fd
);
484 i
= (i
+1) % (lc
.len
+1);
485 if (i
== lc
.len
) beep();
487 case 27: /* escape */
488 /* Re-show original buffer */
490 refreshLine(current
->prompt
, current
);
495 /* Update buffer and return */
497 set_current(current
,lc
.cvec
[i
]);
505 freeCompletions(&lc
);
506 return c
; /* Return last read character */
509 /* Register a callback function to be called for tab-completion. */
510 void linenoiseSetCompletionCallback(linenoiseCompletionCallback
*fn
) {
511 completionCallback
= fn
;
514 void linenoiseAddCompletion(linenoiseCompletions
*lc
, const char *str
) {
515 lc
->cvec
= realloc(lc
->cvec
,sizeof(char*)*(lc
->len
+1));
516 lc
->cvec
[lc
->len
++] = strdup(str
);
522 * Returns 0 if no chars were removed or non-zero otherwise.
524 static int remove_chars(struct current
*current
, int pos
, int n
)
527 while (n
-- && remove_char(current
, pos
)) {
534 * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
536 * A timeout of -1 means to wait forever.
538 * Returns -1 if no char is received within the time or an error occurs.
540 static int fd_read_char(int fd
, int timeout
)
548 if (poll(&p
, 1, timeout
) == 0) {
552 if (read(fd
, &c
, 1) != 1) {
559 * Reads a complete utf-8 character
560 * and returns the unicode value, or -1 on error.
562 static int fd_read(int fd
)
570 if (read(fd
, &buf
[0], 1) != 1) {
573 n
= utf8_charlen(buf
[0]);
574 if (n
< 1 || n
> 3) {
577 for (i
= 1; i
< n
; i
++) {
578 if (read(fd
, &buf
[i
], 1) != 1) {
583 /* decode and return the character */
584 utf8_tounicode(buf
, &c
);
587 return fd_read_char(fd
, -1);
591 static void getColumns(int fd
, int *cols
) {
594 if (ioctl(1, TIOCGWINSZ
, &ws
) == 0 && ws
.ws_col
!= 0) {
598 /* Failed to query the window size. Perhaps we are on a serial terminal.
599 * Try to query the width by sending the cursor as far to the right
600 * and reading back the cursor position.
601 * Note that this is only done once per call to linenoise rather than
602 * every time the line is refreshed for efficiency reasons.
607 /* Move cursor far right and report cursor position */
608 fd_printf(fd
, "\x1b[999G" "\x1b[6n");
610 /* Parse the response: ESC [ rows ; cols R */
611 if (fd_read_char(fd
, 100) == 0x1b && fd_read_char(fd
, 100) == '[') {
614 int ch
= fd_read_char(fd
, 100);
619 else if (ch
== 'R') {
621 if (n
!= 0 && n
< 1000) {
626 else if (ch
>= 0 && ch
<= '9') {
627 n
= n
* 10 + ch
- '0';
637 /* Use -ve numbers here to co-exist with normal unicode chars */
644 SPECIAL_DELETE
= -24,
650 * If escape (27) was received, reads subsequent
651 * chars to determine if this is a known special key.
653 * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
655 * If no additional char is received within a short time,
658 static int check_special(int fd
)
660 int c
= fd_read_char(fd
, 50);
667 c2
= fd_read_char(fd
, 50);
671 if (c
== '[' || c
== 'O') {
672 /* Potential arrow key */
679 return SPECIAL_RIGHT
;
688 if (c
== '[' && c2
>= '1' && c2
<= '6') {
689 /* extended escape */
690 int c3
= fd_read_char(fd
, 50);
691 if (c2
== '3' && c3
== '~') {
692 /* delete char under cursor */
693 return SPECIAL_DELETE
;
695 while (c3
!= -1 && c3
!= '~') {
696 /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */
697 c3
= fd_read_char(fd
, 50);
704 #define ctrl(C) ((C) - '@')
706 static int linenoisePrompt(struct current
*current
) {
707 int history_index
= 0;
709 /* The latest history entry is always our current buffer, that
710 * initially is just an empty string. */
711 linenoiseHistoryAdd("");
713 set_current(current
, "");
714 refreshLine(current
->prompt
, current
);
717 int c
= fd_read(current
->fd
);
719 #ifndef NO_COMPLETION
720 /* Only autocomplete when the callback is set. It returns < 0 when
721 * there was an error reading from fd. Otherwise it will return the
722 * character that should be handled next. */
723 if (c
== 9 && completionCallback
!= NULL
) {
724 c
= completeLine(current
);
725 /* Return on errors */
726 if (c
< 0) return current
->len
;
727 /* Read next character when 0 */
728 if (c
== 0) continue;
733 if (c
== -1) return current
->len
;
735 case '\r': /* enter */
737 free(history
[history_len
]);
739 case ctrl('C'): /* ctrl-c */
742 case 127: /* backspace */
744 if (remove_char(current
, current
->pos
- 1) == 1) {
745 refreshLine(current
->prompt
, current
);
748 case ctrl('D'): /* ctrl-d */
749 if (current
->len
== 0) {
750 /* Empty line, so EOF */
752 free(history
[history_len
]);
755 /* Otherwise delete char to right of cursor */
756 if (remove_char(current
, current
->pos
)) {
757 refreshLine(current
->prompt
, current
);
760 case ctrl('W'): /* ctrl-w */
761 /* eat any spaces on the left */
763 int pos
= current
->pos
;
764 while (pos
> 0 && get_char(current
, pos
- 1) == ' ') {
768 /* now eat any non-spaces on the left */
769 while (pos
> 0 && get_char(current
, pos
- 1) != ' ') {
773 if (remove_chars(current
, pos
, current
->pos
- pos
)) {
774 refreshLine(current
->prompt
, current
);
778 case ctrl('R'): /* ctrl-r */
780 /* Display the reverse-i-search prompt and process chars */
785 int searchpos
= history_len
- 1;
790 const char *p
= NULL
;
794 snprintf(rprompt
, sizeof(rprompt
), "(reverse-i-search)'%s': ", rbuf
);
795 refreshLine(rprompt
, current
);
796 c
= fd_read(current
->fd
);
797 if (c
== ctrl('H') || c
== 127) {
799 int p
= utf8_index(rbuf
, --rchars
);
806 c
= check_special(current
->fd
);
808 if (c
== ctrl('P') || c
== SPECIAL_UP
) {
809 /* Search for the previous (earlier) match */
815 else if (c
== ctrl('N') || c
== SPECIAL_DOWN
) {
816 /* Search for the next (later) match */
817 if (searchpos
< history_len
) {
824 if (rlen
>= (int)sizeof(rbuf
) + 3) {
828 n
= utf8_getchars(rbuf
+ rlen
, c
);
833 /* Adding a new char resets the search location */
834 searchpos
= history_len
- 1;
837 /* Exit from incremental search mode */
841 /* Now search through the history for a match */
842 for (; searchpos
>= 0 && searchpos
< history_len
; searchpos
+= searchdir
) {
843 p
= strstr(history
[searchpos
], rbuf
);
846 if (skipsame
&& strcmp(history
[searchpos
], current
->buf
) == 0) {
847 /* But it is identical, so skip it */
850 /* Copy the matching line and set the cursor position */
851 set_current(current
,history
[searchpos
]);
852 current
->pos
= utf8_strlen(history
[searchpos
], p
- history
[searchpos
]);
857 /* No match, so don't add it */
863 if (c
== ctrl('G') || c
== ctrl('C')) {
864 /* ctrl-g terminates the search with no effect */
865 set_current(current
, "");
868 else if (c
== ctrl('J')) {
869 /* ctrl-j terminates the search leaving the buffer in place */
872 /* Go process the char normally */
873 refreshLine(current
->prompt
, current
);
877 case ctrl('T'): /* ctrl-t */
878 if (current
->pos
> 0 && current
->pos
< current
->chars
) {
879 c
= get_char(current
, current
->pos
);
880 remove_char(current
, current
->pos
);
881 insert_char(current
, current
->pos
- 1, c
);
882 refreshLine(current
->prompt
, current
);
885 case ctrl('V'): /* ctrl-v */
886 if (has_room(current
, 3)) {
887 /* Insert the ^V first */
888 if (insert_char(current
, current
->pos
, c
)) {
889 refreshLine(current
->prompt
, current
);
890 /* Now wait for the next char. Can insert anything except \0 */
891 c
= fd_read(current
->fd
);
893 /* Remove the ^V first */
894 remove_char(current
, current
->pos
- 1);
896 /* Insert the actual char */
897 insert_char(current
, current
->pos
, c
);
899 refreshLine(current
->prompt
, current
);
903 case ctrl('B'): /* ctrl-b */
904 case ctrl('F'): /* ctrl-f */
905 case ctrl('P'): /* ctrl-p */
906 case ctrl('N'): /* ctrl-n */
907 case 27: { /* escape sequence */
910 c
= check_special(current
->fd
);
915 if (current
->pos
> 0) {
917 refreshLine(current
->prompt
, current
);
922 if (current
->pos
< current
->chars
) {
924 refreshLine(current
->prompt
, current
);
932 if (history_len
> 1) {
933 /* Update the current history entry before to
934 * overwrite it with tne next one. */
935 free(history
[history_len
-1-history_index
]);
936 history
[history_len
-1-history_index
] = strdup(current
->buf
);
937 /* Show the new entry */
938 history_index
+= dir
;
939 if (history_index
< 0) {
942 } else if (history_index
>= history_len
) {
943 history_index
= history_len
-1;
946 set_current(current
, history
[history_len
-1-history_index
]);
947 refreshLine(current
->prompt
, current
);
952 if (remove_char(current
, current
->pos
) == 1) {
953 refreshLine(current
->prompt
, current
);
958 refreshLine(current
->prompt
, current
);
961 current
->pos
= current
->chars
;
962 refreshLine(current
->prompt
, current
);
968 /* Only tab is allowed without ^V */
969 if (c
== '\t' || c
>= ' ') {
970 if (insert_char(current
, current
->pos
, c
) == 1) {
971 refreshLine(current
->prompt
, current
);
975 case ctrl('U'): /* Ctrl+u, delete to beginning of line. */
976 if (remove_chars(current
, 0, current
->pos
)) {
977 refreshLine(current
->prompt
, current
);
980 case ctrl('K'): /* Ctrl+k, delete from current to end of line. */
981 if (remove_chars(current
, current
->pos
, current
->chars
- current
->pos
)) {
982 refreshLine(current
->prompt
, current
);
985 case ctrl('A'): /* Ctrl+a, go to the start of the line */
987 refreshLine(current
->prompt
, current
);
989 case ctrl('E'): /* ctrl+e, go to the end of the line */
990 current
->pos
= current
->chars
;
991 refreshLine(current
->prompt
, current
);
993 case ctrl('L'): /* Ctrl+L, clear screen */
995 fd_printf(current
->fd
, "\x1b[H\x1b[2J");
996 /* Force recalc of window size for serial terminals */
998 refreshLine(current
->prompt
, current
);
1002 return current
->len
;
1005 static int linenoiseRaw(char *buf
, size_t buflen
, const char *prompt
) {
1006 int fd
= STDIN_FILENO
;
1013 if (!isatty(STDIN_FILENO
)) {
1014 if (fgets(buf
, buflen
, stdin
) == NULL
) return -1;
1015 count
= strlen(buf
);
1016 if (count
&& buf
[count
-1] == '\n') {
1021 struct current current
;
1023 if (enableRawMode(fd
) == -1) return -1;
1027 current
.bufmax
= buflen
;
1032 current
.prompt
= prompt
;
1034 count
= linenoisePrompt(¤t
);
1042 char *linenoise(const char *prompt
) {
1043 char buf
[LINENOISE_MAX_LINE
];
1046 if (isUnsupportedTerm()) {
1049 printf("%s",prompt
);
1051 if (fgets(buf
,LINENOISE_MAX_LINE
,stdin
) == NULL
) return NULL
;
1053 while(len
&& (buf
[len
-1] == '\n' || buf
[len
-1] == '\r')) {
1059 count
= linenoiseRaw(buf
,LINENOISE_MAX_LINE
,prompt
);
1060 if (count
== -1) return NULL
;
1065 /* Using a circular buffer is smarter, but a bit more complex to handle. */
1066 int linenoiseHistoryAdd(const char *line
) {
1069 if (history_max_len
== 0) return 0;
1070 if (history
== NULL
) {
1071 history
= malloc(sizeof(char*)*history_max_len
);
1072 if (history
== NULL
) return 0;
1073 memset(history
,0,(sizeof(char*)*history_max_len
));
1075 linecopy
= strdup(line
);
1076 if (!linecopy
) return 0;
1077 if (history_len
== history_max_len
) {
1079 memmove(history
,history
+1,sizeof(char*)*(history_max_len
-1));
1082 history
[history_len
] = linecopy
;
1087 int linenoiseHistorySetMaxLen(int len
) {
1090 if (len
< 1) return 0;
1092 int tocopy
= history_len
;
1094 new = malloc(sizeof(char*)*len
);
1095 if (new == NULL
) return 0;
1096 if (len
< tocopy
) tocopy
= len
;
1097 memcpy(new,history
+(history_max_len
-tocopy
), sizeof(char*)*tocopy
);
1101 history_max_len
= len
;
1102 if (history_len
> history_max_len
)
1103 history_len
= history_max_len
;
1107 /* Save the history in the specified file. On success 0 is returned
1108 * otherwise -1 is returned. */
1109 int linenoiseHistorySave(char *filename
) {
1110 FILE *fp
= fopen(filename
,"w");
1113 if (fp
== NULL
) return -1;
1114 for (j
= 0; j
< history_len
; j
++) {
1115 const char *str
= history
[j
];
1116 /* Need to encode backslash, nl and cr */
1121 else if (*str
== '\n') {
1124 else if (*str
== '\r') {
1139 /* Load the history from the specified file. If the file does not exist
1140 * zero is returned and no operation is performed.
1142 * If the file exists and the operation succeeded 0 is returned, otherwise
1143 * on error -1 is returned. */
1144 int linenoiseHistoryLoad(char *filename
) {
1145 FILE *fp
= fopen(filename
,"r");
1146 char buf
[LINENOISE_MAX_LINE
];
1148 if (fp
== NULL
) return -1;
1150 while (fgets(buf
,LINENOISE_MAX_LINE
,fp
) != NULL
) {
1153 /* Decode backslash escaped values */
1154 for (src
= dest
= buf
; *src
; src
++) {
1162 else if (*src
== 'r') {
1170 /* Remove trailing newline */
1171 if (dest
!= buf
&& (dest
[-1] == '\n' || dest
[-1] == '\r')) {
1176 linenoiseHistoryAdd(buf
);
1182 /* Provide access to the history buffer.
1184 * If 'len' is not NULL, the length is stored in *len.
1186 char **linenoiseHistory(int *len
) {