Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Is it possible to...

  • Step up local ZSH shell history (actions only happened in that prompt)

  • Step up global ZSH history (shared history is on) - default what happens when you press UP arrow when shared history is on

... separately.

For example one might bind CTRL+up for global history, normal up for local history. At the same time it makes sense to use the global history for a backwards history search (i.e. CTRL+R).

This might speed up some shell operations, as some operations are specific to that shell window and you want to go back in them.

share|improve this question
up vote 15 down vote accepted

Copy & Paste this to your .zshrc:

Cursors are using local history:

bindkey "${key[Up]}" up-line-or-local-history
bindkey "${key[Down]}" down-line-or-local-history

up-line-or-local-history() {
    zle set-local-history 1
    zle up-line-or-history
    zle set-local-history 0
}
zle -N up-line-or-local-history
down-line-or-local-history() {
    zle set-local-history 1
    zle down-line-or-history
    zle set-local-history 0
}
zle -N down-line-or-local-history

If you need also key bindings (CTRL + cursors) to step through the global history add also this to your .zshrc:

bindkey "^[[1;5A" up-line-or-history    # [CTRL] + Cursor up
bindkey "^[[1;5B" down-line-or-history  # [CTRL] + Cursor down

To make this work the option SHARE_HISTORY (see 16.2.4 History) needs to be enabled. Run setopt and check if "sharehistory" is listed. If not add setopt sharehistory to your .zshrc. Then one can use set-local-history as we did above. The documenation says:

By default, history movement commands visit the imported lines as well as the local lines, but you can toggle this on and off with the set-local-history zle binding. It is also possible to create a zle widget that will make some commands ignore imported commands, and some include them.

Note that by default global history is used (and all functions end with "zle set-local-history 0", i.e. local history is disabled). So pressing CTRL + R will search the global history by default (which makes sense in most cases).

This is quite similar to the solution by @mpy, but ready for copy & paste. It overwrites the cursor keys up and down. I used this mail list entry.

See also:

share|improve this answer
    
On zsh 5.0.2 I get an error that it cannot bind to an empty key sequence. Even if I replace it with the keys from another answer below, both up/down and Ctrl+up/down just go through global history. Anything I'm doing wrong here? – rjh Feb 22 at 20:10
    
@rjh: Try this: In an editor like vim, delete the ${key[Up]}. Then (in edit mode), type Ctrl+V followed by up arrow. This should insert the correct key code. Do the same for down arrow. – robinst Mar 1 at 0:19

You can setup a special zle widget to show only local history items:

function only-local-history () {
        zle set-local-history 1
        zle up-history
        zle set-local-history 0
}
zle -N only-local-history

Assuming, that is bound to up-line-or-history (I think that is default), you can bind this widget to another key stroke, like CTRL+:

 bindkey "^[Oa" only-local-history

If this works is probably dependent of your terminal. Above line works in URxvt/Screen. With xterm you'll need

 bindkey "^[[1;5A" only-local-history

for CTRL+.

Another variant could be

function peek-history () {
        zle set-local-history
        zle up-history
        zle set-local-history
}
zle -N peek-history

so, if you have local history enabled, you can peek into the global one or vice versa.

share|improve this answer

@lumbic's answer worked for me only with a few changes:

setopt share_history

up-line-or-local-history() {
    zle set-local-history 1
    zle up-line-or-history
    zle set-local-history 0
}
zle -N up-line-or-local-history
down-line-or-local-history() {
    zle set-local-history 1
    zle down-line-or-history
    zle set-local-history 0
}
zle -N down-line-or-local-history

bindkey '^[OA' up-line-or-history     # Cursor up
bindkey '^[OB' down-line-or-history   # Cursor down
bindkey '^[[1;5A' up-line-or-local-history    # [CTRL] + Cursor up
bindkey '^[[1;5B' down-line-or-local-history  # [CTRL] + Cursor down

This code makes the global history the default, and uses CTRL-arrow for local history.

Note: I use zsh 5.0.2 together with oh-my-zsh.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.