4 /* (c) 2017 Workware Systems Pty Ltd -- All Rights Reserved */
11 * A stringbuf is a resizing, null terminated string buffer.
13 * The buffer is reallocated as necessary.
15 * In general it is *not* OK to call these functions with a NULL pointer
16 * unless stated otherwise.
18 * If USE_UTF8 is defined, supports utf8.
22 * The stringbuf structure should not be accessed directly.
23 * Use the functions below.
26 int remaining
; /**< Allocated, but unused space */
27 int last
; /**< Index of the null terminator (and thus the length of the string) */
29 int chars
; /**< Count of characters */
31 char *data
; /**< Allocated memory containing the string or NULL for empty */
35 * Allocates and returns a new stringbuf with no elements.
37 stringbuf
*sb_alloc(void);
41 * It is OK to call this with NULL.
43 void sb_free(stringbuf
*sb
);
46 * Returns an allocated copy of the stringbuf
48 stringbuf
*sb_copy(stringbuf
*sb
);
51 * Returns the length of the buffer.
53 * Returns 0 for both a NULL buffer and an empty buffer.
55 static inline int sb_len(stringbuf
*sb
) {
60 * Returns the utf8 character length of the buffer.
62 * Returns 0 for both a NULL buffer and an empty buffer.
64 static inline int sb_chars(stringbuf
*sb
) {
73 * Appends a null terminated string to the stringbuf
75 void sb_append(stringbuf
*sb
, const char *str
);
78 * Like sb_append() except does not require a null terminated string.
79 * The length of 'str' is given as 'len'
81 * Note that in utf8 mode, characters will *not* be counted correctly
82 * if a partial utf8 sequence is added with sb_append_len()
84 void sb_append_len(stringbuf
*sb
, const char *str
, int len
);
87 * Returns a pointer to the null terminated string in the buffer.
89 * Note this pointer only remains valid until the next modification to the
92 * The returned pointer can be used to update the buffer in-place
93 * as long as care is taken to not overwrite the end of the buffer.
95 static inline char *sb_str(const stringbuf
*sb
)
101 * Inserts the given string *before* (zero-based) 'index' in the stringbuf.
102 * If index is past the end of the buffer, the string is appended,
103 * just like sb_append()
105 void sb_insert(stringbuf
*sb
, int index
, const char *str
);
108 * Delete 'len' bytes in the string at the given index.
110 * Any bytes past the end of the buffer are ignored.
111 * The buffer remains null terminated.
113 * If len is -1, deletes to the end of the buffer.
115 void sb_delete(stringbuf
*sb
, int index
, int len
);
118 * Clear to an empty buffer.
120 void sb_clear(stringbuf
*sb
);
123 * Return an allocated copy of buffer and frees 'sb'.
125 * If 'sb' is empty, returns an allocated copy of "".
127 char *sb_to_string(stringbuf
*sb
);
141 #include "stringbuf.h"
147 #define SB_INCREMENT 200
149 stringbuf
*sb_alloc(void)
151 stringbuf
*sb
= (stringbuf
*)malloc(sizeof(*sb
));
162 void sb_free(stringbuf
*sb
)
170 void sb_realloc(stringbuf
*sb
, int newlen
)
172 sb
->data
= (char *)realloc(sb
->data
, newlen
);
173 sb
->remaining
= newlen
- sb
->last
;
176 void sb_append(stringbuf
*sb
, const char *str
)
178 sb_append_len(sb
, str
, strlen(str
));
181 void sb_append_len(stringbuf
*sb
, const char *str
, int len
)
183 int utf8_strlen(const char *str
, int bytelen
);
184 if (sb
->remaining
< len
+ 1) {
185 sb_realloc(sb
, sb
->last
+ len
+ 1 + SB_INCREMENT
);
187 memcpy(sb
->data
+ sb
->last
, str
, len
);
188 sb
->data
[sb
->last
+ len
] = 0;
191 sb
->remaining
-= len
;
193 sb
->chars
+= utf8_strlen(str
, len
);
197 char *sb_to_string(stringbuf
*sb
)
199 if (sb
->data
== NULL
) {
200 /* Return an allocated empty string, not null */
204 /* Just return the data and free the stringbuf structure */
211 /* Insert and delete operations */
213 /* Moves up all the data at position 'pos' and beyond by 'len' bytes
214 * to make room for new data
216 * Note: Does *not* update sb->chars
218 static void sb_insert_space(stringbuf
*sb
, int pos
, int len
)
220 assert(pos
<= sb
->last
);
222 /* Make sure there is enough space */
223 if (sb
->remaining
< len
) {
224 sb_realloc(sb
, sb
->last
+ len
+ SB_INCREMENT
);
227 memmove(sb
->data
+ pos
+ len
, sb
->data
+ pos
, sb
->last
- pos
);
229 sb
->remaining
-= len
;
230 /* And null terminate */
231 sb
->data
[sb
->last
] = 0;
235 * Move down all the data from pos + len, effectively
236 * deleting the data at position 'pos' of length 'len'
238 static void sb_delete_space(stringbuf
*sb
, int pos
, int len
)
240 assert(pos
< sb
->last
);
241 assert(pos
+ len
<= sb
->last
);
244 sb
->chars
-= utf8_strlen(sb
->data
+ pos
, len
);
248 memmove(sb
->data
+ pos
, sb
->data
+ pos
+ len
, sb
->last
- pos
- len
);
250 sb
->remaining
+= len
;
251 /* And null terminate */
252 sb
->data
[sb
->last
] = 0;
255 void sb_insert(stringbuf
*sb
, int index
, const char *str
)
257 if (index
>= sb
->last
) {
258 /* Inserting after the end of the list appends. */
262 int len
= strlen(str
);
264 sb_insert_space(sb
, index
, len
);
265 memcpy(sb
->data
+ index
, str
, len
);
267 sb
->chars
+= utf8_strlen(str
, len
);
273 * Delete the bytes at index 'index' for length 'len'
274 * Has no effect if the index is past the end of the list.
276 void sb_delete(stringbuf
*sb
, int index
, int len
)
278 if (index
< sb
->last
) {
279 char *pos
= sb
->data
+ index
;
284 sb_delete_space(sb
, pos
- sb
->data
, len
);
288 void sb_clear(stringbuf
*sb
)
299 /* linenoise.c -- guerrilla line editing library against the idea that a
300 * line editing lib needs to be 20,000 lines of C code.
302 * You can find the latest source code at:
304 * http://github.com/msteveb/linenoise
305 * (forked from http://github.com/antirez/linenoise)
307 * Does a number of crazy assumptions that happen to be true in 99.9999% of
308 * the 2010 UNIX computers around.
310 * ------------------------------------------------------------------------
312 * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
313 * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
314 * Copyright (c) 2011, Steve Bennett <steveb at workware dot net dot au>
316 * All rights reserved.
318 * Redistribution and use in source and binary forms, with or without
319 * modification, are permitted provided that the following conditions are
322 * * Redistributions of source code must retain the above copyright
323 * notice, this list of conditions and the following disclaimer.
325 * * Redistributions in binary form must reproduce the above copyright
326 * notice, this list of conditions and the following disclaimer in the
327 * documentation and/or other materials provided with the distribution.
329 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
330 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
331 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
332 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
333 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
334 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
335 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
336 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
338 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
339 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
341 * ------------------------------------------------------------------------
344 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
345 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
352 * List of escape sequences used by this program, we do everything just
353 * a few sequences. In order to be so cheap we may have some
354 * flickering effect with some slow terminal, but the lesser sequences
355 * the more compatible.
358 * Sequence: ESC [ 0 K
359 * Effect: clear from cursor to end of line
361 * CUF (CUrsor Forward)
362 * Sequence: ESC [ n C
363 * Effect: moves cursor forward n chars
365 * CR (Carriage Return)
367 * Effect: moves cursor to column 1
369 * The following are used to clear the screen: ESC [ H ESC [ 2 J
370 * This is actually composed of two sequences:
374 * Effect: moves the cursor to upper left corner
376 * ED2 (Clear entire screen)
377 * Sequence: ESC [ 2 J
378 * Effect: clear the whole screen
380 * == For highlighting control characters, we also use the following two ==
381 * SO (enter StandOut)
382 * Sequence: ESC [ 7 m
383 * Effect: Uses some standout mode such as reverse video
386 * Sequence: ESC [ 0 m
387 * Effect: Exit standout mode
389 * == Only used if TIOCGWINSZ fails ==
390 * DSR/CPR (Report cursor position)
391 * Sequence: ESC [ 6 n
392 * Effect: reports current cursor position as ESC [ NNN ; MMM R
394 * == Only used in multiline mode ==
396 * Sequence: ESC [ n A
397 * Effect: moves cursor up n chars.
400 * Sequence: ESC [ n B
401 * Effect: moves cursor down n chars.
405 * If __MINGW32__ is defined, the win32 console API is used.
406 * This could probably be made to work for the msvc compiler too.
407 * This support based in part on work by Jon Griffiths.
410 #ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */
413 #define USE_WINCONSOLE
415 #define HAVE_UNISTD_H
417 /* Microsoft headers don't like old POSIX names */
418 #define strdup _strdup
419 #define snprintf _snprintf
423 #include <sys/ioctl.h>
426 #define HAVE_UNISTD_H
440 #include <sys/types.h>
442 #include "linenoise.h"
444 #include "stringbuf.h"
448 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
450 #define ctrl(C) ((C) - '@')
452 /* Use -ve numbers here to co-exist with normal unicode chars */
455 /* don't use -1 here since that indicates error */
460 SPECIAL_DELETE
= -24,
463 SPECIAL_INSERT
= -27,
464 SPECIAL_PAGE_UP
= -28,
465 SPECIAL_PAGE_DOWN
= -29,
467 /* Some handy names for other special keycodes */
472 static int history_max_len
= LINENOISE_DEFAULT_HISTORY_MAX_LEN
;
473 static int history_len
= 0;
474 static char **history
= NULL
;
476 /* Structure to contain the status of the current (being edited) line */
478 stringbuf
*buf
; /* Current buffer. Always null terminated */
479 int pos
; /* Cursor position, measured in chars */
480 int cols
; /* Size of the window, in chars */
481 int nrows
; /* How many rows are being used in multiline mode (>= 1) */
482 int rpos
; /* The current row containing the cursor - multiline mode only */
484 stringbuf
*capture
; /* capture buffer, or NULL for none. Always null terminated */
485 stringbuf
*output
; /* used only during refreshLine() - output accumulator */
486 #if defined(USE_TERMIOS)
487 int fd
; /* Terminal fd */
488 #elif defined(USE_WINCONSOLE)
489 HANDLE outh
; /* Console output handle */
490 HANDLE inh
; /* Console input handle */
491 int rows
; /* Screen rows */
492 int x
; /* Current column during output */
493 int y
; /* Current row */
495 #define UBUF_MAX_CHARS 132
496 WORD ubuf
[UBUF_MAX_CHARS
+ 1]; /* Accumulates utf16 output - one extra for final surrogate pairs */
497 int ubuflen
; /* length used in ubuf */
498 int ubufcols
; /* how many columns are represented by the chars in ubuf? */
503 static int fd_read(struct current
*current
);
504 static int getWindowSize(struct current
*current
);
505 static void cursorDown(struct current
*current
, int n
);
506 static void cursorUp(struct current
*current
, int n
);
507 static void eraseEol(struct current
*current
);
508 static void refreshLine(struct current
*current
);
509 static void refreshLineAlt(struct current
*current
, const char *prompt
, const char *buf
, int cursor_pos
);
510 static void setCursorPos(struct current
*current
, int x
);
511 static void setOutputHighlight(struct current
*current
, const int *props
, int nprops
);
512 static void set_current(struct current
*current
, const char *str
);
514 void linenoiseHistoryFree(void) {
518 for (j
= 0; j
< history_len
; j
++)
528 EP_START
, /* looking for ESC */
529 EP_ESC
, /* looking for [ */
530 EP_DIGITS
, /* parsing digits */
531 EP_PROPS
, /* parsing digits or semicolons */
533 EP_ERROR
, /* error */
535 int props
[5]; /* properties are stored here */
536 int maxprops
; /* size of the props[] array */
537 int numprops
; /* number of properties found */
538 int termchar
; /* terminator char, or 0 for any alpha */
539 int current
; /* current (partial) property value */
543 * Initialise the escape sequence parser at *parser.
545 * If termchar is 0 any alpha char terminates ok. Otherwise only the given
546 * char terminates successfully.
547 * Run the parser state machine with calls to parseEscapeSequence() for each char.
549 static void initParseEscapeSeq(struct esc_parser
*parser
, int termchar
)
551 parser
->state
= EP_START
;
552 parser
->maxprops
= sizeof(parser
->props
) / sizeof(*parser
->props
);
553 parser
->numprops
= 0;
555 parser
->termchar
= termchar
;
559 * Pass character 'ch' into the state machine to parse:
560 * 'ESC' '[' <digits> (';' <digits>)* <termchar>
562 * The first character must be ESC.
563 * Returns the current state. The state machine is done when it returns either EP_END
566 * On EP_END, the "property/attribute" values can be read from parser->props[]
567 * of length parser->numprops.
569 static int parseEscapeSequence(struct esc_parser
*parser
, int ch
)
571 switch (parser
->state
) {
573 parser
->state
= (ch
== '\x1b') ? EP_ESC
: EP_ERROR
;
576 parser
->state
= (ch
== '[') ? EP_DIGITS
: EP_ERROR
;
580 parser
->state
= EP_DIGITS
;
582 if (parser
->numprops
+ 1 < parser
->maxprops
) {
583 parser
->props
[parser
->numprops
++] = parser
->current
;
590 if (ch
>= '0' && ch
<= '9') {
591 parser
->current
= parser
->current
* 10 + (ch
- '0');
592 parser
->state
= EP_PROPS
;
595 /* must be terminator */
596 if (parser
->termchar
!= ch
) {
597 if (parser
->termchar
!= 0 || !((ch
>= 'A' && ch
<= 'Z') || (ch
>= 'a' && ch
<= 'z'))) {
598 parser
->state
= EP_ERROR
;
602 parser
->state
= EP_END
;
605 parser
->state
= EP_ERROR
;
610 return parser
->state
;
613 /*#define DEBUG_REFRESHLINE*/
615 #ifdef DEBUG_REFRESHLINE
616 #define DRL(ARGS...) fprintf(dfh, ARGS)
619 static void DRL_CHAR(int ch
)
622 DRL("^%c", ch
+ '@');
631 static void DRL_STR(const char *str
)
635 int n
= utf8_tounicode(str
, &ch
);
646 #if defined(USE_WINCONSOLE)
647 #include "linenoise-win32.c"
650 #if defined(USE_TERMIOS)
651 static void linenoiseAtExit(void);
652 static struct termios orig_termios
; /* in order to restore at exit */
653 static int rawmode
= 0; /* for atexit() function to check if restore is needed*/
654 static int atexit_registered
= 0; /* register atexit just 1 time */
656 static const char *unsupported_term
[] = {"dumb","cons25","emacs",NULL
};
658 static int isUnsupportedTerm(void) {
659 char *term
= getenv("TERM");
663 for (j
= 0; unsupported_term
[j
]; j
++) {
664 if (strcmp(term
, unsupported_term
[j
]) == 0) {
672 static int enableRawMode(struct current
*current
) {
675 current
->fd
= STDIN_FILENO
;
678 if (!isatty(current
->fd
) || isUnsupportedTerm() ||
679 tcgetattr(current
->fd
, &orig_termios
) == -1) {
685 if (!atexit_registered
) {
686 atexit(linenoiseAtExit
);
687 atexit_registered
= 1;
690 raw
= orig_termios
; /* modify the original mode */
691 /* input modes: no break, no CR to NL, no parity check, no strip char,
692 * no start/stop output control. */
693 raw
.c_iflag
&= ~(BRKINT
| ICRNL
| INPCK
| ISTRIP
| IXON
);
694 /* output modes - actually, no need to disable post processing */
695 /*raw.c_oflag &= ~(OPOST);*/
696 /* control modes - set 8 bit chars */
697 raw
.c_cflag
|= (CS8
);
698 /* local modes - choing off, canonical off, no extended functions,
699 * no signal chars (^Z,^C) */
700 raw
.c_lflag
&= ~(ECHO
| ICANON
| IEXTEN
| ISIG
);
701 /* control chars - set return condition: min number of bytes and timer.
702 * We want read to return every single byte, without timeout. */
703 raw
.c_cc
[VMIN
] = 1; raw
.c_cc
[VTIME
] = 0; /* 1 byte, no timer */
705 /* put terminal in raw mode after flushing */
706 if (tcsetattr(current
->fd
,TCSADRAIN
,&raw
) < 0) {
713 static void disableRawMode(struct current
*current
) {
714 /* Don't even check the return value as it's too late. */
715 if (rawmode
&& tcsetattr(current
->fd
,TCSADRAIN
,&orig_termios
) != -1)
719 /* At exit we'll try to fix the terminal to the initial conditions. */
720 static void linenoiseAtExit(void) {
722 tcsetattr(STDIN_FILENO
, TCSADRAIN
, &orig_termios
);
724 linenoiseHistoryFree();
727 /* gcc/glibc insists that we care about the return code of write!
728 * Clarification: This means that a void-cast like "(void) (EXPR)"
731 #define IGNORE_RC(EXPR) if (EXPR) {}
734 * Output bytes directly, or accumulate output (if current->output is set)
736 static void outputChars(struct current
*current
, const char *buf
, int len
)
741 if (current
->output
) {
742 sb_append_len(current
->output
, buf
, len
);
745 IGNORE_RC(write(current
->fd
, buf
, len
));
749 /* Like outputChars, but using printf-style formatting
751 static void outputFormatted(struct current
*current
, const char *format
, ...)
757 va_start(args
, format
);
758 n
= vsnprintf(buf
, sizeof(buf
), format
, args
);
759 /* This will never happen because we are sure to use outputFormatted() only for short sequences */
760 assert(n
< (int)sizeof(buf
));
762 outputChars(current
, buf
, n
);
765 static void cursorToLeft(struct current
*current
)
767 outputChars(current
, "\r", -1);
770 static void setOutputHighlight(struct current
*current
, const int *props
, int nprops
)
772 outputChars(current
, "\x1b[", -1);
774 outputFormatted(current
, "%d%c", *props
, (nprops
== 0) ? 'm' : ';');
779 static void eraseEol(struct current
*current
)
781 outputChars(current
, "\x1b[0K", -1);
784 static void setCursorPos(struct current
*current
, int x
)
787 cursorToLeft(current
);
790 outputFormatted(current
, "\r\x1b[%dC", x
);
794 static void cursorUp(struct current
*current
, int n
)
797 outputFormatted(current
, "\x1b[%dA", n
);
801 static void cursorDown(struct current
*current
, int n
)
804 outputFormatted(current
, "\x1b[%dB", n
);
808 void linenoiseClearScreen(void)
810 write(STDOUT_FILENO
, "\x1b[H\x1b[2J", 7);
814 * Reads a char from 'fd', waiting at most 'timeout' milliseconds.
816 * A timeout of -1 means to wait forever.
818 * Returns -1 if no char is received within the time or an error occurs.
820 static int fd_read_char(int fd
, int timeout
)
828 if (poll(&p
, 1, timeout
) == 0) {
832 if (read(fd
, &c
, 1) != 1) {
839 * Reads a complete utf-8 character
840 * and returns the unicode value, or -1 on error.
842 static int fd_read(struct current
*current
)
845 char buf
[MAX_UTF8_LEN
];
850 if (read(current
->fd
, &buf
[0], 1) != 1) {
853 n
= utf8_charlen(buf
[0]);
857 for (i
= 1; i
< n
; i
++) {
858 if (read(current
->fd
, &buf
[i
], 1) != 1) {
862 /* decode and return the character */
863 utf8_tounicode(buf
, &c
);
866 return fd_read_char(current
->fd
, -1);
872 * Stores the current cursor column in '*cols'.
873 * Returns 1 if OK, or 0 if failed to determine cursor pos.
875 static int queryCursor(struct current
*current
, int* cols
)
877 struct esc_parser parser
;
880 /* Should not be buffering this output, it needs to go immediately */
881 assert(current
->output
== NULL
);
883 /* control sequence - report cursor location */
884 outputChars(current
, "\x1b[6n", -1);
886 /* Parse the response: ESC [ rows ; cols R */
887 initParseEscapeSeq(&parser
, 'R');
888 while ((ch
= fd_read_char(current
->fd
, 100)) > 0) {
889 switch (parseEscapeSequence(&parser
, ch
)) {
893 if (parser
.numprops
== 2 && parser
.props
[1] < 1000) {
894 *cols
= parser
.props
[1];
908 * Updates current->cols with the current window size (width)
910 static int getWindowSize(struct current
*current
)
914 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) == 0 && ws
.ws_col
!= 0) {
915 current
->cols
= ws
.ws_col
;
919 /* Failed to query the window size. Perhaps we are on a serial terminal.
920 * Try to query the width by sending the cursor as far to the right
921 * and reading back the cursor position.
922 * Note that this is only done once per call to linenoise rather than
923 * every time the line is refreshed for efficiency reasons.
925 * In more detail, we:
926 * (a) request current cursor position,
927 * (b) move cursor far right,
928 * (c) request cursor position again,
929 * (d) at last move back to the old position.
930 * This gives us the width without messing with the externally
931 * visible cursor position.
934 if (current
->cols
== 0) {
937 /* If anything fails => default 80 */
941 if (queryCursor (current
, &here
)) {
943 setCursorPos(current
, 999);
945 /* (c). Note: If (a) succeeded, then (c) should as well.
946 * For paranoia we still check and have a fallback action
947 * for (d) in case of failure..
949 if (queryCursor (current
, ¤t
->cols
)) {
950 /* (d) Reset the cursor back to the original location. */
951 if (current
->cols
> here
) {
952 setCursorPos(current
, here
);
962 * If CHAR_ESCAPE was received, reads subsequent
963 * chars to determine if this is a known special key.
965 * Returns SPECIAL_NONE if unrecognised, or -1 if EOF.
967 * If no additional char is received within a short time,
968 * CHAR_ESCAPE is returned.
970 static int check_special(int fd
)
972 int c
= fd_read_char(fd
, 50);
979 c2
= fd_read_char(fd
, 50);
983 if (c
== '[' || c
== 'O') {
984 /* Potential arrow key */
991 return SPECIAL_RIGHT
;
1000 if (c
== '[' && c2
>= '1' && c2
<= '8') {
1001 /* extended escape */
1002 c
= fd_read_char(fd
, 50);
1006 return SPECIAL_INSERT
;
1008 return SPECIAL_DELETE
;
1010 return SPECIAL_PAGE_UP
;
1012 return SPECIAL_PAGE_DOWN
;
1014 return SPECIAL_HOME
;
1019 while (c
!= -1 && c
!= '~') {
1020 /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */
1021 c
= fd_read_char(fd
, 50);
1025 return SPECIAL_NONE
;
1029 static void clearOutputHighlight(struct current
*current
)
1031 int nohighlight
= 0;
1032 setOutputHighlight(current
, &nohighlight
, 1);
1035 static void outputControlChar(struct current
*current
, char ch
)
1038 setOutputHighlight(current
, &reverse
, 1);
1039 outputChars(current
, "^", 1);
1040 outputChars(current
, &ch
, 1);
1041 clearOutputHighlight(current
);
1044 #ifndef utf8_getchars
1045 static int utf8_getchars(char *buf
, int c
)
1048 return utf8_fromunicode(buf
, c
);
1057 * Returns the unicode character at the given offset,
1060 static int get_char(struct current
*current
, int pos
)
1062 if (pos
>= 0 && pos
< sb_chars(current
->buf
)) {
1064 int i
= utf8_index(sb_str(current
->buf
), pos
);
1065 (void)utf8_tounicode(sb_str(current
->buf
) + i
, &c
);
1071 static int char_display_width(int ch
)
1074 /* control chars take two positions */
1078 return utf8_width(ch
);
1082 #ifndef NO_COMPLETION
1083 static linenoiseCompletionCallback
*completionCallback
= NULL
;
1084 static void *completionUserdata
= NULL
;
1085 static int showhints
= 1;
1086 static linenoiseHintsCallback
*hintsCallback
= NULL
;
1087 static linenoiseFreeHintsCallback
*freeHintsCallback
= NULL
;
1088 static void *hintsUserdata
= NULL
;
1090 static void beep() {
1092 fprintf(stderr
, "\x7");
1097 static void freeCompletions(linenoiseCompletions
*lc
) {
1099 for (i
= 0; i
< lc
->len
; i
++)
1104 static int completeLine(struct current
*current
) {
1105 linenoiseCompletions lc
= { 0, NULL
};
1108 completionCallback(sb_str(current
->buf
),&lc
,completionUserdata
);
1112 size_t stop
= 0, i
= 0;
1115 /* Show completion or original buffer */
1117 int chars
= utf8_strlen(lc
.cvec
[i
], -1);
1118 refreshLineAlt(current
, current
->prompt
, lc
.cvec
[i
], chars
);
1120 refreshLine(current
);
1123 c
= fd_read(current
);
1129 case '\t': /* tab */
1130 i
= (i
+1) % (lc
.len
+1);
1131 if (i
== lc
.len
) beep();
1133 case CHAR_ESCAPE
: /* escape */
1134 /* Re-show original buffer */
1136 refreshLine(current
);
1141 /* Update buffer and return */
1143 set_current(current
,lc
.cvec
[i
]);
1151 freeCompletions(&lc
);
1152 return c
; /* Return last read character */
1155 /* Register a callback function to be called for tab-completion.
1156 Returns the prior callback so that the caller may (if needed)
1157 restore it when done. */
1158 linenoiseCompletionCallback
* linenoiseSetCompletionCallback(linenoiseCompletionCallback
*fn
, void *userdata
) {
1159 linenoiseCompletionCallback
* old
= completionCallback
;
1160 completionCallback
= fn
;
1161 completionUserdata
= userdata
;
1165 void linenoiseAddCompletion(linenoiseCompletions
*lc
, const char *str
) {
1166 lc
->cvec
= (char **)realloc(lc
->cvec
,sizeof(char*)*(lc
->len
+1));
1167 lc
->cvec
[lc
->len
++] = strdup(str
);
1170 void linenoiseSetHintsCallback(linenoiseHintsCallback
*callback
, void *userdata
)
1172 hintsCallback
= callback
;
1173 hintsUserdata
= userdata
;
1176 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback
*callback
)
1178 freeHintsCallback
= callback
;
1184 static const char *reduceSingleBuf(const char *buf
, int availcols
, int *cursor_pos
)
1186 /* We have availcols columns available.
1187 * If necessary, strip chars off the front of buf until *cursor_pos
1188 * fits within availcols
1192 int new_cursor_pos
= *cursor_pos
;
1193 const char *pt
= buf
;
1195 DRL("reduceSingleBuf: availcols=%d, cursor_pos=%d\n", availcols
, *cursor_pos
);
1199 int n
= utf8_tounicode(pt
, &ch
);
1202 needcols
+= char_display_width(ch
);
1204 /* If we need too many cols, strip
1205 * chars off the front of buf to make it fit.
1206 * We keep 3 extra cols to the right of the cursor.
1207 * 2 for possible wide chars, 1 for the last column that
1210 while (needcols
>= availcols
- 3) {
1211 n
= utf8_tounicode(buf
, &ch
);
1213 needcols
-= char_display_width(ch
);
1216 /* and adjust the apparent cursor position */
1220 /* can't remove more than this */
1225 if (pos
++ == *cursor_pos
) {
1232 DRL("\nafter reduce, needcols=%d, new_cursor_pos=%d\n", needcols
, new_cursor_pos
);
1234 /* Done, now new_cursor_pos contains the adjusted cursor position
1235 * and buf points to he adjusted start
1237 *cursor_pos
= new_cursor_pos
;
1241 static int mlmode
= 0;
1243 void linenoiseSetMultiLine(int enableml
)
1248 /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
1249 * to the right of the prompt. */
1250 static void refreshShowHints(struct current
*current
, const char *buf
, int availcols
) {
1251 if (showhints
&& hintsCallback
&& availcols
> 0) {
1254 char *hint
= hintsCallback(buf
, &color
, &bold
, hintsUserdata
);
1257 if (bold
== 1 && color
== -1) color
= 37;
1258 if (bold
|| color
> 0) {
1259 int props
[3] = { bold
, color
, 49 }; /* bold, color, fgnormal */
1260 setOutputHighlight(current
, props
, 3);
1262 DRL("<hint bold=%d,color=%d>", bold
, color
);
1266 int n
= utf8_tounicode(pt
, &ch
);
1267 int width
= char_display_width(ch
);
1269 if (width
>= availcols
) {
1276 outputChars(current
, pt
, n
);
1279 if (bold
|| color
> 0) {
1280 clearOutputHighlight(current
);
1282 /* Call the function to free the hint returned. */
1283 if (freeHintsCallback
) freeHintsCallback(hint
, hintsUserdata
);
1289 static void refreshStart(struct current
*current
)
1291 /* We accumulate all output here */
1292 assert(current
->output
== NULL
);
1293 current
->output
= sb_alloc();
1296 static void refreshEnd(struct current
*current
)
1298 /* Output everything at once */
1299 IGNORE_RC(write(current
->fd
, sb_str(current
->output
), sb_len(current
->output
)));
1300 sb_free(current
->output
);
1301 current
->output
= NULL
;
1304 static void refreshStartChars(struct current
*current
)
1308 static void refreshNewline(struct current
*current
)
1311 outputChars(current
, "\n", 1);
1314 static void refreshEndChars(struct current
*current
)
1319 static void refreshLineAlt(struct current
*current
, const char *prompt
, const char *buf
, int cursor_pos
)
1330 struct esc_parser parser
;
1332 #ifdef DEBUG_REFRESHLINE
1333 dfh
= fopen("linenoise.debuglog", "a");
1336 /* Should intercept SIGWINCH. For now, just get the size every time */
1337 getWindowSize(current
);
1339 refreshStart(current
);
1341 DRL("wincols=%d, cursor_pos=%d, nrows=%d, rpos=%d\n", current
->cols
, cursor_pos
, current
->nrows
, current
->rpos
);
1343 /* Here is the plan:
1344 * (a) move the the bottom row, going down the appropriate number of lines
1345 * (b) move to beginning of line and erase the current line
1346 * (c) go up one line and do the same, until we have erased up to the first row
1347 * (d) output the prompt, counting cols and rows, taking into account escape sequences
1348 * (e) output the buffer, counting cols and rows
1349 * (e') when we hit the current pos, save the cursor position
1350 * (f) move the cursor to the saved cursor position
1351 * (g) save the current cursor row and number of rows
1354 /* (a) - The cursor is currently at row rpos */
1355 cursorDown(current
, current
->nrows
- current
->rpos
- 1);
1356 DRL("<cud=%d>", current
->nrows
- current
->rpos
- 1);
1358 /* (b), (c) - Erase lines upwards until we get to the first row */
1359 for (i
= 0; i
< current
->nrows
; i
++) {
1362 cursorUp(current
, 1);
1365 cursorToLeft(current
);
1370 /* (d) First output the prompt. control sequences don't take up display space */
1372 displaycol
= 0; /* current display column */
1373 displayrow
= 0; /* current display row */
1376 refreshStartChars(current
);
1381 int n
= utf8_tounicode(pt
, &ch
);
1383 if (visible
&& ch
== CHAR_ESCAPE
) {
1384 /* The start of an escape sequence, so not visible */
1386 initParseEscapeSeq(&parser
, 'm');
1387 DRL("<esc-seq-start>");
1390 if (ch
== '\n' || ch
== '\r') {
1391 /* treat both CR and NL the same and force wrap */
1392 refreshNewline(current
);
1397 width
= visible
* utf8_width(ch
);
1399 displaycol
+= width
;
1400 if (displaycol
>= current
->cols
) {
1401 /* need to wrap to the next line because of newline or if it doesn't fit
1402 * XXX this is a problem in single line mode
1404 refreshNewline(current
);
1410 #ifdef USE_WINCONSOLE
1412 outputChars(current
, pt
, n
);
1415 outputChars(current
, pt
, n
);
1421 switch (parseEscapeSequence(&parser
, ch
)) {
1424 setOutputHighlight(current
, parser
.props
, parser
.numprops
);
1425 DRL("<esc-seq-end,numprops=%d>", parser
.numprops
);
1428 DRL("<esc-seq-err>");
1435 /* Now we are at the first line with all lines erased */
1436 DRL("\nafter prompt: displaycol=%d, displayrow=%d\n", displaycol
, displayrow
);
1439 /* (e) output the buffer, counting cols and rows */
1441 /* In this mode we may need to trim chars from the start of the buffer until the
1442 * cursor fits in the window.
1444 pt
= reduceSingleBuf(buf
, current
->cols
- displaycol
, &cursor_pos
);
1455 int n
= utf8_tounicode(pt
, &ch
);
1456 int width
= char_display_width(ch
);
1458 if (currentpos
== cursor_pos
) {
1459 /* (e') wherever we output this character is where we want the cursor */
1463 if (displaycol
+ width
>= current
->cols
) {
1465 /* In single line mode stop once we print as much as we can on one line */
1469 /* need to wrap to the next line since it doesn't fit */
1470 refreshNewline(current
);
1475 if (notecursor
== 1) {
1476 /* (e') Save this position as the current cursor position */
1477 cursorcol
= displaycol
;
1478 cursorrow
= displayrow
;
1483 displaycol
+= width
;
1486 outputControlChar(current
, ch
+ '@');
1489 outputChars(current
, pt
, n
);
1493 DRL("<w=%d>", width
);
1500 /* If we didn't see the cursor, it is at the current location */
1503 cursorcol
= displaycol
;
1504 cursorrow
= displayrow
;
1507 DRL("\nafter buf: displaycol=%d, displayrow=%d, cursorcol=%d, cursorrow=%d\n\n", displaycol
, displayrow
, cursorcol
, cursorrow
);
1509 /* (f) show hints */
1510 refreshShowHints(current
, buf
, current
->cols
- displaycol
);
1512 refreshEndChars(current
);
1514 /* (g) move the cursor to the correct place */
1515 cursorUp(current
, displayrow
- cursorrow
);
1516 setCursorPos(current
, cursorcol
);
1518 /* (h) Update the number of rows if larger, but never reduce this */
1519 if (displayrow
>= current
->nrows
) {
1520 current
->nrows
= displayrow
+ 1;
1522 /* And remember the row that the cursor is on */
1523 current
->rpos
= cursorrow
;
1525 refreshEnd(current
);
1527 #ifdef DEBUG_REFRESHLINE
1532 static void refreshLine(struct current
*current
)
1534 refreshLineAlt(current
, current
->prompt
, sb_str(current
->buf
), current
->pos
);
1537 static void set_current(struct current
*current
, const char *str
)
1539 sb_clear(current
->buf
);
1540 sb_append(current
->buf
, str
);
1541 current
->pos
= sb_chars(current
->buf
);
1545 * Removes the char at 'pos'.
1547 * Returns 1 if the line needs to be refreshed, 2 if not
1548 * and 0 if nothing was removed
1550 static int remove_char(struct current
*current
, int pos
)
1552 if (pos
>= 0 && pos
< sb_chars(current
->buf
)) {
1553 int offset
= utf8_index(sb_str(current
->buf
), pos
);
1554 int nbytes
= utf8_index(sb_str(current
->buf
) + offset
, 1);
1556 /* Note that we no longer try to optimise the remove-at-end case
1557 * since control characters and wide characters mess
1558 * up the simple count
1560 sb_delete(current
->buf
, offset
, nbytes
);
1562 if (current
->pos
> pos
) {
1571 * Insert 'ch' at position 'pos'
1573 * Returns 1 if the line needs to be refreshed, 2 if not
1574 * and 0 if nothing was inserted (no room)
1576 static int insert_char(struct current
*current
, int pos
, int ch
)
1578 if (pos
>= 0 && pos
<= sb_chars(current
->buf
)) {
1579 char buf
[MAX_UTF8_LEN
+ 1];
1580 int offset
= utf8_index(sb_str(current
->buf
), pos
);
1581 int n
= utf8_getchars(buf
, ch
);
1583 /* null terminate since sb_insert() requires it */
1586 /* Optimisation removed - see reason in remove_char() */
1588 sb_insert(current
->buf
, offset
, buf
);
1589 if (current
->pos
>= pos
) {
1598 * Captures up to 'n' characters starting at 'pos' for the cut buffer.
1600 * This replaces any existing characters in the cut buffer.
1602 static void capture_chars(struct current
*current
, int pos
, int nchars
)
1604 if (pos
>= 0 && (pos
+ nchars
- 1) < sb_chars(current
->buf
)) {
1605 int offset
= utf8_index(sb_str(current
->buf
), pos
);
1606 int nbytes
= utf8_index(sb_str(current
->buf
) + offset
, nchars
);
1609 if (current
->capture
) {
1610 sb_clear(current
->capture
);
1613 current
->capture
= sb_alloc();
1615 sb_append_len(current
->capture
, sb_str(current
->buf
) + offset
, nbytes
);
1621 * Removes up to 'n' characters at cursor position 'pos'.
1623 * Returns 0 if no chars were removed or non-zero otherwise.
1625 static int remove_chars(struct current
*current
, int pos
, int n
)
1629 /* First save any chars which will be removed */
1630 capture_chars(current
, pos
, n
);
1632 while (n
-- && remove_char(current
, pos
)) {
1638 * Inserts the characters (string) 'chars' at the cursor position 'pos'.
1640 * Returns 0 if no chars were inserted or non-zero otherwise.
1642 static int insert_chars(struct current
*current
, int pos
, const char *chars
)
1648 int n
= utf8_tounicode(chars
, &ch
);
1649 if (insert_char(current
, pos
, ch
) == 0) {
1660 * Returns the keycode to process, or 0 if none.
1662 static int reverseIncrementalSearch(struct current
*current
)
1664 /* Display the reverse-i-search prompt and process chars */
1669 int searchpos
= history_len
- 1;
1675 const char *p
= NULL
;
1679 snprintf(rprompt
, sizeof(rprompt
), "(reverse-i-search)'%s': ", rbuf
);
1680 refreshLineAlt(current
, rprompt
, sb_str(current
->buf
), current
->pos
);
1681 c
= fd_read(current
);
1682 if (c
== ctrl('H') || c
== CHAR_DELETE
) {
1684 int p
= utf8_index(rbuf
, --rchars
);
1686 rlen
= strlen(rbuf
);
1691 if (c
== CHAR_ESCAPE
) {
1692 c
= check_special(current
->fd
);
1695 if (c
== ctrl('P') || c
== SPECIAL_UP
) {
1696 /* Search for the previous (earlier) match */
1697 if (searchpos
> 0) {
1702 else if (c
== ctrl('N') || c
== SPECIAL_DOWN
) {
1703 /* Search for the next (later) match */
1704 if (searchpos
< history_len
) {
1710 else if (c
>= ' ') {
1711 /* >= here to allow for null terminator */
1712 if (rlen
>= (int)sizeof(rbuf
) - MAX_UTF8_LEN
) {
1716 n
= utf8_getchars(rbuf
+ rlen
, c
);
1721 /* Adding a new char resets the search location */
1722 searchpos
= history_len
- 1;
1725 /* Exit from incremental search mode */
1729 /* Now search through the history for a match */
1730 for (; searchpos
>= 0 && searchpos
< history_len
; searchpos
+= searchdir
) {
1731 p
= strstr(history
[searchpos
], rbuf
);
1734 if (skipsame
&& strcmp(history
[searchpos
], sb_str(current
->buf
)) == 0) {
1735 /* But it is identical, so skip it */
1738 /* Copy the matching line and set the cursor position */
1739 set_current(current
,history
[searchpos
]);
1740 current
->pos
= utf8_strlen(history
[searchpos
], p
- history
[searchpos
]);
1745 /* No match, so don't add it */
1751 if (c
== ctrl('G') || c
== ctrl('C')) {
1752 /* ctrl-g terminates the search with no effect */
1753 set_current(current
, "");
1756 else if (c
== ctrl('J')) {
1757 /* ctrl-j terminates the search leaving the buffer in place */
1761 /* Go process the char normally */
1762 refreshLine(current
);
1766 static int linenoiseEdit(struct current
*current
) {
1767 int history_index
= 0;
1769 /* The latest history entry is always our current buffer, that
1770 * initially is just an empty string. */
1771 linenoiseHistoryAdd("");
1773 set_current(current
, "");
1774 refreshLine(current
);
1778 int c
= fd_read(current
);
1780 #ifndef NO_COMPLETION
1781 /* Only autocomplete when the callback is set. It returns < 0 when
1782 * there was an error reading from fd. Otherwise it will return the
1783 * character that should be handled next. */
1784 if (c
== '\t' && current
->pos
== sb_chars(current
->buf
) && completionCallback
!= NULL
) {
1785 c
= completeLine(current
);
1788 if (c
== ctrl('R')) {
1789 /* reverse incremental search will provide an alternative keycode or 0 for none */
1790 c
= reverseIncrementalSearch(current
);
1791 /* go on to process the returned char normally */
1795 if (c
== CHAR_ESCAPE
) { /* escape sequence */
1796 c
= check_special(current
->fd
);
1800 /* Return on errors */
1801 return sb_len(current
->buf
);
1807 case '\r': /* enter */
1809 free(history
[history_len
]);
1810 current
->pos
= sb_chars(current
->buf
);
1811 if (mlmode
|| hintsCallback
) {
1813 refreshLine(current
);
1816 return sb_len(current
->buf
);
1817 case ctrl('C'): /* ctrl-c */
1820 case ctrl('Z'): /* ctrl-z */
1822 /* send ourselves SIGSUSP */
1823 disableRawMode(current
);
1826 enableRawMode(current
);
1827 refreshLine(current
);
1830 case CHAR_DELETE
: /* backspace */
1832 if (remove_char(current
, current
->pos
- 1) == 1) {
1833 refreshLine(current
);
1836 case ctrl('D'): /* ctrl-d */
1837 if (sb_len(current
->buf
) == 0) {
1838 /* Empty line, so EOF */
1840 free(history
[history_len
]);
1843 /* Otherwise fall through to delete char to right of cursor */
1844 case SPECIAL_DELETE
:
1845 if (remove_char(current
, current
->pos
) == 1) {
1846 refreshLine(current
);
1849 case SPECIAL_INSERT
:
1850 /* Ignore. Expansion Hook.
1851 * Future possibility: Toggle Insert/Overwrite Modes
1854 case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */
1855 /* eat any spaces on the left */
1857 int pos
= current
->pos
;
1858 while (pos
> 0 && get_char(current
, pos
- 1) == ' ') {
1862 /* now eat any non-spaces on the left */
1863 while (pos
> 0 && get_char(current
, pos
- 1) != ' ') {
1867 if (remove_chars(current
, pos
, current
->pos
- pos
)) {
1868 refreshLine(current
);
1872 case ctrl('T'): /* ctrl-t */
1873 if (current
->pos
> 0 && current
->pos
<= sb_chars(current
->buf
)) {
1874 /* If cursor is at end, transpose the previous two chars */
1875 int fixer
= (current
->pos
== sb_chars(current
->buf
));
1876 c
= get_char(current
, current
->pos
- fixer
);
1877 remove_char(current
, current
->pos
- fixer
);
1878 insert_char(current
, current
->pos
- 1, c
);
1879 refreshLine(current
);
1882 case ctrl('V'): /* ctrl-v */
1883 /* Insert the ^V first */
1884 if (insert_char(current
, current
->pos
, c
)) {
1885 refreshLine(current
);
1886 /* Now wait for the next char. Can insert anything except \0 */
1887 c
= fd_read(current
);
1889 /* Remove the ^V first */
1890 remove_char(current
, current
->pos
- 1);
1892 /* Insert the actual char, can't be error or null */
1893 insert_char(current
, current
->pos
, c
);
1895 refreshLine(current
);
1900 if (current
->pos
> 0) {
1902 refreshLine(current
);
1907 if (current
->pos
< sb_chars(current
->buf
)) {
1909 refreshLine(current
);
1912 case SPECIAL_PAGE_UP
:
1913 dir
= history_len
- history_index
- 1; /* move to start of history */
1914 goto history_navigation
;
1915 case SPECIAL_PAGE_DOWN
:
1916 dir
= -history_index
; /* move to 0 == end of history, i.e. current */
1917 goto history_navigation
;
1921 goto history_navigation
;
1925 if (history_len
> 1) {
1926 /* Update the current history entry before to
1927 * overwrite it with tne next one. */
1928 free(history
[history_len
- 1 - history_index
]);
1929 history
[history_len
- 1 - history_index
] = strdup(sb_str(current
->buf
));
1930 /* Show the new entry */
1931 history_index
+= dir
;
1932 if (history_index
< 0) {
1935 } else if (history_index
>= history_len
) {
1936 history_index
= history_len
- 1;
1939 set_current(current
, history
[history_len
- 1 - history_index
]);
1940 refreshLine(current
);
1943 case ctrl('A'): /* Ctrl+a, go to the start of the line */
1946 refreshLine(current
);
1948 case ctrl('E'): /* ctrl+e, go to the end of the line */
1950 current
->pos
= sb_chars(current
->buf
);
1951 refreshLine(current
);
1953 case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */
1954 if (remove_chars(current
, 0, current
->pos
)) {
1955 refreshLine(current
);
1958 case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */
1959 if (remove_chars(current
, current
->pos
, sb_chars(current
->buf
) - current
->pos
)) {
1960 refreshLine(current
);
1963 case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */
1964 if (current
->capture
&& insert_chars(current
, current
->pos
, sb_str(current
->capture
))) {
1965 refreshLine(current
);
1968 case ctrl('L'): /* Ctrl+L, clear screen */
1969 linenoiseClearScreen();
1970 /* Force recalc of window size for serial terminals */
1973 refreshLine(current
);
1976 /* Only tab is allowed without ^V */
1977 if (c
== '\t' || c
>= ' ') {
1978 if (insert_char(current
, current
->pos
, c
) == 1) {
1979 refreshLine(current
);
1985 return sb_len(current
->buf
);
1988 int linenoiseColumns(void)
1990 struct current current
;
1991 enableRawMode (¤t
);
1992 getWindowSize (¤t
);
1993 disableRawMode (¤t
);
1994 return current
.cols
;
1998 * Reads a line from the file handle (without the trailing NL or CRNL)
1999 * and returns it in a stringbuf.
2000 * Returns NULL if no characters are read before EOF or error.
2002 * Note that the character count will *not* be correct for lines containing
2003 * utf8 sequences. Do not rely on the character count.
2005 static stringbuf
*sb_getline(FILE *fh
)
2007 stringbuf
*sb
= sb_alloc();
2011 while ((c
= getc(fh
)) != EOF
) {
2018 if (c
== '\n' || c
== '\r') {
2022 /* ignore the effect of character count for partial utf8 sequences */
2023 sb_append_len(sb
, &ch
, 1);
2032 char *linenoise(const char *prompt
)
2035 struct current current
;
2038 memset(¤t
, 0, sizeof(current
));
2040 if (enableRawMode(¤t
) == -1) {
2041 printf("%s", prompt
);
2043 sb
= sb_getline(stdin
);
2046 current
.buf
= sb_alloc();
2049 current
.prompt
= prompt
;
2051 count
= linenoiseEdit(¤t
);
2053 disableRawMode(¤t
);
2056 sb_free(current
.capture
);
2058 sb_free(current
.buf
);
2063 return sb
? sb_to_string(sb
) : NULL
;
2066 /* Using a circular buffer is smarter, but a bit more complex to handle. */
2067 int linenoiseHistoryAddAllocated(char *line
) {
2069 if (history_max_len
== 0) {
2074 if (history
== NULL
) {
2075 history
= (char **)calloc(sizeof(char*), history_max_len
);
2078 /* do not insert duplicate lines into history */
2079 if (history_len
> 0 && strcmp(line
, history
[history_len
- 1]) == 0) {
2083 if (history_len
== history_max_len
) {
2085 memmove(history
,history
+1,sizeof(char*)*(history_max_len
-1));
2088 history
[history_len
] = line
;
2093 int linenoiseHistoryAdd(const char *line
) {
2094 return linenoiseHistoryAddAllocated(strdup(line
));
2097 int linenoiseHistoryGetMaxLen(void) {
2098 return history_max_len
;
2101 int linenoiseHistorySetMaxLen(int len
) {
2104 if (len
< 1) return 0;
2106 int tocopy
= history_len
;
2108 newHistory
= (char **)calloc(sizeof(char*), len
);
2110 /* If we can't copy everything, free the elements we'll not use. */
2114 for (j
= 0; j
< tocopy
-len
; j
++) free(history
[j
]);
2117 memcpy(newHistory
,history
+(history_len
-tocopy
), sizeof(char*)*tocopy
);
2119 history
= newHistory
;
2121 history_max_len
= len
;
2122 if (history_len
> history_max_len
)
2123 history_len
= history_max_len
;
2127 /* Save the history in the specified file. On success 0 is returned
2128 * otherwise -1 is returned. */
2129 int linenoiseHistorySave(const char *filename
) {
2130 FILE *fp
= fopen(filename
,"w");
2133 if (fp
== NULL
) return -1;
2134 for (j
= 0; j
< history_len
; j
++) {
2135 const char *str
= history
[j
];
2136 /* Need to encode backslash, nl and cr */
2141 else if (*str
== '\n') {
2144 else if (*str
== '\r') {
2159 /* Load the history from the specified file.
2161 * If the file does not exist or can't be opened, no operation is performed
2162 * and -1 is returned.
2163 * Otherwise 0 is returned.
2165 int linenoiseHistoryLoad(const char *filename
) {
2166 FILE *fp
= fopen(filename
,"r");
2169 if (fp
== NULL
) return -1;
2171 while ((sb
= sb_getline(fp
)) != NULL
) {
2172 /* Take the stringbuf and decode backslash escaped values */
2173 char *buf
= sb_to_string(sb
);
2177 for (src
= buf
; *src
; src
++) {
2185 else if (*src
== 'r') {
2195 linenoiseHistoryAddAllocated(buf
);
2201 /* Provide access to the history buffer.
2203 * If 'len' is not NULL, the length is stored in *len.
2205 char **linenoiseHistory(int *len
) {