aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 31e392147..5d9080131 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -354,7 +354,7 @@ int adjust_width_and_validate_wc(unsigned *width_adj, int wc);
354/* Put 'command_ps[cursor]', cursor++. 354/* Put 'command_ps[cursor]', cursor++.
355 * Advance cursor on screen. If we reached right margin, scroll text up 355 * Advance cursor on screen. If we reached right margin, scroll text up
356 * and remove terminal margin effect by printing 'next_char' */ 356 * and remove terminal margin effect by printing 'next_char' */
357#define HACK_FOR_WRONG_WIDTH 1 357#define HACK_FOR_WRONG_WIDTH 1 && !ENABLE_PLATFORM_MINGW32
358static void put_cur_glyph_and_inc_cursor(void) 358static void put_cur_glyph_and_inc_cursor(void)
359{ 359{
360 CHAR_T c = command_ps[cursor]; 360 CHAR_T c = command_ps[cursor];
@@ -417,6 +417,42 @@ static void put_cur_glyph_and_inc_cursor(void)
417 } 417 }
418} 418}
419 419
420#if ENABLE_PLATFORM_MINGW32
421static void inc_cursor(void)
422{
423 CHAR_T c = command_ps[cursor];
424 unsigned width = 0;
425 int ofs_to_right;
426
427 /* advance cursor */
428 cursor++;
429 if (unicode_status == UNICODE_ON) {
430 IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;)
431 c = adjust_width_and_validate_wc(&cmdedit_x, c);
432 IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;)
433 } else {
434 cmdedit_x++;
435 }
436
437 ofs_to_right = cmdedit_x - cmdedit_termw;
438 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) {
439 /* cursor remains on this line */
440 printf(ESC"[1C");
441 }
442
443 if (ofs_to_right >= 0) {
444 /* we go to the next line */
445 printf(ESC"[1B");
446 bb_putchar('\r');
447 cmdedit_y++;
448 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) {
449 width = 0;
450 }
451 cmdedit_x = width;
452 }
453}
454#endif
455
420/* Move to end of line (by printing all chars till the end) */ 456/* Move to end of line (by printing all chars till the end) */
421static void put_till_end_and_adv_cursor(void) 457static void put_till_end_and_adv_cursor(void)
422{ 458{
@@ -469,6 +505,7 @@ static void input_backward(unsigned num)
469 505
470 if (cmdedit_x >= num) { 506 if (cmdedit_x >= num) {
471 cmdedit_x -= num; 507 cmdedit_x -= num;
508#if !ENABLE_PLATFORM_MINGW32
472 if (num <= 4) { 509 if (num <= 4) {
473 /* This is longer by 5 bytes on x86. 510 /* This is longer by 5 bytes on x86.
474 * Also gets miscompiled for ARM users 511 * Also gets miscompiled for ARM users
@@ -481,6 +518,7 @@ static void input_backward(unsigned num)
481 } while (--num); 518 } while (--num);
482 return; 519 return;
483 } 520 }
521#endif
484 printf(ESC"[%uD", num); 522 printf(ESC"[%uD", num);
485 return; 523 return;
486 } 524 }
@@ -610,7 +648,11 @@ static void input_backspace(void)
610static void input_forward(void) 648static void input_forward(void)
611{ 649{
612 if (cursor < command_len) 650 if (cursor < command_len)
651#if !ENABLE_PLATFORM_MINGW32
613 put_cur_glyph_and_inc_cursor(); 652 put_cur_glyph_and_inc_cursor();
653#else
654 inc_cursor();
655#endif
614} 656}
615 657
616#if ENABLE_FEATURE_TAB_COMPLETION 658#if ENABLE_FEATURE_TAB_COMPLETION
@@ -638,6 +680,14 @@ static void add_match(char *matched)
638 num_matches++; 680 num_matches++;
639} 681}
640 682
683#if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1
684static void add_partial_match(const char *part, const char *full, int plen)
685{
686 if (strncmp(part, full, plen) == 0)
687 add_match(xstrdup(full));
688}
689#endif
690
641# if ENABLE_FEATURE_USERNAME_COMPLETION 691# if ENABLE_FEATURE_USERNAME_COMPLETION
642/* Replace "~user/..." with "/homedir/...". 692/* Replace "~user/..." with "/homedir/...".
643 * The parameter is malloced, free it or return it 693 * The parameter is malloced, free it or return it
@@ -718,7 +768,11 @@ static int path_parse(char ***p)
718 tmp = (char*)pth; 768 tmp = (char*)pth;
719 npth = 1; /* path component count */ 769 npth = 1; /* path component count */
720 while (1) { 770 while (1) {
771#if ENABLE_PLATFORM_MINGW32
772 tmp = (char *)next_path_sep(tmp);
773#else
721 tmp = strchr(tmp, ':'); 774 tmp = strchr(tmp, ':');
775#endif
722 if (!tmp) 776 if (!tmp)
723 break; 777 break;
724 tmp++; 778 tmp++;
@@ -731,7 +785,11 @@ static int path_parse(char ***p)
731 res[0] = tmp = xstrdup(pth); 785 res[0] = tmp = xstrdup(pth);
732 npth = 1; 786 npth = 1;
733 while (1) { 787 while (1) {
788#if ENABLE_PLATFORM_MINGW32
789 tmp = (char *)next_path_sep(tmp);
790#else
734 tmp = strchr(tmp, ':'); 791 tmp = strchr(tmp, ':');
792#endif
735 if (!tmp) 793 if (!tmp)
736 break; 794 break;
737 *tmp++ = '\0'; /* ':' -> '\0' */ 795 *tmp++ = '\0'; /* ':' -> '\0' */
@@ -781,11 +839,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
781 const char *p = applet_names; 839 const char *p = applet_names;
782 840
783 while (*p) { 841 while (*p) {
784 if (strncmp(pfind, p, pf_len) == 0) 842 add_partial_match(pfind, p, pf_len);
785 add_match(xstrdup(p));
786 while (*p++ != '\0') 843 while (*p++ != '\0')
787 continue; 844 continue;
788 } 845 }
846 add_partial_match(pfind, "busybox", pf_len);
789 } 847 }
790#endif 848#endif
791 849
@@ -817,6 +875,9 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
817 if (stat(found, &st) && lstat(found, &st)) 875 if (stat(found, &st) && lstat(found, &st))
818 goto cont; /* hmm, remove in progress? */ 876 goto cont; /* hmm, remove in progress? */
819 877
878 if (type == FIND_EXE_ONLY && !file_is_executable(found))
879 goto cont;
880
820 /* Save only name */ 881 /* Save only name */
821 len = strlen(name_found); 882 len = strlen(name_found);
822 found = xrealloc(found, len + 2); /* +2: for slash and NUL */ 883 found = xrealloc(found, len + 2); /* +2: for slash and NUL */
@@ -1898,7 +1959,16 @@ static void parse_and_put_prompt(const char *prmt_ptr)
1898 char *after_home_user; 1959 char *after_home_user;
1899 1960
1900 /* /home/user[/something] -> ~[/something] */ 1961 /* /home/user[/something] -> ~[/something] */
1962#if !ENABLE_PLATFORM_MINGW32
1901 after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); 1963 after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf);
1964#else
1965 after_home_user = NULL;
1966 l = strlen(home_pwd_buf);
1967 if (l != 0
1968 && strncasecmp(home_pwd_buf, cwd_buf, l) == 0) {
1969 after_home_user = cwd_buf + l;
1970 }
1971#endif
1902 if (after_home_user 1972 if (after_home_user
1903 && (*after_home_user == '/' || *after_home_user == '\0') 1973 && (*after_home_user == '/' || *after_home_user == '\0')
1904 ) { 1974 ) {
@@ -2272,9 +2342,16 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2272 2342
2273 INIT_S(); 2343 INIT_S();
2274 2344
2345#if ENABLE_PLATFORM_MINGW32
2346 memset(initial_settings.c_cc, 0, sizeof(initial_settings.c_cc));
2347 initial_settings.c_cc[VINTR] = CTRL('C');
2348 initial_settings.c_cc[VEOF] = CTRL('D');
2349 if (!isatty(0) || !isatty(1)) {
2350#else
2275 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 2351 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
2276 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON 2352 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON
2277 ) { 2353 ) {
2354#endif
2278 /* Happens when e.g. stty -echo was run before. 2355 /* Happens when e.g. stty -echo was run before.
2279 * But if ICANON is not set, we don't come here. 2356 * But if ICANON is not set, we don't come here.
2280 * (example: interactive python ^Z-backgrounded, 2357 * (example: interactive python ^Z-backgrounded,
@@ -2383,6 +2460,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2383 } 2460 }
2384 2461
2385 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); 2462 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
2463#if ENABLE_PLATFORM_MINGW32
2464 /* scroll to cursor position on any keypress */
2465 if (isatty(fileno(stdin)) && isatty(fileno(stdout)))
2466 move_cursor_row(0);
2467#endif
2386 2468
2387#if ENABLE_FEATURE_REVERSE_SEARCH 2469#if ENABLE_FEATURE_REVERSE_SEARCH
2388 again: 2470 again:
@@ -2650,6 +2732,44 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2650 vi_cmdmode = 1; 2732 vi_cmdmode = 1;
2651 input_backward(1); 2733 input_backward(1);
2652 } 2734 }
2735 /* Handle a few ESC-<key> combinations the same way
2736 * standard readline bindings (IOW: bash) do.
2737 * Often, Alt-<key> generates ESC-<key>.
2738 */
2739 ic = lineedit_read_key(read_key_buffer, 20);
2740 switch (ic) {
2741 //case KEYCODE_LEFT: - bash doesn't do this
2742 case 'b':
2743 ctrl_left();
2744 break;
2745 //case KEYCODE_RIGHT: - bash doesn't do this
2746 case 'f':
2747 ctrl_right();
2748 break;
2749 //case KEYCODE_DELETE: - bash doesn't do this
2750 case 'd': /* Alt-D */
2751 {
2752 /* Delete word forward */
2753 int nc, sc = cursor;
2754 ctrl_right();
2755 nc = cursor - sc;
2756 input_backward(nc);
2757 while (--nc >= 0)
2758 input_delete(1);
2759 break;
2760 }
2761 case '\b': /* Alt-Backspace(?) */
2762 case '\x7f': /* Alt-Backspace(?) */
2763 //case 'w': - bash doesn't do this
2764 {
2765 /* Delete word backward */
2766 int sc = cursor;
2767 ctrl_left();
2768 while (sc-- > cursor)
2769 input_delete(1);
2770 break;
2771 }
2772 }
2653 break; 2773 break;
2654#endif /* FEATURE_COMMAND_EDITING_VI */ 2774#endif /* FEATURE_COMMAND_EDITING_VI */
2655 2775