1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -953,24 +953,33 @@
#if MAX_HISTORY > 0
+static void save_command_ps_at_cur_history(void)
+{
+ if (command_ps[0] != '\0') {
+ int cur = state->cur_history;
+ free(state->history[cur]);
+ state->history[cur] = xstrdup(command_ps);
+ }
+}
+
/* state->flags is already checked to be nonzero */
-static void get_previous_history(void)
+static int get_previous_history(void)
{
- if (command_ps[0] != '\0' || state->history[state->cur_history] == NULL) {
- free(state->history[state->cur_history]);
- state->history[state->cur_history] = xstrdup(command_ps);
+ if ((state->flags & DO_HISTORY) && state->cur_history) {
+ save_command_ps_at_cur_history();
+ state->cur_history--;
+ return 1;
}
- state->cur_history--;
+ beep();
+ return 0;
}
static int get_next_history(void)
{
if (state->flags & DO_HISTORY) {
- int ch = state->cur_history;
- if (ch < state->cnt_history) {
- get_previous_history(); /* save the current history line */
- state->cur_history = ch + 1;
- return state->cur_history;
+ if (state->cur_history < state->cnt_history) {
+ save_command_ps_at_cur_history(); /* save the current history line */
+ return ++state->cur_history;
}
}
beep();
@@ -992,6 +1001,7 @@
for (hi = state->cnt_history; hi > 0;) {
hi--;
free(state->history[hi]);
+ state->history[hi] = NULL;
}
for (hi = 0; hi < MAX_HISTORY;) {
@@ -1003,7 +1013,7 @@
l = strlen(hl);
if (l >= MAX_LINELEN)
hl[MAX_LINELEN-1] = '\0';
- if (l == 0 || hl[0] == ' ') {
+ if (l == 0) {
free(hl);
continue;
}
@@ -1040,19 +1050,27 @@
if (!(state->flags & DO_HISTORY))
return;
-
+ if (str[0] == '\0')
+ return;
i = state->cnt_history;
- free(state->history[MAX_HISTORY]);
- state->history[MAX_HISTORY] = NULL;
- /* After max history, remove the oldest command */
+ /* Don't save dupes */
+ if (i && strcmp(state->history[i-1], str) == 0)
+ 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) {
free(state->history[0]);
for (i = 0; i < MAX_HISTORY-1; i++)
state->history[i] = state->history[i+1];
+ /* i == MAX_HISTORY-1 */
}
-// Maybe "if (!i || strcmp(history[i-1], command) != 0) ..."
-// (i.e. do not save dups?)
+ /* i <= MAX_HISTORY-1 */
state->history[i++] = xstrdup(str);
+ /* i <= MAX_HISTORY */
state->cur_history = i;
state->cnt_history = i;
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -1429,6 +1447,13 @@
}
}
#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 */
parse_and_put_prompt(prompt);
@@ -1537,11 +1562,8 @@
vi_case(CTRL('P')|vbit:)
vi_case('k'|vbit:)
/* Control-p -- Get previous command from history */
- if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
- get_previous_history();
+ if (get_previous_history())
goto rewrite_line;
- }
- beep();
break;
#endif
@@ -1730,10 +1752,8 @@
#if MAX_HISTORY > 0
case 'A':
/* Up Arrow -- Get previous command from history */
- if ((state->flags & DO_HISTORY) && state->cur_history > 0) {
- get_previous_history();
+ if (get_previous_history())
goto rewrite_line;
- }
beep();
break;
case 'B':
@@ -1743,7 +1763,7 @@
rewrite_line:
/* Rewrite the line with the selected history item */
/* 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(cmdedit_y, (state->flags & VI_MODE) ? 9999 : 0);
break;
|