lineedit: print prompt and editing operations to stderr
For shells, this is mandated by standards function old new delta input_backward 215 231 +16 read_line_input 3015 3028 +13 draw_custom 66 78 +12 put_cur_glyph_and_inc_cursor 149 159 +10 put_prompt_custom 47 56 +9 show_history 40 46 +6 input_tab 927 933 +6 input_delete 136 142 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 8/0 up/down: 78/0) Total: 78 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
681e4f5d92
commit
fd47f05676
1 changed files with 34 additions and 28 deletions
|
@ -345,7 +345,7 @@ static unsigned save_string(char *dst, unsigned maxsize)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* I thought just fputwc(c, stdout) would work. But no... */
|
/* I thought just fputwc(c, stderr) would work. But no... */
|
||||||
static void BB_PUTCHAR(wchar_t c)
|
static void BB_PUTCHAR(wchar_t c)
|
||||||
{
|
{
|
||||||
if (unicode_status == UNICODE_ON) {
|
if (unicode_status == UNICODE_ON) {
|
||||||
|
@ -354,11 +354,11 @@ static void BB_PUTCHAR(wchar_t c)
|
||||||
ssize_t len = wcrtomb(buf, c, &mbst);
|
ssize_t len = wcrtomb(buf, c, &mbst);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
fputs_stdout(buf);
|
fputs(buf, stderr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* In this case, c is always one byte */
|
/* In this case, c is always one byte */
|
||||||
putchar(c);
|
bb_putchar_stderr(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
|
# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
|
||||||
|
@ -404,7 +404,7 @@ static void save_string(char *dst, unsigned maxsize)
|
||||||
safe_strncpy(dst, command_ps, maxsize);
|
safe_strncpy(dst, command_ps, maxsize);
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
# define BB_PUTCHAR(c) bb_putchar(c)
|
# define BB_PUTCHAR(c) bb_putchar_stderr(c)
|
||||||
/* Should never be called: */
|
/* Should never be called: */
|
||||||
int adjust_width_and_validate_wc(unsigned *width_adj, int wc);
|
int adjust_width_and_validate_wc(unsigned *width_adj, int wc);
|
||||||
#endif
|
#endif
|
||||||
|
@ -463,7 +463,7 @@ static void put_cur_glyph_and_inc_cursor(void)
|
||||||
if (c == BB_NUL)
|
if (c == BB_NUL)
|
||||||
c = ' ';
|
c = ' ';
|
||||||
BB_PUTCHAR(c);
|
BB_PUTCHAR(c);
|
||||||
bb_putchar('\b');
|
bb_putchar_stderr('\b');
|
||||||
#endif
|
#endif
|
||||||
cmdedit_y++;
|
cmdedit_y++;
|
||||||
if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) {
|
if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) {
|
||||||
|
@ -489,12 +489,12 @@ static void goto_new_line(void)
|
||||||
put_till_end_and_adv_cursor();
|
put_till_end_and_adv_cursor();
|
||||||
/* "cursor == 0" is only if prompt is "" and user input is empty */
|
/* "cursor == 0" is only if prompt is "" and user input is empty */
|
||||||
if (cursor == 0 || cmdedit_x != 0)
|
if (cursor == 0 || cmdedit_x != 0)
|
||||||
bb_putchar('\n');
|
bb_putchar_stderr('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
static void beep(void)
|
static void beep(void)
|
||||||
{
|
{
|
||||||
bb_putchar('\007');
|
bb_putchar_stderr('\007');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor.
|
/* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor.
|
||||||
|
@ -502,7 +502,10 @@ static void beep(void)
|
||||||
*/
|
*/
|
||||||
static void put_prompt_custom(bool is_full)
|
static void put_prompt_custom(bool is_full)
|
||||||
{
|
{
|
||||||
fputs_stdout((is_full ? cmdedit_prompt : prompt_last_line));
|
/* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||||
|
* says that shells must write $PSn to stderr, not stdout.
|
||||||
|
*/
|
||||||
|
fputs((is_full ? cmdedit_prompt : prompt_last_line), stderr);
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */
|
cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */
|
||||||
cmdedit_x = cmdedit_prmt_len % cmdedit_termw;
|
cmdedit_x = cmdedit_prmt_len % cmdedit_termw;
|
||||||
|
@ -539,15 +542,15 @@ static void input_backward(unsigned num)
|
||||||
/* This is longer by 5 bytes on x86.
|
/* This is longer by 5 bytes on x86.
|
||||||
* Also gets miscompiled for ARM users
|
* Also gets miscompiled for ARM users
|
||||||
* (busybox.net/bugs/view.php?id=2274).
|
* (busybox.net/bugs/view.php?id=2274).
|
||||||
* printf(("\b\b\b\b" + 4) - num);
|
* fprintf(("\b\b\b\b" + 4) - num, stderr);
|
||||||
* return;
|
* return;
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
bb_putchar('\b');
|
bb_putchar_stderr('\b');
|
||||||
} while (--num);
|
} while (--num);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf(ESC"[%uD", num);
|
fprintf(stderr, ESC"[%uD", num);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,7 +575,7 @@ static void input_backward(unsigned num)
|
||||||
*/
|
*/
|
||||||
unsigned sv_cursor;
|
unsigned sv_cursor;
|
||||||
/* go to 1st column; go up to first line */
|
/* go to 1st column; go up to first line */
|
||||||
printf("\r" ESC"[%uA", cmdedit_y);
|
fprintf(stderr, "\r" ESC"[%uA", cmdedit_y);
|
||||||
cmdedit_y = 0;
|
cmdedit_y = 0;
|
||||||
sv_cursor = cursor;
|
sv_cursor = cursor;
|
||||||
put_prompt_last_line(); /* sets cursor to 0 */
|
put_prompt_last_line(); /* sets cursor to 0 */
|
||||||
|
@ -587,12 +590,12 @@ static void input_backward(unsigned num)
|
||||||
cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw;
|
cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw;
|
||||||
cmdedit_y -= lines_up;
|
cmdedit_y -= lines_up;
|
||||||
/* go to 1st column; go up */
|
/* go to 1st column; go up */
|
||||||
printf("\r" ESC"[%uA", lines_up);
|
fprintf(stderr, "\r" ESC"[%uA", lines_up);
|
||||||
/* go to correct column.
|
/* go to correct column.
|
||||||
* xterm, konsole, Linux VT interpret 0 as 1 below! wow.
|
* xterm, konsole, Linux VT interpret 0 as 1 below! wow.
|
||||||
* need to *make sure* we skip it if cmdedit_x == 0 */
|
* need to *make sure* we skip it if cmdedit_x == 0 */
|
||||||
if (cmdedit_x)
|
if (cmdedit_x)
|
||||||
printf(ESC"[%uC", cmdedit_x);
|
fprintf(stderr, ESC"[%uC", cmdedit_x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,11 +603,11 @@ static void input_backward(unsigned num)
|
||||||
static void draw_custom(int y, int back_cursor, bool is_full)
|
static void draw_custom(int y, int back_cursor, bool is_full)
|
||||||
{
|
{
|
||||||
if (y > 0) /* up y lines */
|
if (y > 0) /* up y lines */
|
||||||
printf(ESC"[%uA", y);
|
fprintf(stderr, ESC"[%uA", y);
|
||||||
bb_putchar('\r');
|
bb_putchar_stderr('\r');
|
||||||
put_prompt_custom(is_full);
|
put_prompt_custom(is_full);
|
||||||
put_till_end_and_adv_cursor();
|
put_till_end_and_adv_cursor();
|
||||||
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
|
fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr);
|
||||||
input_backward(back_cursor);
|
input_backward(back_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,7 +652,7 @@ static void input_delete(int save)
|
||||||
command_len--;
|
command_len--;
|
||||||
put_till_end_and_adv_cursor();
|
put_till_end_and_adv_cursor();
|
||||||
/* Last char is still visible, erase it (and more) */
|
/* Last char is still visible, erase it (and more) */
|
||||||
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
|
fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr);
|
||||||
input_backward(cursor - j); /* back to old pos cursor */
|
input_backward(cursor - j); /* back to old pos cursor */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,8 +987,8 @@ static void remove_chunk(int16_t *int_buf, int beg, int end)
|
||||||
if (dbg_bmp) {
|
if (dbg_bmp) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; int_buf[i]; i++)
|
for (i = 0; int_buf[i]; i++)
|
||||||
bb_putchar((unsigned char)int_buf[i]);
|
bb_putchar_stderr((unsigned char)int_buf[i]);
|
||||||
bb_putchar('\n');
|
bb_putchar_stderr('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Caller ensures that match_buf points to a malloced buffer
|
/* Caller ensures that match_buf points to a malloced buffer
|
||||||
|
@ -1162,7 +1165,7 @@ static void showfiles(void)
|
||||||
int nc;
|
int nc;
|
||||||
|
|
||||||
for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) {
|
for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) {
|
||||||
printf("%s%-*s", matches[n],
|
fprintf(stderr, "%s%-*s", matches[n],
|
||||||
(int)(column_width - unicode_strwidth(matches[n])), ""
|
(int)(column_width - unicode_strwidth(matches[n])), ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1460,7 +1463,7 @@ void FAST_FUNC show_history(const line_input_t *st)
|
||||||
if (!st)
|
if (!st)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < st->cnt_history; i++)
|
for (i = 0; i < st->cnt_history; i++)
|
||||||
printf("%4d %s\n", i, st->history[i]);
|
fprintf(stderr, "%4d %s\n", i, st->history[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
# if ENABLE_FEATURE_EDITING_SAVEHISTORY
|
# if ENABLE_FEATURE_EDITING_SAVEHISTORY
|
||||||
|
@ -1900,7 +1903,7 @@ static void ask_terminal(void)
|
||||||
pfd.events = POLLIN;
|
pfd.events = POLLIN;
|
||||||
if (safe_poll(&pfd, 1, 0) == 0) {
|
if (safe_poll(&pfd, 1, 0) == 0) {
|
||||||
S.sent_ESC_br6n = 1;
|
S.sent_ESC_br6n = 1;
|
||||||
fputs_stdout(ESC"[6n");
|
fputs(ESC"[6n", stderr);
|
||||||
fflush_all(); /* make terminal see it ASAP! */
|
fflush_all(); /* make terminal see it ASAP! */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2639,13 +2642,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
|
||||||
/* Control-k -- clear to end of line */
|
/* Control-k -- clear to end of line */
|
||||||
command_ps[cursor] = BB_NUL;
|
command_ps[cursor] = BB_NUL;
|
||||||
command_len = cursor;
|
command_len = cursor;
|
||||||
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
|
fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr);
|
||||||
break;
|
break;
|
||||||
case CTRL('L'):
|
case CTRL('L'):
|
||||||
vi_case(CTRL('L')|VI_CMDMODE_BIT:)
|
vi_case(CTRL('L')|VI_CMDMODE_BIT:)
|
||||||
/* Control-l -- clear screen */
|
/* Control-l -- clear screen */
|
||||||
/* cursor to top,left; clear to the end of screen */
|
/* cursor to top,left; clear to the end of screen */
|
||||||
printf(ESC"[H" ESC"[J");
|
fputs(ESC"[H" ESC"[J", stderr);
|
||||||
draw_full(command_len - cursor);
|
draw_full(command_len - cursor);
|
||||||
break;
|
break;
|
||||||
#if MAX_HISTORY > 0
|
#if MAX_HISTORY > 0
|
||||||
|
@ -2832,8 +2835,8 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
|
||||||
beep();
|
beep();
|
||||||
} else {
|
} else {
|
||||||
command_ps[cursor] = ic;
|
command_ps[cursor] = ic;
|
||||||
bb_putchar(ic);
|
bb_putchar_stderr(ic);
|
||||||
bb_putchar('\b');
|
bb_putchar_stderr('\b');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '\x1b': /* ESC */
|
case '\x1b': /* ESC */
|
||||||
|
@ -3027,7 +3030,10 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
|
||||||
#undef read_line_input
|
#undef read_line_input
|
||||||
int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize)
|
int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize)
|
||||||
{
|
{
|
||||||
fputs_stdout(prompt);
|
/* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
|
||||||
|
* says that shells must write $PSn to stderr, not stdout.
|
||||||
|
*/
|
||||||
|
fputs(prompt, stderr);
|
||||||
fflush_all();
|
fflush_all();
|
||||||
if (!fgets(command, maxsize, stdin))
|
if (!fgets(command, maxsize, stdin))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue