Merged vi-mode plugin with Emacs key bindings.

This commit is contained in:
Sorin Ionescu 2011-08-14 21:14:57 -04:00
parent cee7ff7e40
commit 0e284f6c2a
3 changed files with 223 additions and 166 deletions

View file

@ -1,6 +1,13 @@
# Beep on error in line editor. # Beep on error in line editor.
setopt beep setopt beep
# Reset to default key bindings.
bindkey -d
# Allow command line editing in an external editor.
autoload -Uz edit-command-line
zle -N edit-command-line
# Use human-friendly identifiers. # Use human-friendly identifiers.
typeset -g -A keys typeset -g -A keys
keys=( keys=(
@ -33,75 +40,220 @@ keys=(
'Menu' '^[[29~' 'Menu' '^[[29~'
) )
bindkey -d # Reset to default key bindings. if [[ "$KEYMAP" == (emacs|) ]]; then
bindkey -e # Use Emacs key bindings. # Use Emacs key bindings.
bindkey -e
# Do history expansion on space. bindkey "${keys[Escape]}b" emacs-backward-word
bindkey ' ' magic-space bindkey "${keys[Escape]}f" emacs-forward-word
bindkey "${keys[Escape]}${keys[Left]}" emacs-backward-word
bindkey "${keys[Escape]}${keys[Right]}" emacs-forward-word
# Avoid binding ^J, ^M, ^C, ^?, ^S, ^Q, etc. # Kill to the beginning of the line.
bindkey "${keys[Control]}u" backward-kill-line
# Kill to the beginning of the word.
bindkey "${keys[Control]}w" backward-kill-word
# Undo/Redo
bindkey "${keys[Control]}_" undo
bindkey "${keys[Escape]}_" redo
# Search character.
bindkey "${keys[Control]}]" vi-find-next-char
bindkey "${keys[Escape]}${keys[Control]}]" vi-find-prev-char
# Edit command in an external editor.
bindkey "${keys[Control]}x${keys[Control]}e" edit-command-line
# Expand .... to ../..
if ! check-bool "$DISABLE_DOT_EXPANSION"; then
bindkey "." expand-dot-to-parent-directory-path
fi
# Bind to history substring search plugin if enabled;
# otherwise, bind to built-in ZSH history search.
if (( ${+widgets[history-incremental-pattern-search-backward]} )); then
bindkey "${keys[Control]}r" history-incremental-pattern-search-backward
bindkey "${keys[Control]}s" history-incremental-pattern-search-forward
else
bindkey "${keys[Control]}r" history-incremental-search-backward
bindkey "${keys[Control]}s" history-incremental-search-forward
fi
elif [[ "$KEYMAP" == 'vi' ]]; then
# Use vi key bindings.
bindkey -v
# The default mode indicator.
MODE_INDICATOR="%B%F{red}%f%b%F{red}%f"
# Restores RPROMPT when exiting vicmd.
function vi-restore-rprompt() {
if (( $+RPROMPT_CACHED )); then
RPROMPT="$RPROMPT_CACHED"
unset RPROMPT_CACHED
zle reset-prompt
return 0
fi
return 1
}
add-zsh-trap INT vi-restore-rprompt
# Displays the current vi mode (command).
function zle-keymap-select() {
if ! vi-restore-rprompt && [[ "$KEYMAP" == 'vicmd' ]]; then
RPROMPT_CACHED="$RPROMPT"
RPROMPT="$MODE_INDICATOR"
zle reset-prompt
fi
}
zle -N zle-keymap-select
# Resets the prompt after exiting edit-command-line.
function zle-line-init() {
vi-restore-rprompt
}
zle -N zle-line-init
# Resets the prompt after the line has been accepted.
function zle-line-finish() {
vi-restore-rprompt
}
zle -N zle-line-finish
# Edit command in an external editor.
bindkey -M vicmd "v" edit-command-line
# Show cursor position.
bindkey -M vicmd "ga" what-cursor-position
# Undo/Redo
bindkey -M vicmd "u" undo
bindkey -M vicmd "${keys[Control]}r" redo
# Expand .... to ../..
if ! check-bool "$DISABLE_DOT_EXPANSION"; then
bindkey -M viins "." expand-dot-to-parent-directory-path
fi
# Switch to command mode.
bindkey -M viins "jk" vi-cmd-mode
bindkey -M viins "kj" vi-cmd-mode
# Emacs key bindings in insert mode.
bindkey -M viins "${keys[Control]}a" beginning-of-line
bindkey -M viins "${keys[Control]}b" backward-char
bindkey -M viins "${keys[Escape]}b" emacs-backward-word
bindkey -M viins "${keys[Control]}d" delete-char-or-list
bindkey -M viins "${keys[Escape]}d" kill-word
bindkey -M viins "${keys[Control]}e" end-of-line
bindkey -M viins "${keys[Control]}f" forward-char
bindkey -M viins "${keys[Escape]}f" emacs-forward-word
bindkey -M viins "${keys[Control]}k" kill-line
bindkey -M viins "${keys[Control]}u" backward-kill-line
bindkey -M viins "${keys[Control]}w" backward-kill-word
bindkey -M viins "${keys[Escape]}w" copy-region-as-kill
bindkey -M viins "${keys[Escape]}h" run-help
bindkey -M viins "${keys[Escape]}${keys[Left]}" emacs-backward-word
bindkey -M viins "${keys[Escape]}${keys[Right]}" emacs-forward-word
# History
bindkey -M vicmd "gg" beginning-of-history
bindkey -M vicmd "G" end-of-history
# Bind to history substring search plugin if enabled;
# otherwise, bind to built-in ZSH history search.
if (( $+plugins[(er)history-substring-search] )); then
bindkey -M vicmd "k" history-substring-search-up
bindkey -M vicmd "j" history-substring-search-down
else
bindkey -M vicmd "k" up-line-or-history
bindkey -M vicmd "j" down-line-or-history
fi
if (( ${+widgets[history-incremental-pattern-search-backward]} )); then
bindkey -M vicmd "?" history-incremental-pattern-search-backward
bindkey -M vicmd "/" history-incremental-pattern-search-forward
# Emacs key bindings in insert mode.
bindkey -M viins "${keys[Control]}r" history-incremental-pattern-search-backward
bindkey -M viins "${keys[Control]}s" history-incremental-pattern-search-forward
else
bindkey -M vicmd "?" history-incremental-search-backward
bindkey -M vicmd "/" history-incremental-search-forward
# Emacs key bindings in insert mode.
bindkey -M viins "${keys[Control]}r" history-incremental-search-backward
bindkey -M viins "${keys[Control]}s" history-incremental-search-forward
fi
else
echo "oh-my-zsh: KEYMAP must be set 'emacs' or 'vi' but is set to '$KEYMAP'" >&2
return 1
fi
# The next key bindings are for both Emacs and Vi.
bindkey "${keys[Home]}" beginning-of-line bindkey "${keys[Home]}" beginning-of-line
bindkey "${keys[End]}" end-of-line bindkey "${keys[End]}" end-of-line
bindkey "${keys[Insert]}" overwrite-mode bindkey "${keys[Insert]}" overwrite-mode
bindkey "${keys[Delete]}" delete-char bindkey "${keys[Delete]}" delete-char
bindkey "${keys[Backspace]}" backward-delete-char
bindkey "${keys[Up]}" up-line-or-history
bindkey "${keys[Down]}" down-line-or-history
bindkey "${keys[Left]}" backward-char bindkey "${keys[Left]}" backward-char
bindkey "${keys[Right]}" forward-char bindkey "${keys[Right]}" forward-char
bindkey "${keys[Meta]}b" emacs-backward-word # Expand history on space.
bindkey "${keys[Meta]}f" emacs-forward-word bindkey ' ' magic-space
bindkey "${keys[Escape]}${keys[Left]}" emacs-backward-word
bindkey "${keys[Escape]}${keys[Right]}" emacs-forward-word
bindkey "${keys[Control]}w" kill-region if (( $+plugins[(er)history-substring-search] )); then
bindkey "${keys[Up]}" history-substring-search-up
bindkey "${keys[Down]}" history-substring-search-down
bindkey "${keys[Control]}p" history-substring-search-up
bindkey "${keys[Control]}n" history-substring-search-down
else
bindkey "${keys[Up]}" up-line-or-history
bindkey "${keys[Down]}" down-line-or-history
bindkey "${keys[Control]}p" up-line-or-history
bindkey "${keys[Control]}n" down-line-or-history
fi
# Clear screen.
bindkey "${keys[Control]}l" clear-screen
# Expand command name to full path.
bindkey "${keys[Escape]}e" expand-cmd-path bindkey "${keys[Escape]}e" expand-cmd-path
# Duplicate the previous word.
bindkey "${keys[Escape]}m" copy-prev-shell-word bindkey "${keys[Escape]}m" copy-prev-shell-word
bindkey '^[[Z' reverse-menu-complete # Shift + Tab # Bind Shift + Tab to go to the previous menu item.
bindkey "${keys[Control]}i" expand-or-complete-prefix # Complete in middle of word. bindkey '^[[Z' reverse-menu-complete
bindkey "${keys[Control]}_" undo # Complete in the middle of word.
bindkey "${keys[Escape]}_" redo bindkey "${keys[Control]}i" expand-or-complete-prefix
# History
if autoloadable history-search-end; then
autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "${keys[Control]}p" history-beginning-search-backward-end
bindkey "${keys[Control]}n" history-beginning-search-forward-end
else
bindkey "${keys[Control]}p" history-beginning-search-backward
bindkey "${keys[Control]}n" history-beginning-search-forward
fi
if (( ${+widgets[history-incremental-pattern-search-backward]} )); then
bindkey "${keys[Control]}r" history-incremental-pattern-search-backward
bindkey "${keys[Control]}s" history-incremental-pattern-search-forward
else
bindkey "${keys[Control]}r" history-incremental-search-backward
bindkey "${keys[Control]}s" history-incremental-search-forward
fi
# Allow command line editing in an external editor.
autoload -Uz edit-command-line
zle -N edit-command-line
bindkey "${keys[Control]}x${keys[Control]}e" edit-command-line
# Convert .... to ../.. automatically. # Convert .... to ../.. automatically.
function rationalize-dot() { if ! check-bool "$DISABLE_DOT_EXPANSION"; then
function expand-dot-to-parent-directory-path() {
if [[ $LBUFFER = *.. ]]; then if [[ $LBUFFER = *.. ]]; then
LBUFFER+=/.. LBUFFER+=/..
else else
LBUFFER+=. LBUFFER+=.
fi fi
} }
zle -N rationalize-dot zle -N expand-dot-to-parent-directory-path
bindkey '.' rationalize-dot # Do not expand .... to ../.. during incremental search.
bindkey -M isearch . self-insert 2>/dev/null bindkey -M isearch . self-insert 2>/dev/null
fi
# Display an indicator when completing.
if ! check-bool "$DISABLE_COMPLETION_INDICATOR"; then
function expand-or-complete-prefix-with-indicator() {
echo -n "\e[31m...\e[0m"
zle expand-or-complete-prefix
zle redisplay
}
zle -N expand-or-complete-prefix-with-indicator
bindkey "${keys[Control]}i" expand-or-complete-prefix-with-indicator
fi

View file

@ -1,104 +0,0 @@
# ------------------------------------------------------------------------------
# FILE: vi-mode.plugin.zsh
# DESCRIPTION: oh-my-zsh plugin file.
# AUTHOR: Sorin Ionescu <sorin.ionescu@gmail.com>
# VERSION: 1.0.3
# ------------------------------------------------------------------------------
# Allow command line editing in an external editor.
autoload -Uz edit-command-line
# If mode indicator wasn't setup by theme, define a default.
if [[ "$MODE_INDICATOR" == "" ]]; then
MODE_INDICATOR="%B%F{red}<%f%b%F{red}<<%f"
fi
# If I am using vi keys, I want to know what mode I'm currently using.
# zle-keymap-select is executed every time KEYMAP changes.
# From http://zshwiki.org/home/examples/zlewidgets
function zle-line-init zle-keymap-select {
if [[ "$KEYMAP" == 'vicmd' ]]; then
rprompt_cached="$RPROMPT"
RPROMPT="$MODE_INDICATOR"
elif [[ -n "$rprompt_cached" ]]; then
RPROMPT="$rprompt_cached"
rprompt_cached=""
fi
zle reset-prompt
}
# Accept RETURN in vi command mode.
function accept_line {
if [[ -n "$rprompt_cached" ]]; then
RPROMPT="$rprompt_cached"
rprompt_cached=""
fi
builtin zle .accept-line
}
zle -N zle-line-init
zle -N zle-keymap-select
zle -N accept_line
zle -N edit-command-line
# Avoid binding ^J, ^M, ^C, ^?, ^S, ^Q, etc.
bindkey -d # Reset to default.
bindkey -v # Use vi key bindings.
bindkey -M vicmd "^M" accept_line # Alow RETURN in vi command.
bindkey -M vicmd v edit-command-line # ESC-v to edit in an external editor.
bindkey ' ' magic-space
bindkey -M vicmd "gg" beginning-of-history
bindkey -M vicmd "G" end-of-history
# Bind to history substring search plugin if enabled;
# otherwise, bind to built-in ZSH history search.
if (( $+plugins[(er)history-substring-search] )); then
bindkey -M vicmd "k" history-substring-search-up
bindkey -M vicmd "j" history-substring-search-down
else
bindkey -M vicmd "k" history-search-backward
bindkey -M vicmd "j" history-search-forward
fi
bindkey "^P" up-line-or-search
bindkey -M vicmd "k" up-line-or-search
bindkey -M vicmd "^k" up-line-or-search
bindkey -M viins "^k" up-line-or-search
bindkey "^N" down-line-or-search
bindkey -M vicmd "j" down-line-or-search
bindkey -M vicmd "^j" down-line-or-search
bindkey -M viins "^j" down-line-or-search
bindkey -M viins '^r' history-incremental-pattern-search-backward
bindkey -M viins '^f' history-incremental-pattern-search-forward
bindkey -M vicmd "?" history-incremental-pattern-search-backward
bindkey -M vicmd "/" history-incremental-pattern-search-forward
bindkey -M vicmd "^l" clear-screen
bindkey -M viins "^l" clear-screen
bindkey -M vicmd "^w" backward-kill-word
bindkey -M viins "^w" backward-kill-word
bindkey -M vicmd "^a" beginning-of-line
bindkey -M viins "^a" beginning-of-line
bindkey -M vicmd "^e" end-of-line
bindkey -M viins "^e" end-of-line
bindkey -M vicmd '^d' delete
bindkey -M viins '^d' delete
bindkey -M vicmd '^?' backward-delete-char
bindkey -M viins '^?' backward-delete-char
# 'jj' = ESC
bindkey -M viins 'jj' vi-cmd-mode
if (( ${+functions[rationalize-dot]} )); then
bindkey -M viins '.' rationalize-dot
bindkey -M isearch . self-insert 2>/dev/null
fi

View file

@ -1,6 +1,9 @@
# Path to oh-my-zsh. # Path to oh-my-zsh.
OMZ="$HOME/.oh-my-zsh" OMZ="$HOME/.oh-my-zsh"
# Set the key mapping style to 'emacs' or 'vi'.
KEYMAP='emacs'
# Set to 'true' to enable case-sensitivity. # Set to 'true' to enable case-sensitivity.
CASE_SENSITIVE='false' CASE_SENSITIVE='false'
@ -10,6 +13,12 @@ DISABLE_COLOR='false'
# Set to 'true' to disable auto setting the tab and window titles. # Set to 'true' to disable auto setting the tab and window titles.
DISABLE_AUTO_TITLE='false' DISABLE_AUTO_TITLE='false'
# Set to 'false' to enable converting .... to ../.. automatically.
DISABLE_DOT_EXPANSION='true'
# Set to 'false' to enable the completion indicator.
DISABLE_COMPLETION_INDICATOR='true'
# Set the plugins to load (see $OMZ/plugins/). # Set the plugins to load (see $OMZ/plugins/).
# Example: plugins=(git lighthouse rails ruby textmate) # Example: plugins=(git lighthouse rails ruby textmate)
plugins=(git) plugins=(git)