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