1 ## tags: interactive
2 ## compare_shells: bash
3 ## oils_failures_allowed: 9
4 ## oils_cpp_failures_allowed: 7
5
6 #### history -a
7 rm -f tmp
8
9 echo '
10 history -c
11
12 HISTFILE=tmp
13 echo 1
14 history -a
15 cat tmp
16
17 echo 2
18
19 cat tmp
20 ' | $SH -i
21
22 # match osh's behaviour of echoing ^D for EOF
23 case $SH in bash) echo '^D' ;; esac
24
25 ## STDOUT:
26 1
27 HISTFILE=tmp
28 echo 1
29 history -a
30 2
31 HISTFILE=tmp
32 echo 1
33 history -a
34 ^D
35 ## END
36
37
38 #### history -w writes out the in-memory history to the history file
39
40 cd $TMP
41
42 # Populate a history file with a command to be overwritten
43 echo 'cmd old' > tmp
44 HISTFILE=tmp
45 history -c
46 echo 'cmd new' > /dev/null
47 history -w # Overwrite history file
48
49 # Verify that old command is gone
50 grep 'old' tmp > /dev/null
51 echo "found=$?"
52 ## STDOUT:
53 found=1
54 ## END
55
56
57 #### history -r reads from the history file, and appends it to the current history
58
59 cd $TMP
60 printf "cmd orig%s\n" {1..10} > tmp
61 HISTFILE=tmp
62
63 history -c
64
65 history -r
66 history -r
67
68 history | grep orig | wc -l
69
70 ## STDOUT:
71 20
72 ## END
73
74
75 #### history -n reads *new* commands from the history file, and appends them to the current history
76 # NB: Based on line ranges, not contents
77
78 cd $TMP
79
80 printf "cmd orig%s\n" {1..10} > tmp1
81 cp tmp1 tmp2
82 printf "cmd new%s\n" {1..10} >> tmp2
83
84 history -c
85 HISTFILE=tmp1 history -r
86 HISTFILE=tmp2 history -n
87
88 history | grep orig | wc -l
89 history | grep new | wc -l
90
91 ## STDOUT:
92 10
93 10
94 ## END
95
96
97 #### history -c clears in-memory history
98
99 $SH --norc -i <<'EOF'
100 echo 'foo' > /dev/null
101 echo 'bar' > /dev/null
102 history -c
103 history | wc -l
104 EOF
105
106 case $SH in bash) echo '^D' ;; esac
107
108 ## STDOUT:
109 1
110 ^D
111 ## END
112
113
114 #### history -d to delete 1 item
115
116 cd $TMP
117 HISTFILE=tmp
118 printf "cmd orig%s\n" {1..3} > tmp
119 history -c
120 history -r
121 history -d 1
122 history | grep orig1 > /dev/null
123 echo "status=$?"
124
125 ## STDOUT:
126 status=1
127 ## END
128
129
130 #### history -d to delete history from end
131 # bash 4 doesn't support negative indices or ranges
132
133 rm -f myhist
134 export HISTFILE=myhist
135
136 $SH --norc -i <<'EOF'
137
138 echo 42
139 echo 43
140 echo 44
141
142 history -a
143
144 history -d 1
145 echo status=$?
146
147 # Invalid integers
148 history -d -1
149 echo status=$?
150 history -d -2
151 echo status=$?
152 history -d 99
153 echo status=$?
154
155 case $SH in bash*) echo '^D' ;; esac
156
157 EOF
158
159 ## STDOUT:
160 42
161 43
162 44
163 status=0
164 status=2
165 status=2
166 status=2
167 ^D
168 ## END
169
170 # bash-4.4 used to give more errors like OSH? Weird
171
172 ## STDOUT:
173 42
174 43
175 44
176 status=0
177 status=0
178 status=0
179 status=1
180 ^D
181 ## END
182
183
184 #### HISTFILE is defined initially
185 echo '
186 if test -n $HISTFILE; then echo exists; fi
187 ' | $SH -i
188
189 # match osh's behaviour of echoing ^D for EOF
190 case $SH in bash) echo '^D' ;; esac
191
192 ## STDOUT:
193 exists
194 ^D
195 ## END
196
197 #### HISTFILE must point to a file
198
199 rm -f _tmp/does-not-exist
200
201 echo '
202 HISTFILE=_tmp/does-not-exist
203 history -r
204 echo status=$?
205 ' | $SH -i
206
207 # match osh's behaviour of echoing ^D for EOF
208 case $SH in bash) echo '^D' ;; esac
209
210 ## STDOUT:
211 status=1
212 ^D
213 ## END
214
215 #### HISTFILE set to array
216
217 echo '
218 HISTFILE=(a b c)
219 history -a
220 echo status=$?
221 ' | $SH -i
222
223 case $SH in bash) echo '^D' ;; esac
224
225 # note that bash actually writes the file 'a', since that's ${HISTFILE[0]}
226
227 ## STDOUT:
228 status=1
229 ^D
230 ## END
231
232 ## OK bash STDOUT:
233 status=0
234 ^D
235 ## END
236
237 #### HISTFILE unset
238
239 echo '
240 unset HISTFILE
241 history -a
242 echo status=$?
243 ' | $SH -i
244
245 case $SH in bash) echo '^D' ;; esac
246
247 ## STDOUT:
248 status=1
249 ^D
250 ## END
251
252
253 #### history usage
254
255 history not-a-number
256 echo status=$?
257
258 history 3 too-many
259 echo status=$?
260
261 ## STDOUT:
262 status=2
263 status=2
264 ## END
265
266 ## OK bash STDOUT:
267 status=1
268 status=1
269 ## END
270
271
272 #### HISTSIZE shrinks the in-memory history when changed
273
274 cd $TMP
275 printf "cmd %s\n" {1..10} > tmp
276 HISTFILE=tmp
277 history -c
278 history -r
279 history | wc -l
280 HISTSIZE=5
281 history | wc -l
282
283 ## STDOUT:
284 10
285 5
286 ## END
287
288
289 #### HISTFILESIZE shrinks the history file when changed
290
291 cd $TMP
292 printf "cmd %s\n" {1..10} > tmp
293 HISTFILE=tmp
294 HISTFILESIZE=5
295 cat tmp | wc -l
296
297 ## STDOUT:
298 5
299 ## END
300
301
302 #### recording history can be toggled with set -o/+o history
303
304 cd $TMP
305 printf "echo %s\n" {1..3} > tmp
306 HISTFILE=tmp $SH -i <<'EOF'
307 set +o history
308 echo "not recorded" >> /dev/null
309 set -o history
310 echo "recorded" >> /dev/null
311 EOF
312
313 case $SH in bash) echo '^D' ;; esac
314
315 grep "not recorded" tmp >> /dev/null
316 echo status=$?
317 grep "recorded" tmp >> /dev/null
318 echo status=$?
319
320 ## STDOUT:
321 ^D
322 status=1
323 status=0
324 ## END
325
326
327 #### shopt histappend toggle check
328
329 shopt -s histappend
330 echo status=$?
331 shopt -p histappend
332 shopt -u histappend
333 echo status=$?
334 shopt -p histappend
335
336 # match osh's behaviour of echoing ^D for EOF
337 case $SH in bash) echo '^D' ;; esac
338
339 ## STDOUT:
340 status=0
341 shopt -s histappend
342 status=0
343 shopt -u histappend
344 ^D
345 ## END
346
347
348 #### shopt histappend - osh ignores shopt and appends, bash sometimes overwrites
349 # When set, bash always appends when exiting, no matter what.
350 # When unset, bash will append anyway as long the # of new commands < the hist length
351 # Either way, the file is truncated to HISTFILESIZE afterwards.
352 # osh always appends
353
354 cd $TMP
355
356 export HISTSIZE=10
357 export HISTFILESIZE=1000
358 export HISTFILE=tmp
359
360 histappend_test() {
361 local histopt
362 if [[ "$1" == true ]]; then
363 histopt='shopt -s histappend'
364 else
365 histopt='shopt -u histappend'
366 fi
367
368 printf "cmd orig%s\n" {1..10} > tmp
369
370 $SH --norc -i <<EOF
371 HISTSIZE=2 # Stifle the history down to 2 commands
372 $histopt
373 # Now run >2 commands to trigger bash's overwrite behavior
374 echo cmd new1 > /dev/null
375 echo cmd new2 > /dev/null
376 echo cmd new3 > /dev/null
377 EOF
378
379 case $SH in bash) echo '^D' ;; esac
380 }
381
382 # If we force histappend, bash won't overwrite the history file
383 histappend_test true
384 grep "orig" tmp > /dev/null
385 echo status=$?
386
387 # If we don't force histappend, bash will overwrite the history file when the number of cmds exceeds HISTSIZE
388 histappend_test false
389 grep "orig" tmp > /dev/null
390 echo status=$?
391
392 ## STDOUT:
393 ^D
394 status=0
395 ^D
396 status=1
397 ## OK osh STDOUT:
398 ^D
399 status=0
400 ^D
401 status=0
402 ## END
403