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>
This commit is contained in:
parent
2679e3c8cc
commit
3c460b005c
@ -638,14 +638,16 @@ static char *username_path_completion(char *ud)
|
||||
return tilde_name;
|
||||
}
|
||||
|
||||
/* ~use<tab> - find all users with this prefix */
|
||||
static NOINLINE void complete_username(const char *ud)
|
||||
/* ~use<tab> - find all users with this prefix.
|
||||
* Return the length of the prefix used for matching.
|
||||
*/
|
||||
static NOINLINE unsigned complete_username(const char *ud)
|
||||
{
|
||||
/* Using _r function to avoid pulling in static buffers */
|
||||
char line_buff[256];
|
||||
struct passwd pwd;
|
||||
struct passwd *result;
|
||||
int userlen;
|
||||
unsigned userlen;
|
||||
|
||||
ud++; /* skip ~ */
|
||||
userlen = strlen(ud);
|
||||
@ -658,6 +660,8 @@ static NOINLINE void complete_username(const char *ud)
|
||||
}
|
||||
}
|
||||
endpwent();
|
||||
|
||||
return 1 + userlen;
|
||||
}
|
||||
#endif /* FEATURE_USERNAME_COMPLETION */
|
||||
|
||||
@ -710,14 +714,17 @@ static int path_parse(char ***p)
|
||||
return npth;
|
||||
}
|
||||
|
||||
static NOINLINE void complete_cmd_dir_file(char *command, int type)
|
||||
/* Complete command, directory or file name.
|
||||
* Return the length of the prefix used for matching.
|
||||
*/
|
||||
static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
|
||||
{
|
||||
char *path1[1];
|
||||
char **paths = path1;
|
||||
int npaths;
|
||||
int i;
|
||||
unsigned pf_len;
|
||||
char *pfind;
|
||||
const char *pfind;
|
||||
char *dirbuf = NULL;
|
||||
|
||||
npaths = 1;
|
||||
@ -797,8 +804,12 @@ static NOINLINE void complete_cmd_dir_file(char *command, int type)
|
||||
if (paths != path1) {
|
||||
free(paths[0]); /* allocated memory is only in first member */
|
||||
free(paths);
|
||||
} else if (dirbuf) {
|
||||
pf_len += strlen(dirbuf);
|
||||
free(dirbuf);
|
||||
}
|
||||
free(dirbuf);
|
||||
|
||||
return pf_len;
|
||||
}
|
||||
|
||||
/* build_match_prefix:
|
||||
@ -829,7 +840,7 @@ static void collapse_pos(int beg, int end)
|
||||
bb_putchar('\n');
|
||||
}
|
||||
}
|
||||
static NOINLINE int build_match_prefix(char *matchBuf, int *len_with_quotes)
|
||||
static NOINLINE int build_match_prefix(char *matchBuf)
|
||||
{
|
||||
int i, j;
|
||||
int command_mode;
|
||||
@ -992,9 +1003,6 @@ static NOINLINE int build_match_prefix(char *matchBuf, int *len_with_quotes)
|
||||
pos = pos_buf[i] + 1;
|
||||
}
|
||||
matchBuf[j] = '\0';
|
||||
/* old length matchBuf with quotes symbols */
|
||||
*len_with_quotes = pos ? pos - pos_buf[0] : 0;
|
||||
if (dbg_bmp) printf("len_with_quotes:%d\n", *len_with_quotes);
|
||||
}
|
||||
|
||||
return command_mode;
|
||||
@ -1067,12 +1075,13 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
return;
|
||||
|
||||
if (!*lastWasTab) {
|
||||
char *tmp, *tmp1;
|
||||
char *tmp;
|
||||
size_t len_found;
|
||||
/* char matchBuf[MAX_LINELEN]; */
|
||||
#define matchBuf (S.input_tab__matchBuf)
|
||||
/* Length of string used for matching */
|
||||
unsigned match_pfx_len = match_pfx_len;
|
||||
int find_type;
|
||||
int recalc_pos;
|
||||
#if ENABLE_UNICODE_SUPPORT
|
||||
/* cursor pos in command converted to multibyte form */
|
||||
int cursor_mb;
|
||||
@ -1095,7 +1104,7 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
#endif
|
||||
tmp = matchBuf;
|
||||
|
||||
find_type = build_match_prefix(matchBuf, &recalc_pos);
|
||||
find_type = build_match_prefix(matchBuf);
|
||||
|
||||
/* Free up any memory already allocated */
|
||||
free_tab_completion_data();
|
||||
@ -1105,11 +1114,11 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
* then try completing this word as a username. */
|
||||
if (state->flags & USERNAME_COMPLETION)
|
||||
if (matchBuf[0] == '~' && strchr(matchBuf, '/') == NULL)
|
||||
complete_username(matchBuf);
|
||||
match_pfx_len = complete_username(matchBuf);
|
||||
#endif
|
||||
/* Try to match a command in $PATH, or a directory, or a file */
|
||||
if (!matches)
|
||||
complete_cmd_dir_file(matchBuf, find_type);
|
||||
match_pfx_len = complete_cmd_dir_file(matchBuf, find_type);
|
||||
/* Remove duplicates */
|
||||
if (matches) {
|
||||
unsigned i;
|
||||
@ -1130,23 +1139,26 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
}
|
||||
/* Did we find exactly one match? */
|
||||
if (num_matches != 1) { /* no */
|
||||
char *tmp1;
|
||||
beep();
|
||||
if (!matches)
|
||||
return; /* no matches at all */
|
||||
/* Find common prefix */
|
||||
tmp1 = xstrdup(matches[0]);
|
||||
for (tmp = tmp1; *tmp; tmp++) {
|
||||
for (len_found = 1; len_found < num_matches; len_found++) {
|
||||
if (matches[len_found][tmp - tmp1] != *tmp) {
|
||||
*tmp = '\0';
|
||||
break;
|
||||
unsigned n;
|
||||
for (n = 1; n < num_matches; n++) {
|
||||
if (matches[n][tmp - tmp1] != *tmp) {
|
||||
goto stop;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*tmp1 == '\0') { /* have unique prefix? */
|
||||
stop:
|
||||
if (tmp1 == tmp) { /* have unique prefix? */
|
||||
free(tmp1); /* no */
|
||||
return;
|
||||
}
|
||||
*tmp = '\0';
|
||||
tmp = add_quote_for_spec_chars(tmp1);
|
||||
free(tmp1);
|
||||
len_found = strlen(tmp);
|
||||
@ -1163,41 +1175,43 @@ static NOINLINE void input_tab(smallint *lastWasTab)
|
||||
}
|
||||
|
||||
#if !ENABLE_UNICODE_SUPPORT
|
||||
/* have space to place the match? */
|
||||
/* Have space to place the match? */
|
||||
/* The result consists of three parts with these lengths: */
|
||||
/* (cursor - recalc_pos) + len_found + (command_len - cursor) */
|
||||
/* cursor + (len_found - match_pfx_len) + (command_len - cursor) */
|
||||
/* it simplifies into: */
|
||||
if ((int)(len_found + command_len - recalc_pos) < S.maxsize) {
|
||||
if ((int)(len_found - match_pfx_len + command_len) < S.maxsize) {
|
||||
int pos;
|
||||
/* save tail */
|
||||
strcpy(matchBuf, command_ps + cursor);
|
||||
strcpy(matchBuf, &command_ps[cursor]);
|
||||
/* add match and tail */
|
||||
sprintf(&command_ps[cursor - recalc_pos], "%s%s", tmp, matchBuf);
|
||||
sprintf(&command_ps[cursor], "%s%s", tmp + match_pfx_len, matchBuf);
|
||||
command_len = strlen(command_ps);
|
||||
/* new pos */
|
||||
recalc_pos = cursor - recalc_pos + len_found;
|
||||
pos = cursor + len_found - match_pfx_len;
|
||||
/* write out the matched command */
|
||||
redraw(cmdedit_y, command_len - recalc_pos);
|
||||
redraw(cmdedit_y, command_len - pos);
|
||||
}
|
||||
#else
|
||||
{
|
||||
char command[MAX_LINELEN];
|
||||
int len = save_string(command, sizeof(command));
|
||||
/* have space to place the match? */
|
||||
/* (cursor_mb - recalc_pos) + len_found + (len - cursor_mb) */
|
||||
if ((int)(len_found + len - recalc_pos) < MAX_LINELEN) {
|
||||
/* Have space to place the match? */
|
||||
/* cursor_mb + (len_found - match_pfx_len) + (len - cursor_mb) */
|
||||
if ((int)(len_found - match_pfx_len + len) < MAX_LINELEN) {
|
||||
int pos;
|
||||
/* save tail */
|
||||
strcpy(matchBuf, command + cursor_mb);
|
||||
strcpy(matchBuf, &command[cursor_mb]);
|
||||
/* where do we want to have cursor after all? */
|
||||
strcpy(&command[cursor_mb - recalc_pos], tmp);
|
||||
strcpy(&command[cursor_mb], tmp + match_pfx_len);
|
||||
len = load_string(command, S.maxsize);
|
||||
/* add match and tail */
|
||||
sprintf(&command[cursor_mb - recalc_pos], "%s%s", tmp, matchBuf);
|
||||
sprintf(&command[cursor_mb], "%s%s", tmp + match_pfx_len, matchBuf);
|
||||
command_len = load_string(command, S.maxsize);
|
||||
/* write out the matched command */
|
||||
/* paranoia: load_string can return 0 on conv error,
|
||||
* prevent passing len = (0 - 12) to redraw */
|
||||
len = command_len - len;
|
||||
redraw(cmdedit_y, len >= 0 ? len : 0);
|
||||
* prevent passing pos = (0 - 12) to redraw */
|
||||
pos = command_len - len;
|
||||
redraw(cmdedit_y, pos >= 0 ? pos : 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user