diff options
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r-- | libbb/lineedit.c | 126 |
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 |
358 | static void put_cur_glyph_and_inc_cursor(void) | 358 | static 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 | ||
421 | static 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) */ |
421 | static void put_till_end_and_adv_cursor(void) | 457 | static 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) | |||
610 | static void input_forward(void) | 648 | static 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 | ||
684 | static 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 | ||