truly the nix pad rabbit hole
This commit is contained in:
8
dot_zsh-vi-mode/zsh-vi-mode.plugin.zsh
Normal file
8
dot_zsh-vi-mode/zsh-vi-mode.plugin.zsh
Normal file
@@ -0,0 +1,8 @@
|
||||
# According to the standard:
|
||||
# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
|
||||
0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}"
|
||||
0="${${(M)0:#/*}:-$PWD/$0}"
|
||||
|
||||
source "${0:h}/zsh-vi-mode.zsh"
|
||||
|
||||
|
||||
716
dot_zsh-vi-mode/zsh-vi-mode.zsh
Normal file
716
dot_zsh-vi-mode/zsh-vi-mode.zsh
Normal file
@@ -0,0 +1,716 @@
|
||||
# zsh-vi-mode.zsh -- A better and friendly vi(vim) mode for Zsh
|
||||
# https://github.com/jeffreytse/zsh-vi-mode
|
||||
#
|
||||
# Copyright (c) 2020 Jeffrey Tse
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# All Settings
|
||||
# Some of these variables should be set before sourcing this file.
|
||||
#
|
||||
# ZVM_CONFIG_FUNC
|
||||
# the config function (default is `zvm_config`), if this config function
|
||||
# exists, it will be called automatically, you can do some configurations
|
||||
# in this aspect before you source this plugin.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# ```zsh
|
||||
# function zvm_config() {
|
||||
# ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
|
||||
# ZVM_VI_INSERT_ESCAPE_BINDKEY=jk
|
||||
# }
|
||||
#
|
||||
# source ~/zsh-vi-mode.zsh
|
||||
# ```
|
||||
#
|
||||
# ZVM_INIT_MODE
|
||||
# the plugin initial mode (default is doing the initialization when the first
|
||||
# new command line is starting. For doing the initialization instantly, you
|
||||
# can set it to `sourcing`.
|
||||
#
|
||||
# ZVM_VI_ESCAPE_BINDKEY
|
||||
# the vi escape key for all modes (default is ^[ => <ESC>), you can set it
|
||||
# to whatever you like, such as `jj`, `jk` and so on.
|
||||
#
|
||||
# ZVM_VI_INSERT_ESCAPE_BINDKEY
|
||||
# the vi escape key of insert mode (default is $ZVM_VI_ESCAPE_BINDKEY), you
|
||||
# can set it to whatever, such as `jj`, `jk` and so on.
|
||||
#
|
||||
# ZVM_VI_VISUAL_ESCAPE_BINDKEY
|
||||
# the vi escape key of visual mode (default is $ZVM_VI_ESCAPE_BINDKEY), you
|
||||
# can set it to whatever, such as `jj`, `jk` and so on.
|
||||
#
|
||||
# ZVM_VI_OPPEND_ESCAPE_BINDKEY
|
||||
# the vi escape key of operator pendding mode (default is
|
||||
# $ZVM_VI_ESCAPE_BINDKEY), you can set it to whatever, such as `jj`, `jk`
|
||||
# and so on.
|
||||
#
|
||||
# ZVM_VI_INSERT_MODE_LEGACY_UNDO:
|
||||
# using legacy undo behavior in vi insert mode (default is false)
|
||||
#
|
||||
# ZVM_VI_HIGHLIGHT_FOREGROUND:
|
||||
# the behavior of highlight foreground (surrounds, visual-line, etc) in vi mode
|
||||
#
|
||||
# ZVM_VI_HIGHLIGHT_BACKGROUND:
|
||||
# the behavior of highlight background (surrounds, visual-line, etc) in vi mode
|
||||
#
|
||||
# ZVM_VI_HIGHLIGHT_EXTRASTYLE:
|
||||
# the behavior of highlight extra style (i.e. bold, underline) in vi mode
|
||||
#
|
||||
# For example:
|
||||
# ZVM_VI_HIGHLIGHT_FOREGROUND=green # Color name
|
||||
# ZVM_VI_HIGHLIGHT_FOREGROUND=#008800 # Hex value
|
||||
# ZVM_VI_HIGHLIGHT_BACKGROUND=red # Color name
|
||||
# ZVM_VI_HIGHLIGHT_BACKGROUND=#ff0000 # Hex value
|
||||
# ZVM_VI_HIGHLIGHT_EXTRASTYLE=bold,underline # bold and underline
|
||||
#
|
||||
# ZVM_VI_SURROUND_BINDKEY
|
||||
# the key binding mode for surround operating (default is 'classic')
|
||||
#
|
||||
# 1. 'classic' mode (verb->s->surround):
|
||||
# S" Add " for visual selection
|
||||
# ys" Add " for visual selection
|
||||
# cs"' Change " to '
|
||||
# ds" Delete "
|
||||
#
|
||||
# 2. 's-prefix' mode (s->verb->surround):
|
||||
# sa" Add " for visual selection
|
||||
# sd" Delete "
|
||||
# sr"' Change " to '
|
||||
#
|
||||
# How to select surround text object?
|
||||
# vi" Select the text object inside the quotes
|
||||
# va( Select the text object including the brackets
|
||||
#
|
||||
# Then you can do any operation for the selection:
|
||||
#
|
||||
# 1. Add surrounds for text object
|
||||
# vi" -> S[ or sa[ => "object" -> "[object]"
|
||||
#
|
||||
# 2. Delete/Yank/Change text object
|
||||
# di( or vi( -> d
|
||||
# ca( or va( -> c
|
||||
# yi( or vi( -> y
|
||||
#
|
||||
# ZVM_READKEY_ENGINE
|
||||
# the readkey engine for reading and processing the key events, and the
|
||||
# below engines are supported:
|
||||
# ZVM_READKEY_ENGINE_NEX (Default)
|
||||
# ZVM_READKEY_ENGINE_ZLE
|
||||
#
|
||||
# the NEX is a better engine for reading and handling the key events than
|
||||
# the Zsh's ZLE engine, currently the NEX engine is at beta stage, and
|
||||
# you can change to Zsh's ZLE engine if you want.
|
||||
#
|
||||
# ZVM_KEYTIMEOUT:
|
||||
# the key input timeout for waiting for next key (default is 0.4 seconds)
|
||||
#
|
||||
# ZVM_ESCAPE_KEYTIMEOUT:
|
||||
# the key input timeout for waiting for next key if it is beginning with
|
||||
# an escape character (default is 0.03 seconds), and this option is just
|
||||
# available for the NEX readkey engine
|
||||
#
|
||||
# ZVM_LINE_INIT_MODE
|
||||
# the setting for init mode of command line (default is empty), empty will
|
||||
# keep the last command mode, for the first command line it will be insert
|
||||
# mode, you can also set it to a specific vi mode to alway keep the mode
|
||||
# for each command line
|
||||
#
|
||||
# For example:
|
||||
# ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
|
||||
# ZVM_LINE_INIT_MODE=$ZVM_MODE_NORMAL
|
||||
#
|
||||
# ZVM_LAZY_KEYBINDINGS:
|
||||
# the setting for lazy keybindings (default is true), and lazy keybindings
|
||||
# will postpone the keybindings of vicmd and visual keymaps to the first
|
||||
# time entering normal mode
|
||||
#
|
||||
# ZVM_NORMAL_MODE_CURSOR:
|
||||
# the prompt cursor in normal mode
|
||||
#
|
||||
# ZVM_INSERT_MODE_CURSOR:
|
||||
# the prompt cursor in insert mode
|
||||
#
|
||||
# ZVM_VISUAL_MODE_CURSOR:
|
||||
# the prompt cursor in visual mode
|
||||
#
|
||||
# ZVM_VISUAL_LINE_MODE_CURSOR:
|
||||
# the prompt cursor in visual line mode
|
||||
#
|
||||
# ZVM_OPPEND_MODE_CURSOR:
|
||||
# the prompt cursor in operator pending mode
|
||||
#
|
||||
# You can change the cursor style by below:
|
||||
# ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BLOCK
|
||||
#
|
||||
# and the below cursor style are supported:
|
||||
# ZVM_CURSOR_USER_DEFAULT
|
||||
# ZVM_CURSOR_BLOCK
|
||||
# ZVM_CURSOR_UNDERLINE
|
||||
# ZVM_CURSOR_BEAM
|
||||
# ZVM_CURSOR_BLINKING_BLOCK
|
||||
# ZVM_CURSOR_BLINKING_UNDERLINE
|
||||
# ZVM_CURSOR_BLINKING_BEAM
|
||||
#
|
||||
# ZVM_VI_EDITOR
|
||||
# the editor to edit your command line (default is $EDITOR)
|
||||
#
|
||||
# ZVM_TMPDIR
|
||||
# the temporary directory (default is $TMPDIR, otherwise it's /tmp)
|
||||
#
|
||||
# ZVM_TERM
|
||||
# the term for handling terminal sequences, it's important for some
|
||||
# terminal emulators to show cursor properly (default is $TERM)
|
||||
#
|
||||
# ZVM_CURSOR_STYLE_ENABLED
|
||||
# enable the cursor style feature (default is true)
|
||||
#
|
||||
# ZVM_SYSTEM_CLIPBOARD_ENABLED
|
||||
# enable the system clipboard feature (default is false), if you want to enable
|
||||
# it, you should also set the copy and paste commands below:
|
||||
#
|
||||
# ZVM_CLIPBOARD_COPY_CMD
|
||||
# the command for copying text to system clipboard
|
||||
#
|
||||
# ZVM_CLIPBOARD_PASTE_CMD
|
||||
# the command for pasting text from system clipboard
|
||||
#
|
||||
# For example:
|
||||
# - For macOS, you can set it to `pbcopy` and `pbpaste`
|
||||
# - For Linux, you can set it to `xclip -selection clipboard` and
|
||||
# `xclip -selection clipboard -o`)
|
||||
# - For Wayland, you can also use `wl-copy` and `wl-paste`
|
||||
# - For WSL, you can also use `clip.exe`
|
||||
#
|
||||
# If you don't set these two commands, the plugin will try to detect them
|
||||
# automatically for you.
|
||||
#
|
||||
# ZVM_OPEN_CMD
|
||||
# the command for opening URL or file path (e.g. `xdg-open`, `open`, `start`
|
||||
# and so on)
|
||||
#
|
||||
# ZVM_OPEN_URL_CMD
|
||||
# the command for opening URL (default is $ZVM_OPEN_CMD)
|
||||
#
|
||||
# ZVM_OPEN_FILE_CMD
|
||||
# the command for opening file path (default is $ZVM_OPEN_CMD)
|
||||
#
|
||||
|
||||
# Avoid sourcing plugin multiple times
|
||||
command -v 'zvm_version' >/dev/null && return
|
||||
|
||||
# Plugin information
|
||||
typeset -gr ZVM_NAME='zsh-vi-mode'
|
||||
typeset -gr ZVM_DESCRIPTION='💻 A better and friendly vi(vim) mode plugin for ZSH.'
|
||||
typeset -gr ZVM_REPOSITORY='https://github.com/jeffreytse/zsh-vi-mode'
|
||||
typeset -gr ZVM_VERSION='0.12.0'
|
||||
|
||||
# Plugin initial status
|
||||
ZVM_INIT_DONE=false
|
||||
|
||||
# Postpone reset prompt (i.e. postpone the widget `reset-prompt`)
|
||||
# -1 (No postponing)
|
||||
# >=0 (Postponing, the decimal value stands for calling times of `reset-prompt`)
|
||||
ZVM_POSTPONE_RESET_PROMPT=-1
|
||||
|
||||
# Disable reset prompt (i.e. postpone the widget `reset-prompt`)
|
||||
ZVM_RESET_PROMPT_DISABLED=false
|
||||
|
||||
# Operator pending mode
|
||||
ZVM_OPPEND_MODE=false
|
||||
|
||||
# Insert mode could be
|
||||
# `i` (insert)
|
||||
# `a` (append)
|
||||
# `I` (insert at the non-blank beginning of current line)
|
||||
# `A` (append at the end of current line)
|
||||
ZVM_INSERT_MODE='i'
|
||||
|
||||
# The mode could be the below value:
|
||||
# `n` (normal)
|
||||
# `i` (insert)
|
||||
# `v` (visual)
|
||||
# `vl` (visual-line)
|
||||
ZVM_MODE=''
|
||||
|
||||
# The keys typed to invoke this widget, as a literal string
|
||||
ZVM_KEYS=''
|
||||
|
||||
# The region hilight information
|
||||
ZVM_REGION_HIGHLIGHT=()
|
||||
|
||||
# Default zvm readkey engines
|
||||
ZVM_READKEY_ENGINE_NEX='nex'
|
||||
ZVM_READKEY_ENGINE_ZLE='zle'
|
||||
ZVM_READKEY_ENGINE_DEFAULT=$ZVM_READKEY_ENGINE_NEX
|
||||
|
||||
# Default alternative character for escape characters
|
||||
ZVM_ESCAPE_SPACE='\s'
|
||||
ZVM_ESCAPE_NEWLINE='^J'
|
||||
|
||||
# Default vi modes
|
||||
ZVM_MODE_LAST=''
|
||||
ZVM_MODE_NORMAL='n'
|
||||
ZVM_MODE_INSERT='i'
|
||||
ZVM_MODE_VISUAL='v'
|
||||
ZVM_MODE_VISUAL_LINE='vl'
|
||||
ZVM_MODE_REPLACE='r'
|
||||
|
||||
# Default cursor styles
|
||||
ZVM_CURSOR_USER_DEFAULT='ud'
|
||||
ZVM_CURSOR_BLOCK='bl'
|
||||
ZVM_CURSOR_UNDERLINE='ul'
|
||||
ZVM_CURSOR_BEAM='be'
|
||||
ZVM_CURSOR_BLINKING_BLOCK='bbl'
|
||||
ZVM_CURSOR_BLINKING_UNDERLINE='bul'
|
||||
ZVM_CURSOR_BLINKING_BEAM='bbe'
|
||||
|
||||
# The commands need to be repeated
|
||||
ZVM_REPEAT_MODE=false
|
||||
ZVM_REPEAT_RESET=false
|
||||
ZVM_REPEAT_COMMANDS=($ZVM_MODE_NORMAL i)
|
||||
|
||||
# Range handling return values
|
||||
ZVM_RANGE_HANDLER_RET_OK=0
|
||||
ZVM_RANGE_HANDLER_RET_CONTINUE=1
|
||||
ZVM_RANGE_HANDLER_RET_PUSHBACK=2
|
||||
ZVM_RANGE_HANDLER_RET_CANCEL=3
|
||||
|
||||
# URL regex pattern
|
||||
ZVM_URL_SCHEME='^(http(s)?:\/\/.)?(ftp(s)?:\/\/.)?(file:\/\/.)?(www\.)?'
|
||||
ZVM_URL_HOST='[-a-zA-Z0-9@:%._\+~#=]{0,255}\.[a-z]{2,6}'
|
||||
ZVM_URL_PATH='([-a-zA-Z0-9@:%_\+.~#?&\/=]*)$'
|
||||
ZVM_URL_REGEX="${ZVM_URL_SCHEME}${ZVM_URL_HOST}${ZVM_URL_PATH}"
|
||||
|
||||
##########################################
|
||||
# Initial all default settings
|
||||
|
||||
# Default config function
|
||||
: ${ZVM_CONFIG_FUNC:='zvm_config'}
|
||||
|
||||
# Set the readkey engine (default is NEX engine)
|
||||
: ${ZVM_READKEY_ENGINE:=$ZVM_READKEY_ENGINE_DEFAULT}
|
||||
|
||||
# Set key input timeout (default is 0.4 seconds)
|
||||
: ${ZVM_KEYTIMEOUT:=0.4}
|
||||
|
||||
# Set the escape key timeout (default is 0.03 seconds)
|
||||
: ${ZVM_ESCAPE_KEYTIMEOUT:=0.03}
|
||||
|
||||
# Set keybindings mode (default is true)
|
||||
# The lazy keybindings will post the keybindings of vicmd and visual
|
||||
# keymaps to the first time entering the normal mode
|
||||
: ${ZVM_LAZY_KEYBINDINGS:=true}
|
||||
|
||||
# All keybindings for lazy loading
|
||||
if $ZVM_LAZY_KEYBINDINGS; then
|
||||
ZVM_LAZY_KEYBINDINGS_LIST=()
|
||||
fi
|
||||
|
||||
# Set the cursor style in defferent vi modes, the value you could use
|
||||
# the predefined value, such as $ZVM_CURSOR_BLOCK, $ZVM_CURSOR_BEAM,
|
||||
# $ZVM_CURSOR_BLINKING_BLOCK and so on.
|
||||
: ${ZVM_INSERT_MODE_CURSOR:=$ZVM_CURSOR_BEAM}
|
||||
: ${ZVM_NORMAL_MODE_CURSOR:=$ZVM_CURSOR_BLOCK}
|
||||
: ${ZVM_VISUAL_MODE_CURSOR:=$ZVM_CURSOR_BLOCK}
|
||||
: ${ZVM_VISUAL_LINE_MODE_CURSOR:=$ZVM_CURSOR_BLOCK}
|
||||
|
||||
# Operator pending mode cursor style (default is underscore)
|
||||
: ${ZVM_OPPEND_MODE_CURSOR:=$ZVM_CURSOR_UNDERLINE}
|
||||
|
||||
# Set the vi escape key (default is ^[ => <ESC>)
|
||||
: ${ZVM_VI_ESCAPE_BINDKEY:=^[}
|
||||
: ${ZVM_VI_INSERT_ESCAPE_BINDKEY:=$ZVM_VI_ESCAPE_BINDKEY}
|
||||
: ${ZVM_VI_VISUAL_ESCAPE_BINDKEY:=$ZVM_VI_ESCAPE_BINDKEY}
|
||||
: ${ZVM_VI_OPPEND_ESCAPE_BINDKEY:=$ZVM_VI_ESCAPE_BINDKEY}
|
||||
|
||||
# Set the line init mode (empty will keep the last mode)
|
||||
# you can also set it to others, such as $ZVM_MODE_INSERT.
|
||||
: ${ZVM_LINE_INIT_MODE:=$ZVM_MODE_LAST}
|
||||
|
||||
: ${ZVM_VI_INSERT_MODE_LEGACY_UNDO:=false}
|
||||
: ${ZVM_VI_SURROUND_BINDKEY:=classic}
|
||||
: ${ZVM_VI_HIGHLIGHT_BACKGROUND:=#cc0000}
|
||||
: ${ZVM_VI_HIGHLIGHT_FOREGROUND:=#eeeeee}
|
||||
: ${ZVM_VI_HIGHLIGHT_EXTRASTYLE:=default}
|
||||
: ${ZVM_VI_EDITOR:=${EDITOR:-vim}}
|
||||
: ${ZVM_TMPDIR:=${TMPDIR:-/tmp}}
|
||||
|
||||
# Set the term for handling terminal sequences, it's important for some
|
||||
# terminal emulators to show cursor properly (default is $TERM)
|
||||
: ${ZVM_TERM:=${TERM:-xterm-256color}}
|
||||
|
||||
# Enable the cursor style feature
|
||||
: ${ZVM_CURSOR_STYLE_ENABLED:=true}
|
||||
|
||||
# Enable system clipboard feature
|
||||
: ${ZVM_SYSTEM_CLIPBOARD_ENABLED:=false}
|
||||
: ${ZVM_CLIPBOARD_COPY_CMD:=}
|
||||
: ${ZVM_CLIPBOARD_PASTE_CMD:=}
|
||||
|
||||
# Open URL or file path feature
|
||||
: ${ZVM_OPEN_CMD:=}
|
||||
: ${ZVM_OPEN_URL_CMD:=${ZVM_OPEN_CMD:-}}
|
||||
: ${ZVM_OPEN_FILE_CMD:=${ZVM_OPEN_CMD:-}}
|
||||
|
||||
# All the extra commands
|
||||
commands_array_names=(
|
||||
zvm_before_init_commands
|
||||
zvm_after_init_commands
|
||||
zvm_before_select_vi_mode_commands
|
||||
zvm_after_select_vi_mode_commands
|
||||
zvm_before_lazy_keybindings_commands
|
||||
zvm_after_lazy_keybindings_commands
|
||||
)
|
||||
for commands_array_name in $commands_array_names; do
|
||||
# Ensure commands set to an empty array, if not already set.
|
||||
if [[ -z "${(P)commands_array_name}" ]]; then
|
||||
typeset -g -a $commands_array_name
|
||||
fi
|
||||
done
|
||||
|
||||
# All the handlers for switching keyword
|
||||
zvm_switch_keyword_handlers=(
|
||||
zvm_switch_number
|
||||
zvm_switch_boolean
|
||||
zvm_switch_operator
|
||||
zvm_switch_weekday
|
||||
zvm_switch_month
|
||||
)
|
||||
|
||||
# History for switching keyword
|
||||
zvm_switch_keyword_history=()
|
||||
|
||||
# Display version information
|
||||
function zvm_version() {
|
||||
local git_info=$(git show -s --format="(%h, %ci)" 2>/dev/null)
|
||||
echo -e "$ZVM_NAME $ZVM_VERSION $git_info"
|
||||
echo -e "\e[4m$ZVM_REPOSITORY\e[0m"
|
||||
echo -e "$ZVM_DESCRIPTION"
|
||||
}
|
||||
|
||||
# The widget wrapper
|
||||
function zvm_widget_wrapper() {
|
||||
local rawfunc=$1;
|
||||
local func=$2;
|
||||
local called=$3;
|
||||
local -i retval=0
|
||||
if ! $called; then
|
||||
$rawfunc "${@:4}"
|
||||
retval=$?
|
||||
fi
|
||||
$func "${@:4}"
|
||||
[[ $retval -eq 0 ]] && retval=$?
|
||||
return $retval
|
||||
}
|
||||
|
||||
# Define widget function
|
||||
function zvm_define_widget() {
|
||||
local widget=$1
|
||||
local func=$2 || $1
|
||||
local result=($(zle -l -L "${widget}"))
|
||||
|
||||
# Check if existing the same name
|
||||
if [[ ${#result[@]} == 4 ]]; then
|
||||
local rawfunc=${result[4]}
|
||||
local wrapper="zvm_${widget}-wrapper"
|
||||
|
||||
# To avoid double calling, we need to check if the raw function
|
||||
# has been called already in the custom widget function
|
||||
local rawcode=$(declare -f $func 2>/dev/null)
|
||||
local called=false
|
||||
[[ "$rawcode" == *"\$rawfunc"* ]] && { called=true }
|
||||
|
||||
eval "$wrapper() { zvm_widget_wrapper $rawfunc $func $called \"\$@\" }"
|
||||
func=$wrapper
|
||||
fi
|
||||
|
||||
zle -N $widget $func
|
||||
}
|
||||
|
||||
# Get the keys typed to invoke this widget, as a literal string
|
||||
function zvm_keys() {
|
||||
local keys=${ZVM_KEYS:-$KEYS}
|
||||
|
||||
# Append the prefix of keys if it is visual or visual-line mode
|
||||
case "${ZVM_MODE}" in
|
||||
$ZVM_MODE_VISUAL)
|
||||
if [[ "$keys" != v* ]]; then
|
||||
keys="v${keys}"
|
||||
fi
|
||||
;;
|
||||
$ZVM_MODE_VISUAL_LINE)
|
||||
if [[ "$keys" != V* ]]; then
|
||||
keys="V${keys}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Escape the newline and space characters, otherwise, we can't
|
||||
# get the output from subshell correctly.
|
||||
keys=${keys//$'\n'/$ZVM_ESCAPE_NEWLINE}
|
||||
keys=${keys// /$ZVM_ESCAPE_SPACE}
|
||||
|
||||
echo $keys
|
||||
}
|
||||
|
||||
# Find the widget on a specified bindkey
|
||||
function zvm_find_bindkey_widget() {
|
||||
local keymap=$1
|
||||
local keys=$2
|
||||
local prefix_mode=${3:-false}
|
||||
retval=()
|
||||
|
||||
if $prefix_mode; then
|
||||
local pos=0
|
||||
local spos=3
|
||||
local prefix_keys=$keys
|
||||
|
||||
# Get the prefix keys
|
||||
if [[ $prefix_keys ]]; then
|
||||
prefix_keys=${prefix_keys:0:-1}
|
||||
|
||||
# If the last key is an escape key (e.g. \", \`, \\) we still
|
||||
# need to remove the escape backslash `\`
|
||||
if [[ ${prefix_keys: -1} == '\' ]]; then
|
||||
prefix_keys=${prefix_keys:0:-1}
|
||||
fi
|
||||
fi
|
||||
|
||||
local result=$(bindkey -M ${keymap} -p "$prefix_keys")$'\n'
|
||||
|
||||
# Split string to array by newline
|
||||
local i=
|
||||
for ((i=$spos;i<$#result;i++)); do
|
||||
|
||||
# Save the last whitespace character of the line
|
||||
# and continue continue handling while meeting `\n`
|
||||
case "${result:$i:1}" in
|
||||
' ') spos=$i; i=$i+1; continue;;
|
||||
[$'\n']);;
|
||||
*) continue;;
|
||||
esac
|
||||
|
||||
# Check if it has the same prefix keys and retrieve the widgets
|
||||
if [[ "${result:$((pos+1)):$#keys}" == "$keys" ]]; then
|
||||
|
||||
# Get the binding keys
|
||||
local k=${result:$((pos+1)):$((spos-pos-2))}
|
||||
|
||||
# Escape spaces in key bindings (space -> $ZVM_ESCAPE_SPACE)
|
||||
k=${k// /$ZVM_ESCAPE_SPACE}
|
||||
retval+=($k ${result:$((spos+1)):$((i-spos-1))})
|
||||
fi
|
||||
|
||||
# Save as new position
|
||||
pos=$i+1
|
||||
|
||||
# Skip 3 characters
|
||||
# One key and quotes at least (i.e \n"_" )
|
||||
i=$i+3
|
||||
done
|
||||
else
|
||||
local result=$(bindkey -M ${keymap} "$keys")
|
||||
if [[ "${result: -14}" == ' undefined-key' ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Escape spaces in key bindings (space -> $ZVM_ESCAPE_SPACE)
|
||||
local i=
|
||||
for ((i=$#result;i>=0;i--)); do
|
||||
|
||||
# Backward find the first whitespace character
|
||||
[[ "${result:$i:1}" == ' ' ]] || continue
|
||||
|
||||
# Retrieve the keys and widget
|
||||
local k=${result:1:$i-2}
|
||||
|
||||
# Escape spaces in key bindings (space -> $ZVM_ESCAPE_SPACE)
|
||||
k=${k// /$ZVM_ESCAPE_SPACE}
|
||||
retval+=($k ${result:$i+1})
|
||||
|
||||
break
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Read keys for retrieving widget
|
||||
function zvm_readkeys() {
|
||||
local keymap=$1
|
||||
local key=${2:-$(zvm_keys)}
|
||||
local keys=
|
||||
local widget=
|
||||
local result=
|
||||
local pattern=
|
||||
local timeout=
|
||||
|
||||
while :; do
|
||||
# Keep reading key for escape character
|
||||
if [[ "$key" == $'\e' ]]; then
|
||||
while :; do
|
||||
local k=
|
||||
read -t $ZVM_ESCAPE_KEYTIMEOUT -k 1 k || break
|
||||
key="${key}${k}"
|
||||
done
|
||||
fi
|
||||
|
||||
keys="${keys}${key}"
|
||||
|
||||
# Handle the pattern
|
||||
if [[ -n "$key" ]]; then
|
||||
# Transform the non-printed characters
|
||||
local k=$(zvm_escape_non_printed_characters "${key}")
|
||||
|
||||
# Escape keys
|
||||
# " -> \" It's a special character in bash syntax
|
||||
# ` -> \` It's a special character in bash syntax
|
||||
# <space> -> ` ` It's a special character in bash syntax
|
||||
k=${k//\"/\\\"}
|
||||
k=${k//\`/\\\`}
|
||||
k=${k//$ZVM_ESCAPE_SPACE/ }
|
||||
|
||||
pattern="${pattern}${k}"
|
||||
fi
|
||||
|
||||
# Find out widgets that match this key pattern
|
||||
zvm_find_bindkey_widget $keymap "$pattern" true
|
||||
result=(${retval[@]})
|
||||
|
||||
# Exit key input if there is only one widget matched
|
||||
# or no more widget matched.
|
||||
case ${#result[@]} in
|
||||
2) key=; widget=${result[2]}; break;;
|
||||
0) break;;
|
||||
esac
|
||||
|
||||
# Evaluate the readkey timeout
|
||||
# Special timeout for the escape sequence
|
||||
if [[ "${keys}" == $'\e' ]]; then
|
||||
timeout=$ZVM_ESCAPE_KEYTIMEOUT
|
||||
# Check if there is any one custom escape sequence
|
||||
local i=
|
||||
for ((i=1; i<=${#result[@]}; i=i+2)); do
|
||||
if [[ "${result[$i]}" =~ '^\^\[\[?[A-Z0-9]*~?\^\[' ]]; then
|
||||
timeout=$ZVM_KEYTIMEOUT
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
timeout=$ZVM_KEYTIMEOUT
|
||||
fi
|
||||
|
||||
# Wait for reading next key, and we should save the widget
|
||||
# as the final widget if it is full matching
|
||||
key=
|
||||
if [[ "${result[1]}" == "${pattern}" ]]; then
|
||||
widget=${result[2]}
|
||||
# Get current widget as final widget when reading key timeout
|
||||
read -t $timeout -k 1 key || break
|
||||
else
|
||||
zvm_enter_oppend_mode
|
||||
read -k 1 key
|
||||
fi
|
||||
done
|
||||
|
||||
# Exit operator pending mode
|
||||
if $ZVM_OPPEND_MODE; then
|
||||
zvm_exit_oppend_mode
|
||||
fi
|
||||
|
||||
if [[ -z "$key" ]]; then
|
||||
retval=(${keys} $widget)
|
||||
else
|
||||
retval=(${keys:0:-$#key} $widget $key)
|
||||
fi
|
||||
}
|
||||
|
||||
# Add key bindings
|
||||
function zvm_bindkey() {
|
||||
local keymap=$1
|
||||
local keys=$2
|
||||
local widget=$3
|
||||
local params=$4
|
||||
local key=
|
||||
|
||||
# We should bind keys with an existing widget
|
||||
[[ -z $widget ]] && return
|
||||
|
||||
# If lazy keybindings is enabled, we need to add to the lazy list
|
||||
if [[ ${ZVM_LAZY_KEYBINDINGS_LIST+x} && ${keymap} != viins ]]; then
|
||||
keys=${keys//\"/\\\"}
|
||||
keys=${keys//\`/\\\`}
|
||||
ZVM_LAZY_KEYBINDINGS_LIST+=(
|
||||
"${keymap} \"${keys}\" ${widget} \"${params}\""
|
||||
)
|
||||
return
|
||||
fi
|
||||
|
||||
# Hanle the keybinding of NEX readkey engine
|
||||
if [[ $ZVM_READKEY_ENGINE == $ZVM_READKEY_ENGINE_NEX ]]; then
|
||||
# Get the first key (especially check if ctrl characters)
|
||||
if [[ $#keys -gt 1 && "${keys:0:1}" == '^' ]]; then
|
||||
key=${keys:0:2}
|
||||
else
|
||||
key=${keys:0:1}
|
||||
|
||||
# As any character that is not bound to one of the history control
|
||||
# related functions, or self-insert or self-insert-unmeta, will
|
||||
# cause the mode to be exited To prevent history search, so that
|
||||
# we need to bind keys explicitly.
|
||||
if [[ "$keymap" == "viins" ]]; then
|
||||
bindkey -M isearch "${key}" self-insert
|
||||
fi
|
||||
fi
|
||||
bindkey -M $keymap "${key}" zvm_readkeys_handler
|
||||
fi
|
||||
|
||||
# Wrap params to a new widget
|
||||
if [[ -n $params ]]; then
|
||||
local suffix=$(zvm_string_to_hex $params)
|
||||
eval "$widget:$suffix() { $widget $params }"
|
||||
widget="$widget:$suffix"
|
||||
zvm_define_widget $widget
|
||||
fi
|
||||
|
||||
# Bind keys with with a widget
|
||||
bindkey -M $keymap "${keys}" $widget
|
||||
}
|
||||
|
||||
# Convert string to hexadecimal
|
||||
function zvm_string_to_hex() {
|
||||
local str= i=
|
||||
for ((i=1;i<=$#1;i++)); do
|
||||
str+=$(printf '%x' "'${1[$i]}")
|
||||
done
|
||||
echo "$str"
|
||||
}
|
||||
|
||||
# Escape non-printed characters
|
||||
function zvm_escape_non_printed_characters() {
|
||||
local str= i=
|
||||
for ((i=0;i<$#1;i++)); do
|
||||
local c=${1:$i:1}
|
||||
if [[ "$c" < ' ' ]]; then
|
||||
local ord=$(($(printf '%d' "'$c")+64))
|
||||
c=$(printf \\$(printf '%03o' $ord))
|
||||
str="${str}^${c}"
|
||||
elif [[ "$c" == '' ]]; then
|
||||
str="${str}^?"
|
||||
elif [[ "$c" == '
|
||||
Reference in New Issue
Block a user