This source file includes following definitions.
- linenoiseMaskModeEnable
- linenoiseMaskModeDisable
- linenoiseSetMultiLine
- isUnsupportedTerm
- enableRawMode
- disableRawMode
- getCursorPosition
- getColumns
- linenoiseClearScreen
- linenoiseBeep
- freeCompletions
- completeLine
- linenoiseSetCompletionCallback
- linenoiseSetHintsCallback
- linenoiseSetFreeHintsCallback
- linenoiseAddCompletion
- abInit
- abAppend
- abFree
- refreshShowHints
- refreshSingleLine
- refreshMultiLine
- refreshLine
- linenoiseEditInsert
- linenoiseEditMoveLeft
- linenoiseEditMoveRight
- linenoiseEditMoveWordEnd
- linenoiseEditMoveWordStart
- linenoiseEditMoveHome
- linenoiseEditMoveEnd
- linenoiseEditHistoryNext
- linenoiseSearchInHistory
- linenoiseEditDelete
- linenoiseEditBackspace
- linenoiseEditDeletePrevWord
- linenoiseEditDeleteNextWord
- linenoiseEdit
- linenoiseRaw
- linenoiseNoTTY
- linenoise
- linenoiseFree
- freeHistory
- linenoiseAtExit
- linenoiseHistoryAdd
- linenoiseHistorySetMaxLen
- pstrlen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 #ifndef _POSIX_C_SOURCE
49 # define _POSIX_C_SOURCE 200809L
50 #endif
51
52 #if !defined ( __MINGW32__ ) \
53 && !defined ( CROSS_MINGW32 ) \
54 && !defined ( CROSS_MINGW64 ) \
55 && !defined ( __MINGW64__ ) \
56 && !defined ( _MSC_VER ) \
57 && !defined ( _MSC_BUILD )
58
59 # if defined( __sun ) && defined( __SVR4 )
60 # ifndef __EXTENSIONS__
61 # define __EXTENSIONS__ 1
62 # endif
63 # endif
64 # include <termios.h>
65 # if defined( __sun ) && defined( __SVR4 )
66 # include <sys/termiox.h>
67 # endif
68 # include "linehistory.h"
69 # ifndef __NetBSD__
70 # include "../dps8/dps8.h"
71 # endif
72 # include <ctype.h>
73 # include <errno.h>
74 # include <stdio.h>
75 # include <stdlib.h>
76 # include <string.h>
77 # include <strings.h>
78 # include <sys/ioctl.h>
79 # include <sys/stat.h>
80 # include <sys/types.h>
81 # include <unistd.h>
82
83 # undef FREE
84 # define FREE(p) do \
85 { \
86 free((p)); \
87 (p) = NULL; \
88 } while(0)
89
90 # ifdef TESTING
91 # undef realloc
92 # undef FREE
93 # define FREE(p) free(p)
94 # define realloc trealloc
95 # endif
96
97 # define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
98 # define LINENOISE_MAX_LINE 4096
99
100 static char *unsupported_term[] = {
101 "dumb", "cons25", "emacs", NULL
102 };
103
104 # ifdef LH_COMPLETION
105 static linenoiseCompletionCallback *completionCallback = NULL;
106 # endif
107
108 # ifdef LH_HINTS
109 static linenoiseHintsCallback *hintsCallback = NULL;
110 static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
111 # endif
112
113 static struct termios orig_termios;
114
115 # ifdef LH_MASKMODE
116 static int maskmode = 0;
117 # endif
118
119 static int rawmode = 0;
120 static int mlmode = 0;
121 static int atexit_registered = 0;
122 static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
123 static int history_len = 0;
124 static char **history = NULL;
125
126
127
128
129
130
131
132 struct linenoiseState
133 {
134 int ifd;
135 int ofd;
136 char *buf;
137 size_t buflen;
138 const char *prompt;
139 size_t plen;
140 size_t pos;
141 size_t oldpos;
142 size_t len;
143 size_t cols;
144 size_t maxrows;
145 int history_index;
146 };
147
148 enum KEY_ACTION
149 {
150 KEY_NULL = 0,
151 CTRL_A = 1,
152 CTRL_B = 2,
153 CTRL_C = 3,
154 CTRL_D = 4,
155 CTRL_E = 5,
156 CTRL_F = 6,
157 CTRL_H = 8,
158 TAB = 9,
159 CTRL_K = 11,
160 CTRL_L = 12,
161 ENTER = 13,
162 CTRL_N = 14,
163 CTRL_P = 16,
164 CTRL_T = 20,
165 CTRL_U = 21,
166 CTRL_W = 23,
167 ESC = 27,
168 BACKSPACE = 127
169 };
170
171 static void linenoiseAtExit(void);
172 static void refreshLine(struct linenoiseState *l);
173 size_t pstrlen(const char *s);
174
175 # ifdef LH_MASKMODE
176
177
178
179
180
181
182
183
184 void
185 linenoiseMaskModeEnable(void)
186 {
187 maskmode = 1;
188 }
189
190
191 void
192 linenoiseMaskModeDisable(void)
193 {
194 maskmode = 0;
195 }
196 # endif
197
198
199 void
200 linenoiseSetMultiLine(int ml)
201 {
202 mlmode = ml;
203 }
204
205
206
207
208
209
210 static int
211 isUnsupportedTerm(void)
212 {
213 char *term = getenv("TERM");
214 int j;
215
216 if (term == NULL)
217 {
218 return ( 0 );
219 }
220
221 for (j = 0; unsupported_term[j]; j++)
222 {
223 if (!strcasecmp(term, unsupported_term[j]))
224 {
225 return ( 1 );
226 }
227 }
228
229 return ( 0 );
230 }
231
232
233 static int
234 enableRawMode(int fd)
235 {
236 struct termios raw;
237
238 if (!isatty(STDIN_FILENO))
239 {
240 goto fatal;
241 }
242
243 if (!atexit_registered)
244 {
245 atexit(linenoiseAtExit);
246 atexit_registered = 1;
247 }
248
249 if (tcgetattr(fd, &orig_termios) == -1)
250 {
251 goto fatal;
252 }
253
254 raw = orig_termios;
255
256
257 raw.c_iflag &= ~( BRKINT | ICRNL | INPCK | ISTRIP | IXON );
258
259 raw.c_cflag |= ( CS8 );
260
261
262 raw.c_lflag &= ~( ECHO | ICANON | IEXTEN | ISIG );
263
264
265 raw.c_cc[VMIN] = 1;
266 raw.c_cc[VTIME] = 0;
267
268
269 if (tcsetattr(fd, TCSAFLUSH, &raw) < 0)
270 {
271 goto fatal;
272 }
273
274 rawmode = 1;
275 return ( 0 );
276
277 fatal:
278 errno = ENOTTY;
279 return ( -1 );
280 }
281
282 static void
283 disableRawMode(int fd)
284 {
285
286 if (rawmode && tcsetattr(fd, TCSAFLUSH, &orig_termios) != -1)
287 {
288 rawmode = 0;
289 }
290 }
291
292
293
294
295
296
297
298 static int
299 getCursorPosition(int ifd, int ofd)
300 {
301 char buf[32];
302 int cols, rows;
303 unsigned int i = 0;
304
305
306 if (write(ofd, "\x1b[6n", 4) != 4)
307 {
308 return ( -1 );
309 }
310
311
312 while (i < sizeof ( buf ) - 1)
313 {
314 if (read(ifd, buf + i, 1) != 1)
315 {
316 break;
317 }
318
319 if (buf[i] == 'R')
320 {
321 break;
322 }
323
324 i++;
325 }
326 buf[i] = '\0';
327
328
329 if (buf[0] != ESC || buf[1] != '[')
330 {
331 return ( -1 );
332 }
333
334 if (sscanf(buf + 2, "%d;%d", &rows, &cols) != 2)
335 {
336 return ( -1 );
337 }
338
339 return ( cols );
340 }
341
342
343 static int
344 getColumns(int ifd, int ofd)
345 {
346 struct winsize ws;
347
348 if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0)
349 {
350
351 int start, cols;
352
353
354 start = getCursorPosition(ifd, ofd);
355 if (start == -1)
356 {
357 goto failed;
358 }
359
360
361 if (write(ofd, "\x1b[999C", 6) != 6)
362 {
363 goto failed;
364 }
365
366 cols = getCursorPosition(ifd, ofd);
367 if (cols == -1)
368 {
369 goto failed;
370 }
371
372
373 if (cols > start)
374 {
375 char seq[32];
376 snprintf(seq, sizeof ( seq ), "\x1b[%dD", cols - start);
377 if (write(ofd, seq, strlen(seq)) == -1)
378 {
379 }
380 }
381
382 return ( cols );
383 }
384 else
385 {
386 return ( ws.ws_col );
387 }
388
389 failed:
390 return ( 80 );
391 }
392
393
394 void
395 linenoiseClearScreen(void)
396 {
397 if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) <= 0)
398 {
399 }
400 }
401
402 # ifdef LH_COMPLETION
403
404
405
406
407
408
409 static void
410 linenoiseBeep(void)
411 {
412 fprintf(stderr, "\x7");
413 fflush(stderr);
414 }
415
416
417 static void
418 freeCompletions(const linenoiseCompletions *lc)
419 {
420 size_t i;
421
422 for (i = 0; i < lc->len; i++)
423 {
424 FREE(lc->cvec[i]);
425 }
426
427 if (lc->cvec != NULL)
428 {
429 FREE(lc->cvec);
430 }
431 }
432
433
434
435
436
437
438
439
440
441
442 static int
443 completeLine(struct linenoiseState *ls)
444 {
445 linenoiseCompletions lc = {
446 0, NULL
447 };
448 int nread, nwritten;
449 char c = 0;
450
451 completionCallback(ls->buf, &lc);
452 if (lc.len == 0)
453 {
454 linenoiseBeep();
455 }
456 else
457 {
458 size_t stop = 0, i = 0;
459
460 while (!stop)
461 {
462
463 if (i < lc.len)
464 {
465 struct linenoiseState saved = *ls;
466
467 ls->len = ls->pos = strlen(lc.cvec[i]);
468 ls->buf = lc.cvec[i];
469 refreshLine(ls);
470 ls->len = saved.len;
471 ls->pos = saved.pos;
472 ls->buf = saved.buf;
473 }
474 else
475 {
476 refreshLine(ls);
477 }
478
479 nread = read(ls->ifd, &c, 1);
480 if (nread <= 0)
481 {
482 freeCompletions(&lc);
483 return ( -1 );
484 }
485
486 switch (c)
487 {
488 case 9:
489 i = ( i + 1 ) % ( lc.len + 1 );
490 if (i == lc.len)
491 {
492 linenoiseBeep();
493 }
494
495 stop = 1;
496 break;
497
498 default:
499
500 if (i < lc.len)
501 {
502 nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[i]);
503 ls->len = ls->pos = nwritten;
504 }
505
506 stop = 1;
507 break;
508 }
509 }
510 }
511
512 freeCompletions(&lc);
513 return ( c );
514 }
515
516
517 void
518 linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn)
519 {
520 completionCallback = fn;
521 }
522
523 # endif
524
525 # ifdef LH_HINTS
526
527
528
529
530
531
532 void
533 linenoiseSetHintsCallback(linenoiseHintsCallback *fn)
534 {
535 hintsCallback = fn;
536 }
537
538
539
540
541
542
543 void
544 linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn)
545 {
546 freeHintsCallback = fn;
547 }
548
549 # endif
550
551 # ifdef LH_COMPLETION
552
553
554
555
556
557
558
559 void
560 linenoiseAddCompletion(linenoiseCompletions *lc, const char *str)
561 {
562 size_t len = strlen(str);
563 char *copy, **cvec;
564
565 copy = malloc(len + 1);
566 if (copy == NULL)
567 {
568 return;
569 }
570
571 memcpy(copy, str, len + 1);
572 cvec = realloc(lc->cvec, sizeof ( char * ) * ( lc->len + 1 ));
573 if (cvec == NULL)
574 {
575 FREE(copy);
576 return;
577 }
578
579 lc->cvec = cvec;
580 lc->cvec[lc->len++] = copy;
581 }
582
583 # endif
584
585
586
587
588
589
590
591
592 struct abuf
593 {
594 char *b;
595 int len;
596 };
597
598 static void
599 abInit(struct abuf *ab)
600 {
601 ab->b = NULL;
602 ab->len = 0;
603 }
604
605 static void
606 abAppend(struct abuf *ab, const char *s, int len)
607 {
608 if (len <= 0)
609 {
610 return;
611 }
612
613 char *new = realloc(ab->b, 1 + ab->len + len);
614
615 if (new == NULL)
616 {
617 return;
618 }
619
620 memcpy(new + ab->len, s, len);
621 ab->b = new;
622 ab->len += len;
623 }
624
625 static void
626 abFree(const struct abuf *ab)
627 {
628 free(ab->b);
629 }
630
631 # ifdef LH_HINTS
632
633
634
635
636
637
638 static void
639 refreshShowHints(struct abuf *ab, const struct linenoiseState *l, int plen)
640 {
641 char seq[64];
642
643 seq[0] = '\0';
644 if (hintsCallback && plen + l->len < l->cols)
645 {
646 int color = -1, bold = 0;
647 char *hint = hintsCallback(l->buf, &color, &bold);
648 if (hint)
649 {
650 int hintlen = strlen(hint);
651 int hintmaxlen = l->cols - ( plen + l->len );
652 if (hintlen > hintmaxlen)
653 {
654 hintlen = hintmaxlen;
655 }
656
657 if (bold == 1 && color == -1)
658 {
659 color = 37;
660 }
661
662 if (color != -1 || bold != 0)
663 {
664 snprintf(seq, sizeof ( seq ), "\033[%d;%d;49m", bold, color);
665 }
666 else
667 {
668 seq[0] = '\0';
669 }
670
671 abAppend(ab, seq, strlen(seq));
672 abAppend(ab, hint, hintlen);
673 if (color != -1 || bold != 0)
674 {
675 abAppend(ab, "\033[0m", 4);
676 }
677
678
679 if (freeHintsCallback)
680 {
681 freeHintsCallback(hint);
682 }
683 }
684 }
685 }
686
687 # endif
688
689
690
691
692
693
694
695
696 static void
697 refreshSingleLine(const struct linenoiseState *l)
698 {
699 char seq[64];
700 size_t plen = pstrlen(l->prompt);
701 int fd = l->ofd;
702 char *buf = l->buf;
703 size_t len = l->len;
704 size_t pos = l->pos;
705 struct abuf ab;
706
707 while (( plen + pos ) >= l->cols)
708 {
709 buf++;
710 len--;
711 pos--;
712 }
713 while (plen + len > l->cols)
714 {
715 len--;
716 }
717
718 abInit(&ab);
719
720 snprintf(seq, sizeof ( seq ), "\r");
721 abAppend(&ab, seq, strlen(seq));
722
723 abAppend(&ab, l->prompt, strlen(l->prompt));
724 # ifdef LH_MASKMODE
725 if (maskmode == 1)
726 {
727 while (len--)
728 {
729 abAppend(&ab, "*", 1);
730 }
731 }
732 else
733 {
734 # endif
735 abAppend(&ab, buf, len);
736 # ifdef LH_MASKMODE
737 }
738 # endif
739 # ifdef LH_HINTS
740
741 refreshShowHints(&ab, l, plen);
742 # endif
743
744 snprintf(seq, sizeof ( seq ), "\x1b[0K");
745 abAppend(&ab, seq, strlen(seq));
746
747 snprintf(seq, sizeof ( seq ), "\r\x1b[%dC", (int)( pos + plen ));
748 abAppend(&ab, seq, strlen(seq));
749 if (write(fd, ab.b, ab.len) == -1)
750 {
751 }
752
753 abFree(&ab);
754 }
755
756
757
758
759
760
761
762
763 static void
764 refreshMultiLine(struct linenoiseState *l)
765 {
766 char seq[64];
767 int plen = strlen(l->prompt);
768 int rows = ( plen + l->len + l->cols - 1 )
769 / l->cols;
770 int rpos = ( plen + l->oldpos + l->cols ) / l->cols;
771 int rpos2;
772 int col;
773 int old_rows = l->maxrows;
774 int fd = l->ofd, j;
775 struct abuf ab;
776
777
778 if (rows > (int)l->maxrows)
779 {
780 l->maxrows = rows;
781 }
782
783
784
785
786
787
788 abInit(&ab);
789 if (old_rows - rpos > 0)
790 {
791 snprintf(seq, sizeof ( seq ), "\x1b[%dB", old_rows - rpos);
792 abAppend(&ab, seq, strlen(seq));
793 }
794
795
796 for (j = 0; j < old_rows - 1; j++)
797 {
798 snprintf(seq, sizeof ( seq ), "\r\x1b[0K\x1b[1A");
799 abAppend(&ab, seq, strlen(seq));
800 }
801
802
803 snprintf(seq, sizeof ( seq ), "\r\x1b[0K");
804 abAppend(&ab, seq, strlen(seq));
805
806
807 abAppend(&ab, l->prompt, strlen(l->prompt));
808 # ifdef LH_MASKMODE
809 if (maskmode == 1)
810 {
811 unsigned int i;
812 for (i = 0; i < l->len; i++)
813 {
814 abAppend(&ab, "*", 1);
815 }
816 }
817 else
818 {
819 # endif
820 abAppend(&ab, l->buf, l->len);
821 # ifdef LH_MASKMODE
822 }
823 # endif
824
825 # ifdef LH_HINTS
826
827 refreshShowHints(&ab, l, plen);
828 # endif
829
830
831
832
833
834
835 if (l->pos && l->pos == l->len && ( l->pos + plen ) % l->cols == 0)
836 {
837 abAppend(&ab, "\n", 1);
838 snprintf(seq, sizeof ( seq ), "\r");
839 abAppend(&ab, seq, strlen(seq));
840 rows++;
841 if (rows > (int)l->maxrows)
842 {
843 l->maxrows = rows;
844 }
845 }
846
847
848 rpos2 = ( plen + l->pos + l->cols ) / l->cols;
849
850
851 if (rows - rpos2 > 0)
852 {
853 snprintf(seq, sizeof ( seq ), "\x1b[%dA", rows - rpos2);
854 abAppend(&ab, seq, strlen(seq));
855 }
856
857
858 col = ( plen + (int)l->pos ) % (int)l->cols;
859 if (col)
860 {
861 snprintf(seq, sizeof ( seq ), "\r\x1b[%dC", col);
862 }
863 else
864 {
865 snprintf(seq, sizeof ( seq ), "\r");
866 }
867
868 abAppend(&ab, seq, strlen(seq));
869
870 l->oldpos = l->pos;
871
872 if (write(fd, ab.b, ab.len) == -1)
873 {
874 }
875
876 abFree(&ab);
877 }
878
879
880
881
882
883
884 static void
885 refreshLine(struct linenoiseState *l)
886 {
887 l->cols = getColumns(STDIN_FILENO, STDOUT_FILENO);
888 if (mlmode)
889 {
890 refreshMultiLine(l);
891 }
892 else
893 {
894 refreshSingleLine(l);
895 }
896 }
897
898
899
900
901
902
903 int
904 linenoiseEditInsert(struct linenoiseState *l, char c)
905 {
906 if (l->len < l->buflen)
907 {
908 if (l->len == l->pos)
909 {
910 l->buf[l->pos] = c;
911 l->pos++;
912 l->len++;
913 l->buf[l->len] = '\0';
914 # if defined( LH_MASKMODE ) && defined( LH_HINTS )
915 if (( !mlmode && l->plen + l->len < l->cols && !hintsCallback ))
916 {
917
918 char d = ( maskmode == 1 ) ? '*' : (char)c;
919 if (write(l->ofd, &d, 1) == -1)
920 {
921 return ( -1 );
922 }
923 }
924 else
925 {
926 # endif
927 refreshLine(l);
928 # if defined( LH_MASKMODE ) && defined( LH_HINTS )
929 }
930 # endif
931 }
932 else
933 {
934 memmove(l->buf + l->pos + 1, l->buf + l->pos, l->len - l->pos);
935 l->buf[l->pos] = c;
936 l->len++;
937 l->pos++;
938 l->buf[l->len] = '\0';
939 refreshLine(l);
940 }
941 }
942
943 return ( 0 );
944 }
945
946
947 void
948 linenoiseEditMoveLeft(struct linenoiseState *l)
949 {
950 if (l->pos > 0)
951 {
952 l->pos--;
953 refreshLine(l);
954 }
955 }
956
957
958 void
959 linenoiseEditMoveRight(struct linenoiseState *l)
960 {
961 if (l->pos != l->len)
962 {
963 l->pos++;
964 refreshLine(l);
965 }
966 }
967
968
969 void
970 linenoiseEditMoveWordEnd(struct linenoiseState *l)
971 {
972 if (l->len == 0 || l->pos >= l->len)
973 {
974 return;
975 }
976
977 if (l->buf[l->pos] == ' ')
978 {
979 while (l->pos < l->len && l->buf[l->pos] == ' ')
980 {
981 ++l->pos;
982 }
983 }
984
985 while (l->pos < l->len && l->buf[l->pos] != ' ')
986 {
987 ++l->pos;
988 }
989 refreshLine(l);
990 }
991
992
993 void
994 linenoiseEditMoveWordStart(struct linenoiseState *l)
995 {
996 if (l->len == 0)
997 {
998 return;
999 }
1000
1001 if (l->buf[l->pos - 1] == ' ')
1002 {
1003 --l->pos;
1004 }
1005
1006 if (l->buf[l->pos] == ' ')
1007 {
1008 while (l->pos > 0 && l->buf[l->pos] == ' ')
1009 {
1010 --l->pos;
1011 }
1012 }
1013
1014 while (l->pos > 0 && l->buf[l->pos - 1] != ' ')
1015 {
1016 --l->pos;
1017 }
1018 refreshLine(l);
1019 }
1020
1021
1022 void
1023 linenoiseEditMoveHome(struct linenoiseState *l)
1024 {
1025 if (l->pos != 0)
1026 {
1027 l->pos = 0;
1028 refreshLine(l);
1029 }
1030 }
1031
1032
1033 void
1034 linenoiseEditMoveEnd(struct linenoiseState *l)
1035 {
1036 if (l->pos != l->len)
1037 {
1038 l->pos = l->len;
1039 refreshLine(l);
1040 }
1041 }
1042
1043
1044
1045
1046
1047
1048 # define LINENOISE_HISTORY_NEXT 0
1049 # define LINENOISE_HISTORY_PREV 1
1050 void
1051 linenoiseEditHistoryNext(struct linenoiseState *l, int dir)
1052 {
1053 if (history_len > 1)
1054 {
1055
1056
1057
1058
1059
1060
1061 FREE(history[history_len - 1 - l->history_index]);
1062 history[history_len - 1 - l->history_index] = strdup(l->buf);
1063 if (!history[history_len - 1 - l->history_index])
1064 {
1065 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1066 __func__, __FILE__, __LINE__);
1067 # if defined(USE_BACKTRACE)
1068 # ifdef SIGUSR2
1069 (void)raise(SIGUSR2);
1070
1071 # endif
1072 # endif
1073 abort();
1074 }
1075
1076 l->history_index += ( dir == LINENOISE_HISTORY_PREV ) ? 1 : -1;
1077 if (l->history_index < 0)
1078 {
1079 l->history_index = 0;
1080 return;
1081 }
1082 else if (l->history_index >= history_len)
1083 {
1084 l->history_index = history_len - 1;
1085 return;
1086 }
1087
1088 strncpy(l->buf, history[history_len - 1 - l->history_index], l->buflen);
1089 l->buf[l->buflen - 1] = '\0';
1090 l->len = l->pos = strlen(l->buf);
1091 refreshLine(l);
1092 }
1093 }
1094
1095
1096
1097
1098
1099
1100 # define LINENOISE_SEARCH_HISTORY_FORWARD 0
1101 # define LINENOISE_SEARCH_HISTORY_REVERSE 1
1102 void
1103 linenoiseSearchInHistory(struct linenoiseState *l, int direction)
1104 {
1105 if (history_len > 1)
1106 {
1107
1108
1109
1110
1111
1112
1113 FREE(history[history_len - 1 - l->history_index]);
1114 history[history_len - 1 - l->history_index] = strdup(l->buf);
1115 if (!history[history_len - 1 - l->history_index])
1116 {
1117 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1118 __func__, __FILE__, __LINE__);
1119 # if defined(USE_BACKTRACE)
1120 # ifdef SIGUSR2
1121 (void)raise(SIGUSR2);
1122
1123 # endif
1124 # endif
1125 abort();
1126 }
1127
1128
1129 int cnt;
1130 if (direction == LINENOISE_SEARCH_HISTORY_FORWARD)
1131 {
1132 cnt = history_len - 2 - l->history_index;
1133 for (; cnt >= 0; cnt--)
1134 {
1135
1136
1137
1138
1139
1140
1141 if (strncmp(l->buf, history[cnt], l->pos) == 0)
1142 {
1143 strncpy(l->buf, history[cnt], l->buflen);
1144 l->buf[l->buflen - 1] = '\0';
1145
1146 l->len = strlen(l->buf);
1147
1148
1149
1150
1151
1152
1153 l->history_index = history_len - 1 - cnt;
1154 refreshLine(l);
1155 return;
1156 }
1157 }
1158 }
1159 else if (direction == LINENOISE_SEARCH_HISTORY_REVERSE)
1160 {
1161 cnt = history_len - l->history_index;
1162 for (; cnt < history_len; cnt++)
1163 {
1164
1165
1166
1167
1168
1169
1170 if (strncmp(l->buf, history[cnt], l->pos) == 0)
1171 {
1172 strncpy(l->buf, history[cnt], l->buflen);
1173 l->buf[l->buflen - 1] = '\0';
1174
1175 l->len = strlen(l->buf);
1176
1177
1178
1179
1180
1181
1182 l->history_index = history_len - 1 - cnt;
1183 refreshLine(l);
1184 return;
1185 }
1186 }
1187 }
1188 }
1189 }
1190
1191
1192
1193
1194
1195
1196 void
1197 linenoiseEditDelete(struct linenoiseState *l)
1198 {
1199 if (l->len > 0 && l->pos < l->len)
1200 {
1201 memmove(l->buf + l->pos, l->buf + l->pos + 1, l->len - l->pos - 1);
1202 l->len--;
1203 l->buf[l->len] = '\0';
1204 refreshLine(l);
1205 }
1206 }
1207
1208
1209 void
1210 linenoiseEditBackspace(struct linenoiseState *l)
1211 {
1212 if (l->pos > 0 && l->len > 0)
1213 {
1214 memmove(l->buf + l->pos - 1, l->buf + l->pos, l->len - l->pos);
1215 l->pos--;
1216 l->len--;
1217 l->buf[l->len] = '\0';
1218 refreshLine(l);
1219 }
1220 }
1221
1222
1223
1224
1225
1226
1227 void
1228 linenoiseEditDeletePrevWord(struct linenoiseState *l)
1229 {
1230 size_t old_pos = l->pos;
1231 size_t diff;
1232
1233 while (l->pos > 0 && l->buf[l->pos - 1] == ' ')
1234 {
1235 l->pos--;
1236 }
1237 while (l->pos > 0 && l->buf[l->pos - 1] != ' ')
1238 {
1239 l->pos--;
1240 }
1241 diff = old_pos - l->pos;
1242 memmove(l->buf + l->pos, l->buf + old_pos, l->len - old_pos + 1);
1243 l->len -= diff;
1244 refreshLine(l);
1245 }
1246
1247
1248 void
1249 linenoiseEditDeleteNextWord(struct linenoiseState *l)
1250 {
1251 size_t next_word_end = l->pos;
1252
1253 while (next_word_end < l->len && l->buf[next_word_end] == ' ')
1254 {
1255 ++next_word_end;
1256 }
1257 while (next_word_end < l->len && l->buf[next_word_end] != ' ')
1258 {
1259 ++next_word_end;
1260 }
1261 memmove(l->buf + l->pos, l->buf + next_word_end, l->len - next_word_end);
1262 l->len -= next_word_end - l->pos;
1263 refreshLine(l);
1264 }
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 static int
1278 linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
1279 const char *prompt)
1280 {
1281 struct linenoiseState l;
1282
1283
1284
1285
1286
1287
1288 l.ifd = stdin_fd;
1289 l.ofd = stdout_fd;
1290 l.buf = buf;
1291 l.buflen = buflen;
1292 l.prompt = prompt;
1293 l.plen = pstrlen(prompt);
1294 l.oldpos = l.pos = 0;
1295 l.len = 0;
1296 l.cols = getColumns(stdin_fd, stdout_fd);
1297 l.maxrows = 0;
1298 l.history_index = 0;
1299
1300
1301 l.buf[0] = '\0';
1302 l.buflen--;
1303
1304
1305
1306
1307
1308
1309 (void)linenoiseHistoryAdd("");
1310
1311 if (write(l.ofd, prompt, strlen(prompt)) == -1)
1312 {
1313 return ( -1 );
1314 }
1315
1316 while (1)
1317 {
1318 signed char c;
1319 int nread;
1320 char seq[3];
1321
1322 nread = read(l.ifd, &c, 1);
1323 if (nread <= 0)
1324 {
1325 return ( l.len );
1326 }
1327
1328 # ifdef LH_COMPLETION
1329
1330
1331
1332
1333
1334
1335
1336 if (c == 9 && completionCallback != NULL)
1337 {
1338 int cint = completeLine(&l);
1339
1340 if (cint < 0)
1341 {
1342 return ( l.len );
1343 }
1344
1345
1346 if (cint == 0)
1347 {
1348 continue;
1349 }
1350
1351 c = (char)cint;
1352 }
1353
1354 # endif
1355
1356 switch (c)
1357 {
1358 case 9:
1359 break;
1360
1361 case ENTER:
1362 history_len--;
1363 FREE(history[history_len]);
1364 if (mlmode)
1365 {
1366 linenoiseEditMoveEnd(&l);
1367 }
1368
1369 # ifdef LH_HINTS
1370 if (hintsCallback)
1371 {
1372
1373
1374
1375
1376
1377
1378 linenoiseHintsCallback *hc = hintsCallback;
1379 hintsCallback = NULL;
1380 refreshLine(&l);
1381 hintsCallback = hc;
1382 }
1383
1384 # endif
1385 return ((int)l.len );
1386
1387 case CTRL_C:
1388 errno = EAGAIN;
1389 return ( -1 );
1390
1391 case BACKSPACE:
1392 case 8:
1393 linenoiseEditBackspace(&l);
1394 break;
1395
1396 case CTRL_D:
1397 if (l.len > 0)
1398 {
1399 linenoiseEditDelete(&l);
1400 }
1401 else
1402 {
1403 history_len--;
1404 FREE(history[history_len]);
1405 return ( -1 );
1406 }
1407
1408 break;
1409
1410 case CTRL_T:
1411 break;
1412
1413 case CTRL_B:
1414 linenoiseEditMoveLeft(&l);
1415 break;
1416
1417 case CTRL_F:
1418 linenoiseEditMoveRight(&l);
1419 break;
1420
1421 case CTRL_P:
1422 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
1423 break;
1424
1425 case CTRL_N:
1426 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
1427 break;
1428
1429 case ESC:
1430
1431
1432
1433
1434
1435
1436
1437 if (read(l.ifd, seq, 1) == -1)
1438 {
1439 break;
1440 }
1441
1442 if (read(l.ifd, seq + 1, 1) == -1)
1443 {
1444 break;
1445 }
1446
1447
1448 if (seq[0] == '[')
1449 {
1450 if (seq[1] >= '0' && seq[1] <= '9')
1451 {
1452
1453 if (read(l.ifd, seq + 2, 1) == -1)
1454 {
1455 break;
1456 }
1457
1458 if (seq[2] == '~')
1459 {
1460 switch (seq[1])
1461 {
1462 case '3':
1463 linenoiseEditDelete(&l);
1464 break;
1465
1466 case '6':
1467 linenoiseSearchInHistory(
1468 &l,
1469 LINENOISE_SEARCH_HISTORY_REVERSE);
1470 break;
1471
1472 case '5':
1473 linenoiseSearchInHistory(
1474 &l,
1475 LINENOISE_SEARCH_HISTORY_FORWARD);
1476 break;
1477 }
1478 }
1479 }
1480 else
1481 {
1482 switch (seq[1])
1483 {
1484 case 'A':
1485 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
1486 break;
1487
1488 case 'B':
1489 linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
1490 break;
1491
1492 case 'C':
1493 linenoiseEditMoveRight(&l);
1494 break;
1495
1496 case 'D':
1497 linenoiseEditMoveLeft(&l);
1498 break;
1499
1500 case 'H':
1501 linenoiseEditMoveHome(&l);
1502 break;
1503
1504 case 'F':
1505 linenoiseEditMoveEnd(&l);
1506 break;
1507 }
1508 }
1509 }
1510
1511 break;
1512
1513 default:
1514 if (linenoiseEditInsert(&l, c))
1515 {
1516 return ( -1 );
1517 }
1518
1519 break;
1520
1521 case CTRL_U:
1522 buf[0] = '\0';
1523 l.pos = l.len = 0;
1524 refreshLine(&l);
1525 break;
1526
1527 case CTRL_K:
1528 buf[l.pos] = '\0';
1529 l.len = l.pos;
1530 refreshLine(&l);
1531 break;
1532
1533 case CTRL_A:
1534 linenoiseEditMoveHome(&l);
1535 break;
1536
1537 case CTRL_E:
1538 linenoiseEditMoveEnd(&l);
1539 break;
1540
1541 case CTRL_L:
1542 linenoiseClearScreen();
1543 refreshLine(&l);
1544 break;
1545
1546 case CTRL_W:
1547 linenoiseEditDeletePrevWord(&l);
1548 break;
1549 }
1550 }
1551
1552 return ( -1 );
1553 }
1554
1555
1556
1557
1558
1559
1560 static int
1561 linenoiseRaw(char *buf, size_t buflen, const char *prompt)
1562 {
1563 int count;
1564
1565 if (buflen == 0)
1566 {
1567 errno = EINVAL;
1568 return ( -1 );
1569 }
1570
1571 if (enableRawMode(STDIN_FILENO) == -1)
1572 {
1573 return ( -1 );
1574 }
1575
1576 count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
1577 disableRawMode(STDIN_FILENO);
1578 printf("\n");
1579 return ( count );
1580 }
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590 static char *
1591 linenoiseNoTTY(void)
1592 {
1593 char *line = NULL;
1594 size_t len = 0, maxlen = 0;
1595
1596 while (1)
1597 {
1598 if (len == maxlen)
1599 {
1600 if (maxlen == 0)
1601 {
1602 maxlen = 16;
1603 }
1604
1605 maxlen *= 2;
1606 char *oldval = line;
1607 line = realloc(line, maxlen);
1608 if (line == NULL)
1609 {
1610 if (oldval)
1611 {
1612 FREE(oldval);
1613 }
1614
1615 return ( NULL );
1616 }
1617 }
1618
1619 int c = fgetc(stdin);
1620 if (c == EOF || c == '\n')
1621 {
1622 if (c == EOF && len == 0)
1623 {
1624 FREE(line);
1625 return ( NULL );
1626 }
1627 else
1628 {
1629 line[len] = '\0';
1630 return ( line );
1631 }
1632 }
1633 else
1634 {
1635 line[len] = c;
1636 len++;
1637 }
1638 }
1639
1640 return ( NULL );
1641 }
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651 char *
1652 linenoise(const char *prompt)
1653 {
1654 char buf[LINENOISE_MAX_LINE];
1655 int count;
1656
1657 if (!isatty(STDIN_FILENO))
1658 {
1659
1660
1661
1662
1663
1664
1665 return ( linenoiseNoTTY());
1666 }
1667 else if (isUnsupportedTerm())
1668 {
1669 size_t len;
1670
1671 printf("%s", prompt);
1672 fflush(stdout);
1673 if (fgets(buf, LINENOISE_MAX_LINE, stdin) == NULL)
1674 {
1675 return ( NULL );
1676 }
1677
1678 len = strlen(buf);
1679 while (len && ( buf[len - 1] == '\n' || buf[len - 1] == '\r' ))
1680 {
1681 len--;
1682 buf[len] = '\0';
1683 }
1684 return ( strdup(buf));
1685 }
1686 else
1687 {
1688 count = linenoiseRaw(buf, LINENOISE_MAX_LINE, prompt);
1689 if (count == -1)
1690 {
1691 return ( NULL );
1692 }
1693
1694 return ( strdup(buf));
1695 }
1696 }
1697
1698
1699
1700
1701
1702
1703
1704
1705 void
1706 linenoiseFree(void *ptr)
1707 {
1708 FREE(ptr);
1709 }
1710
1711
1712
1713
1714
1715
1716 static void
1717 freeHistory(void)
1718 {
1719 if (history)
1720 {
1721 int j;
1722
1723 for (j = 0; j < history_len; j++)
1724 {
1725 FREE(history[j]);
1726 }
1727
1728 FREE(history);
1729 }
1730 }
1731
1732
1733 static void
1734 linenoiseAtExit(void)
1735 {
1736 disableRawMode(STDIN_FILENO);
1737 freeHistory();
1738 }
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 int
1749 linenoiseHistoryAdd(const char *line)
1750 {
1751 char *linecopy;
1752
1753 if (history_max_len == 0)
1754 {
1755 return ( 0 );
1756 }
1757
1758
1759 if (history == NULL)
1760 {
1761 history = malloc(sizeof ( char * ) * history_max_len);
1762 if (history == NULL)
1763 {
1764 return ( 0 );
1765 }
1766
1767 memset(history, 0, ( sizeof ( char * ) * history_max_len ));
1768 }
1769
1770
1771 if (( history_len > 0 ) && ( !strcmp(history[history_len - 1], line)))
1772 {
1773 return ( 0 );
1774 }
1775
1776
1777
1778
1779
1780
1781 linecopy = strdup(line);
1782 if (!linecopy)
1783 {
1784 return ( 0 );
1785 }
1786
1787 if (history_len == history_max_len)
1788 {
1789 FREE(history[0]);
1790 memmove(
1791 history,
1792 history + 1,
1793 sizeof ( char * ) * ( history_max_len - 1 ));
1794 history_len--;
1795 }
1796
1797 history[history_len] = linecopy;
1798 history_len++;
1799 return ( 1 );
1800 }
1801
1802
1803
1804
1805
1806
1807
1808
1809 int
1810 linenoiseHistorySetMaxLen(int len)
1811 {
1812 char **new;
1813
1814 if (len < 1)
1815 {
1816 return ( 0 );
1817 }
1818
1819 if (history)
1820 {
1821 int tocopy = history_len;
1822
1823 new = malloc(sizeof ( char * ) * len);
1824 if (new == NULL)
1825 {
1826 return ( 0 );
1827 }
1828
1829
1830 if (len < tocopy)
1831 {
1832 int j;
1833
1834 for (j = 0; j < tocopy - len; j++)
1835 {
1836 FREE(history[j]);
1837 }
1838
1839 tocopy = len;
1840 }
1841
1842 memset(new, 0, sizeof ( char * ) * len);
1843 memcpy(
1844 new,
1845 history + ( history_len - tocopy ),
1846 sizeof ( char * ) * tocopy);
1847 FREE(history);
1848 history = new;
1849 }
1850
1851 history_max_len = len;
1852 if (history_len > history_max_len)
1853 {
1854 history_len = history_max_len;
1855 }
1856
1857 return ( 1 );
1858 }
1859
1860
1861 size_t
1862 pstrlen(const char *s)
1863 {
1864 size_t len = 0, i = 0;
1865
1866 while (s[i] != '\0')
1867 {
1868 if (s[i] == '\033')
1869 {
1870 i = strpbrk(s + i, "m") - s + 1;
1871 continue;
1872 }
1873
1874 len++;
1875 i++;
1876 }
1877 return ( len );
1878 }
1879
1880 #endif
1881
1882
1883
1884
1885