summaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index a68e5a3c0..c2c3ea996 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -956,24 +956,33 @@ static void input_tab(smallint *lastWasTab)
956 956
957#if MAX_HISTORY > 0 957#if MAX_HISTORY > 0
958 958
959static void save_command_ps_at_cur_history(void)
960{
961 if (command_ps[0] != '\0') {
962 int cur = state->cur_history;
963 free(state->history[cur]);
964 state->history[cur] = xstrdup(command_ps);
965 }
966}
967
959/* state->flags is already checked to be nonzero */ 968/* state->flags is already checked to be nonzero */
960static void get_previous_history(void) 969static int get_previous_history(void)
961{ 970{
962 if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) { 971 if ((state->flags & DO_HISTORY) && state->cur_history) {
963 free(state->history[state->cur_history]); 972 save_command_ps_at_cur_history();
964 state->history[state->cur_history] = xstrdup(command_ps); 973 state->cur_history--;
974 return 1;
965 } 975 }
966 state->cur_history--; 976 beep();
977 return 0;
967} 978}
968 979
969static int get_next_history(void) 980static int get_next_history(void)
970{ 981{
971 if (state->flags & DO_HISTORY) { 982 if (state->flags & DO_HISTORY) {
972 int ch = state->cur_history; 983 if (state->cur_history < state->cnt_history) {
973 if (ch < state->cnt_history) { 984 save_command_ps_at_cur_history(); /* save the current history line */
974 get_previous_history(); /* save the current history line */ 985 return ++state->cur_history;
975 state->cur_history = ch + 1;
976 return state->cur_history;
977 } 986 }
978 } 987 }
979 beep(); 988 beep();
@@ -995,6 +1004,7 @@ static void load_history(const char *fromfile)
995 for (hi = state->cnt_history; hi > 0;) { 1004 for (hi = state->cnt_history; hi > 0;) {
996 hi--; 1005 hi--;
997 free(state->history[hi]); 1006 free(state->history[hi]);
1007 state->history[hi] = NULL;
998 } 1008 }
999 1009
1000 for (hi = 0; hi < MAX_HISTORY;) { 1010 for (hi = 0; hi < MAX_HISTORY;) {
@@ -1006,14 +1016,14 @@ static void load_history(const char *fromfile)
1006 l = strlen(hl); 1016 l = strlen(hl);
1007 if (l >= MAX_LINELEN) 1017 if (l >= MAX_LINELEN)
1008 hl[MAX_LINELEN-1] = '\0'; 1018 hl[MAX_LINELEN-1] = '\0';
1009 if (l == 0 || hl[0] == ' ') { 1019 if (l == 0) {
1010 free(hl); 1020 free(hl);
1011 continue; 1021 continue;
1012 } 1022 }
1013 state->history[hi++] = hl; 1023 state->history[hi++] = hl;
1014 } 1024 }
1015 fclose(fp); 1025 fclose(fp);
1016 state->cur_history = state->cnt_history = hi; 1026 state->cnt_history = hi;
1017 } 1027 }
1018} 1028}
1019 1029
@@ -1043,19 +1053,27 @@ static void remember_in_history(const char *str)
1043 1053
1044 if (!(state->flags & DO_HISTORY)) 1054 if (!(state->flags & DO_HISTORY))
1045 return; 1055 return;
1046 1056 if (str[0] == '\0')
1057 return;
1047 i = state->cnt_history; 1058 i = state->cnt_history;
1048 free(state->history[MAX_HISTORY]); 1059 /* Don't save dupes */
1049 state->history[MAX_HISTORY] = NULL; 1060 if (i && strcmp(state->history[i-1], str) == 0)
1050 /* After max history, remove the oldest command */ 1061 return;
1062
1063 free(state->history[MAX_HISTORY]); /* redundant, paranoia */
1064 state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
1065
1066 /* If history[] is full, remove the oldest command */
1067 /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
1051 if (i >= MAX_HISTORY) { 1068 if (i >= MAX_HISTORY) {
1052 free(state->history[0]); 1069 free(state->history[0]);
1053 for (i = 0; i < MAX_HISTORY-1; i++) 1070 for (i = 0; i < MAX_HISTORY-1; i++)
1054 state->history[i] = state->history[i+1]; 1071 state->history[i] = state->history[i+1];
1072 /* i == MAX_HISTORY-1 */
1055 } 1073 }
1056// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..." 1074 /* i <= MAX_HISTORY-1 */
1057// (i.e. do not save dups?)
1058 state->history[i++] = xstrdup(str); 1075 state->history[i++] = xstrdup(str);
1076 /* i <= MAX_HISTORY */
1059 state->cur_history = i; 1077 state->cur_history = i;
1060 state->cnt_history = i; 1078 state->cnt_history = i;
1061#if ENABLE_FEATURE_EDITING_SAVEHISTORY 1079#if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -1397,6 +1415,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1397 if ((state->flags & SAVE_HISTORY) && state->hist_file) 1415 if ((state->flags & SAVE_HISTORY) && state->hist_file)
1398 load_history(state->hist_file); 1416 load_history(state->hist_file);
1399#endif 1417#endif
1418 state->cur_history = state->cnt_history;
1400 1419
1401 /* prepare before init handlers */ 1420 /* prepare before init handlers */
1402 cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ 1421 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
1432 } 1451 }
1433 } 1452 }
1434#endif 1453#endif
1454
1455#if 0
1456 for (ic = 0; ic <= MAX_HISTORY; ic++)
1457 bb_error_msg("history[%d]:'%s'", ic, state->history[ic]);
1458 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
1459#endif
1460
1435 /* Print out the command prompt */ 1461 /* Print out the command prompt */
1436 parse_and_put_prompt(prompt); 1462 parse_and_put_prompt(prompt);
1437 1463
@@ -1540,11 +1566,8 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1540 vi_case(CTRL('P')|vbit:) 1566 vi_case(CTRL('P')|vbit:)
1541 vi_case('k'|vbit:) 1567 vi_case('k'|vbit:)
1542 /* Control-p -- Get previous command from history */ 1568 /* Control-p -- Get previous command from history */
1543 if ((state->flags & DO_HISTORY) && state->cur_history > 0) { 1569 if (get_previous_history())
1544 get_previous_history();
1545 goto rewrite_line; 1570 goto rewrite_line;
1546 }
1547 beep();
1548 break; 1571 break;
1549#endif 1572#endif
1550 1573
@@ -1733,10 +1756,8 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1733#if MAX_HISTORY > 0 1756#if MAX_HISTORY > 0
1734 case 'A': 1757 case 'A':
1735 /* Up Arrow -- Get previous command from history */ 1758 /* Up Arrow -- Get previous command from history */
1736 if ((state->flags & DO_HISTORY) && state->cur_history > 0) { 1759 if (get_previous_history())
1737 get_previous_history();
1738 goto rewrite_line; 1760 goto rewrite_line;
1739 }
1740 beep(); 1761 beep();
1741 break; 1762 break;
1742 case 'B': 1763 case 'B':
@@ -1746,7 +1767,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1746 rewrite_line: 1767 rewrite_line:
1747 /* Rewrite the line with the selected history item */ 1768 /* Rewrite the line with the selected history item */
1748 /* change command */ 1769 /* change command */
1749 command_len = strlen(strcpy(command, state->history[state->cur_history])); 1770 command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
1750 /* redraw and go to eol (bol, in vi */ 1771 /* redraw and go to eol (bol, in vi */
1751 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); 1772 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
1752 break; 1773 break;