lineedit+unicode: make TAB completion work again

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-07-12 02:50:35 +02:00
parent 1302892a14
commit 044b18083b

View File

@ -115,6 +115,9 @@ struct lineedit_statics {
unsigned cursor; unsigned cursor;
unsigned command_len; unsigned command_len;
/* *int* maxsize: we want x in "if (x > S.maxsize)"
* to _not_ be promoted to unsigned */
int maxsize;
CHAR_T *command_ps; CHAR_T *command_ps;
const char *cmdedit_prompt; const char *cmdedit_prompt;
@ -389,12 +392,12 @@ static void put_prompt(void)
/* draw prompt, editor line, and clear tail */ /* draw prompt, editor line, and clear tail */
static void redraw(int y, int back_cursor) static void redraw(int y, int back_cursor)
{ {
if (y > 0) /* up to start y */ if (y > 0) /* up to start y */
printf("\033[%dA", y); printf("\033[%uA", y);
bb_putchar('\r'); bb_putchar('\r');
put_prompt(); put_prompt();
input_end(); /* rewrite */ input_end(); /* rewrite */
printf("\033[J"); /* erase after cursor */ printf("\033[J"); /* erase after cursor */
input_backward(back_cursor); input_backward(back_cursor);
} }
@ -687,7 +690,7 @@ static void exe_n_cwd_tab_completion(char *command, int type)
memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \ memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in)) * sizeof(pos_buf[0])); \
} while (0) } while (0)
static int find_match(char *matchBuf, int *len_with_quotes) static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
{ {
int i, j; int i, j;
int command_mode; int command_mode;
@ -922,12 +925,19 @@ static void input_tab(smallint *lastWasTab)
#define matchBuf (S.input_tab__matchBuf) #define matchBuf (S.input_tab__matchBuf)
int find_type; int find_type;
int recalc_pos; int recalc_pos;
#if ENABLE_FEATURE_ASSUME_UNICODE
/* cursor pos in command converted to multibyte form */
int cursor_mb;
#endif
*lastWasTab = TRUE; /* flop trigger */ *lastWasTab = TRUE; /* flop trigger */
/* Make a local copy of the string -- /* Make a local copy of the string --
* up to the position of the cursor */ * up to the position of the cursor */
save_string(matchBuf, cursor + 1); save_string(matchBuf, cursor + 1);
#if ENABLE_FEATURE_ASSUME_UNICODE
cursor_mb = strlen(matchBuf);
#endif
tmp = matchBuf; tmp = matchBuf;
find_type = find_match(matchBuf, &recalc_pos); find_type = find_match(matchBuf, &recalc_pos);
@ -939,7 +949,7 @@ static void input_tab(smallint *lastWasTab)
/* If the word starts with `~' and there is no slash in the word, /* If the word starts with `~' and there is no slash in the word,
* then try completing this word as a username. */ * then try completing this word as a username. */
if (state->flags & USERNAME_COMPLETION) if (state->flags & USERNAME_COMPLETION)
if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) if (matchBuf[0] == '~' && strchr(matchBuf, '/') == NULL)
username_tab_completion(matchBuf, NULL); username_tab_completion(matchBuf, NULL);
#endif #endif
/* Try to match any executable in our path and everything /* Try to match any executable in our path and everything
@ -965,18 +975,20 @@ static void input_tab(smallint *lastWasTab)
num_matches = n + 1; num_matches = n + 1;
} }
/* Did we find exactly one match? */ /* Did we find exactly one match? */
if (!matches || num_matches > 1) { if (!matches || num_matches > 1) { /* no */
beep(); beep();
if (!matches) if (!matches)
return; /* not found */ return; /* not found */
/* find minimal match */ /* find minimal match */
tmp1 = xstrdup(matches[0]); tmp1 = xstrdup(matches[0]);
for (tmp = tmp1; *tmp; tmp++) for (tmp = tmp1; *tmp; tmp++) {
for (len_found = 1; len_found < num_matches; len_found++) for (len_found = 1; len_found < num_matches; len_found++) {
if (matches[len_found][(tmp - tmp1)] != *tmp) { if (matches[len_found][tmp - tmp1] != *tmp) {
*tmp = '\0'; *tmp = '\0';
break; break;
} }
}
}
if (*tmp1 == '\0') { /* have unique */ if (*tmp1 == '\0') { /* have unique */
free(tmp1); free(tmp1);
return; return;
@ -994,29 +1006,44 @@ static void input_tab(smallint *lastWasTab)
tmp[len_found+1] = '\0'; tmp[len_found+1] = '\0';
} }
} }
len_found = strlen(tmp); len_found = strlen(tmp);
/* have space to placed match? */
if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) {
/* before word for match */
//TODO:
#if !ENABLE_FEATURE_ASSUME_UNICODE #if !ENABLE_FEATURE_ASSUME_UNICODE
command_ps[cursor - recalc_pos] = '\0'; /* have space to place the match? */
/* save tail line */ /* The result consists of three parts with these lengths: */
/* (cursor - recalc_pos) + len_found + (command_len - cursor) */
/* it simplifies into: */
if ((int)(len_found + command_len - recalc_pos) < S.maxsize) {
/* save tail */
strcpy(matchBuf, command_ps + cursor); strcpy(matchBuf, command_ps + cursor);
/* add match */ /* add match and tail */
strcat(command_ps, tmp); sprintf(&command_ps[cursor - recalc_pos], "%s%s", tmp, matchBuf);
/* add tail */
strcat(command_ps, matchBuf);
/* back to begin word for match */
input_backward(recalc_pos);
/* new pos */
recalc_pos = cursor + len_found;
/* new len */
command_len = strlen(command_ps); command_len = strlen(command_ps);
/* write out the matched command */ /* new pos */
#endif recalc_pos = cursor - recalc_pos + len_found;
/* write out the matched command */
redraw(cmdedit_y, command_len - recalc_pos); redraw(cmdedit_y, command_len - recalc_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) {
/* save tail */
strcpy(matchBuf, command + cursor_mb);
/* where do we want to have cursor after all? */
strcpy(&command[cursor_mb - recalc_pos], tmp);
len = load_string(command, S.maxsize);
/* add match and tail */
sprintf(&command[cursor_mb - recalc_pos], "%s%s", tmp, matchBuf);
command_len = load_string(command, S.maxsize);
/* write out the matched command */
redraw(cmdedit_y, command_len - len);
}
}
#endif
free(tmp); free(tmp);
#undef matchBuf #undef matchBuf
} else { } else {
@ -1024,7 +1051,8 @@ static void input_tab(smallint *lastWasTab)
* just hit TAB again, print a list of all the * just hit TAB again, print a list of all the
* available choices... */ * available choices... */
if (matches && num_matches > 0) { if (matches && num_matches > 0) {
int sav_cursor = cursor; /* change goto_new_line() */ /* changed by goto_new_line() */
int sav_cursor = cursor;
/* Go to the next line */ /* Go to the next line */
goto_new_line(); goto_new_line();
@ -1641,6 +1669,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
// FIXME: audit & improve this // FIXME: audit & improve this
if (maxsize > MAX_LINELEN) if (maxsize > MAX_LINELEN)
maxsize = MAX_LINELEN; maxsize = MAX_LINELEN;
S.maxsize = maxsize;
/* With null flags, no other fields are ever used */ /* With null flags, no other fields are ever used */
state = st ? st : (line_input_t*) &const_int_0; state = st ? st : (line_input_t*) &const_int_0;