zsh (or maybe oh-my-zsh) history gets confused with multi-line commands
if I use the up arrow in a zsh session, as you'd expect I get previous commands, from newest to oldest. Now (whether it's zsh or oh-my-zsh doing this I don't know), but if I type the start of a line and hit the up arrow I get the lines from my history that start with whatever I've typed. All good so far.
The problem occurs if I type in a multi line command, eg:
for i in foo bar
echo $i
then if I later hit the up arrow, once it gets to the multi line command it will then only display results starting with for
. So if my history is like:
touch foo
rm foo
for i in foo bar
echo $i
ls
and I hit the up arrow I get the ls
command then the multi-line for
command, and from then on I only see only for
commands that are in my history, rather than the rm
or touch
commands.
Is there any way to be able to search chronologically, without getting stuck whenever the history gets to a multi-line command?
The behaviour described is due to the use of up-line-or-search
, which will move up through the line of a command and on the first line of a command it will search in the history for lines beginning with the first word.
Explanation for your issue:
Starting from an empty line any line in the history will match. As long as only single-line commands are found there is no difference in behaviour to up-history
or up-line-or-history
. But when reaching a multi-line command it is no longer searching but going through the lines. When the top line is reached it starts a new search, but now it is looking for the first word in this line instead of continuing the old search for any line.
By default Up is mapped to up-line-or-history
, which goes backward through the history entries and in case of multi-line commands through each line. up-history
would also go through the history but treat multi-line commands just like single-line ones. Both would provide the expected behaviour.
I'd suggest searching your zsh and Oh-my-ZSH configuration for where up-line-or-search
is bound and replace it with up-line-or-history
or delete the binding as up-line-or-history
is the default anyway.
Also, depending on the terminal used, the key sequenze for Up is either ^[OA
or ^[[A
. To get consisten behaviour from your shell, both should be set to the same commands.