diff options
author | "Vladimir N. Oleynik" <dzo@simtreas.ru> | 2006-01-25 11:53:47 +0000 |
---|---|---|
committer | "Vladimir N. Oleynik" <dzo@simtreas.ru> | 2006-01-25 11:53:47 +0000 |
commit | fdb871c4988c4426fd119f7b311540253d141ac2 (patch) | |
tree | 1f01feb96a0f8063243b3913744a7aebd14fd22a | |
parent | 7d501a867388cb1f1f0117cbb440598b5418bcad (diff) | |
download | busybox-w32-fdb871c4988c4426fd119f7b311540253d141ac2.tar.gz busybox-w32-fdb871c4988c4426fd119f7b311540253d141ac2.tar.bz2 busybox-w32-fdb871c4988c4426fd119f7b311540253d141ac2.zip |
Add more bash-like dot-dirs cmdedit feature
Close bug 648.
Restore my whitespace
-rw-r--r-- | shell/ash.c | 4 | ||||
-rw-r--r-- | shell/cmdedit.c | 203 |
2 files changed, 109 insertions, 98 deletions
diff --git a/shell/ash.c b/shell/ash.c index 69062e02d..671069771 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -841,7 +841,7 @@ static int SIT(int c, int syntax) | |||
841 | return S_I_T[indx][syntax]; | 841 | return S_I_T[indx][syntax]; |
842 | } | 842 | } |
843 | 843 | ||
844 | #else /* USE_SIT_FUNCTION */ | 844 | #else /* USE_SIT_FUNCTION */ |
845 | 845 | ||
846 | #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax] | 846 | #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax] |
847 | 847 | ||
@@ -1142,7 +1142,7 @@ static const char syntax_index_table[258] = { | |||
1142 | /* 257 127 */ CWORD_CWORD_CWORD_CWORD, | 1142 | /* 257 127 */ CWORD_CWORD_CWORD_CWORD, |
1143 | }; | 1143 | }; |
1144 | 1144 | ||
1145 | #endif /* USE_SIT_FUNCTION */ | 1145 | #endif /* USE_SIT_FUNCTION */ |
1146 | 1146 | ||
1147 | /* alias.c */ | 1147 | /* alias.c */ |
1148 | 1148 | ||
diff --git a/shell/cmdedit.c b/shell/cmdedit.c index db246315c..f999b88e9 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c | |||
@@ -67,7 +67,7 @@ | |||
67 | #define CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT | 67 | #define CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT |
68 | #define CONFIG_FEATURE_CLEAN_UP | 68 | #define CONFIG_FEATURE_CLEAN_UP |
69 | 69 | ||
70 | #endif /* TEST */ | 70 | #endif /* TEST */ |
71 | 71 | ||
72 | #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION | 72 | #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION |
73 | #include <dirent.h> | 73 | #include <dirent.h> |
@@ -82,7 +82,7 @@ | |||
82 | 82 | ||
83 | #ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR | 83 | #ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR |
84 | #include "pwd_.h" | 84 | #include "pwd_.h" |
85 | #endif /* advanced FEATURES */ | 85 | #endif /* advanced FEATURES */ |
86 | 86 | ||
87 | 87 | ||
88 | /* Maximum length of the linked list for the command line history */ | 88 | /* Maximum length of the linked list for the command line history */ |
@@ -177,7 +177,7 @@ static void win_changed(int nsig) | |||
177 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | 177 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); |
178 | else if (nsig == SIGWINCH) /* signaled called handler */ | 178 | else if (nsig == SIGWINCH) /* signaled called handler */ |
179 | signal(SIGWINCH, win_changed); /* set for next call */ | 179 | signal(SIGWINCH, win_changed); /* set for next call */ |
180 | else /* nsig == 0 */ | 180 | else /* nsig == 0 */ |
181 | /* set previous handler */ | 181 | /* set previous handler */ |
182 | signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */ | 182 | signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */ |
183 | } | 183 | } |
@@ -444,7 +444,7 @@ static void redraw(int y, int back_cursor) | |||
444 | #ifdef CONFIG_FEATURE_COMMAND_EDITING_VI | 444 | #ifdef CONFIG_FEATURE_COMMAND_EDITING_VI |
445 | static char delbuf[BUFSIZ]; /* a place to store deleted characters */ | 445 | static char delbuf[BUFSIZ]; /* a place to store deleted characters */ |
446 | static char *delp = delbuf; | 446 | static char *delp = delbuf; |
447 | static int newdelflag; /* whether delbuf should be reused yet */ | 447 | static int newdelflag; /* whether delbuf should be reused yet */ |
448 | #endif | 448 | #endif |
449 | 449 | ||
450 | /* Delete the char in front of the cursor, optionally saving it | 450 | /* Delete the char in front of the cursor, optionally saving it |
@@ -563,6 +563,22 @@ static void cmdedit_init(void) | |||
563 | 563 | ||
564 | #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION | 564 | #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION |
565 | 565 | ||
566 | static char **matches; | ||
567 | static int num_matches; | ||
568 | static char *add_char_to_match; | ||
569 | |||
570 | static void add_match(char *matched, int add_char) | ||
571 | { | ||
572 | int nm = num_matches; | ||
573 | int nm1 = nm + 1; | ||
574 | |||
575 | matches = xrealloc(matches, nm1 * sizeof(char *)); | ||
576 | add_char_to_match = xrealloc(add_char_to_match, nm1); | ||
577 | matches[nm] = matched; | ||
578 | add_char_to_match[nm] = (char)add_char; | ||
579 | num_matches++; | ||
580 | } | ||
581 | |||
566 | static int is_execute(const struct stat *st) | 582 | static int is_execute(const struct stat *st) |
567 | { | 583 | { |
568 | if ((!my_euid && (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) || | 584 | if ((!my_euid && (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) || |
@@ -574,19 +590,18 @@ static int is_execute(const struct stat *st) | |||
574 | 590 | ||
575 | #ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION | 591 | #ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION |
576 | 592 | ||
577 | static char **username_tab_completion(char *ud, int *num_matches) | 593 | static void username_tab_completion(char *ud, char *with_shash_flg) |
578 | { | 594 | { |
579 | struct passwd *entry; | 595 | struct passwd *entry; |
580 | int userlen; | 596 | int userlen; |
581 | char *temp; | ||
582 | |||
583 | 597 | ||
584 | ud++; /* ~user/... to user/... */ | 598 | ud++; /* ~user/... to user/... */ |
585 | userlen = strlen(ud); | 599 | userlen = strlen(ud); |
586 | 600 | ||
587 | if (num_matches == 0) { /* "~/..." or "~user/..." */ | 601 | if (with_shash_flg) { /* "~/..." or "~user/..." */ |
588 | char *sav_ud = ud - 1; | 602 | char *sav_ud = ud - 1; |
589 | char *home = 0; | 603 | char *home = 0; |
604 | char *temp; | ||
590 | 605 | ||
591 | if (*ud == '/') { /* "~/..." */ | 606 | if (*ud == '/') { /* "~/..." */ |
592 | home = home_pwd_buf; | 607 | home = home_pwd_buf; |
@@ -609,28 +624,18 @@ static char **username_tab_completion(char *ud, int *num_matches) | |||
609 | strcpy(sav_ud, temp2); | 624 | strcpy(sav_ud, temp2); |
610 | } | 625 | } |
611 | } | 626 | } |
612 | return 0; /* void, result save to argument :-) */ | ||
613 | } else { | 627 | } else { |
614 | /* "~[^/]*" */ | 628 | /* "~[^/]*" */ |
615 | char **matches = (char **) NULL; | ||
616 | int nm = 0; | ||
617 | |||
618 | setpwent(); | 629 | setpwent(); |
619 | 630 | ||
620 | while ((entry = getpwent()) != NULL) { | 631 | while ((entry = getpwent()) != NULL) { |
621 | /* Null usernames should result in all users as possible completions. */ | 632 | /* Null usernames should result in all users as possible completions. */ |
622 | if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) { | 633 | if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) { |
623 | 634 | add_match(bb_xasprintf("~%s", entry->pw_name), '/'); | |
624 | temp = bb_xasprintf("~%s/", entry->pw_name); | ||
625 | matches = xrealloc(matches, (nm + 1) * sizeof(char *)); | ||
626 | |||
627 | matches[nm++] = temp; | ||
628 | } | 635 | } |
629 | } | 636 | } |
630 | 637 | ||
631 | endpwent(); | 638 | endpwent(); |
632 | (*num_matches) = nm; | ||
633 | return (matches); | ||
634 | } | 639 | } |
635 | } | 640 | } |
636 | #endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */ | 641 | #endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */ |
@@ -693,7 +698,7 @@ static int path_parse(char ***p, int flags) | |||
693 | return npth; | 698 | return npth; |
694 | } | 699 | } |
695 | 700 | ||
696 | static char *add_quote_for_spec_chars(char *found) | 701 | static char *add_quote_for_spec_chars(char *found, int add) |
697 | { | 702 | { |
698 | int l = 0; | 703 | int l = 0; |
699 | char *s = xmalloc((strlen(found) + 1) * 2); | 704 | char *s = xmalloc((strlen(found) + 1) * 2); |
@@ -703,19 +708,17 @@ static char *add_quote_for_spec_chars(char *found) | |||
703 | s[l++] = '\\'; | 708 | s[l++] = '\\'; |
704 | s[l++] = *found++; | 709 | s[l++] = *found++; |
705 | } | 710 | } |
711 | if(add) | ||
712 | s[l++] = (char)add; | ||
706 | s[l] = 0; | 713 | s[l] = 0; |
707 | return s; | 714 | return s; |
708 | } | 715 | } |
709 | 716 | ||
710 | static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | 717 | static void exe_n_cwd_tab_completion(char *command, int type) |
711 | int type) | ||
712 | { | 718 | { |
713 | |||
714 | char **matches = 0; | ||
715 | DIR *dir; | 719 | DIR *dir; |
716 | struct dirent *next; | 720 | struct dirent *next; |
717 | char dirbuf[BUFSIZ]; | 721 | char dirbuf[BUFSIZ]; |
718 | int nm = *num_matches; | ||
719 | struct stat st; | 722 | struct stat st; |
720 | char *path1[1]; | 723 | char *path1[1]; |
721 | char **paths = path1; | 724 | char **paths = path1; |
@@ -738,7 +741,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | |||
738 | dirbuf[(pfind - command) + 1] = 0; | 741 | dirbuf[(pfind - command) + 1] = 0; |
739 | #ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION | 742 | #ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION |
740 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ | 743 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ |
741 | username_tab_completion(dirbuf, 0); | 744 | username_tab_completion(dirbuf, dirbuf); |
742 | #endif | 745 | #endif |
743 | /* "strip" dirname in command */ | 746 | /* "strip" dirname in command */ |
744 | pfind++; | 747 | pfind++; |
@@ -755,6 +758,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | |||
755 | 758 | ||
756 | while ((next = readdir(dir)) != NULL) { | 759 | while ((next = readdir(dir)) != NULL) { |
757 | char *str_found = next->d_name; | 760 | char *str_found = next->d_name; |
761 | int add_chr = 0; | ||
758 | 762 | ||
759 | /* matched ? */ | 763 | /* matched ? */ |
760 | if (strncmp(str_found, pfind, strlen(pfind))) | 764 | if (strncmp(str_found, pfind, strlen(pfind))) |
@@ -775,23 +779,22 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, | |||
775 | strcpy(found, next->d_name); /* only name */ | 779 | strcpy(found, next->d_name); /* only name */ |
776 | if (S_ISDIR(st.st_mode)) { | 780 | if (S_ISDIR(st.st_mode)) { |
777 | /* name is directory */ | 781 | /* name is directory */ |
778 | str_found = found; | 782 | char *e = found + strlen(found) - 1; |
779 | found = concat_path_file(found, ""); | 783 | |
780 | free(str_found); | 784 | add_chr = '/'; |
781 | str_found = add_quote_for_spec_chars(found); | 785 | if(*e == '/') |
786 | *e = '\0'; | ||
782 | } else { | 787 | } else { |
783 | /* not put found file if search only dirs for cd */ | 788 | /* not put found file if search only dirs for cd */ |
784 | if (type == FIND_DIR_ONLY) | 789 | if (type == FIND_DIR_ONLY) |
785 | goto cont; | 790 | goto cont; |
786 | str_found = add_quote_for_spec_chars(found); | ||
787 | if (type == FIND_FILE_ONLY || | 791 | if (type == FIND_FILE_ONLY || |
788 | (type == FIND_EXE_ONLY && is_execute(&st))) | 792 | (type == FIND_EXE_ONLY && is_execute(&st))) |
789 | strcat(str_found, " "); | 793 | add_chr = ' '; |
790 | } | 794 | } |
791 | /* Add it to the list */ | 795 | /* Add it to the list */ |
792 | matches = xrealloc(matches, (nm + 1) * sizeof(char *)); | 796 | add_match(found, add_chr); |
793 | 797 | continue; | |
794 | matches[nm++] = str_found; | ||
795 | cont: | 798 | cont: |
796 | free(found); | 799 | free(found); |
797 | } | 800 | } |
@@ -801,17 +804,9 @@ cont: | |||
801 | free(paths[0]); /* allocated memory only in first member */ | 804 | free(paths[0]); /* allocated memory only in first member */ |
802 | free(paths); | 805 | free(paths); |
803 | } | 806 | } |
804 | *num_matches = nm; | ||
805 | return (matches); | ||
806 | } | ||
807 | |||
808 | static int match_compare(const void *a, const void *b) | ||
809 | { | ||
810 | return strcmp(*(char **) a, *(char **) b); | ||
811 | } | 807 | } |
812 | 808 | ||
813 | 809 | ||
814 | |||
815 | #define QUOT (UCHAR_MAX+1) | 810 | #define QUOT (UCHAR_MAX+1) |
816 | 811 | ||
817 | #define collapse_pos(is, in) { \ | 812 | #define collapse_pos(is, in) { \ |
@@ -907,7 +902,7 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
907 | } | 902 | } |
908 | 903 | ||
909 | /* collapse (command...(command...)...) or {command...{command...}...} */ | 904 | /* collapse (command...(command...)...) or {command...{command...}...} */ |
910 | c = 0; /* "recursive" level */ | 905 | c = 0; /* "recursive" level */ |
911 | c2 = 0; | 906 | c2 = 0; |
912 | for (i = 0; int_buf[i]; i++) | 907 | for (i = 0; int_buf[i]; i++) |
913 | if (int_buf[i] == '(' || int_buf[i] == '{') { | 908 | if (int_buf[i] == '(' || int_buf[i] == '{') { |
@@ -984,16 +979,20 @@ static int find_match(char *matchBuf, int *len_with_quotes) | |||
984 | display by column original ideas from ls applet, | 979 | display by column original ideas from ls applet, |
985 | very optimize by my :) | 980 | very optimize by my :) |
986 | */ | 981 | */ |
987 | static void showfiles(char **matches, int nfiles) | 982 | static void showfiles(void) |
988 | { | 983 | { |
989 | int ncols, row; | 984 | int ncols, row; |
990 | int column_width = 0; | 985 | int column_width = 0; |
986 | int nfiles = num_matches; | ||
991 | int nrows = nfiles; | 987 | int nrows = nfiles; |
988 | char str_add_chr[2]; | ||
989 | int l; | ||
992 | 990 | ||
993 | /* find the longest file name- use that as the column width */ | 991 | /* find the longest file name- use that as the column width */ |
994 | for (row = 0; row < nrows; row++) { | 992 | for (row = 0; row < nrows; row++) { |
995 | int l = strlen(matches[row]); | 993 | l = strlen(matches[row]); |
996 | 994 | if(add_char_to_match[row]) | |
995 | l++; | ||
997 | if (column_width < l) | 996 | if (column_width < l) |
998 | column_width = l; | 997 | column_width = l; |
999 | } | 998 | } |
@@ -1004,17 +1003,27 @@ static void showfiles(char **matches, int nfiles) | |||
1004 | nrows /= ncols; | 1003 | nrows /= ncols; |
1005 | if(nfiles % ncols) | 1004 | if(nfiles % ncols) |
1006 | nrows++; /* round up fractionals */ | 1005 | nrows++; /* round up fractionals */ |
1007 | column_width = -column_width; /* for printf("%-Ns", ...); */ | ||
1008 | } else { | 1006 | } else { |
1009 | ncols = 1; | 1007 | ncols = 1; |
1010 | } | 1008 | } |
1009 | str_add_chr[1] = 0; | ||
1011 | for (row = 0; row < nrows; row++) { | 1010 | for (row = 0; row < nrows; row++) { |
1012 | int n = row; | 1011 | int n = row; |
1013 | int nc; | 1012 | int nc; |
1014 | 1013 | int acol; | |
1015 | for(nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) | 1014 | |
1016 | printf("%*s", column_width, matches[n]); | 1015 | for(nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) { |
1017 | printf("%s\n", matches[n]); | 1016 | str_add_chr[0] = add_char_to_match[n]; |
1017 | acol = str_add_chr[0] ? column_width - 1 : column_width; | ||
1018 | printf("%s%s", matches[n], str_add_chr); | ||
1019 | l = strlen(matches[n]); | ||
1020 | while(l < acol) { | ||
1021 | putchar(' '); | ||
1022 | l++; | ||
1023 | } | ||
1024 | } | ||
1025 | str_add_chr[0] = add_char_to_match[n]; | ||
1026 | printf("%s%s\n", matches[n], str_add_chr); | ||
1018 | } | 1027 | } |
1019 | } | 1028 | } |
1020 | 1029 | ||
@@ -1022,21 +1031,20 @@ static void showfiles(char **matches, int nfiles) | |||
1022 | static void input_tab(int *lastWasTab) | 1031 | static void input_tab(int *lastWasTab) |
1023 | { | 1032 | { |
1024 | /* Do TAB completion */ | 1033 | /* Do TAB completion */ |
1025 | static int num_matches; | ||
1026 | static char **matches; | ||
1027 | |||
1028 | if (lastWasTab == 0) { /* free all memory */ | 1034 | if (lastWasTab == 0) { /* free all memory */ |
1029 | if (matches) { | 1035 | if (matches) { |
1030 | while (num_matches > 0) | 1036 | while (num_matches > 0) |
1031 | free(matches[--num_matches]); | 1037 | free(matches[--num_matches]); |
1032 | free(matches); | 1038 | free(matches); |
1033 | matches = (char **) NULL; | 1039 | matches = (char **) NULL; |
1040 | free(add_char_to_match); | ||
1041 | add_char_to_match = NULL; | ||
1034 | } | 1042 | } |
1035 | return; | 1043 | return; |
1036 | } | 1044 | } |
1037 | if (! *lastWasTab) { | 1045 | if (! *lastWasTab) { |
1038 | 1046 | ||
1039 | char *tmp; | 1047 | char *tmp, *tmp1; |
1040 | int len_found; | 1048 | int len_found; |
1041 | char matchBuf[BUFSIZ]; | 1049 | char matchBuf[BUFSIZ]; |
1042 | int find_type; | 1050 | int find_type; |
@@ -1059,64 +1067,68 @@ static void input_tab(int *lastWasTab) | |||
1059 | * then try completing this word as a username. */ | 1067 | * then try completing this word as a username. */ |
1060 | 1068 | ||
1061 | if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) | 1069 | if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) |
1062 | matches = username_tab_completion(matchBuf, &num_matches); | 1070 | username_tab_completion(matchBuf, NULL); |
1071 | if (!matches) | ||
1063 | #endif | 1072 | #endif |
1064 | /* Try to match any executable in our path and everything | 1073 | /* Try to match any executable in our path and everything |
1065 | * in the current working directory that matches. */ | 1074 | * in the current working directory that matches. */ |
1066 | if (!matches) | 1075 | exe_n_cwd_tab_completion(matchBuf, find_type); |
1067 | matches = | 1076 | /* Remove duplicate found and sort */ |
1068 | exe_n_cwd_tab_completion(matchBuf, | ||
1069 | &num_matches, find_type); | ||
1070 | /* Remove duplicate found */ | ||
1071 | if(matches) { | 1077 | if(matches) { |
1072 | int i, j; | 1078 | int i, j, n, srt; |
1073 | /* bubble */ | 1079 | /* bubble */ |
1074 | for(i=0; i<(num_matches-1); i++) | 1080 | n = num_matches; |
1075 | for(j=i+1; j<num_matches; j++) | 1081 | for(i=0; i<(n-1); i++) |
1076 | if(matches[i]!=0 && matches[j]!=0 && | 1082 | for(j=i+1; j<n; j++) |
1077 | strcmp(matches[i], matches[j])==0) { | 1083 | if(matches[i]!=NULL && matches[j]!=NULL) { |
1078 | free(matches[j]); | 1084 | srt = strcmp(matches[i], matches[j]); |
1079 | matches[j]=0; | 1085 | if(srt == 0) { |
1080 | } | 1086 | free(matches[j]); |
1081 | j=num_matches; | 1087 | matches[j]=0; |
1082 | num_matches = 0; | 1088 | } else if(srt > 0) { |
1083 | for(i=0; i<j; i++) | 1089 | tmp1 = matches[i]; |
1084 | if(matches[i]) { | 1090 | matches[i] = matches[j]; |
1085 | if(!strcmp(matches[i], "./")) | 1091 | matches[j] = tmp1; |
1086 | matches[i][1]=0; | 1092 | srt = add_char_to_match[i]; |
1087 | else if(!strcmp(matches[i], "../")) | 1093 | add_char_to_match[i] = add_char_to_match[j]; |
1088 | matches[i][2]=0; | 1094 | add_char_to_match[j] = srt; |
1089 | matches[num_matches++]=matches[i]; | 1095 | } |
1090 | } | 1096 | } |
1097 | j = n; | ||
1098 | n = 0; | ||
1099 | for(i=0; i<j; i++) | ||
1100 | if(matches[i]) { | ||
1101 | matches[n]=matches[i]; | ||
1102 | add_char_to_match[n]=add_char_to_match[i]; | ||
1103 | n++; | ||
1104 | } | ||
1105 | num_matches = n; | ||
1091 | } | 1106 | } |
1092 | /* Did we find exactly one match? */ | 1107 | /* Did we find exactly one match? */ |
1093 | if (!matches || num_matches > 1) { | 1108 | if (!matches || num_matches > 1) { |
1094 | char *tmp1; | ||
1095 | 1109 | ||
1096 | beep(); | 1110 | beep(); |
1097 | if (!matches) | 1111 | if (!matches) |
1098 | return; /* not found */ | 1112 | return; /* not found */ |
1099 | /* sort */ | ||
1100 | qsort(matches, num_matches, sizeof(char *), match_compare); | ||
1101 | |||
1102 | /* find minimal match */ | 1113 | /* find minimal match */ |
1103 | tmp = bb_xstrdup(matches[0]); | 1114 | tmp1 = bb_xstrdup(matches[0]); |
1104 | for (tmp1 = tmp; *tmp1; tmp1++) | 1115 | for (tmp = tmp1; *tmp; tmp++) |
1105 | for (len_found = 1; len_found < num_matches; len_found++) | 1116 | for (len_found = 1; len_found < num_matches; len_found++) |
1106 | if (matches[len_found][(tmp1 - tmp)] != *tmp1) { | 1117 | if (matches[len_found][(tmp - tmp1)] != *tmp) { |
1107 | *tmp1 = 0; | 1118 | *tmp = 0; |
1108 | break; | 1119 | break; |
1109 | } | 1120 | } |
1110 | if (*tmp == 0) { /* have unique */ | 1121 | if (*tmp1 == 0) { /* have unique */ |
1111 | free(tmp); | 1122 | free(tmp1); |
1112 | return; | 1123 | return; |
1113 | } | 1124 | } |
1125 | tmp = add_quote_for_spec_chars(tmp1, 0); | ||
1126 | free(tmp1); | ||
1114 | } else { /* one match */ | 1127 | } else { /* one match */ |
1115 | tmp = matches[0]; | 1128 | tmp = add_quote_for_spec_chars(matches[0], add_char_to_match[0]); |
1116 | /* for next completion current found */ | 1129 | /* for next completion current found */ |
1117 | *lastWasTab = FALSE; | 1130 | *lastWasTab = FALSE; |
1118 | } | 1131 | } |
1119 | |||
1120 | len_found = strlen(tmp); | 1132 | len_found = strlen(tmp); |
1121 | /* have space to placed match? */ | 1133 | /* have space to placed match? */ |
1122 | if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { | 1134 | if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { |
@@ -1138,8 +1150,7 @@ static void input_tab(int *lastWasTab) | |||
1138 | /* write out the matched command */ | 1150 | /* write out the matched command */ |
1139 | redraw(cmdedit_y, len - recalc_pos); | 1151 | redraw(cmdedit_y, len - recalc_pos); |
1140 | } | 1152 | } |
1141 | if (tmp != matches[0]) | 1153 | free(tmp); |
1142 | free(tmp); | ||
1143 | } else { | 1154 | } else { |
1144 | /* Ok -- the last char was a TAB. Since they | 1155 | /* Ok -- the last char was a TAB. Since they |
1145 | * just hit TAB again, print a list of all the | 1156 | * just hit TAB again, print a list of all the |
@@ -1149,7 +1160,7 @@ static void input_tab(int *lastWasTab) | |||
1149 | 1160 | ||
1150 | /* Go to the next line */ | 1161 | /* Go to the next line */ |
1151 | goto_new_line(); | 1162 | goto_new_line(); |
1152 | showfiles(matches, num_matches); | 1163 | showfiles(); |
1153 | redraw(0, len - sav_cursor); | 1164 | redraw(0, len - sav_cursor); |
1154 | } | 1165 | } |
1155 | } | 1166 | } |
@@ -1368,8 +1379,8 @@ vi_back_motion(char *command) | |||
1368 | * hopes of letting the jump tables get smaller: | 1379 | * hopes of letting the jump tables get smaller: |
1369 | * #define vcase(caselabel) caselabel | 1380 | * #define vcase(caselabel) caselabel |
1370 | * and then | 1381 | * and then |
1371 | * case CNTRL('A'): | 1382 | * case CNTRL('A'): |
1372 | * case vcase(VICMD('0'):) | 1383 | * case vcase(VICMD('0'):) |
1373 | * but it didn't seem to make any difference in code size, | 1384 | * but it didn't seem to make any difference in code size, |
1374 | * and the macro-ized code was too ugly. | 1385 | * and the macro-ized code was too ugly. |
1375 | */ | 1386 | */ |