aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-03 12:56:36 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-03 12:56:36 +0200
commit3c460b005c3c422fe73dc464902e0626fc57938a (patch)
tree79d5d815280dac6d2f3e1c4cf534842c4ef4486e /libbb
parent2679e3c8cccbf3ae4cac8e735e5430ebbe714b00 (diff)
downloadbusybox-w32-3c460b005c3c422fe73dc464902e0626fc57938a.tar.gz
busybox-w32-3c460b005c3c422fe73dc464902e0626fc57938a.tar.bz2
busybox-w32-3c460b005c3c422fe73dc464902e0626fc57938a.zip
lineedit: return prefix len from tab completion helpers
This kills horrific logic which deletes and re-adds prefix (!) function old new delta complete_cmd_dir_file 705 731 +26 complete_username 121 124 +3 input_tab 1041 1016 -25 build_match_prefix 838 804 -34 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/2 up/down: 29/-59) Total: -30 bytes Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'libbb')
-rw-r--r--libbb/lineedit.c86
1 files changed, 50 insertions, 36 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index dd9d85b28..e40917f62 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -638,14 +638,16 @@ static char *username_path_completion(char *ud)
638 return tilde_name; 638 return tilde_name;
639} 639}
640 640
641/* ~use<tab> - find all users with this prefix */ 641/* ~use<tab> - find all users with this prefix.
642static NOINLINE void complete_username(const char *ud) 642 * Return the length of the prefix used for matching.
643 */
644static NOINLINE unsigned complete_username(const char *ud)
643{ 645{
644 /* Using _r function to avoid pulling in static buffers */ 646 /* Using _r function to avoid pulling in static buffers */
645 char line_buff[256]; 647 char line_buff[256];
646 struct passwd pwd; 648 struct passwd pwd;
647 struct passwd *result; 649 struct passwd *result;
648 int userlen; 650 unsigned userlen;
649 651
650 ud++; /* skip ~ */ 652 ud++; /* skip ~ */
651 userlen = strlen(ud); 653 userlen = strlen(ud);
@@ -658,6 +660,8 @@ static NOINLINE void complete_username(const char *ud)
658 } 660 }
659 } 661 }
660 endpwent(); 662 endpwent();
663
664 return 1 + userlen;
661} 665}
662#endif /* FEATURE_USERNAME_COMPLETION */ 666#endif /* FEATURE_USERNAME_COMPLETION */
663 667
@@ -710,14 +714,17 @@ static int path_parse(char ***p)
710 return npth; 714 return npth;
711} 715}
712 716
713static NOINLINE void complete_cmd_dir_file(char *command, int type) 717/* Complete command, directory or file name.
718 * Return the length of the prefix used for matching.
719 */
720static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
714{ 721{
715 char *path1[1]; 722 char *path1[1];
716 char **paths = path1; 723 char **paths = path1;
717 int npaths; 724 int npaths;
718 int i; 725 int i;
719 unsigned pf_len; 726 unsigned pf_len;
720 char *pfind; 727 const char *pfind;
721 char *dirbuf = NULL; 728 char *dirbuf = NULL;
722 729
723 npaths = 1; 730 npaths = 1;
@@ -797,8 +804,12 @@ static NOINLINE void complete_cmd_dir_file(char *command, int type)
797 if (paths != path1) { 804 if (paths != path1) {
798 free(paths[0]); /* allocated memory is only in first member */ 805 free(paths[0]); /* allocated memory is only in first member */
799 free(paths); 806 free(paths);
807 } else if (dirbuf) {
808 pf_len += strlen(dirbuf);
809 free(dirbuf);
800 } 810 }
801 free(dirbuf); 811
812 return pf_len;
802} 813}
803 814
804/* build_match_prefix: 815/* build_match_prefix:
@@ -829,7 +840,7 @@ static void collapse_pos(int beg, int end)
829 bb_putchar('\n'); 840 bb_putchar('\n');
830 } 841 }
831} 842}
832static NOINLINE int build_match_prefix(char *matchBuf, int *len_with_quotes) 843static NOINLINE int build_match_prefix(char *matchBuf)
833{ 844{
834 int i, j; 845 int i, j;
835 int command_mode; 846 int command_mode;
@@ -992,9 +1003,6 @@ static NOINLINE int build_match_prefix(char *matchBuf, int *len_with_quotes)
992 pos = pos_buf[i] + 1; 1003 pos = pos_buf[i] + 1;
993 } 1004 }
994 matchBuf[j] = '\0'; 1005 matchBuf[j] = '\0';
995 /* old length matchBuf with quotes symbols */
996 *len_with_quotes = pos ? pos - pos_buf[0] : 0;
997 if (dbg_bmp) printf("len_with_quotes:%d\n", *len_with_quotes);
998 } 1006 }
999 1007
1000 return command_mode; 1008 return command_mode;
@@ -1067,12 +1075,13 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1067 return; 1075 return;
1068 1076
1069 if (!*lastWasTab) { 1077 if (!*lastWasTab) {
1070 char *tmp, *tmp1; 1078 char *tmp;
1071 size_t len_found; 1079 size_t len_found;
1072/* char matchBuf[MAX_LINELEN]; */ 1080/* char matchBuf[MAX_LINELEN]; */
1073#define matchBuf (S.input_tab__matchBuf) 1081#define matchBuf (S.input_tab__matchBuf)
1082 /* Length of string used for matching */
1083 unsigned match_pfx_len = match_pfx_len;
1074 int find_type; 1084 int find_type;
1075 int recalc_pos;
1076#if ENABLE_UNICODE_SUPPORT 1085#if ENABLE_UNICODE_SUPPORT
1077 /* cursor pos in command converted to multibyte form */ 1086 /* cursor pos in command converted to multibyte form */
1078 int cursor_mb; 1087 int cursor_mb;
@@ -1095,7 +1104,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1095#endif 1104#endif
1096 tmp = matchBuf; 1105 tmp = matchBuf;
1097 1106
1098 find_type = build_match_prefix(matchBuf, &recalc_pos); 1107 find_type = build_match_prefix(matchBuf);
1099 1108
1100 /* Free up any memory already allocated */ 1109 /* Free up any memory already allocated */
1101 free_tab_completion_data(); 1110 free_tab_completion_data();
@@ -1105,11 +1114,11 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1105 * then try completing this word as a username. */ 1114 * then try completing this word as a username. */
1106 if (state->flags & USERNAME_COMPLETION) 1115 if (state->flags & USERNAME_COMPLETION)
1107 if (matchBuf[0] == '~' && strchr(matchBuf, '/') == NULL) 1116 if (matchBuf[0] == '~' && strchr(matchBuf, '/') == NULL)
1108 complete_username(matchBuf); 1117 match_pfx_len = complete_username(matchBuf);
1109#endif 1118#endif
1110 /* Try to match a command in $PATH, or a directory, or a file */ 1119 /* Try to match a command in $PATH, or a directory, or a file */
1111 if (!matches) 1120 if (!matches)
1112 complete_cmd_dir_file(matchBuf, find_type); 1121 match_pfx_len = complete_cmd_dir_file(matchBuf, find_type);
1113 /* Remove duplicates */ 1122 /* Remove duplicates */
1114 if (matches) { 1123 if (matches) {
1115 unsigned i; 1124 unsigned i;
@@ -1130,23 +1139,26 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1130 } 1139 }
1131 /* Did we find exactly one match? */ 1140 /* Did we find exactly one match? */
1132 if (num_matches != 1) { /* no */ 1141 if (num_matches != 1) { /* no */
1142 char *tmp1;
1133 beep(); 1143 beep();
1134 if (!matches) 1144 if (!matches)
1135 return; /* no matches at all */ 1145 return; /* no matches at all */
1136 /* Find common prefix */ 1146 /* Find common prefix */
1137 tmp1 = xstrdup(matches[0]); 1147 tmp1 = xstrdup(matches[0]);
1138 for (tmp = tmp1; *tmp; tmp++) { 1148 for (tmp = tmp1; *tmp; tmp++) {
1139 for (len_found = 1; len_found < num_matches; len_found++) { 1149 unsigned n;
1140 if (matches[len_found][tmp - tmp1] != *tmp) { 1150 for (n = 1; n < num_matches; n++) {
1141 *tmp = '\0'; 1151 if (matches[n][tmp - tmp1] != *tmp) {
1142 break; 1152 goto stop;
1143 } 1153 }
1144 } 1154 }
1145 } 1155 }
1146 if (*tmp1 == '\0') { /* have unique prefix? */ 1156 stop:
1157 if (tmp1 == tmp) { /* have unique prefix? */
1147 free(tmp1); /* no */ 1158 free(tmp1); /* no */
1148 return; 1159 return;
1149 } 1160 }
1161 *tmp = '\0';
1150 tmp = add_quote_for_spec_chars(tmp1); 1162 tmp = add_quote_for_spec_chars(tmp1);
1151 free(tmp1); 1163 free(tmp1);
1152 len_found = strlen(tmp); 1164 len_found = strlen(tmp);
@@ -1163,41 +1175,43 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1163 } 1175 }
1164 1176
1165#if !ENABLE_UNICODE_SUPPORT 1177#if !ENABLE_UNICODE_SUPPORT
1166 /* have space to place the match? */ 1178 /* Have space to place the match? */
1167 /* The result consists of three parts with these lengths: */ 1179 /* The result consists of three parts with these lengths: */
1168 /* (cursor - recalc_pos) + len_found + (command_len - cursor) */ 1180 /* cursor + (len_found - match_pfx_len) + (command_len - cursor) */
1169 /* it simplifies into: */ 1181 /* it simplifies into: */
1170 if ((int)(len_found + command_len - recalc_pos) < S.maxsize) { 1182 if ((int)(len_found - match_pfx_len + command_len) < S.maxsize) {
1183 int pos;
1171 /* save tail */ 1184 /* save tail */
1172 strcpy(matchBuf, command_ps + cursor); 1185 strcpy(matchBuf, &command_ps[cursor]);
1173 /* add match and tail */ 1186 /* add match and tail */
1174 sprintf(&command_ps[cursor - recalc_pos], "%s%s", tmp, matchBuf); 1187 sprintf(&command_ps[cursor], "%s%s", tmp + match_pfx_len, matchBuf);
1175 command_len = strlen(command_ps); 1188 command_len = strlen(command_ps);
1176 /* new pos */ 1189 /* new pos */
1177 recalc_pos = cursor - recalc_pos + len_found; 1190 pos = cursor + len_found - match_pfx_len;
1178 /* write out the matched command */ 1191 /* write out the matched command */
1179 redraw(cmdedit_y, command_len - recalc_pos); 1192 redraw(cmdedit_y, command_len - pos);
1180 } 1193 }
1181#else 1194#else
1182 { 1195 {
1183 char command[MAX_LINELEN]; 1196 char command[MAX_LINELEN];
1184 int len = save_string(command, sizeof(command)); 1197 int len = save_string(command, sizeof(command));
1185 /* have space to place the match? */ 1198 /* Have space to place the match? */
1186 /* (cursor_mb - recalc_pos) + len_found + (len - cursor_mb) */ 1199 /* cursor_mb + (len_found - match_pfx_len) + (len - cursor_mb) */
1187 if ((int)(len_found + len - recalc_pos) < MAX_LINELEN) { 1200 if ((int)(len_found - match_pfx_len + len) < MAX_LINELEN) {
1201 int pos;
1188 /* save tail */ 1202 /* save tail */
1189 strcpy(matchBuf, command + cursor_mb); 1203 strcpy(matchBuf, &command[cursor_mb]);
1190 /* where do we want to have cursor after all? */ 1204 /* where do we want to have cursor after all? */
1191 strcpy(&command[cursor_mb - recalc_pos], tmp); 1205 strcpy(&command[cursor_mb], tmp + match_pfx_len);
1192 len = load_string(command, S.maxsize); 1206 len = load_string(command, S.maxsize);
1193 /* add match and tail */ 1207 /* add match and tail */
1194 sprintf(&command[cursor_mb - recalc_pos], "%s%s", tmp, matchBuf); 1208 sprintf(&command[cursor_mb], "%s%s", tmp + match_pfx_len, matchBuf);
1195 command_len = load_string(command, S.maxsize); 1209 command_len = load_string(command, S.maxsize);
1196 /* write out the matched command */ 1210 /* write out the matched command */
1197 /* paranoia: load_string can return 0 on conv error, 1211 /* paranoia: load_string can return 0 on conv error,
1198 * prevent passing len = (0 - 12) to redraw */ 1212 * prevent passing pos = (0 - 12) to redraw */
1199 len = command_len - len; 1213 pos = command_len - len;
1200 redraw(cmdedit_y, len >= 0 ? len : 0); 1214 redraw(cmdedit_y, pos >= 0 ? pos : 0);
1201 } 1215 }
1202 } 1216 }
1203#endif 1217#endif