Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
# Luke's config for the Zoomer Shell
# Enable colors and change prompt:
autoload -U colors && colors
PS1="%B%{$fg[red]%}[%{$fg[yellow]%}%n%{$fg[green]%}@%{$fg[blue]%}%M %{$fg[magenta]%}%~%{$fg[red]%}]%{$reset_color%}$%b "
# History in cache directory:
# Basic auto/tab complete:
autoload -U compinit
zstyle ':completion:*' menu select
zmodload zsh/complist
_comp_options+=(globdots) # Include hidden files.
# vi mode
bindkey -v
# Use vim keys in tab complete menu:
bindkey -M menuselect 'h' vi-backward-char
bindkey -M menuselect 'k' vi-up-line-or-history
bindkey -M menuselect 'l' vi-forward-char
bindkey -M menuselect 'j' vi-down-line-or-history
bindkey -v '^?' backward-delete-char
# Change cursor shape for different vi modes.
function zle-keymap-select {
if [[ ${KEYMAP} == vicmd ]] ||
[[ $1 = 'block' ]]; then
echo -ne '\e[1 q'
elif [[ ${KEYMAP} == main ]] ||
[[ ${KEYMAP} == viins ]] ||
[[ ${KEYMAP} = '' ]] ||
[[ $1 = 'beam' ]]; then
echo -ne '\e[5 q'
zle -N zle-keymap-select
zle-line-init() {
zle -K viins # initiate `vi insert` as keymap (can be removed if `bindkey -V` has been set elsewhere)
echo -ne "\e[5 q"
zle -N zle-line-init
echo -ne '\e[5 q' # Use beam shape cursor on startup.
preexec() { echo -ne '\e[5 q' ;} # Use beam shape cursor for each new prompt.
# Use lf to switch directories and bind it to ctrl-o
lfcd () {
lf -last-dir-path="$tmp" "$@"
if [ -f "$tmp" ]; then
dir="$(cat "$tmp")"
rm -f "$tmp"
[ -d "$dir" ] && [ "$dir" != "$(pwd)" ] && cd "$dir"
bindkey -s '^o' 'lfcd\n'
# Edit line in vim with ctrl-e:
autoload edit-command-line; zle -N edit-command-line
bindkey '^e' edit-command-line
# Load aliases and shortcuts if existent.
[ -f "$HOME/.config/shortcutrc" ] && source "$HOME/.config/shortcutrc"
[ -f "$HOME/.config/aliasrc" ] && source "$HOME/.config/aliasrc"
# Load zsh-syntax-highlighting; should be last.
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 2>/dev/null
Copy link

corneliusroemer commented Oct 12, 2020

The code to change the cursor based on vi mode works perfectly, thanks so much! I've been trying loads of suggestions from SO but they all had bugs.

Wit this table, one can customise the type of cursor one gets as requested by @yochem and suggested by @gregops:

Replace number in '\e[5 q' with number below for customisation:
          Set cursor style (DECSCUSR), VT520.
            Ps = 0  ⇒  blinking block.
            Ps = 1  ⇒  blinking block (default).
            Ps = 2  ⇒  steady block.
            Ps = 3  ⇒  blinking underline.
            Ps = 4  ⇒  steady underline.
            Ps = 5  ⇒  blinking bar, xterm.
            Ps = 6  ⇒  steady bar, xterm.


Copy link

JDeepD commented Oct 25, 2020

I'd also remove line 21 (setting KEYTIMEOUT). Setting it to 1 is not a good idea anyway. The default of 20 is perhaps too high (I use 5). Setting it to 1 gets widely perpetuated as advice for vi mode. At some point, it alleviated one problem while creating a different problem, but since around zsh 5.1 the original problem has been fixed properly.

Make sure you've really got vi mode. What is escape bound to - run bindkey '\e'

The man page printing is the run-help widget which is typically bound to F1. Given that F1 is right next to Escape, could you be sometimes hitting that by mistake.

How are you invoking the "script"? It needs to be sourced or included in .zshrc. Running it as a script will use a subshell which is no help at all.

Setting KEYTIMEOUT=1 or deleting it will create problems as you will not be able to bind the jj key to Esc. The minimum KEYTIMEOUT for making jj work is 20ms. So if someone wants to map jj to Esc , he has to set KEYTIMEOUT=20

Copy link

therajat08 commented Nov 4, 2020

turn CTRL+z into a toggle switch

ctrlz() {
  if [[ $#BUFFER == 0 ]]; then
    fg >/dev/null 2>&1 && zle redisplay
    zle push-input
zle -N ctrlz
bindkey '^Z' ctrlz

what is this used for?

Copy link

rod-stuchi commented Nov 5, 2020

hi @therajat08 it's for alternate your processes in background.
Try this:

open vim, then ctrl+z (back to terminal), then ctrl+z (back to vim)

Copy link

Blugil commented Dec 31, 2020

Both the bindkey -s '^o' 'lfcd\n' and bindkey '^e' edit-command-line keybinds don't work for me. I saw someone above that had a similar issue and I've tried my best to look up how to do this on my own. I've made sure there are no conflicting keybinds but I've also set a myriad of different keybinds besides ^o and ^e just in case but to no avail. Let me know if anyone else has had this issue and how you fixed it or if you know the fix.

Copy link

souvikhaldar commented Dec 31, 2020

hi @therajat08 it's for alternate your processes in background.
Try this:

open vim, then ctrl+z (back to terminal), then ctrl+z (back to vim)

Ctrl+z did take me to terminal from vim, but pressing ctrl+z from terminal did not take me back to vim, I ran ‘fg’ for that.

Copy link

dm17 commented Dec 31, 2020 might be a candidate to replace a bit of this... Thoughts?

Copy link

RichardBronosky commented Feb 17, 2021

@Arjentix @zaid-g
It turns out that, unless told to do otherwise, vim will just use whatever cursor shaped your terminal/shell is currently using. And when you type vim and hit <return> (even if you hit <esc> to enter vi-mode and then hit <return>) you are in main or viins mode/keymap in your shell and the zle-keymap-select function has used echo -ne '\e[5 q' to set your cursor to "blinking vertical bar". You can overcome this by doing:

echo -ne "\e[1 q"; vim

Or in vim you can do:

:!echo -ne "\e[1 q";

That is not convenient, but if it's possible, then it has to be scriptable! Sure enough, armed with that info, I was able to find this…

Taken from adding this to my ~/.vim/vimrc gave me the same behavior in vim as in zsh.

"Mode Settings

let &t_SI.="\e[5 q" "SI = INSERT mode
let &t_SR.="\e[4 q" "SR = REPLACE mode
let &t_EI.="\e[1 q" "EI = NORMAL mode (ELSE)

"Cursor settings:

"  1 -> blinking block
"  2 -> solid block 
"  3 -> blinking underscore
"  4 -> solid underscore
"  5 -> blinking vertical bar
"  6 -> solid vertical bar

Copy link

RichardBronosky commented Mar 3, 2021

Also, it seems that Luke is not updating this gist and the voidrice version is being maintained instead. To compare you can vimdiff 2 process substitutions curling the raw URLs of each like so:

vimdiff <(curl -sL "") \
        <(curl -sL "")


A process substitution is shell syntactic sugar that creates temporary FIFOs (ie /dev/fd/11) for a process. These can be used where a file is expected. Learn it. Love it.

Copy link

dm17 commented Mar 3, 2021

I ended up going with fish +

Copy link

chris-w-jarvis commented Mar 16, 2021

Also, it seems that Luke is not updating this gist and the voidrice version is being maintained instead.

Thanks @RichardBronosky , for anyone else attempting to install this on MacOS, the last line where you install the syntax highlighting did not work for me out of the box. You will need to also install the syntax highlighting plugin from and then correctly reference your install location in the last line of the .zshrc file.

Also, the autosuggestions were the killer feature of Fish for me, here is good alternative for zsh: It works well but it doesn't seem to query the global history as Fish does.

Copy link

array-in-a-matrix commented Sep 21, 2021

You inspired me to do a rangercd:

rangercd () {
    ranger --choosedir="$tmp" "$@"
    if [ -f "$tmp" ]; then
        dir="$(cat "$tmp")"
        rm -f "$tmp"
        [ --datadir "$dir" ] && [ "$dir" != "$(pwd)" ] && cd "$dir"                                               

so you just have to switch
last-dir-path with --choosedir and -d with --datadir

another plugin you could very appreciate is zsh-autosuggestions or fzf (fuzzy finder for ZSH)

also: does lf have an imagepreview?

I am a bit late to reply lol but lf actually does have image preview check out lfimg. It works flawless and I prefer it over ranger.

Copy link

jessebrennan commented Dec 28, 2021

@RichardBronosky (and @Arjentix and @zaid-g if you're still following),

Taken from adding this to my ~/.vim/vimrc gave me the same behavior in vim as in zsh.

None of these worked for me, but what finally got the cursor to reset was:

:silent !echo -ne "\e[2 q"

Copy link

RyanTippsTX commented Mar 8, 2022

Did you come up with the name "zoomer" shell? That is hilarious

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment