ditch [sr]mkx in favor of custom bindkey extension

This commit is contained in:
Andrew Janke 2016-02-21 12:37:22 -05:00
parent 644bc641ad
commit a4fbf19a9e
7 changed files with 251 additions and 109 deletions

View File

@ -229,3 +229,13 @@ function omz_urldecode {
echo -E "$decoded"
}
# Print input iff $_OMZ_DEBUG is enabled (>0)
# All arguments are passed verbatim to print()
function _omz_dbg_print() {
if ! (( $_OMZ_DEBUG )); then
return
fi
print "$@"
}

200
lib/key-binding-support.zsh Normal file
View File

@ -0,0 +1,200 @@
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Builtins
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Standard-Widgets
zmodload -i zsh/zutil
# OMZ takes over zle-line-init/finish, to:
# a) provide hooks for multiple init/finish functions, like $precmd_functions does
# b) disable [sr]mkx on the few systems whose system zsh configuration enables it
typeset -g -a zle_line_init_functions zle_line_finish_functions
function zle-line-init() {
local fcn
for fcn in "${zle_line_init_functions[@]}"; do
$fcn
done
}
function zle-line-finish() {
local fcn
for fcn in "${zle_line_finish_functions[@]}"; do
$fcn
done
}
zle -N zle-line-init
zle -N zle-line-finish
# DEBUG: This is the old stuff we used to do to put the keypads in application mode
# during command line editing. It's included here to make it easy to test the
# new key binding logic under both normal and application modes. This should
# go away once the modeless key binding stuff is tested.
# Note: This breaks the zle-line-init/finish hooks from above.
if (( $_OMZ_DEBUG_SMKX )); then
if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
function zle-line-init() {
echoti smkx
}
function zle-line-finish() {
echoti rmkx
}
zle -N zle-line-init
zle -N zle-line-finish
fi
fi
# end old keypad-mode stuff
# Extra portability cursor key mappings for local-mode keypad and terminals
# which deviate from typical terminfo entries. Supplements $terminfo.
# Maps capability names to |-delimited lists of character sequences.
# Reflects the capabilities of the $TERM defined at startup.
typeset -AHg _omz_terminfo_extra
_omz_terminfo_extra=(
# Start with the basic Xterm local-mode sequences. (Some people call
# these "ANSI" key sequences.)
kcuu1 "\e[A" # up
kcud1 "\e[B" # down
kcuf1 "\e[C" # right ("forward")
kcub1 "\e[D" # left ("backward")
khome "\e[H" # home
kend "\e[F" # end
)
# Portability entries for terminals we can't recognize from $TERM
# Putty and others may send the VT220 editing keypad sequences for
# Home/End. Bind those too, since there's no collision risk AFAIK.
# TODO: Should we alias the whole 6-key VT220 editing keypad?
_omz_terminfo_extra[khome]="$_omz_terminfo_extra[khome]|\e[1~"
_omz_terminfo_extra[kend]="$_omz_terminfo_extra[kend]|\e[4~"
# Do *not* bind '\e[Ow' here, which Putty may also send for End, because
# it collides with application-mode numeric keypad sequences.
# Terminal-specific portability entries for the current terminal, for
# terminals whose local-mode sequences are known to differ from Xterm's
case "$TERM" in
rxvt-unicode*)
# rxvt-unicde local-cursor sequences that differ from xterm
_omz_terminfo_extra[khome]="$_omz_terminfo_extra[khome]|\e[7~"
_omz_terminfo_extra[kend]="$_omz_terminfo_extra[kend]|\e[8~"
esac
# omz_bindkey - an extension to bindkey
#
# omz_bindkey [options] -t <capability> <command>
# omz_bindkey -c <modifier> <cursor-key> <command>
# omz_bindkey [...normal bindkey arguments...]
#
# Adds the following features on top of bindkey:
# 1) Logging
# 2) -t: binds a key, using terminfo and OMZ portability mappings
# 3) -c: binds an Xterm-style modified cursor key sequence
#
# Returns:
# 0 if a binding was made
# 1 if no binding was made
# 2 if an error occurred
function omz_bindkey() {
emulate -L zsh
# Note: "seq" is short for "sequence" in these functions
# We must capture all of bindkey's options to get ordering right when calling it
local -a omz_opts bindkey_opts
omz_opts=()
bindkey_opts=()
local -A optvals
zparseopts -a bindkey_opts -A optvals -D -E t:=omz_opts c=omz_opts M:
if [[ -n ${omz_opts[(r)-t]} ]]; then
# OMZ terminfo-based binding
local cap=${optvals[-t]}
local retval=1 seq seqs
seqs=()
if [[ -n "${terminfo[$cap]}" ]]; then
seqs=("$seqs[@]" "${terminfo[$cap]}")
fi
if [[ -n "${_omz_terminfo_extra[$cap]}" ]]; then
seqs=("$seqs[@]" "${(s:|:)_omz_terminfo_extra[$cap]}")
fi
# Done with a while loop because for seems to break here
local ix=0
while (( ++ix <= $#seqs )); do
seq="${seqs[$ix]}"
_omz_dbg_print -r "omz_bindkey: terminfo: $cap '${(q)seq}' $@"
bindkey "${bindkey_opts[@]}" $seq "$@"
retval=0
done
return $retval
elif [[ -n ${omz_opts[(r)-c]} ]]; then
# "-c" for "composed modified-cursor" keys
_omz_dbg_print -r "omz_bindkey: modified-cursor: '$1' '$2' '$3'"
_omz_bindkey_modified_cursor_key_xterm "$1" "$2" "$3"
else
_omz_dbg_print -r "omz_bindkey: passthrough: ${(q)@}"
bindkey "${bindkey_opts[@]}" "$@"
fi
}
# Xterm style function key modifier codes
typeset -Ag _omz_ti_modifiers
_omz_ti_modifiers=(
'shift' 2
'alt' 3
'alt-shift' 4
'ctrl' 5
'ctrl-shift' 6
'ctrl-alt' 7
'ctrl-alt-shift' 8
'meta' 9
'meta-shift' 10
'meta-alt' 11
'meta-alt-shift' 12
'meta-ctrl' 13
'meta-ctrl-shift' 14
'meta-ctrl-alt' 15
'meta-ctrl-alt-shift' 16
)
# Binds a modified cursor key sequence
# Uses xterm modifier mask codes,
# per http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
# When used in combination, modifier keys must be supplied in the following canonical order:
# meta ctrl alt shift
function _omz_bindkey_modified_cursor_key_xterm() {
emulate -L zsh
local opts
opts=()
zparseopts -a opts -D -E M:
local modifier=$1 key=$2 widget=$3
local CSI='\e[' # Control Sequence Introducer
local seq modified_seq
local -A modifiers keys
set -A modifiers ${(kv)_omz_ti_modifiers}
keys=(
up A
down B
right C
left D
home H
end F
)
if [[ -z "$modifiers[$modifier]" ]] || [[ -z "$keys[$key]" ]]; then
_omz_dbg_print -r "Invalid modified-cursor-key: modifier=$modifier key=$key"
return 1
fi
seq="${CSI}${keys[$key]}"
_omz_bindkey_modified_cursor_seq_xterm_step "$seq" "$modifier"
# Wokaround for iTerm2: it reports alt as meta, so bind alt-modified sequences
# to the meta-modified variant, too.
# See https://gitlab.com/gnachman/iterm2/issues/3753
if [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then
if [[ "$modifier" == "alt" ]]; then
_omz_bindkey_modified_cursor_seq_xterm_step "$seq" "meta"
fi
fi
}
function _omz_bindkey_modified_cursor_seq_xterm_step() {
local seq="$1" modifier="$2"
local modified_seq
local -A modifiers keys
set -A modifiers ${(kv)_omz_ti_modifiers}
modified_seq="${seq[1,-2]}1;$modifiers[$modifier]${seq[-1,-1]}"
omz_bindkey "${opts[@]}" "$modified_seq" "$widget"
}

View File

@ -1,93 +1,39 @@
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Builtins
# http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Standard-Widgets
# Make sure that the terminal is in application mode when zle is active, since
# only then values from $terminfo are valid
if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
function zle-line-init() {
echoti smkx
}
function zle-line-finish() {
echoti rmkx
}
zle -N zle-line-init
zle -N zle-line-finish
fi
# Specific key bindings
# See also key-binding-support.zsh for helper functions used here
bindkey -e # Use emacs key bindings
bindkey '\ew' kill-region # [Esc-w] - Kill from the cursor to the mark
bindkey -s '\el' 'ls\n' # [Esc-l] - run command: ls
bindkey '^r' history-incremental-search-backward # [Ctrl-r] - Search backward incrementally for a specified string. The string may begin with ^ to anchor the search to the beginning of the line.
if [[ "${terminfo[kpp]}" != "" ]]; then
bindkey "${terminfo[kpp]}" up-line-or-history # [PageUp] - Up a line of history
fi
if [[ "${terminfo[knp]}" != "" ]]; then
bindkey "${terminfo[knp]}" down-line-or-history # [PageDown] - Down a line of history
fi
omz_bindkey '\ew' kill-region # [Esc-w] - Kill from the cursor to the mark
omz_bindkey -s '\el' 'ls\n' # [Esc-l] - run command: ls
omz_bindkey '^r' history-incremental-search-backward # [Ctrl-r] - Search backward incrementally for a specified string.
# The string may begin with ^ to anchor the search to the beginning of the line.
# start typing + [Up-Arrow] - fuzzy find history forward
if [[ "${terminfo[kcuu1]}" != "" ]]; then
autoload -U up-line-or-beginning-search
zle -N up-line-or-beginning-search
bindkey "${terminfo[kcuu1]}" up-line-or-beginning-search
fi
# start typing + [Down-Arrow] - fuzzy find history backward
if [[ "${terminfo[kcud1]}" != "" ]]; then
autoload -U down-line-or-beginning-search
zle -N down-line-or-beginning-search
bindkey "${terminfo[kcud1]}" down-line-or-beginning-search
fi
omz_bindkey -t kpp up-line-or-history # [PageUp] - Up a line of history
omz_bindkey -t knp down-line-or-history # [PageDown] - Down a line of history
omz_bindkey -t kcuu1 up-line-or-search # start typing + [Up-Arrow] - fuzzy find history forward
omz_bindkey -t kcud1 down-line-or-search # start typing + [Down-Arrow] - fuzzy find history backward
omz_bindkey -t khome beginning-of-line # [Home] - Go to beginning of line
omz_bindkey -t kend end-of-line # [End] - Go to end of line
omz_bindkey -c ctrl right forward-word # [Ctrl-Right] - move forward one word
omz_bindkey -c ctrl left backward-word # [Ctrl-Left] - move backward one word
omz_bindkey ' ' magic-space # [Space] - do history expansion
if [[ "${terminfo[khome]}" != "" ]]; then
bindkey "${terminfo[khome]}" beginning-of-line # [Home] - Go to beginning of line
fi
if [[ "${terminfo[kend]}" != "" ]]; then
bindkey "${terminfo[kend]}" end-of-line # [End] - Go to end of line
fi
omz_bindkey -t kcbt reverse-menu-complete # [Shift-Tab] - move through the completion menu backwards
bindkey ' ' magic-space # [Space] - do history expansion
bindkey '^[[1;5C' forward-word # [Ctrl-RightArrow] - move forward one word
bindkey '^[[1;5D' backward-word # [Ctrl-LeftArrow] - move backward one word
if [[ "${terminfo[kcbt]}" != "" ]]; then
bindkey "${terminfo[kcbt]}" reverse-menu-complete # [Shift-Tab] - move through the completion menu backwards
fi
bindkey '^?' backward-delete-char # [Backspace] - delete backward
if [[ "${terminfo[kdch1]}" != "" ]]; then
bindkey "${terminfo[kdch1]}" delete-char # [Delete] - delete forward
else
bindkey "^[[3~" delete-char
bindkey "^[3;5~" delete-char
bindkey "\e[3~" delete-char
omz_bindkey '^?' backward-delete-char # [Backspace] - delete backward
omz_bindkey -t kdch1 delete-char # [Delete] - delete forward
if [[ $? != 0 ]]; then
# Alternate forward-delete sequences, if not in terminfo
omz_bindkey '\e[3~' delete-char # VT220 editing keypad Del
omz_bindkey '\e3;5~' delete-char # I don't know what this is, but it was here before -apjanke
fi
# Edit the current command line in $EDITOR
autoload -U edit-command-line
zle -N edit-command-line
bindkey '\C-x\C-e' edit-command-line
omz_bindkey '\C-x\C-e' edit-command-line
# file rename magick
bindkey "^[m" copy-prev-shell-word
# File rename magick
omz_bindkey '\em' copy-prev-shell-word
# consider emacs keybindings:
#bindkey -e ## emacs key bindings
#
#bindkey '^[[A' up-line-or-search
#bindkey '^[[B' down-line-or-search
#bindkey '^[^[[C' emacs-forward-word
#bindkey '^[^[[D' emacs-backward-word
#
#bindkey -s '^X^Z' '%-^M'
#bindkey '^[e' expand-cmd-path
#bindkey '^[^I' reverse-menu-complete
#bindkey '^X^N' accept-and-infer-next-history
#bindkey '^W' kill-region
#bindkey '^I' complete-word
## Fix weird sequence that rxvt produces
#bindkey -s '^[[Z' '\t'
#

View File

@ -27,11 +27,5 @@ insert-cycledright () {
zle -N insert-cycledright
# These sequences work for xterm, Apple Terminal.app, and probably others.
# Not for rxvt-unicode, but it doesn't seem differentiate Ctrl-Shift-Arrow
# from plain Shift-Arrow, at least by default.
# iTerm2 does not have these key combinations defined by default; you will need
# to add them under "Keys" in your profile if you want to use this. You can do
# this conveniently by loading the "xterm with Numeric Keypad" preset.
bindkey "\e[1;6D" insert-cycledleft
bindkey "\e[1;6C" insert-cycledright
omz_bindkey -c ctrl-shift left insert-cycledleft
omz_bindkey -c ctrl-shift right insert-cycledright

View File

@ -11,16 +11,11 @@ if test "$DISABLE_COLOR" = true; then
unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
fi
# Bind terminal-specific up and down keys
# Bind in both emacs and vi modes so it works in both, and is not
# sensitive to whether this is loaded before or after the vi-mode plugin
if [[ -n "$terminfo[kcuu1]" ]]; then
bindkey -M emacs "$terminfo[kcuu1]" history-substring-search-up
bindkey -M viins "$terminfo[kcuu1]" history-substring-search-up
fi
if [[ -n "$terminfo[kcud1]" ]]; then
bindkey -M emacs "$terminfo[kcud1]" history-substring-search-down
bindkey -M viins "$terminfo[kcud1]" history-substring-search-down
fi
omz_bindkey -M emacs -t kcuu1 history-substring-search-up
omz_bindkey -M viins -t kcuu1 history-substring-search-up
omz_bindkey -M emacs -t kcud1 history-substring-search-down
omz_bindkey -M viins -t kcud1 history-substring-search-down

View File

@ -75,14 +75,10 @@ cat >> $plugin_basename.plugin.zsh <<EOF
# Bind terminal-specific up and down keys
if [[ -n "\$terminfo[kcuu1]" ]]; then
bindkey -M emacs "\$terminfo[kcuu1]" history-substring-search-up
bindkey -M viins "\$terminfo[kcuu1]" history-substring-search-up
fi
if [[ -n "\$terminfo[kcud1]" ]]; then
bindkey -M emacs "\$terminfo[kcud1]" history-substring-search-down
bindkey -M viins "\$terminfo[kcud1]" history-substring-search-down
fi
omz_bindkey -M emacs -t kcuu1 history-substring-search-up
omz_bindkey -M viins -t kcuu1 history-substring-search-up
omz_bindkey -M emacs -t kcud1 history-substring-search-down
omz_bindkey -M viins -t kcud1 history-substring-search-down
EOF

View File

@ -17,10 +17,11 @@ bindkey -M paste -s '^M' '^J'
zle -N _start_paste
zle -N _end_paste
zle -N zle-line-init _zle_line_init
zle -N zle-line-finish _zle_line_finish
zle -N paste-insert _paste_insert
zle_line_init_functions+=_omz_safe_paste_line_init
zle_line_finish_functions+=_omz_safe_paste_line_finish
# switch the active keymap to paste mode
function _start_paste() {
bindkey -A paste main
@ -41,12 +42,12 @@ function _paste_insert() {
_paste_content+=$KEYS
}
function _zle_line_init() {
function _omz_safe_paste_line_init() {
# Tell terminal to send escape codes around pastes.
[[ $TERM == rxvt-unicode || $TERM == xterm || $TERM = xterm-256color || $TERM = screen || $TERM = screen-256color ]] && printf '\e[?2004h'
}
function _zle_line_finish() {
function _omz_safe_paste_line_finish() {
# Tell it to stop when we leave zle, so pasting in other programs
# doesn't get the ^[[200~ codes around the pasted text.
[[ $TERM == rxvt-unicode || $TERM == xterm || $TERM = xterm-256color || $TERM = screen || $TERM = screen-256color ]] && printf '\e[?2004l'