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 fb595c010..b3f4f5327 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -953,24 +953,33 @@ static void input_tab(smallint *lastWasTab)
953 953
954#if MAX_HISTORY > 0 954#if MAX_HISTORY > 0
955 955
956static void save_command_ps_at_cur_history(void)
957{
958 if (command_ps[0] != '\0') {
959 int cur = state->cur_history;
960 free(state->history[cur]);
961 state->history[cur] = xstrdup(command_ps);
962 }
963}
964
956/* state->flags is already checked to be nonzero */ 965/* state->flags is already checked to be nonzero */
957static void get_previous_history(void) 966static int get_previous_history(void)
958{ 967{
959 if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) { 968 if ((state->flags & DO_HISTORY) && state->cur_history) {
960 free(state->history[state->cur_history]); 969 save_command_ps_at_cur_history();
961 state->history[state->cur_history] = xstrdup(command_ps); 970 state->cur_history--;
971 return 1;
962 } 972 }
963 state->cur_history--; 973 beep();
974 return 0;
964} 975}
965 976
966static int get_next_history(void) 977static int get_next_history(void)
967{ 978{
968 if (state->flags & DO_HISTORY) { 979 if (state->flags & DO_HISTORY) {
969 int ch = state->cur_history; 980 if (state->cur_history < state->cnt_history) {
970 if (ch < state->cnt_history) { 981 save_command_ps_at_cur_history(); /* save the current history line */
971 get_previous_history(); /* save the current history line */ 982 return ++state->cur_history;
972 state->cur_history = ch + 1;
973 return state->cur_history;
974 } 983 }
975 } 984 }
976 beep(); 985 beep();
@@ -992,6 +1001,7 @@ static void load_history(const char *fromfile)
992 for (hi = state->cnt_history; hi > 0;) { 1001 for (hi = state->cnt_history; hi > 0;) {
993 hi--; 1002 hi--;
994 free(state->history[hi]); 1003 free(state->history[hi]);
1004 state->history[hi] = NULL;
995 } 1005 }
996 1006
997 for (hi = 0; hi < MAX_HISTORY;) { 1007 for (hi = 0; hi < MAX_HISTORY;) {
@@ -1003,14 +1013,14 @@ static void load_history(const char *fromfile)
1003 l = strlen(hl); 1013 l = strlen(hl);
1004 if (l >= MAX_LINELEN) 1014 if (l >= MAX_LINELEN)
1005 hl[MAX_LINELEN-1] = '\0'; 1015 hl[MAX_LINELEN-1] = '\0';
1006 if (l == 0 || hl[0] == ' ') { 1016 if (l == 0) {
1007 free(hl); 1017 free(hl);
1008 continue; 1018 continue;
1009 } 1019 }
1010 state->history[hi++] = hl; 1020 state->history[hi++] = hl;
1011 } 1021 }
1012 fclose(fp); 1022 fclose(fp);
1013 state->cur_history = state->cnt_history = hi; 1023 state->cnt_history = hi;
1014 } 1024 }
1015} 1025}
1016 1026
@@ -1040,19 +1050,27 @@ static void remember_in_history(const char *str)
1040 1050
1041 if (!(state->flags & DO_HISTORY)) 1051 if (!(state->flags & DO_HISTORY))
1042 return; 1052 return;
1043 1053 if (str[0] == '\0')
1054 return;
1044 i = state->cnt_history; 1055 i = state->cnt_history;
1045 free(state->history[MAX_HISTORY]); 1056 /* Don't save dupes */
1046 state->history[MAX_HISTORY] = NULL; 1057 if (i && strcmp(state->history[i-1], str) == 0)
1047 /* After max history, remove the oldest command */ 1058 return;
1059
1060 free(state->history[MAX_HISTORY]); /* redundant, paranoia */
1061 state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */
1062
1063 /* If history[] is full, remove the oldest command */
1064 /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */
1048 if (i >= MAX_HISTORY) { 1065 if (i >= MAX_HISTORY) {
1049 free(state->history[0]); 1066 free(state->history[0]);
1050 for (i = 0; i < MAX_HISTORY-1; i++) 1067 for (i = 0; i < MAX_HISTORY-1; i++)
1051 state->history[i] = state->history[i+1]; 1068 state->history[i] = state->history[i+1];
1069 /* i == MAX_HISTORY-1 */
1052 } 1070 }
1053// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..." 1071 /* i <= MAX_HISTORY-1 */
1054// (i.e. do not save dups?)
1055 state->history[i++] = xstrdup(str); 1072 state->history[i++] = xstrdup(str);
1073 /* i <= MAX_HISTORY */
1056 state->cur_history = i; 1074 state->cur_history = i;
1057 state->cnt_history = i; 1075 state->cnt_history = i;
1058#if ENABLE_FEATURE_EDITING_SAVEHISTORY 1076#if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -1394,6 +1412,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1394 if ((state->flags & SAVE_HISTORY) && state->hist_file) 1412 if ((state->flags & SAVE_HISTORY) && state->hist_file)
1395 load_history(state->hist_file); 1413 load_history(state->hist_file);
1396#endif 1414#endif
1415 state->cur_history = state->cnt_history;
1397 1416
1398 /* prepare before init handlers */ 1417 /* prepare before init handlers */
1399 cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ 1418 cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
@@ -1429,6 +1448,13 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1429 } 1448 }
1430 } 1449 }
1431#endif 1450#endif
1451
1452#if 0
1453 for (ic = 0; ic <= MAX_HISTORY; ic++)
1454 bb_error_msg("history[%d]:'%s'", ic, state->history[ic]);
1455 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
1456#endif
1457
1432 /* Print out the command prompt */ 1458 /* Print out the command prompt */
1433 parse_and_put_prompt(prompt); 1459 parse_and_put_prompt(prompt);
1434 1460
@@ -1537,11 +1563,8 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1537 vi_case(CTRL('P')|vbit:) 1563 vi_case(CTRL('P')|vbit:)
1538 vi_case('k'|vbit:) 1564 vi_case('k'|vbit:)
1539 /* Control-p -- Get previous command from history */ 1565 /* Control-p -- Get previous command from history */
1540 if ((state->flags & DO_HISTORY) && state->cur_history > 0) { 1566 if (get_previous_history())
1541 get_previous_history();
1542 goto rewrite_line; 1567 goto rewrite_line;
1543 }
1544 beep();
1545 break; 1568 break;
1546#endif 1569#endif
1547 1570
@@ -1730,10 +1753,8 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1730#if MAX_HISTORY > 0 1753#if MAX_HISTORY > 0
1731 case 'A': 1754 case 'A':
1732 /* Up Arrow -- Get previous command from history */ 1755 /* Up Arrow -- Get previous command from history */
1733 if ((state->flags & DO_HISTORY) && state->cur_history > 0) { 1756 if (get_previous_history())
1734 get_previous_history();
1735 goto rewrite_line; 1757 goto rewrite_line;
1736 }
1737 beep(); 1758 beep();
1738 break; 1759 break;
1739 case 'B': 1760 case 'B':
@@ -1743,7 +1764,7 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
1743 rewrite_line: 1764 rewrite_line:
1744 /* Rewrite the line with the selected history item */ 1765 /* Rewrite the line with the selected history item */
1745 /* change command */ 1766 /* change command */
1746 command_len = strlen(strcpy(command, state->history[state->cur_history])); 1767 command_len = strlen(strcpy(command, state->history[state->cur_history] ? : ""));
1747 /* redraw and go to eol (bol, in vi */ 1768 /* redraw and go to eol (bol, in vi */
1748 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0); 1769 redraw(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
1749 break; 1770 break;