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