lineedit: fix problems with empty commands in history

This commit is contained in:
Denis Vlasenko 2008-09-27 01:28:56 +00:00
parent 75897ea6d5
commit 682ad3045c

View File

@ -956,24 +956,33 @@ static void input_tab(smallint *lastWasTab)
#if MAX_HISTORY > 0 #if MAX_HISTORY > 0
/* state->flags is already checked to be nonzero */ static void save_command_ps_at_cur_history(void)
static void get_previous_history(void)
{ {
if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) { if (command_ps[0] != '\0') {
free(state->history[state->cur_history]); int cur = state->cur_history;
state->history[state->cur_history] = xstrdup(command_ps); free(state->history[cur]);
state->history[cur] = xstrdup(command_ps);
} }
}
/* state->flags is already checked to be nonzero */
static int get_previous_history(void)
{
if ((state->flags & DO_HISTORY) && state->cur_history) {
save_command_ps_at_cur_history();
state->cur_history--; state->cur_history--;
return 1;
}
beep();
return 0;
} }
static int get_next_history(void) static int get_next_history(void)
{ {
if (state->flags & DO_HISTORY) { if (state->flags & DO_HISTORY) {
int ch = state->cur_history; if (state->cur_history < state->cnt_history) {
if (ch < state->cnt_history) { save_command_ps_at_cur_history(); /* save the current history line */
get_previous_history(); /* save the current history line */ return ++state->cur_history;
state->cur_history = ch + 1;
return state->cur_history;
} }
} }
beep(); beep();
@ -995,6 +1004,7 @@ static void load_history(const char *fromfile)
for (hi = state->cnt_history; hi > 0;) { for (hi = state->cnt_history; hi > 0;) {
hi--; hi--;
free(state->history[hi]); free(state->history[hi]);
state->history[hi] = NULL;
} }
for (hi = 0; hi < MAX_HISTORY;) { for (hi = 0; hi < MAX_HISTORY;) {
@ -1006,14 +1016,14 @@ static void load_history(const char *fromfile)
l = strlen(hl); l = strlen(hl);
if (l >= MAX_LINELEN) if (l >= MAX_LINELEN)
hl[MAX_LINELEN-1] = '\0'; hl[MAX_LINELEN-1] = '\0';
if (l == 0 || hl[0] == ' ') { if (l == 0) {
free(hl); free(hl);
continue; continue;
} }
state->history[hi++] = hl; state->history[hi++] = hl;
} }
fclose(fp); fclose(fp);
state->cur_history = state->cnt_history = hi; state->cnt_history = hi;
} }
} }
@ -1043,19 +1053,27 @@ static void remember_in_history(const char *str)
if (!(state->flags & DO_HISTORY)) if (!(state->flags & DO_HISTORY))
return; return;
if (str[0] == '\0')
return;
i = state->cnt_history; i = state->cnt_history;
free(state->history[MAX_HISTORY]); /* Don't save dupes */
state->history[MAX_HISTORY] = NULL; if (i && strcmp(state->history[i-1], str) == 0)
/* After max history, remove the oldest command */ return;
free(state->history[MAX_HISTORY]); /* redundant, paranoia */
state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
/* If history[] is full, remove the oldest command */
/* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
if (i >= MAX_HISTORY) { if (i >= MAX_HISTORY) {
free(state->history[0]); free(state->history[0]);
for (i = 0; i < MAX_HISTORY-1; i++) for (i = 0; i < MAX_HISTORY-1; i++)
state->history[i] = state->history[i+1]; state->history[i] = state->history[i+1];
/* i == MAX_HISTORY-1 */
} }
// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..." /* i <= MAX_HISTORY-1 */
// (i.e. do not save dups?)
state->history[i++] = xstrdup(str); state->history[i++] = xstrdup(str);
/* i <= MAX_HISTORY */
state->cur_history = i; state->cur_history = i;
state->cnt_history = i; state->cnt_history = i;
#if ENABLE_FEATURE_EDITING_SAVEHISTORY #if ENABLE_FEATURE_EDITING_SAVEHISTORY
@ -1397,6 +1415,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
if ((state->flags & SAVE_HISTORY) && state->hist_file) if ((state->flags & SAVE_HISTORY) && state->hist_file)
load_history(state->hist_file); load_history(state->hist_file);
#endif #endif
state->cur_history = state->cnt_history;
/* prepare before init handlers */ /* prepare before init handlers */
cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
@ -1432,6 +1451,13 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
} }
} }
#endif #endif
#if 0
for (ic = 0; ic <= MAX_HISTORY; ic++)
bb_error_msg("history[%d]:'%s'", ic, state->history[ic]);
bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
#endif
/* Print out the command prompt */ /* Print out the command prompt */
parse_and_put_prompt(prompt); parse_and_put_prompt(prompt);
@ -1540,11 +1566,8 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
vi_case(CTRL('P')|vbit:) vi_case(CTRL('P')|vbit:)
vi_case('k'|vbit:) vi_case('k'|vbit:)
/* Control-p -- Get previous command from history */ /* Control-p -- Get previous command from history */
if ((state->flags & DO_HISTORY) && state->cur_history > 0) { if (get_previous_history())
get_previous_history();
goto rewrite_line; goto rewrite_line;
}
beep();
break; break;
#endif #endif
@ -1733,10 +1756,8 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
#if MAX_HISTORY > 0 #if MAX_HISTORY > 0
case 'A': case 'A':
/* Up Arrow -- Get previous command from history */ /* Up Arrow -- Get previous command from history */
if ((state->flags & DO_HISTORY) && state->cur_history > 0) { if (get_previous_history())
get_previous_history();
goto rewrite_line; goto rewrite_line;
}
beep(); beep();
break; break;
case 'B': case 'B':
@ -1746,7 +1767,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
rewrite_line: rewrite_line:
/* Rewrite the line with the selected history item */ /* Rewrite the line with the selected history item */
/* change command */ /* change command */
command_len = strlen(strcpy(command, state->history[state->cur_history])); command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
/* redraw and go to eol (bol, in vi */ /* redraw and go to eol (bol, in vi */
redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
break; break;