diff --git a/README.md b/README.md index 8c0f400..0749f8c 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,21 @@ and multi-terminal history support is enabled. The vi mode line editor is enabled. [zsh-vim-mode][vim-mode] was a reasonable starting point but was replaced as it uses some strange defaults. +#### Cursor Shape + +In order to easily ascertain which vi mode the line editor is currently using +escape sequences are sent to the terminal emulator on certain events to change +the current shape of the cursor. Two cursor shapes are used; block for `vicmd` +mode; a vertical line for `viins` mode. Additional escape sequences are used +when [tmux][tmux] is detected to ensure the terminal emulator receives the +appropriate sequence. [iTerm2][iterm2] and VTE compatible terminal emulators are +supported. + +Three hooks are registered with the line editor; `zle-keymap-select` changes the +cursor shape then the mode is changed; `zle-line-init` changes the shape +starting editing a new command; and `zle-line-finish` resets the cursor shape +when the line edit is complete. + #### `vicmd` Mode Undo and repo and enabled using `u` and `U`. Showing help for the command under @@ -127,4 +142,6 @@ Various aliases are defined at the end of [zshrc](zshrc) for convenience. [syntax]: https://github.com/zsh-users/zsh-syntax-highlighting [search]: https://github.com/zsh-users/zsh-history-substring-search [vim-mode]: https://github.com/sharat87/zsh-vim-mode +[tmux]: https://tmux.github.io +[iterm2]: https://www.iterm2.com [vim]: http://www.vim.org/ diff --git a/zshrc b/zshrc index 8701ab7..9eeab79 100644 --- a/zshrc +++ b/zshrc @@ -66,6 +66,42 @@ autoload -U edit-command-line zle -N edit-command-line bindkey -M vicmd '^V' edit-command-line +# Enable changing cursor shape based on vi mode +if [ "$TMUX" != "" ]; then + tmux_before="\EPtmux;\E" + tmux_after="\E\\" +fi +if [ "$ITERM_SESSION_ID" != "" ]; then + # iterm2 cursor shape escape sequences + cursor_block="$tmux_before\E]50;CursorShape=0\C-G$tmux_after" + cursor_line="$tmux_before\E]50;CursorShape=1\C-G$tmux_after" +else + # VTE compatible cursor shape escape sequences + cursor_block="$tmux_before\E[2 q$tmux_after" + cursor_line="$tmux_before\E[6 q$tmux_after" +fi +unset tmux_before tmux_after + +if [[ ! -z "$cursor_block" && ! -z "$cursor_line" ]]; then + # Change cursor shape when vi mode changes + function zle-keymap-select zle-line-init { + case $KEYMAP in + vicmd) print -n -- "$cursor_block" ;; + viins|main) print -n -- "$cursor_line" ;; + esac + zle reset-prompt + zle -R + } + + # Change cursor shape when line editing is finished + function zle-line-finish { print -n -- "$cursor_block" } + + # Register cursor shape hooks + zle -N zle-keymap-select + zle -N zle-line-init + zle -N zle-line-finish +fi + # Remove duplicates from environment variables typeset -U PATH typeset -U MANPATH