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.
3 *
4 * You can find the latest source code at:
5 *
6 * http://github.com/antirez/linenoise
7 *
8 * Does a number of crazy assumptions that happen to be true in 99.9999% of
9 * the 2010 UNIX computers around.
10 *
11 * ------------------------------------------------------------------------
12 *
13 * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
14 * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
15 *
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met:
21 *
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
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.
28 *
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.
40 *
41 * ------------------------------------------------------------------------
42 *
43 * References:
44 * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
45 * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
46 *
47 * Todo list:
48 * - Filter bogus Ctrl+<char> combinations.
49 * - Win32 support
50 *
51 * Bloat:
52 * - History search like Ctrl+r in readline?
53 *
54 * List of escape sequences used by this program, we do everything just
55 * with three 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.
58 *
59 * EL (Erase Line)
60 * Sequence: ESC [ n K
61 * Effect: if n is 0 or missing, clear from cursor to end of line
62 * Effect: if n is 1, clear from beginning of line to cursor
63 * Effect: if n is 2, clear entire line
64 *
65 * CUF (CUrsor Forward)
66 * Sequence: ESC [ n C
67 * Effect: moves cursor forward n chars
68 *
69 * CUB (CUrsor Backward)
70 * Sequence: ESC [ n D
71 * Effect: moves cursor backward n chars
72 *
73 * The following is used to get the terminal width if getting
74 * the width with the TIOCGWINSZ ioctl fails
75 *
76 * DSR (Device Status Report)
77 * Sequence: ESC [ 6 n
78 * Effect: reports the current cusor position as ESC [ n ; m R
79 * where n is the row and m is the column
80 *
81 * When multi line mode is enabled, we also use an additional escape
82 * sequence. However multi line editing is disabled by default.
83 *
84 * CUU (Cursor Up)
85 * Sequence: ESC [ n A
86 * Effect: moves cursor up of n chars.
87 *
88 * CUD (Cursor Down)
89 * Sequence: ESC [ n B
90 * Effect: moves cursor down of n chars.
91 *
92 * When linenoiseClearScreen() is called, two additional escape sequences
93 * are used in order to clear the screen and position the cursor at home
94 * position.
95 *
96 * CUP (Cursor position)
97 * Sequence: ESC [ H
98 * Effect: moves the cursor to upper left corner
99 *
100 * ED (Erase display)
101 * Sequence: ESC [ 2 J
102 * Effect: clear the whole screen
103 *
104 */
105
106 #include <unistd.h>
107 #include <stdlib.h>
108 #include <stdio.h>
109 #include <stdio_ext.h>
110 #include <errno.h>
111 #include <string.h>
112 #include <stdlib.h>
113 #include <ctype.h>
114 #include <sys/stat.h>
115 #include <sys/types.h>
116 #include <sys/fcntl.h>
117 #include <unistd.h>
118 #include <assert.h>
119 #include "linenoise.h"
120
121 #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
122 #define LINENOISE_DEFAULT_MAX_LINE 4096
123 #define LINENOISE_MINIMAL_MAX_LINE 64
124 #define LINENOISE_COMMAND_MAX_LEN 32
125 #define LINENOISE_PASTE_KEY_DELAY 30 /* Delay, in milliseconds, between two characters being pasted from clipboard */
126
127 static linenoiseCompletionCallback *completionCallback = NULL;
128 static linenoiseHintsCallback *hintsCallback = NULL;
129 static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
130
131 static size_t max_cmdline_length = LINENOISE_DEFAULT_MAX_LINE;
132 static int mlmode = 0; /* Multi line mode. Default is single line. */
133 static int dumbmode = 0; /* Dumb mode where line editing is disabled. Off by default */
134 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
135 static int history_len = 0;
136 static char **history = NULL;
137 static bool allow_empty = true;
138
139 /* The linenoiseState structure represents the state during line editing.
140 * We pass this state to functions implementing specific editing
141 * functionalities. */
142 struct linenoiseState {
143 char *buf; /* Edited line buffer. */
144 size_t buflen; /* Edited line buffer size. */
145 const char *prompt; /* Prompt to display. */
146 size_t plen; /* Prompt length. */
147 size_t pos; /* Current cursor position. */
148 size_t oldpos; /* Previous refresh cursor position. */
149 size_t len; /* Current edited line length. */
150 size_t cols; /* Number of columns in terminal. */
151 size_t maxrows; /* Maximum num of rows used so far (multiline mode) */
152 int history_index; /* The history index we are currently editing. */
153 };
154
155 enum KEY_ACTION{
156 KEY_NULL = 0, /* NULL */
157 CTRL_A = 1, /* Ctrl+a */
158 CTRL_B = 2, /* Ctrl-b */
159 CTRL_C = 3, /* Ctrl-c */
160 CTRL_D = 4, /* Ctrl-d */
161 CTRL_E = 5, /* Ctrl-e */
162 CTRL_F = 6, /* Ctrl-f */
163 CTRL_H = 8, /* Ctrl-h */
164 TAB = 9, /* Tab */
165 CTRL_K = 11, /* Ctrl+k */
166 CTRL_L = 12, /* Ctrl+l */
167 ENTER = 10, /* Enter */
168 CTRL_N = 14, /* Ctrl-n */
169 CTRL_P = 16, /* Ctrl-p */
170 CTRL_T = 20, /* Ctrl-t */
171 CTRL_U = 21, /* Ctrl+u */
172 CTRL_W = 23, /* Ctrl+w */
173 ESC = 27, /* Escape */
174 BACKSPACE = 127 /* Backspace */
175 };
176
177 int linenoiseHistoryAdd(const char *line);
178 static void refreshLine(struct linenoiseState *l);
179
180 /* Debugging macro. */
181 #if 0
182 FILE *lndebug_fp = NULL;
183 #define lndebug(...) \
184 do { \
185 if (lndebug_fp == NULL) { \
186 lndebug_fp = fopen("/tmp/lndebug.txt","a"); \
187 fprintf(lndebug_fp, \
188 "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \
189 (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \
190 (int)l->maxrows,old_rows); \
191 } \
192 fprintf(lndebug_fp, ", " __VA_ARGS__); \
193 fflush(lndebug_fp); \
194 } while (0)
195 #else
196 #define lndebug(fmt, ...)
197 #endif
198
199 /* ======================= Low level terminal handling ====================== */
200
201 /* Set if to use or not the multi line mode. */
linenoiseSetMultiLine(int ml)202 void linenoiseSetMultiLine(int ml) {
203 mlmode = ml;
204 }
205
206 /* Set if terminal does not recognize escape sequences */
linenoiseSetDumbMode(int set)207 void linenoiseSetDumbMode(int set) {
208 dumbmode = set;
209 }
210
211 /* Returns whether the current mode is dumbmode or not. */
linenoiseIsDumbMode(void)212 bool linenoiseIsDumbMode(void) {
213 return dumbmode;
214 }
215
flushWrite(void)216 static void flushWrite(void) {
217 if (__fbufsize(stdout) > 0) {
218 fflush(stdout);
219 }
220 fsync(fileno(stdout));
221 }
222
223 /* Use the ESC [6n escape sequence to query the horizontal cursor position
224 * and return it. On error -1 is returned, on success the position of the
225 * cursor. */
getCursorPosition(void)226 static int getCursorPosition(void) {
227 char buf[LINENOISE_COMMAND_MAX_LEN] = { 0 };
228 int cols = 0;
229 int rows = 0;
230 int i = 0;
231 const int out_fd = fileno(stdout);
232 const int in_fd = fileno(stdin);
233 /* The following ANSI escape sequence is used to get from the TTY the
234 * cursor position. */
235 const char get_cursor_cmd[] = "\x1b[6n";
236
237 /* Send the command to the TTY on the other end of the UART.
238 * Let's use unistd's write function. Thus, data sent through it are raw
239 * reducing the overhead compared to using fputs, fprintf, etc... */
240 write(out_fd, get_cursor_cmd, sizeof(get_cursor_cmd));
241
242 /* For USB CDC, it is required to flush the output. */
243 flushWrite();
244
245 /* The other end will send its response which format is ESC [ rows ; cols R
246 * We don't know exactly how many bytes we have to read, thus, perform a
247 * read for each byte.
248 * Stop right before the last character of the buffer, to be able to NULL
249 * terminate it. */
250 while (i < sizeof(buf)-1) {
251 /* Keep using unistd's functions. Here, using `read` instead of `fgets`
252 * or `fgets` guarantees us that we we can read a byte regardless on
253 * whether the sender sent end of line character(s) (CR, CRLF, LF). */
254 if (read(in_fd, buf + i, 1) != 1 || buf[i] == 'R') {
255 /* If we couldn't read a byte from STDIN or if 'R' was received,
256 * the transmission is finished. */
257 break;
258 }
259
260 /* For some reasons, it is possible that we receive new line character
261 * after querying the cursor position on some UART. Let's ignore them,
262 * this will not affect the rest of the program. */
263 if (buf[i] != '\n') {
264 i++;
265 }
266 }
267
268 /* NULL-terminate the buffer, this is required by `sscanf`. */
269 buf[i] = '\0';
270
271 /* Parse the received data to get the position of the cursor. */
272 if (buf[0] != ESC || buf[1] != '[' || sscanf(buf+2,"%d;%d",&rows,&cols) != 2) {
273 return -1;
274 }
275 return cols;
276 }
277
278 /* Try to get the number of columns in the current terminal, or assume 80
279 * if it fails. */
getColumns(void)280 static int getColumns(void) {
281 int start = 0;
282 int cols = 0;
283 int written = 0;
284 char seq[LINENOISE_COMMAND_MAX_LEN] = { 0 };
285 const int fd = fileno(stdout);
286
287 /* The following ANSI escape sequence is used to tell the TTY to move
288 * the cursor to the most-right position. */
289 const char move_cursor_right[] = "\x1b[999C";
290 const size_t cmd_len = sizeof(move_cursor_right);
291
292 /* This one is used to set the cursor position. */
293 const char set_cursor_pos[] = "\x1b[%dD";
294
295 /* Get the initial position so we can restore it later. */
296 start = getCursorPosition();
297 if (start == -1) {
298 goto failed;
299 }
300
301 /* Send the command to go to right margin. Use `write` function instead of
302 * `fwrite` for the same reasons explained in `getCursorPosition()` */
303 if (write(fd, move_cursor_right, cmd_len) != cmd_len) {
304 goto failed;
305 }
306 flushWrite();
307
308 /* After sending this command, we can get the new position of the cursor,
309 * we'd get the size, in columns, of the opened TTY. */
310 cols = getCursorPosition();
311 if (cols == -1) {
312 goto failed;
313 }
314
315 /* Restore the position of the cursor back. */
316 if (cols > start) {
317 /* Generate the move cursor command. */
318 written = snprintf(seq, LINENOISE_COMMAND_MAX_LEN, set_cursor_pos, cols-start);
319
320 /* If `written` is equal or bigger than LINENOISE_COMMAND_MAX_LEN, it
321 * means that the output has been truncated because the size provided
322 * is too small. */
323 assert (written < LINENOISE_COMMAND_MAX_LEN);
324
325 /* Send the command with `write`, which is not buffered. */
326 if (write(fd, seq, written) == -1) {
327 /* Can't recover... */
328 }
329 flushWrite();
330 }
331 return cols;
332
333 failed:
334 return 80;
335 }
336
337 /* Clear the screen. Used to handle ctrl+l */
linenoiseClearScreen(void)338 void linenoiseClearScreen(void) {
339 fprintf(stdout,"\x1b[H\x1b[2J");
340 flushWrite();
341 }
342
343 /* Beep, used for completion when there is nothing to complete or when all
344 * the choices were already shown. */
linenoiseBeep(void)345 static void linenoiseBeep(void) {
346 fprintf(stdout, "\x7");
347 flushWrite();
348 }
349
350 /* ============================== Completion ================================ */
351
352 /* Free a list of completion option populated by linenoiseAddCompletion(). */
freeCompletions(linenoiseCompletions * lc)353 static void freeCompletions(linenoiseCompletions *lc) {
354 size_t i;
355 for (i = 0; i < lc->len; i++)
356 free(lc->cvec[i]);
357 if (lc->cvec != NULL)
358 free(lc->cvec);
359 }
360
361 /* This is an helper function for linenoiseEdit() and is called when the
362 * user types the <tab> key in order to complete the string currently in the
363 * input.
364 *
365 * The state of the editing is encapsulated into the pointed linenoiseState
366 * structure as described in the structure definition. */
completeLine(struct linenoiseState * ls)367 static int completeLine(struct linenoiseState *ls) {
368 linenoiseCompletions lc = { 0, NULL };
369 int nread, nwritten;
370 char c = 0;
371 int in_fd = fileno(stdin);
372
373 completionCallback(ls->buf,&lc);
374 if (lc.len == 0) {
375 linenoiseBeep();
376 } else {
377 size_t stop = 0, i = 0;
378
379 while(!stop) {
380 /* Show completion or original buffer */
381 if (i < lc.len) {
382 struct linenoiseState saved = *ls;
383
384 ls->len = ls->pos = strlen(lc.cvec[i]);
385 ls->buf = lc.cvec[i];
386 refreshLine(ls);
387 ls->len = saved.len;
388 ls->pos = saved.pos;
389 ls->buf = saved.buf;
390 } else {
391 refreshLine(ls);
392 }
393
394 nread = read(in_fd, &c, 1);
395 if (nread <= 0) {
396 freeCompletions(&lc);
397 return -1;
398 }
399
400 switch(c) {
401 case TAB: /* tab */
402 i = (i+1) % (lc.len+1);
403 if (i == lc.len) linenoiseBeep();
404 break;
405 case ESC: /* escape */
406 /* Re-show original buffer */
407 if (i < lc.len) refreshLine(ls);
408 stop = 1;
409 break;
410 default:
411 /* Update buffer and return */
412 if (i < lc.len) {
413 nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]);
414 ls->len = ls->pos = nwritten;
415 }
416 stop = 1;
417 break;
418 }
419 }
420 }
421
422 freeCompletions(&lc);
423 return c; /* Return last read character */
424 }
425
426 /* Register a callback function to be called for tab-completion. */
linenoiseSetCompletionCallback(linenoiseCompletionCallback * fn)427 void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
428 completionCallback = fn;
429 }
430
431 /* Register a hits function to be called to show hits to the user at the
432 * right of the prompt. */
linenoiseSetHintsCallback(linenoiseHintsCallback * fn)433 void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) {
434 hintsCallback = fn;
435 }
436
437 /* Register a function to free the hints returned by the hints callback
438 * registered with linenoiseSetHintsCallback(). */
linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback * fn)439 void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
440 freeHintsCallback = fn;
441 }
442
443 /* This function is used by the callback function registered by the user
444 * in order to add completion options given the input string when the
445 * user typed <tab>. See the example.c source code for a very easy to
446 * understand example. */
linenoiseAddCompletion(linenoiseCompletions * lc,const char * str)447 void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
448 size_t len = strlen(str);
449 char *copy, **cvec;
450
451 copy = malloc(len+1);
452 if (copy == NULL) return;
453 memcpy(copy,str,len+1);
454 cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
455 if (cvec == NULL) {
456 free(copy);
457 return;
458 }
459 lc->cvec = cvec;
460 lc->cvec[lc->len++] = copy;
461 }
462
463 /* =========================== Line editing ================================= */
464
465 /* We define a very simple "append buffer" structure, that is an heap
466 * allocated string where we can append to. This is useful in order to
467 * write all the escape sequences in a buffer and flush them to the standard
468 * output in a single call, to avoid flickering effects. */
469 struct abuf {
470 char *b;
471 int len;
472 };
473
abInit(struct abuf * ab)474 static void abInit(struct abuf *ab) {
475 ab->b = NULL;
476 ab->len = 0;
477 }
478
abAppend(struct abuf * ab,const char * s,int len)479 static void abAppend(struct abuf *ab, const char *s, int len) {
480 char *new = realloc(ab->b,ab->len+len);
481
482 if (new == NULL) return;
483 memcpy(new+ab->len,s,len);
484 ab->b = new;
485 ab->len += len;
486 }
487
abFree(struct abuf * ab)488 static void abFree(struct abuf *ab) {
489 free(ab->b);
490 }
491
492 /* Helper of refreshSingleLine() and refreshMultiLine() to show hints
493 * to the right of the prompt. */
refreshShowHints(struct abuf * ab,struct linenoiseState * l,int plen)494 void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
495 char seq[64];
496 if (hintsCallback && plen+l->len < l->cols) {
497 int color = -1, bold = 0;
498 char *hint = hintsCallback(l->buf,&color,&bold);
499 if (hint) {
500 int hintlen = strlen(hint);
501 int hintmaxlen = l->cols-(plen+l->len);
502 if (hintlen > hintmaxlen) hintlen = hintmaxlen;
503 if (bold == 1 && color == -1) color = 37;
504 if (color != -1 || bold != 0)
505 snprintf(seq,64,"\033[%d;%d;49m",bold,color);
506 abAppend(ab,seq,strlen(seq));
507 abAppend(ab,hint,hintlen);
508 if (color != -1 || bold != 0)
509 abAppend(ab,"\033[0m",4);
510 /* Call the function to free the hint returned. */
511 if (freeHintsCallback) freeHintsCallback(hint);
512 }
513 }
514 }
515
516 /* Single line low level line refresh.
517 *
518 * Rewrite the currently edited line accordingly to the buffer content,
519 * cursor position, and number of columns of the terminal. */
refreshSingleLine(struct linenoiseState * l)520 static void refreshSingleLine(struct linenoiseState *l) {
521 char seq[64];
522 size_t plen = l->plen;
523 int fd = fileno(stdout);
524 char *buf = l->buf;
525 size_t len = l->len;
526 size_t pos = l->pos;
527 struct abuf ab;
528
529 while((plen+pos) >= l->cols) {
530 buf++;
531 len--;
532 pos--;
533 }
534 while (plen+len > l->cols) {
535 len--;
536 }
537
538 abInit(&ab);
539 /* Cursor to left edge */
540 snprintf(seq,64,"\r");
541 abAppend(&ab,seq,strlen(seq));
542 /* Write the prompt and the current buffer content */
543 abAppend(&ab,l->prompt,strlen(l->prompt));
544 abAppend(&ab,buf,len);
545 /* Show hits if any. */
546 refreshShowHints(&ab,l,plen);
547 /* Erase to right */
548 snprintf(seq,64,"\x1b[0K");
549 abAppend(&ab,seq,strlen(seq));
550 /* Move cursor to original position. */
551 snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
552 abAppend(&ab,seq,strlen(seq));
553 if (write(fd, ab.b, ab.len) == -1) {} /* Can't recover from write error. */
554 flushWrite();
555 abFree(&ab);
556 }
557
558 /* Multi line low level line refresh.
559 *
560 * Rewrite the currently edited line accordingly to the buffer content,
561 * cursor position, and number of columns of the terminal. */
refreshMultiLine(struct linenoiseState * l)562 static void refreshMultiLine(struct linenoiseState *l) {
563 char seq[64];
564 int plen = l->plen;
565 int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */
566 int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
567 int rpos2; /* rpos after refresh. */
568 int col; /* colum position, zero-based. */
569 int old_rows = l->maxrows;
570 int j;
571 int fd = fileno(stdout);
572 struct abuf ab;
573
574 /* Update maxrows if needed. */
575 if (rows > (int)l->maxrows) l->maxrows = rows;
576
577 /* First step: clear all the lines used before. To do so start by
578 * going to the last row. */
579 abInit(&ab);
580 if (old_rows-rpos > 0) {
581 lndebug("go down %d", old_rows-rpos);
582 snprintf(seq,64,"\x1b[%dB", old_rows-rpos);
583 abAppend(&ab,seq,strlen(seq));
584 }
585
586 /* Now for every row clear it, go up. */
587 for (j = 0; j < old_rows-1; j++) {
588 lndebug("clear+up");
589 snprintf(seq,64,"\r\x1b[0K\x1b[1A");
590 abAppend(&ab,seq,strlen(seq));
591 }
592
593 /* Clean the top line. */
594 lndebug("clear");
595 snprintf(seq,64,"\r\x1b[0K");
596 abAppend(&ab,seq,strlen(seq));
597
598 /* Write the prompt and the current buffer content */
599 abAppend(&ab,l->prompt,strlen(l->prompt));
600 abAppend(&ab,l->buf,l->len);
601
602 /* Show hits if any. */
603 refreshShowHints(&ab,l,plen);
604
605 /* If we are at the very end of the screen with our prompt, we need to
606 * emit a newline and move the prompt to the first column. */
607 if (l->pos &&
608 l->pos == l->len &&
609 (l->pos+plen) % l->cols == 0)
610 {
611 lndebug("<newline>");
612 abAppend(&ab,"\n",1);
613 snprintf(seq,64,"\r");
614 abAppend(&ab,seq,strlen(seq));
615 rows++;
616 if (rows > (int)l->maxrows) l->maxrows = rows;
617 }
618
619 /* Move cursor to right position. */
620 rpos2 = (plen+l->pos+l->cols)/l->cols; /* current cursor relative row. */
621 lndebug("rpos2 %d", rpos2);
622
623 /* Go up till we reach the expected positon. */
624 if (rows-rpos2 > 0) {
625 lndebug("go-up %d", rows-rpos2);
626 snprintf(seq,64,"\x1b[%dA", rows-rpos2);
627 abAppend(&ab,seq,strlen(seq));
628 }
629
630 /* Set column. */
631 col = (plen+(int)l->pos) % (int)l->cols;
632 lndebug("set col %d", 1+col);
633 if (col)
634 snprintf(seq,64,"\r\x1b[%dC", col);
635 else
636 snprintf(seq,64,"\r");
637 abAppend(&ab,seq,strlen(seq));
638
639 lndebug("\n");
640 l->oldpos = l->pos;
641
642 if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
643 flushWrite();
644 abFree(&ab);
645 }
646
647 /* Calls the two low level functions refreshSingleLine() or
648 * refreshMultiLine() according to the selected mode. */
refreshLine(struct linenoiseState * l)649 static void refreshLine(struct linenoiseState *l) {
650 if (mlmode)
651 refreshMultiLine(l);
652 else
653 refreshSingleLine(l);
654 }
655
656 /* Insert the character 'c' at cursor current position.
657 *
658 * On error writing to the terminal -1 is returned, otherwise 0. */
linenoiseEditInsert(struct linenoiseState * l,char c)659 int linenoiseEditInsert(struct linenoiseState *l, char c) {
660 int fd = fileno(stdout);
661 if (l->len < l->buflen) {
662 if (l->len == l->pos) {
663 l->buf[l->pos] = c;
664 l->pos++;
665 l->len++;
666 l->buf[l->len] = '\0';
667 if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
668 /* Avoid a full update of the line in the
669 * trivial case. */
670 if (write(fd, &c,1) == -1) {
671 return -1;
672 }
673 flushWrite();
674 } else {
675 refreshLine(l);
676 }
677 } else {
678 memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos);
679 l->buf[l->pos] = c;
680 l->len++;
681 l->pos++;
682 l->buf[l->len] = '\0';
683 refreshLine(l);
684 }
685 }
686 return 0;
687 }
688
linenoiseInsertPastedChar(struct linenoiseState * l,char c)689 int linenoiseInsertPastedChar(struct linenoiseState *l, char c) {
690 int fd = fileno(stdout);
691 if (l->len < l->buflen && l->len == l->pos) {
692 l->buf[l->pos] = c;
693 l->pos++;
694 l->len++;
695 l->buf[l->len] = '\0';
696 if (write(fd, &c,1) == -1) {
697 return -1;
698 }
699 flushWrite();
700 }
701 return 0;
702 }
703
704 /* Move cursor on the left. */
linenoiseEditMoveLeft(struct linenoiseState * l)705 void linenoiseEditMoveLeft(struct linenoiseState *l) {
706 if (l->pos > 0) {
707 l->pos--;
708 refreshLine(l);
709 }
710 }
711
712 /* Move cursor on the right. */
linenoiseEditMoveRight(struct linenoiseState * l)713 void linenoiseEditMoveRight(struct linenoiseState *l) {
714 if (l->pos != l->len) {
715 l->pos++;
716 refreshLine(l);
717 }
718 }
719
720 /* Move cursor to the start of the line. */
linenoiseEditMoveHome(struct linenoiseState * l)721 void linenoiseEditMoveHome(struct linenoiseState *l) {
722 if (l->pos != 0) {
723 l->pos = 0;
724 refreshLine(l);
725 }
726 }
727
728 /* Move cursor to the end of the line. */
linenoiseEditMoveEnd(struct linenoiseState * l)729 void linenoiseEditMoveEnd(struct linenoiseState *l) {
730 if (l->pos != l->len) {
731 l->pos = l->len;
732 refreshLine(l);
733 }
734 }
735
736 /* Substitute the currently edited line with the next or previous history
737 * entry as specified by 'dir'. */
738 #define LINENOISE_HISTORY_NEXT 0
739 #define LINENOISE_HISTORY_PREV 1
linenoiseEditHistoryNext(struct linenoiseState * l,int dir)740 void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) {
741 if (history_len > 1) {
742 /* Update the current history entry before to
743 * overwrite it with the next one. */
744 free(history[history_len - 1 - l->history_index]);
745 history[history_len - 1 - l->history_index] = strdup(l->buf);
746 /* Show the new entry */
747 l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1;
748 if (l->history_index < 0) {
749 l->history_index = 0;
750 return;
751 } else if (l->history_index >= history_len) {
752 l->history_index = history_len-1;
753 return;
754 }
755 strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen);
756 l->buf[l->buflen-1] = '\0';
757 l->len = l->pos = strlen(l->buf);
758 refreshLine(l);
759 }
760 }
761
762 /* Delete the character at the right of the cursor without altering the cursor
763 * position. Basically this is what happens with the "Delete" keyboard key. */
linenoiseEditDelete(struct linenoiseState * l)764 void linenoiseEditDelete(struct linenoiseState *l) {
765 if (l->len > 0 && l->pos < l->len) {
766 memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1);
767 l->len--;
768 l->buf[l->len] = '\0';
769 refreshLine(l);
770 }
771 }
772
773 /* Backspace implementation. */
linenoiseEditBackspace(struct linenoiseState * l)774 void linenoiseEditBackspace(struct linenoiseState *l) {
775 if (l->pos > 0 && l->len > 0) {
776 memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos);
777 l->pos--;
778 l->len--;
779 l->buf[l->len] = '\0';
780 refreshLine(l);
781 }
782 }
783
784 /* Delete the previosu word, maintaining the cursor at the start of the
785 * current word. */
linenoiseEditDeletePrevWord(struct linenoiseState * l)786 void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
787 size_t old_pos = l->pos;
788 size_t diff;
789
790 while (l->pos > 0 && l->buf[l->pos-1] == ' ')
791 l->pos--;
792 while (l->pos > 0 && l->buf[l->pos-1] != ' ')
793 l->pos--;
794 diff = old_pos - l->pos;
795 memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
796 l->len -= diff;
797 refreshLine(l);
798 }
799
getMillis(void)800 uint32_t getMillis(void) {
801 struct timeval tv = { 0 };
802 gettimeofday(&tv, NULL);
803 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
804 }
805
806 /* This function is the core of the line editing capability of linenoise.
807 * It expects 'fd' to be already in "raw mode" so that every key pressed
808 * will be returned ASAP to read().
809 *
810 * The resulting string is put into 'buf' when the user type enter, or
811 * when ctrl+d is typed.
812 *
813 * The function returns the length of the current buffer. */
linenoiseEdit(char * buf,size_t buflen,const char * prompt)814 static int linenoiseEdit(char *buf, size_t buflen, const char *prompt)
815 {
816 uint32_t t1 = 0;
817 struct linenoiseState l;
818 int out_fd = fileno(stdout);
819 int in_fd = fileno(stdin);
820
821 /* Populate the linenoise state that we pass to functions implementing
822 * specific editing functionalities. */
823 l.buf = buf;
824 l.buflen = buflen;
825 l.prompt = prompt;
826 l.plen = strlen(prompt);
827 l.oldpos = l.pos = 0;
828 l.len = 0;
829 l.cols = getColumns();
830 l.maxrows = 0;
831 l.history_index = 0;
832
833 /* Buffer starts empty. */
834 l.buf[0] = '\0';
835 l.buflen--; /* Make sure there is always space for the nulterm */
836
837 /* The latest history entry is always our current buffer, that
838 * initially is just an empty string. */
839 linenoiseHistoryAdd("");
840
841 int pos1 = getCursorPosition();
842 if (write(out_fd, prompt,l.plen) == -1) {
843 return -1;
844 }
845 flushWrite();
846 int pos2 = getCursorPosition();
847 if (pos1 >= 0 && pos2 >= 0) {
848 l.plen = pos2 - pos1;
849 }
850 while(1) {
851 char c;
852 int nread;
853 char seq[3];
854
855 /**
856 * To determine whether the user is pasting data or typing itself, we
857 * need to calculate how many milliseconds elapsed between two key
858 * presses. Indeed, if there is less than LINENOISE_PASTE_KEY_DELAY
859 * (typically 30-40ms), then a paste is being performed, else, the
860 * user is typing.
861 * NOTE: pressing a key down without releasing it will also spend
862 * about 40ms (or even more)
863 */
864 t1 = getMillis();
865 nread = read(in_fd, &c, 1);
866 if (nread <= 0) return l.len;
867
868 if ( (getMillis() - t1) < LINENOISE_PASTE_KEY_DELAY && c != ENTER) {
869 /* Pasting data, insert characters without formatting.
870 * This can only be performed when the cursor is at the end of the
871 * line. */
872 if (linenoiseInsertPastedChar(&l,c)) {
873 return -1;
874 }
875 continue;
876 }
877
878 /* Only autocomplete when the callback is set. It returns < 0 when
879 * there was an error reading from fd. Otherwise it will return the
880 * character that should be handled next. */
881 if (c == 9 && completionCallback != NULL) {
882 int c2 = completeLine(&l);
883 /* Return on errors */
884 if (c2 < 0) return l.len;
885 /* Read next character when 0 */
886 if (c2 == 0) continue;
887 c = c2;
888 }
889
890 switch(c) {
891 case ENTER: /* enter */
892 history_len--;
893 free(history[history_len]);
894 if (mlmode) linenoiseEditMoveEnd(&l);
895 if (hintsCallback) {
896 /* Force a refresh without hints to leave the previous
897 * line as the user typed it after a newline. */
898 linenoiseHintsCallback *hc = hintsCallback;
899 hintsCallback = NULL;
900 refreshLine(&l);
901 hintsCallback = hc;
902 }
903 return (int)l.len;
904 case CTRL_C: /* ctrl-c */
905 errno = EAGAIN;
906 return -1;
907 case BACKSPACE: /* backspace */
908 case 8: /* ctrl-h */
909 linenoiseEditBackspace(&l);
910 break;
911 case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the
912 line is empty, act as end-of-file. */
913 if (l.len > 0) {
914 linenoiseEditDelete(&l);
915 } else {
916 history_len--;
917 free(history[history_len]);
918 return -1;
919 }
920 break;
921 case CTRL_T: /* ctrl-t, swaps current character with previous. */
922 if (l.pos > 0 && l.pos < l.len) {
923 int aux = buf[l.pos-1];
924 buf[l.pos-1] = buf[l.pos];
925 buf[l.pos] = aux;
926 if (l.pos != l.len-1) l.pos++;
927 refreshLine(&l);
928 }
929 break;
930 case CTRL_B: /* ctrl-b */
931 linenoiseEditMoveLeft(&l);
932 break;
933 case CTRL_F: /* ctrl-f */
934 linenoiseEditMoveRight(&l);
935 break;
936 case CTRL_P: /* ctrl-p */
937 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
938 break;
939 case CTRL_N: /* ctrl-n */
940 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
941 break;
942 case ESC: /* escape sequence */
943 /* Read the next two bytes representing the escape sequence. */
944 if (read(in_fd, seq, 2) < 2) {
945 break;
946 }
947
948 /* ESC [ sequences. */
949 if (seq[0] == '[') {
950 if (seq[1] >= '0' && seq[1] <= '9') {
951 /* Extended escape, read additional byte. */
952 if (read(in_fd, seq+2, 1) == -1) {
953 break;
954 }
955 if (seq[2] == '~') {
956 switch(seq[1]) {
957 case '3': /* Delete key. */
958 linenoiseEditDelete(&l);
959 break;
960 }
961 }
962 } else {
963 switch(seq[1]) {
964 case 'A': /* Up */
965 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
966 break;
967 case 'B': /* Down */
968 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
969 break;
970 case 'C': /* Right */
971 linenoiseEditMoveRight(&l);
972 break;
973 case 'D': /* Left */
974 linenoiseEditMoveLeft(&l);
975 break;
976 case 'H': /* Home */
977 linenoiseEditMoveHome(&l);
978 break;
979 case 'F': /* End*/
980 linenoiseEditMoveEnd(&l);
981 break;
982 }
983 }
984 }
985
986 /* ESC O sequences. */
987 else if (seq[0] == 'O') {
988 switch(seq[1]) {
989 case 'H': /* Home */
990 linenoiseEditMoveHome(&l);
991 break;
992 case 'F': /* End*/
993 linenoiseEditMoveEnd(&l);
994 break;
995 }
996 }
997 break;
998 default:
999 if (linenoiseEditInsert(&l,c)) return -1;
1000 break;
1001 case CTRL_U: /* Ctrl+u, delete the whole line. */
1002 buf[0] = '\0';
1003 l.pos = l.len = 0;
1004 refreshLine(&l);
1005 break;
1006 case CTRL_K: /* Ctrl+k, delete from current to end of line. */
1007 buf[l.pos] = '\0';
1008 l.len = l.pos;
1009 refreshLine(&l);
1010 break;
1011 case CTRL_A: /* Ctrl+a, go to the start of the line */
1012 linenoiseEditMoveHome(&l);
1013 break;
1014 case CTRL_E: /* ctrl+e, go to the end of the line */
1015 linenoiseEditMoveEnd(&l);
1016 break;
1017 case CTRL_L: /* ctrl+l, clear screen */
1018 linenoiseClearScreen();
1019 refreshLine(&l);
1020 break;
1021 case CTRL_W: /* ctrl+w, delete previous word */
1022 linenoiseEditDeletePrevWord(&l);
1023 break;
1024 }
1025 flushWrite();
1026 }
1027 return l.len;
1028 }
1029
linenoiseAllowEmpty(bool val)1030 void linenoiseAllowEmpty(bool val) {
1031 allow_empty = val;
1032 }
1033
linenoiseProbe(void)1034 int linenoiseProbe(void) {
1035 /* Switch to non-blocking mode */
1036 int stdin_fileno = fileno(stdin);
1037 int flags = fcntl(stdin_fileno, F_GETFL);
1038 flags |= O_NONBLOCK;
1039 int res = fcntl(stdin_fileno, F_SETFL, flags);
1040 if (res != 0) {
1041 return -1;
1042 }
1043 /* Device status request */
1044 fprintf(stdout, "\x1b[5n");
1045 flushWrite();
1046
1047 /* Try to read response */
1048 int timeout_ms = 200;
1049 const int retry_ms = 10;
1050 size_t read_bytes = 0;
1051 while (timeout_ms > 0 && read_bytes < 4) { // response is ESC[0n or ESC[3n
1052 usleep(retry_ms * 1000);
1053 timeout_ms -= retry_ms;
1054 char c;
1055 int cb = read(stdin_fileno, &c, 1);
1056 if (cb < 0) {
1057 continue;
1058 }
1059 read_bytes += cb;
1060 }
1061 /* Restore old mode */
1062 flags &= ~O_NONBLOCK;
1063 res = fcntl(stdin_fileno, F_SETFL, flags);
1064 if (res != 0) {
1065 return -1;
1066 }
1067 if (read_bytes < 4) {
1068 return -2;
1069 }
1070 return 0;
1071 }
1072
linenoiseRaw(char * buf,size_t buflen,const char * prompt)1073 static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
1074 int count;
1075
1076 if (buflen == 0) {
1077 errno = EINVAL;
1078 return -1;
1079 }
1080
1081 count = linenoiseEdit(buf, buflen, prompt);
1082 fputc('\n', stdout);
1083 flushWrite();
1084 return count;
1085 }
1086
linenoiseDumb(char * buf,size_t buflen,const char * prompt)1087 static int linenoiseDumb(char* buf, size_t buflen, const char* prompt) {
1088 /* dumb terminal, fall back to fgets */
1089 fputs(prompt, stdout);
1090 size_t count = 0;
1091 while (count < buflen) {
1092 int c = fgetc(stdin);
1093 if (c == '\n') {
1094 break;
1095 } else if (c >= 0x1c && c <= 0x1f){
1096 continue; /* consume arrow keys */
1097 } else if (c == BACKSPACE || c == 0x8) {
1098 if (count > 0) {
1099 buf[count - 1] = 0;
1100 count --;
1101 }
1102 fputs("\x08 ", stdout); /* Windows CMD: erase symbol under cursor */
1103 } else {
1104 buf[count] = c;
1105 ++count;
1106 }
1107 fputc(c, stdout); /* echo */
1108 }
1109 fputc('\n', stdout);
1110 flushWrite();
1111 return count;
1112 }
1113
sanitize(char * src)1114 static void sanitize(char* src) {
1115 char* dst = src;
1116 for (int c = *src; c != 0; src++, c = *src) {
1117 if (isprint(c)) {
1118 *dst = c;
1119 ++dst;
1120 }
1121 }
1122 *dst = 0;
1123 }
1124
1125 /* The high level function that is the main API of the linenoise library. */
linenoise(const char * prompt)1126 char *linenoise(const char *prompt) {
1127 char *buf = calloc(1, max_cmdline_length);
1128 int count = 0;
1129 if (buf == NULL) {
1130 return NULL;
1131 }
1132 if (!dumbmode) {
1133 count = linenoiseRaw(buf, max_cmdline_length, prompt);
1134 } else {
1135 count = linenoiseDumb(buf, max_cmdline_length, prompt);
1136 }
1137 if (count > 0) {
1138 sanitize(buf);
1139 count = strlen(buf);
1140 } else if (count == 0 && allow_empty) {
1141 /* will return an empty (0-length) string */
1142 } else {
1143 free(buf);
1144 return NULL;
1145 }
1146 return buf;
1147 }
1148
1149 /* This is just a wrapper the user may want to call in order to make sure
1150 * the linenoise returned buffer is freed with the same allocator it was
1151 * created with. Useful when the main program is using an alternative
1152 * allocator. */
linenoiseFree(void * ptr)1153 void linenoiseFree(void *ptr) {
1154 free(ptr);
1155 }
1156
1157 /* ================================ History ================================= */
1158
linenoiseHistoryFree(void)1159 void linenoiseHistoryFree(void) {
1160 if (history) {
1161 for (int j = 0; j < history_len; j++) {
1162 free(history[j]);
1163 }
1164 free(history);
1165 }
1166 history = NULL;
1167 }
1168
1169 /* This is the API call to add a new entry in the linenoise history.
1170 * It uses a fixed array of char pointers that are shifted (memmoved)
1171 * when the history max length is reached in order to remove the older
1172 * entry and make room for the new one, so it is not exactly suitable for huge
1173 * histories, but will work well for a few hundred of entries.
1174 *
1175 * Using a circular buffer is smarter, but a bit more complex to handle. */
linenoiseHistoryAdd(const char * line)1176 int linenoiseHistoryAdd(const char *line) {
1177 char *linecopy;
1178
1179 if (history_max_len == 0) return 0;
1180
1181 /* Initialization on first call. */
1182 if (history == NULL) {
1183 history = malloc(sizeof(char*)*history_max_len);
1184 if (history == NULL) return 0;
1185 memset(history,0,(sizeof(char*)*history_max_len));
1186 }
1187
1188 /* Don't add duplicated lines. */
1189 if (history_len && !strcmp(history[history_len-1], line)) return 0;
1190
1191 /* Add an heap allocated copy of the line in the history.
1192 * If we reached the max length, remove the older line. */
1193 linecopy = strdup(line);
1194 if (!linecopy) return 0;
1195 if (history_len == history_max_len) {
1196 free(history[0]);
1197 memmove(history,history+1,sizeof(char*)*(history_max_len-1));
1198 history_len--;
1199 }
1200 history[history_len] = linecopy;
1201 history_len++;
1202 return 1;
1203 }
1204
1205 /* Set the maximum length for the history. This function can be called even
1206 * if there is already some history, the function will make sure to retain
1207 * just the latest 'len' elements if the new history length value is smaller
1208 * than the amount of items already inside the history. */
linenoiseHistorySetMaxLen(int len)1209 int linenoiseHistorySetMaxLen(int len) {
1210 char **new;
1211
1212 if (len < 1) return 0;
1213 if (history) {
1214 int tocopy = history_len;
1215
1216 new = malloc(sizeof(char*)*len);
1217 if (new == NULL) return 0;
1218
1219 /* If we can't copy everything, free the elements we'll not use. */
1220 if (len < tocopy) {
1221 int j;
1222
1223 for (j = 0; j < tocopy-len; j++) free(history[j]);
1224 tocopy = len;
1225 }
1226 memset(new,0,sizeof(char*)*len);
1227 memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy);
1228 free(history);
1229 history = new;
1230 }
1231 history_max_len = len;
1232 if (history_len > history_max_len)
1233 history_len = history_max_len;
1234 return 1;
1235 }
1236
1237 /* Save the history in the specified file. On success 0 is returned
1238 * otherwise -1 is returned. */
linenoiseHistorySave(const char * filename)1239 int linenoiseHistorySave(const char *filename) {
1240 FILE *fp;
1241 int j;
1242
1243 fp = fopen(filename,"w");
1244 if (fp == NULL) return -1;
1245 for (j = 0; j < history_len; j++)
1246 fprintf(fp,"%s\n",history[j]);
1247 fclose(fp);
1248 return 0;
1249 }
1250
1251 /* Load the history from the specified file. If the file does not exist
1252 * zero is returned and no operation is performed.
1253 *
1254 * If the file exists and the operation succeeded 0 is returned, otherwise
1255 * on error -1 is returned. */
linenoiseHistoryLoad(const char * filename)1256 int linenoiseHistoryLoad(const char *filename) {
1257 FILE *fp = fopen(filename, "r");
1258 if (fp == NULL) {
1259 return -1;
1260 }
1261
1262 char *buf = calloc(1, max_cmdline_length);
1263 if (buf == NULL) {
1264 fclose(fp);
1265 return -1;
1266 }
1267
1268 while (fgets(buf, max_cmdline_length, fp) != NULL) {
1269 char *p;
1270
1271 p = strchr(buf,'\r');
1272 if (!p) p = strchr(buf,'\n');
1273 if (p) *p = '\0';
1274 linenoiseHistoryAdd(buf);
1275 }
1276
1277 free(buf);
1278 fclose(fp);
1279
1280 return 0;
1281 }
1282
1283 /* Set line maximum length. If len parameter is smaller than
1284 * LINENOISE_MINIMAL_MAX_LINE, -1 is returned
1285 * otherwise 0 is returned. */
linenoiseSetMaxLineLen(size_t len)1286 int linenoiseSetMaxLineLen(size_t len) {
1287 if (len < LINENOISE_MINIMAL_MAX_LINE) {
1288 return -1;
1289 }
1290 max_cmdline_length = len;
1291 return 0;
1292 }
1293