blob: 9a410c1fb88470c96c395497af0a1e900fde604f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# Control whether to force a redraw on each mode change.
#
# Resetting the prompt on every mode change can cause lag when switching modes.
# This is especially true if the prompt does things like checking git status.
#
# Set to "true" to force the prompt to reset on each mode change.
# Unset or set to any other value to do the opposite.
#
# The default is not to reset, unless we're showing the mode in RPS1.
typeset -g VI_MODE_RESET_PROMPT_ON_MODE_CHANGE
# Control whether to change the cursor style on mode change.
#
# Set to "true" to change the cursor on each mode change.
# Unset or set to any other value to do the opposite.
typeset -g VI_MODE_SET_CURSOR
# Control how the cursor appears in the various vim modes. This only applies
# if $VI_MODE_SET_CURSOR=true.
#
# See https://vt100.net/docs/vt510-rm/DECSCUSR for cursor styles
typeset -g VI_MODE_CURSOR_NORMAL=2
typeset -g VI_MODE_CURSOR_VISUAL=6
typeset -g VI_MODE_CURSOR_INSERT=6
typeset -g VI_MODE_CURSOR_OPPEND=0
typeset -g VI_KEYMAP=main
function _vi-mode-set-cursor-shape-for-keymap() {
[[ "$VI_MODE_SET_CURSOR" = true ]] || return
# https://vt100.net/docs/vt510-rm/DECSCUSR
local _shape=0
case "${1:-${VI_KEYMAP:-main}}" in
main) _shape=$VI_MODE_CURSOR_INSERT ;; # vi insert: line
viins) _shape=$VI_MODE_CURSOR_INSERT ;; # vi insert: line
isearch) _shape=$VI_MODE_CURSOR_INSERT ;; # inc search: line
command) _shape=$VI_MODE_CURSOR_INSERT ;; # read a command name
vicmd) _shape=$VI_MODE_CURSOR_NORMAL ;; # vi cmd: block
visual) _shape=$VI_MODE_CURSOR_VISUAL ;; # vi visual mode: block
viopp) _shape=$VI_MODE_CURSOR_OPPEND ;; # vi operation pending: blinking block
*) _shape=0 ;;
esac
printf $'\e[%d q' "${_shape}"
}
# Updates editor information when the keymap changes.
function zle-keymap-select() {
# update keymap variable for the prompt
typeset -g VI_KEYMAP=$KEYMAP
if [[ "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:-}" = true ]]; then
zle reset-prompt
zle -R
fi
_vi-mode-set-cursor-shape-for-keymap "${VI_KEYMAP}"
}
zle -N zle-keymap-select
# These "echoti" statements were originally set in lib/key-bindings.zsh
# Not sure the best way to extend without overriding.
function zle-line-init() {
local prev_vi_keymap
prev_vi_keymap="${VI_KEYMAP:-}"
typeset -g VI_KEYMAP=main
[[ "$prev_vi_keymap" != 'main' ]] && [[ "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:-}" = true ]] && zle reset-prompt
(( ! ${+terminfo[smkx]} )) || echoti smkx
_vi-mode-set-cursor-shape-for-keymap "${VI_KEYMAP}"
}
zle -N zle-line-init
function zle-line-finish() {
typeset -g VI_KEYMAP=main
(( ! ${+terminfo[rmkx]} )) || echoti rmkx
_vi-mode-set-cursor-shape-for-keymap default
}
zle -N zle-line-finish
bindkey -v
# allow vv to edit the command line (standard behaviour)
autoload -Uz edit-command-line
zle -N edit-command-line
bindkey -M vicmd 'vv' edit-command-line
# allow ctrl-p, ctrl-n for navigate history (standard behaviour)
bindkey '^P' up-history
bindkey '^N' down-history
# allow ctrl-h, ctrl-w, ctrl-? for char and word deletion (standard behaviour)
bindkey '^?' backward-delete-char
bindkey '^h' backward-delete-char
bindkey '^w' backward-kill-word
# allow ctrl-r and ctrl-s to search the history
bindkey '^r' history-incremental-search-backward
bindkey '^s' history-incremental-search-forward
# allow ctrl-a and ctrl-e to move to beginning/end of line
bindkey '^a' beginning-of-line
bindkey '^e' end-of-line
function wrap_clipboard_widgets() {
# NB: Assume we are the first wrapper and that we only wrap native widgets
# See zsh-autosuggestions.zsh for a more generic and more robust wrapper
local verb="$1"
shift
local widget
local wrapped_name
for widget in "$@"; do
wrapped_name="_zsh-vi-${verb}-${widget}"
if [ "${verb}" = copy ]; then
eval "
function ${wrapped_name}() {
zle .${widget}
printf %s \"\${CUTBUFFER}\" | clipcopy 2>/dev/null || true
}
"
else
eval "
function ${wrapped_name}() {
CUTBUFFER=\"\$(clippaste 2>/dev/null || echo \$CUTBUFFER)\"
zle .${widget}
}
"
fi
zle -N "${widget}" "${wrapped_name}"
done
}
wrap_clipboard_widgets copy vi-yank vi-yank-eol vi-backward-kill-word vi-change-whole-line vi-delete vi-delete-char
wrap_clipboard_widgets paste vi-put-{before,after}
unfunction wrap_clipboard_widgets
# if mode indicator wasn't setup by theme, define default, we'll leave INSERT_MODE_INDICATOR empty by default
if [[ -z "$MODE_INDICATOR" ]]; then
MODE_INDICATOR='%B%F{red}<%b<<%f'
fi
function vi_mode_prompt_info() {
# If we're using the prompt to display mode info, and we haven't explicitly
# disabled "reset prompt on mode change", then set it here.
#
# We do that here instead of the `if` statement below because the user may
# set RPS1/RPROMPT to something else in their custom config.
: "${VI_MODE_RESET_PROMPT_ON_MODE_CHANGE:=true}"
echo "${${VI_KEYMAP/vicmd/$MODE_INDICATOR}/(main|viins)/$INSERT_MODE_INDICATOR}"
}
# define right prompt, if it wasn't defined by a theme
if [[ -z "$RPS1" && -z "$RPROMPT" ]]; then
RPS1='$(vi_mode_prompt_info)'
fi
|