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