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 /shell | |
| 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
Diffstat (limited to 'shell')
| -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 | */ |
