]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/cli_readline.c
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * Add to readline cmdline-editing by
7 * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
9 * SPDX-License-Identifier: GPL-2.0+
18 #include "con-utils.h"
19 #include "print-utils.h"
21 #include "cli_readline.h"
23 char console_buffer
[CONFIG_SYS_CBSIZE
+ 1]; /* console I/O buffer */
25 static const FLASH
char erase_seq
[] = "\b \b"; /* erase sequence */
26 static const FLASH
char tab_seq
[] = " "; /* used to expand TABs */
28 #ifndef CONFIG_CMDLINE_EDITING
29 static char *delete_char (char *buffer
, char *p
, int *colp
, int *np
, int plen
)
36 if (*(--p
) == '\t') { /* will retype the whole line */
37 while (*colp
> plen
) {
41 for (s
= buffer
; s
< p
; ++s
) {
43 my_puts_P(tab_seq
+ ((*colp
) & 07));
44 *colp
+= 8 - ((*colp
) & 07);
58 #endif /* CONFIG_CMDLINE_EDITING */
61 #ifdef CONFIG_CMDLINE_EDITING
64 * cmdline-editing related codes from vivi.
65 * Author: Janghoon Lyu <nandy@mizi.com>
68 static void putnstr(char *str
, int n
)
70 /* printf_P(PSTR("%.*s"), (int)n, str) */
76 #define CTL_CH(c) ((c) - 'a' + 1)
77 #define CTL_BACKSPACE ('\b')
78 #define DEL ((char)255)
79 #define DEL7 ((char)127)
80 #define CREAD_HIST_CHAR ('!')
82 #define getcmd_putch(ch) putchar(ch)
83 #define getcmd_getch() my_getchar(1)
84 #define getcmd_cbeep() getcmd_putch('\a')
87 #define HIST_SIZE CONFIG_SYS_CBSIZE
90 static int hist_add_idx
;
91 static int hist_cur
= -1;
92 static unsigned hist_num
;
94 static char *hist_list
[HIST_MAX
];
95 static char hist_lines
[HIST_MAX
][HIST_SIZE
+ 1]; /* Save room for NULL */
97 #define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
99 static void hist_init(void)
108 for (i
= 0; i
< HIST_MAX
; i
++) {
109 hist_list
[i
] = hist_lines
[i
];
110 hist_list
[i
][0] = '\0';
114 static void cread_add_to_hist(char *line
)
116 strcpy(hist_list
[hist_add_idx
], line
);
118 if (++hist_add_idx
>= HIST_MAX
)
121 if (hist_add_idx
> hist_max
)
122 hist_max
= hist_add_idx
;
127 static char *hist_prev(void)
139 if (hist_cur
== hist_add_idx
) {
143 ret
= hist_list
[hist_cur
];
149 static char *hist_next(void)
156 if (hist_cur
== hist_add_idx
)
159 if (++hist_cur
> hist_max
)
162 if (hist_cur
== hist_add_idx
)
165 ret
= hist_list
[hist_cur
];
170 #ifndef CONFIG_CMDLINE_EDITING
171 static void cread_print_hist_list(void)
176 n
= hist_num
- hist_max
;
178 i
= hist_add_idx
+ 1;
182 if (i
== hist_add_idx
)
184 printf_P(PSTR("%s\n"), hist_list
[i
]);
189 #endif /* CONFIG_CMDLINE_EDITING */
191 #define BEGINNING_OF_LINE() { \
193 getcmd_putch(CTL_BACKSPACE); \
198 #define ERASE_TO_EOL() { \
199 if (num < eol_num) { \
200 /* printf_P(PSTR("%*S"), (int)(eol_num - num), PSTR("")); */ \
201 print_blanks(eol_num - num); \
203 getcmd_putch(CTL_BACKSPACE); \
204 } while (--eol_num > num); \
208 #define REFRESH_TO_EOL() { \
209 if (num < eol_num) { \
210 wlen = eol_num - num; \
211 putnstr(buf + num, wlen); \
216 static void cread_add_char(char ichar
, int insert
, unsigned int *num
,
217 unsigned int *eol_num
, char *buf
, unsigned int len
)
222 if (insert
|| *num
== *eol_num
) {
223 if (*eol_num
> len
- 1) {
231 wlen
= *eol_num
- *num
;
233 memmove(&buf
[*num
+1], &buf
[*num
], wlen
-1);
236 putnstr(buf
+ *num
, wlen
);
239 getcmd_putch(CTL_BACKSPACE
);
241 /* echo the character */
244 putnstr(buf
+ *num
, wlen
);
249 static void cread_add_str(char *str
, int strsize
, int insert
,
250 unsigned int *num
, unsigned int *eol_num
,
251 char *buf
, unsigned int len
)
254 cread_add_char(*str
, insert
, num
, eol_num
, buf
, len
);
259 static int cread_line(const FLASH
char *const prompt
, char *buf
, unsigned int *len
)
261 unsigned int num
= 0;
262 unsigned int eol_num
= 0;
268 int init_len
= strlen(buf
);
273 cread_add_str(buf
, init_len
, 1, &num
, &eol_num
, buf
, *len
);
276 ichar
= getcmd_getch();
278 if ((ichar
== '\n') || (ichar
== '\r')) {
284 * handle standard linux xterm esc sequences for arrow key, etc.
289 esc_save
[esc_len
] = ichar
;
292 cread_add_str(esc_save
, esc_len
,
293 insert
, &num
, &eol_num
,
301 case 'D': /* <- key */
305 case 'C': /* -> key */
308 break; /* pass off to ^F handler */
309 case 'H': /* Home key */
312 break; /* pass off to ^A handler */
313 case 'A': /* up arrow */
316 break; /* pass off to ^P handler */
317 case 'B': /* down arrow */
320 break; /* pass off to ^N handler */
322 esc_save
[esc_len
++] = ichar
;
323 cread_add_str(esc_save
, esc_len
, insert
,
324 &num
, &eol_num
, buf
, *len
);
333 esc_save
[esc_len
] = ichar
;
336 my_puts_P(PSTR("impossible condition #876\n"));
344 case CTL_CH('c'): /* ^C - break */
345 *buf
= '\0'; /* discard input */
349 getcmd_putch(buf
[num
]);
355 getcmd_putch(CTL_BACKSPACE
);
361 wlen
= eol_num
- num
- 1;
363 memmove(&buf
[num
], &buf
[num
+1], wlen
);
364 putnstr(buf
+ num
, wlen
);
369 getcmd_putch(CTL_BACKSPACE
);
392 wlen
= eol_num
- num
;
394 memmove(&buf
[num
], &buf
[num
+1], wlen
);
395 getcmd_putch(CTL_BACKSPACE
);
396 putnstr(buf
+ num
, wlen
);
399 getcmd_putch(CTL_BACKSPACE
);
411 if (ichar
== CTL_CH('p'))
421 /* nuke the current line */
425 /* erase to end of line */
428 /* copy new line into place and display */
430 eol_num
= strlen(buf
);
434 #ifdef CONFIG_AUTO_COMPLETE
438 /* do not autocomplete when in the middle */
445 col
= strlen_P(prompt
) + eol_num
;
447 if (cmd_auto_complete(prompt
, buf
, &num2
, &col
)) {
456 cread_add_char(ichar
, insert
, &num
, &eol_num
, buf
,
462 buf
[eol_num
] = '\0'; /* lose the newline */
464 if (buf
[0] && buf
[0] != CREAD_HIST_CHAR
)
465 cread_add_to_hist(buf
);
466 hist_cur
= hist_add_idx
;
471 #endif /* CONFIG_CMDLINE_EDITING */
473 /****************************************************************************/
475 static int cli_readline_into_buffer(const FLASH
char *const prompt
, char *buffer
)
478 #ifdef CONFIG_CMDLINE_EDITING
479 unsigned int len
= CONFIG_SYS_CBSIZE
;
491 rc
= cread_line(prompt
, p
, &len
);
492 return rc
< 0 ? rc
: (int) len
;
494 #else /* CONFIG_CMDLINE_EDITING */
496 int n
= 0; /* buffer index */
497 int plen
= 0; /* prompt length */
498 int col
; /* output column cnt */
503 plen
= strlen_P(prompt
);
513 * Special character handling
516 case '\r': /* Enter */
519 my_puts_P(PSTR("\r\n"));
525 case 0x03: /* ^C - break */
526 p_buf
[0] = '\0'; /* discard input */
529 case 0x15: /* ^U - erase line */
531 my_puts_P(erase_seq
);
538 case 0x17: /* ^W - erase word */
539 p
= delete_char(p_buf
, p
, &col
, &n
, plen
);
540 while ((n
> 0) && (*p
!= ' '))
541 p
= delete_char(p_buf
, p
, &col
, &n
, plen
);
544 case 0x08: /* ^H - backspace */
545 case 0x7F: /* DEL - backspace */
546 p
= delete_char(p_buf
, p
, &col
, &n
, plen
);
551 * Must be a normal character then
553 if (n
< CONFIG_SYS_CBSIZE
-2) {
554 if (c
== '\t') { /* expand TABs */
555 #ifdef CONFIG_AUTO_COMPLETE
557 * if auto completion triggered just
561 if (cmd_auto_complete(prompt
,
564 p
= p_buf
+ n
; /* reset */
568 my_puts_P(tab_seq
+ (col
& 07));
569 col
+= 8 - (col
& 07);
574 * Echo input using puts() to force an
575 * LCD flush if we are using an LCD
584 } else { /* Buffer full */
589 #endif /* CONFIG_CMDLINE_EDITING */
592 int cli_readline(const FLASH
char *const prompt
)
595 * If console_buffer isn't 0-length the user will be prompted to modify
596 * it instead of entering it from scratch as desired.
598 console_buffer
[0] = '\0';
600 return cli_readline_into_buffer(prompt
, console_buffer
);