From c3362aefa2e762211409923cfff065541bebf9e7 Mon Sep 17 00:00:00 2001 From: Saumit Dinesan Date: Sun, 22 May 2022 00:37:40 +0530 Subject: ble.sh & z4h addition --- .local/src/blesh/keymap/vi.sh | 6171 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6171 insertions(+) create mode 100644 .local/src/blesh/keymap/vi.sh (limited to '.local/src/blesh/keymap/vi.sh') diff --git a/.local/src/blesh/keymap/vi.sh b/.local/src/blesh/keymap/vi.sh new file mode 100644 index 0000000..ccf8b84 --- /dev/null +++ b/.local/src/blesh/keymap/vi.sh @@ -0,0 +1,6171 @@ +# this script is a part of blesh (https://github.com/akinomyoga/ble.sh) under BSD-3-Clause license +ble/is-function ble-edit/bind/load-editing-mode:vi && return 0 +function ble-edit/bind/load-editing-mode:vi { :; } +source "$_ble_base/keymap/vi_digraph.sh" +bleopt/declare -n keymap_vi_macro_depth 64 +function ble/keymap:vi/k2c { + local key=$1 + local flag=$((key&_ble_decode_MaskFlag)) char=$((key&_ble_decode_MaskChar)) + if ((flag==0&&(32<=char&&char<_ble_decode_FunctionKeyBase))); then + ret=$char + return 0 + elif ((flag==_ble_decode_Ctrl&&63<=char&&char<128&&(char&0x1F)!=0)); then + ((char=char==63?127:char&0x1F)) + ret=$char + return 0 + else + return 1 + fi +} +function ble/string#index-of-chars { + local chars=$2 index=${3:-0} + local text=${1:index} + local cut=${text%%["$chars"]*} + if ((${#cut}<${#text})); then + ((ret=index+${#cut})) + return 0 + else + ret=-1 + return 1 + fi +} +function ble/string#last-index-of-chars { + local text=$1 chars=$2 index=$3 + [[ $index ]] && text=${text::index} + local cut=${text%["$chars"]*} + if ((${#cut}<${#text})); then + ((ret=${#cut})) + return 0 + else + ret=-1 + return 1 + fi +} +function ble-edit/content/nonbol-eolp { + local pos=${1:-$_ble_edit_ind} + ! ble-edit/content/bolp "$pos" && ble-edit/content/eolp "$pos" +} +function ble/keymap:vi/string#encode-rot13 { + local text=$1 + local -a buff=() ch + for ((i=0;i<${#text};i++)); do + ch=${text:i:1} + if [[ $ch == [A-Z] ]]; then + ch=${_ble_util_string_upper_list%%"$ch"*} + ch=${_ble_util_string_upper_list:(${#ch}+13)%26:1} + elif [[ $ch == [a-z] ]]; then + ch=${_ble_util_string_lower_list%%"$ch"*} + ch=${_ble_util_string_lower_list:(${#ch}+13)%26:1} + fi + ble/array#push buff "$ch" + done + IFS= builtin eval 'ret="${buff[*]-}"' +} +_ble_keymap_vi_REX_WORD=$'[a-zA-Z0-9_]+|[!-/:-@[-`{-~]+|[^ \t\na-zA-Z0-9!-/:-@[-`{-~]+' +function ble/widget/vi_imap/__default__ { + local flag=$((KEYS[0]&_ble_decode_MaskFlag)) code=$((KEYS[0]&_ble_decode_MaskChar)) + if ((flag&_ble_decode_Meta)); then + ble/keymap:vi/imap-repeat/pop + local esc=27 # ESC + ble/decode/widget/skip-lastwidget + ble/decode/widget/redispatch-by-keys "$esc" $((KEYS[0]&~_ble_decode_Meta)) "${KEYS[@]:1}" + return 0 + fi + if local ret; ble/keymap:vi/k2c "${KEYS[0]}"; then + local -a KEYS; KEYS=("$ret") + ble/widget/self-insert + return 0 + fi + return 125 +} +function ble/widget/vi-command/decompose-meta { + local flag=$((KEYS[0]&_ble_decode_MaskFlag)) code=$((KEYS[0]&_ble_decode_MaskChar)) + if ((flag&_ble_decode_Meta)); then + local esc=$((_ble_decode_Ctrl|0x5b)) # C-[ (もしくは esc=27 ESC?) + ble/decode/widget/skip-lastwidget + ble/decode/widget/redispatch-by-keys "$esc" $((KEYS[0]&~_ble_decode_Meta)) "${KEYS[@]:1}" + return 0 + fi + return 125 +} +function ble/widget/vi_omap/__default__ { + ble/widget/vi-command/decompose-meta || ble/widget/vi-command/bell + return 0 +} +function ble/widget/vi_omap/cancel { + ble/keymap:vi/adjust-command-mode + return 0 +} +_ble_keymap_vi_irepeat_count= +_ble_keymap_vi_irepeat=() +ble/array#push _ble_textarea_local_VARNAMES \ + _ble_keymap_vi_irepeat_count \ + _ble_keymap_vi_irepeat +function ble/keymap:vi/imap-repeat/pop { + local top_index=$((${#_ble_keymap_vi_irepeat[*]}-1)) + ((top_index>=0)) && builtin unset -v '_ble_keymap_vi_irepeat[top_index]' +} +function ble/keymap:vi/imap-repeat/push { + local IFS=$_ble_term_IFS + ble/array#push _ble_keymap_vi_irepeat "${KEYS[*]-}:$WIDGET" +} +function ble/keymap:vi/imap-repeat/reset { + local count=${1-} + _ble_keymap_vi_irepeat_count= + _ble_keymap_vi_irepeat=() + ((count>1)) && _ble_keymap_vi_irepeat_count=$count +} +function ble/keymap:vi/imap-repeat/process { + if ((_ble_keymap_vi_irepeat_count>1)); then + local repeat=$_ble_keymap_vi_irepeat_count + local -a widgets; widgets=("${_ble_keymap_vi_irepeat[@]}") + local i widget + for ((i=1;i=0)); then + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record-insert + ble/keymap:vi/mark/start-edit-area + fi + ble/keymap:vi/imap-repeat/reset + fi +} +function ble/widget/vi_imap/complete { + ble/keymap:vi/imap-repeat/pop + ble/keymap:vi/undo/add more + ble/widget/complete "$@" +} +function ble/keymap:vi/complete/insert.hook { + [[ $_ble_decode_keymap == vi_imap || + $_ble_decode_keymap == auto_complete ]] || return 1 + local original=${comp_text:insert_beg:insert_end-insert_beg} + local q="'" Q="'\''" + local WIDGET="ble/widget/complete-insert '${original//$q/$Q}' '${insert//$q/$Q}' '${suffix//$q/$Q}'" + ble/keymap:vi/imap-repeat/push + [[ $_ble_decode_keymap == vi_imap ]] && + ble/keymap:vi/undo/add more +} +blehook complete_insert+=ble/keymap:vi/complete/insert.hook +function ble-decode/keymap:vi_imap/bind-complete { + ble-bind -f 'C-i' 'vi_imap/complete' + ble-bind -f 'TAB' 'vi_imap/complete' + ble-bind -f 'C-TAB' 'menu-complete' + ble-bind -f 'S-C-i' 'menu-complete backward' + ble-bind -f 'S-TAB' 'menu-complete backward' + ble-bind -f 'auto_complete_enter' 'auto-complete-enter' + ble-bind -f 'C-x /' 'menu-complete context=filename' + ble-bind -f 'C-x ~' 'menu-complete context=username' + ble-bind -f 'C-x $' 'menu-complete context=variable' + ble-bind -f 'C-x @' 'menu-complete context=hostname' + ble-bind -f 'C-x !' 'menu-complete context=command' + ble-bind -f 'C-]' 'sabbrev-expand' + ble-bind -f 'C-x C-r' 'dabbrev-expand' + ble-bind -f 'C-x *' 'complete insert_all:context=glob' + ble-bind -f 'C-x g' 'complete show_menu:context=glob' +} +_ble_keymap_vi_insert_overwrite= +_ble_keymap_vi_insert_leave= +_ble_keymap_vi_single_command= +_ble_keymap_vi_single_command_overwrite= +ble/array#push _ble_textarea_local_VARNAMES \ + _ble_keymap_vi_insert_overwrite \ + _ble_keymap_vi_insert_leave \ + _ble_keymap_vi_single_command \ + _ble_keymap_vi_single_command_overwrite +bleopt/declare -n keymap_vi_mode_string_nmap $'\e[1m~\e[m' +bleopt/declare -o keymap_vi_nmap_name keymap_vi_mode_string_nmap +bleopt/declare -v term_vi_imap '' +bleopt/declare -v term_vi_nmap '' +bleopt/declare -v term_vi_omap '' +bleopt/declare -v term_vi_xmap '' +bleopt/declare -v term_vi_smap '' +bleopt/declare -v term_vi_cmap '' +bleopt/declare -v keymap_vi_imap_cursor '' +bleopt/declare -v keymap_vi_nmap_cursor '' +bleopt/declare -v keymap_vi_omap_cursor '' +bleopt/declare -v keymap_vi_xmap_cursor '' +bleopt/declare -v keymap_vi_smap_cursor '' +bleopt/declare -v keymap_vi_cmap_cursor '' +function ble/keymap:vi/.process-cursor-options { + local keymap=${FUNCNAME[1]#bleopt/check:keymap_}; keymap=${keymap%_cursor} + ble-bind -m "$keymap" --cursor "$value" + local locate=$'\e[32m'$bleopt_source:$bleopt_lineno$'\e[m' + ble/util/print-lines \ + "bleopt ($locate): The option 'keymap_${keymap}_cursor' has been removed." \ + " Please use 'ble-bind -m $keymap --cursor $value' instead." >&2 +} +function bleopt/check:keymap_vi_imap_cursor { ble/keymap:vi/.process-cursor-options; } +function bleopt/check:keymap_vi_nmap_cursor { ble/keymap:vi/.process-cursor-options; } +function bleopt/check:keymap_vi_omap_cursor { ble/keymap:vi/.process-cursor-options; } +function bleopt/check:keymap_vi_xmap_cursor { ble/keymap:vi/.process-cursor-options; } +function bleopt/check:keymap_vi_smap_cursor { ble/keymap:vi/.process-cursor-options; } +function bleopt/check:keymap_vi_cmap_cursor { ble/keymap:vi/.process-cursor-options; } +function bleopt/obsolete:keymap_vi_imap_cursor { :; } +function bleopt/obsolete:keymap_vi_nmap_cursor { :; } +function bleopt/obsolete:keymap_vi_omap_cursor { :; } +function bleopt/obsolete:keymap_vi_xmap_cursor { :; } +function bleopt/obsolete:keymap_vi_smap_cursor { :; } +function bleopt/obsolete:keymap_vi_cmap_cursor { :; } +bleopt/declare -v keymap_vi_mode_show 1 +function bleopt/check:keymap_vi_mode_show { + local bleopt_keymap_vi_mode_show=$value + [[ $_ble_attached ]] && + ble/keymap:vi/update-mode-name + return 0 +} +bleopt/declare -v keymap_vi_mode_update_prompt '' +bleopt/declare -v keymap_vi_mode_name_insert 'INSERT' +bleopt/declare -v keymap_vi_mode_name_replace 'REPLACE' +bleopt/declare -v keymap_vi_mode_name_vreplace 'VREPLACE' +bleopt/declare -v keymap_vi_mode_name_visual 'VISUAL' +bleopt/declare -v keymap_vi_mode_name_select 'SELECT' +bleopt/declare -v keymap_vi_mode_name_linewise 'LINE' +bleopt/declare -v keymap_vi_mode_name_blockwise 'BLOCK' +function bleopt/check:keymap_vi_mode_name_insert { ble/keymap:vi/update-mode-name; } +function bleopt/check:keymap_vi_mode_name_replace { ble/keymap:vi/update-mode-name; } +function bleopt/check:keymap_vi_mode_name_vreplace { ble/keymap:vi/update-mode-name; } +function bleopt/check:keymap_vi_mode_name_visual { ble/keymap:vi/update-mode-name; } +function bleopt/check:keymap_vi_mode_name_select { ble/keymap:vi/update-mode-name; } +function bleopt/check:keymap_vi_mode_name_linewise { ble/keymap:vi/update-mode-name; } +function bleopt/check:keymap_vi_mode_name_blockwise { ble/keymap:vi/update-mode-name; } +function ble/keymap:vi/script/get-vi-keymap { + ble/prompt/unit/add-hash '$_ble_decode_keymap,${_ble_decode_keymap_stack[*]}' + local i=${#_ble_decode_keymap_stack[@]} + keymap=$_ble_decode_keymap + while [[ $keymap != vi_?map || $keymap == emacs ]]; do + ((i--)) || return 1 + keymap=${_ble_decode_keymap_stack[i]} + done + [[ $keymap == vi_?map ]] +} +function ble/keymap:vi/script/get-mode { + ble/prompt/unit/add-hash '$_ble_decode_keymap,${_ble_decode_keymap_stack[*]}' + ble/prompt/unit/add-hash '$_ble_keymap_vi_single_command,$_ble_edit_mark_active' + mode= + local keymap; ble/keymap:vi/script/get-vi-keymap + if [[ $_ble_keymap_vi_single_command || $keymap == vi_imap ]]; then + local overwrite= + if [[ $keymap == vi_imap ]]; then + overwrite=$_ble_edit_overwrite_mode + elif [[ $keymap == vi_[noxs]map ]]; then + overwrite=$_ble_keymap_vi_single_command_overwrite + fi + case $overwrite in + ('') mode=i ;; + (R) mode=R ;; + (*) mode=$'\x12' ;; # C-r + esac + fi + case $keymap:${_ble_edit_mark_active%+} in + (vi_xmap:vi_line) mode=$mode'V' ;; + (vi_xmap:vi_block)mode=$mode$'\x16' ;; # C-v + (vi_xmap:*) mode=$mode'v' ;; + (vi_smap:vi_line) mode=$mode'S' ;; + (vi_smap:vi_block)mode=$mode$'\x13' ;; # C-s + (vi_smap:*) mode=$mode's' ;; + (vi_[no]map:*) mode=$mode'n' ;; + (vi_cmap:*) mode=$mode'c' ;; + (vi_imap:*) ;; + (*:*) mode=$mode'?' ;; + esac +} +_ble_keymap_vi_mode_name_dirty= +function ble/keymap:vi/info_reveal.hook { + [[ $_ble_keymap_vi_mode_name_dirty ]] || return 0 + _ble_keymap_vi_mode_name_dirty= + ble/keymap:vi/update-mode-name +} +blehook info_reveal+=ble/keymap:vi/info_reveal.hook +function ble/keymap:vi/update-mode-name { + if [[ ! $_ble_attached ]] || ble/edit/is-command-layout; then + _ble_keymap_vi_mode_name_dirty=1 + return 0 + fi + local keymap + ble/keymap:vi/script/get-vi-keymap || return 0 + if [[ $keymap == vi_imap ]]; then + ble/util/buffer "$bleopt_term_vi_imap" + elif [[ $keymap == vi_nmap ]]; then + ble/util/buffer "$bleopt_term_vi_nmap" + elif [[ $keymap == vi_xmap ]]; then + ble/util/buffer "$bleopt_term_vi_xmap" + elif [[ $keymap == vi_smap ]]; then + ble/util/buffer "$bleopt_term_vi_smap" + elif [[ $keymap == vi_omap ]]; then + ble/util/buffer "$bleopt_term_vi_omap" + elif [[ $keymap == vi_cmap ]]; then + ble/edit/info/default text '' + ble/util/buffer "$bleopt_term_vi_cmap" + return 0 + fi + [[ $bleopt_keymap_vi_mode_update_prompt ]] && ble/prompt/clear + local name= + if [[ $bleopt_keymap_vi_mode_show ]]; then + local show= overwrite= + if [[ $keymap == vi_imap ]]; then + show=1 overwrite=$_ble_edit_overwrite_mode + elif [[ $_ble_keymap_vi_single_command && ( $keymap == vi_nmap || $keymap == vi_omap ) ]]; then + show=1 overwrite=$_ble_keymap_vi_single_command_overwrite + elif [[ $keymap == vi_[xs]map ]]; then + show=x overwrite=$_ble_keymap_vi_single_command_overwrite + else + name=$bleopt_keymap_vi_mode_string_nmap + fi + fi + if [[ $show ]]; then + if [[ $overwrite == R ]]; then + name=$bleopt_keymap_vi_mode_name_replace + elif [[ $overwrite ]]; then + name=$bleopt_keymap_vi_mode_name_vreplace + else + name=$bleopt_keymap_vi_mode_name_insert + fi + if [[ $_ble_keymap_vi_single_command ]]; then + local ret; ble/string#tolower "$name"; name="($ret)" + fi + if [[ $show == x ]]; then + local mark_type=${_ble_edit_mark_active%+} + local visual_name=$bleopt_keymap_vi_mode_name_visual + [[ $keymap == vi_smap ]] && visual_name=$bleopt_keymap_vi_mode_name_select + if [[ $mark_type == vi_line ]]; then + visual_name=$visual_name' '$bleopt_keymap_vi_mode_name_linewise + elif [[ $mark_type == vi_block ]]; then + visual_name=$visual_name' '$bleopt_keymap_vi_mode_name_blockwise + fi + if [[ $_ble_keymap_vi_single_command ]]; then + name="$name $visual_name" + else + name=$visual_name + fi + fi + name=$'\e[1m-- '$name$' --\e[m' + fi + if [[ $_ble_keymap_vi_reg_record ]]; then + name=$name${name:+' '}$'\e[1;31mREC @'$_ble_keymap_vi_reg_record_char$'\e[m' + elif [[ $_ble_edit_kbdmacro_record ]]; then + name=$name${name:+' '}$'\e[1;31mREC\e[m' + fi + ble/edit/info/default ansi "$name" # 6ms +} +function ble/widget/vi_imap/normal-mode.impl { + local opts=$1 + ble/keymap:vi/mark/set-local-mark 94 "$_ble_edit_ind" # `^ + ble/keymap:vi/mark/end-edit-area + [[ :$opts: == *:InsertLeave:* ]] && builtin eval -- "$_ble_keymap_vi_insert_leave" + _ble_edit_mark_active= + _ble_edit_overwrite_mode= + _ble_keymap_vi_insert_leave= + _ble_keymap_vi_single_command= + _ble_keymap_vi_single_command_overwrite= + ble-edit/content/bolp || ((_ble_edit_ind--)) + ble/decode/keymap/push vi_nmap +} +function ble/widget/vi_imap/normal-mode { + ble-edit/content/clear-arg + ble/keymap:vi/imap-repeat/pop + ble/keymap:vi/imap-repeat/process + ble/keymap:vi/repeat/record-insert + ble/widget/vi_imap/normal-mode.impl InsertLeave + ble/keymap:vi/update-mode-name + return 0 +} +function ble/widget/vi_imap/normal-mode-without-insert-leave { + ble-edit/content/clear-arg + ble/keymap:vi/imap-repeat/pop + ble/keymap:vi/repeat/record-insert + ble/widget/vi_imap/normal-mode.impl + ble/keymap:vi/update-mode-name + return 0 +} +function ble/widget/vi_imap/single-command-mode { + ble-edit/content/clear-arg + local single_command=1 + local single_command_overwrite=$_ble_edit_overwrite_mode + ble-edit/content/eolp && _ble_keymap_vi_single_command=2 + ble/keymap:vi/imap-repeat/pop + ble/widget/vi_imap/normal-mode.impl + _ble_keymap_vi_single_command=$single_command + _ble_keymap_vi_single_command_overwrite=$single_command_overwrite + ble/keymap:vi/update-mode-name + return 0 +} +function ble/keymap:vi/needs-eol-fix { + [[ $_ble_decode_keymap == vi_nmap || $_ble_decode_keymap == vi_omap ]] || return 1 + [[ $_ble_keymap_vi_single_command ]] && return 1 + local index=${1:-$_ble_edit_ind} + ble-edit/content/nonbol-eolp "$index" +} +function ble/keymap:vi/adjust-command-mode { + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + ble/keymap:vi/xmap/remove-eol-extension + fi + local kmap_popped= + if [[ $_ble_decode_keymap == vi_omap ]]; then + ble/decode/keymap/pop + kmap_popped=1 + fi + if [[ $_ble_keymap_vi_search_activate ]]; then + if [[ $_ble_decode_keymap != vi_[xs]map ]]; then + _ble_edit_mark_active=$_ble_keymap_vi_search_activate + fi + _ble_keymap_vi_search_matched=1 + _ble_keymap_vi_search_activate= + else + [[ $_ble_edit_mark_active == vi_search ]] && _ble_edit_mark_active= + ((_ble_keymap_vi_search_matched)) && _ble_keymap_vi_search_matched= + fi + if [[ $_ble_decode_keymap == vi_nmap && $_ble_keymap_vi_single_command ]]; then + if ((_ble_keymap_vi_single_command==2)); then + local index=$((_ble_edit_ind+1)) + ble-edit/content/nonbol-eolp "$index" && _ble_edit_ind=$index + fi + ble/widget/vi_nmap/.insert-mode 1 "$_ble_keymap_vi_single_command_overwrite" resume + ble/keymap:vi/repeat/clear-insert + elif [[ $kmap_popped ]]; then + ble/keymap:vi/update-mode-name + fi + return 0 +} +function ble/widget/vi-command/bell { + ble/widget/.bell "$1" + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi_nmap/.insert-mode { + [[ $_ble_decode_keymap == vi_[xs]map ]] && ble/decode/keymap/pop + [[ $_ble_decode_keymap == vi_omap ]] && ble/decode/keymap/pop + local arg=$1 overwrite=$2 + ble/keymap:vi/imap-repeat/reset "$arg" + _ble_edit_mark_active= + _ble_edit_overwrite_mode=$overwrite + _ble_keymap_vi_insert_leave= + _ble_keymap_vi_insert_overwrite=$overwrite + _ble_keymap_vi_single_command= + _ble_keymap_vi_single_command_overwrite= + ble/keymap:vi/search/clear-matched + ble/decode/keymap/pop + ble/keymap:vi/update-mode-name + ble/keymap:vi/mark/start-edit-area + if [[ :$opts: != *:resume:* ]]; then + ble/keymap:vi/mark/commit-edit-area "$_ble_edit_ind" "$_ble_edit_ind" + fi +} +function ble/widget/vi_nmap/insert-mode { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/append-mode { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + if ! ble-edit/content/eolp; then + ((_ble_edit_ind++)) + fi + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/append-mode-at-end-of-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret; ble-edit/content/find-logical-eol + _ble_edit_ind=$ret + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/insert-mode-at-beginning-of-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret; ble-edit/content/find-logical-bol + _ble_edit_ind=$ret + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/insert-mode-at-first-non-space { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/first-non-space + [[ ${_ble_edit_str:_ble_edit_ind:1} == [$' \t'] ]] && + ((_ble_edit_ind++)) # 逆eol補正 + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/insert-mode-at-previous-point { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret + ble/keymap:vi/mark/get-local-mark 94 && _ble_edit_ind=$ret + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/replace-mode { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/.insert-mode "$ARG" R + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/virtual-replace-mode { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/.insert-mode "$ARG" 1 + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_nmap/accept-line { + ble/keymap:vi/clear-arg + ble/widget/vi_nmap/.insert-mode + ble/keymap:vi/repeat/clear-insert + [[ $_ble_keymap_vi_reg_record ]] && + ble/widget/vi_nmap/record-register + ble/widget/default/accept-line +} +function ble/widget/vi-command/edit-and-execute-command { + ble/keymap:vi/clear-arg + ble/widget/vi_nmap/.insert-mode + ble/keymap:vi/repeat/clear-insert + [[ $_ble_keymap_vi_reg_record ]] && + ble/widget/vi_nmap/record-register + ble/widget/edit-and-execute-command +} +_ble_keymap_vi_oparg= +_ble_keymap_vi_opfunc= +_ble_keymap_vi_reg= +ble/array#push _ble_textarea_local_VARNAMES \ + _ble_keymap_vi_oparg \ + _ble_keymap_vi_opfunc \ + _ble_keymap_vi_reg +_ble_keymap_vi_register=() +_ble_keymap_vi_register_onplay= +function ble/keymap:vi/clear-arg { + _ble_edit_arg= + _ble_keymap_vi_oparg= + _ble_keymap_vi_opfunc= + _ble_keymap_vi_reg= +} +function ble/keymap:vi/get-arg { + local default_value=$1 + REG=$_ble_keymap_vi_reg + FLAG=$_ble_keymap_vi_opfunc + if [[ ! $_ble_edit_arg && ! $_ble_keymap_vi_oparg ]]; then + ARG=$default_value + else + ARG=$((10#0${_ble_edit_arg:-1}*10#0${_ble_keymap_vi_oparg:-1})) + fi + ble/keymap:vi/clear-arg +} +function ble/keymap:vi/register#load { + local reg=$1 + if [[ $reg ]] && ((reg!=34)); then + if [[ $reg == 37 ]]; then # "% + ble-edit/content/push-kill-ring "$HISTFILE" '' + return 0 + fi + local value=${_ble_keymap_vi_register[reg]} + if [[ $value == */* ]]; then + ble-edit/content/push-kill-ring "${value#*/}" "${value%%/*}" + return 0 + else + ble-edit/content/push-kill-ring + return 1 + fi + fi +} +function ble/keymap:vi/register#set { + local reg=$1 type=$2 content=$3 + if [[ $reg == +* ]]; then + local value=${_ble_keymap_vi_register[reg]} + if [[ $value == */* ]]; then + local otype=${value%%/*} + local oring=${value#*/} + if [[ $otype == L ]]; then + if [[ $type == q ]]; then + type=L content=${oring%$'\n'}$content # V + * → V + else + type=L content=$oring$content # V + * → V + fi + elif [[ $type == L ]]; then + type=L content=$oring$'\n'$content # C-v + V, v + V → V + elif [[ $otype == B:* ]]; then + if [[ $type == B:* ]]; then + type=$otype' '${type#B:} + content=$oring$'\n'$content # C-v + C-v → C-v + elif [[ $type == q ]]; then + local ret; ble/string#count-char "$content" $'\n' + ble/string#repeat ' 0' "$ret" + type=$otype$ret + content=$oring$$content # C-v + q → C-v + else + local ret; ble/string#count-char "$content" $'\n' + ble/string#repeat ' 0' $((ret+1)) + type=$otype$ret + content=$oring$'\n'$content # C-v + v → C-v + fi + else + type= content=$oring$content # v + C-v, v + v, v + q → v + fi + fi + fi + [[ $type == L && $content != *$'\n' ]] && content=$content$'\n' + local suppress_default= + [[ $type == q ]] && type= suppress_default=1 + if [[ ! $reg ]] || ((reg==34)); then # "" + ble-edit/content/push-kill-ring "$content" "$type" + return 0 + elif ((reg==58||reg==46||reg==37||reg==126)); then # ": ". "% "~ + ble/widget/.bell "attempted to write on a read-only register #$reg" + return 1 + elif ((reg==95)); then # "_ + return 0 + else + if [[ ! $suppress_default ]]; then + ble-edit/content/push-kill-ring "$content" "$type" + fi + _ble_keymap_vi_register[reg]=$type/$content + return 0 + fi +} +function ble/keymap:vi/register#set-yank { + ble/keymap:vi/register#set "$@" || return 1 + local reg=$1 type=$2 content=$3 + if [[ $reg == '' || $reg == 34 ]]; then + ble/keymap:vi/register#set 48 "$type" "$content" # "0 + fi +} +_ble_keymap_vi_register_49_widget_list=( + ble/widget/vi-command/search-matchpair-or + ble/widget/vi-command/percentage-line + ble/widget/vi-command/goto-mark + ble/widget/vi-command/search-forward + ble/widget/vi-command/search-backward + ble/widget/vi-command/search-repeat + ble/widget/vi-command/search-reverse-repeat +) +function ble/keymap:vi/register#set-edit { + ble/keymap:vi/register#set "$@" || return 1 + local reg=$1 type=$2 content=$3 + if [[ $reg == '' || $reg == 34 ]]; then + local IFS=$_ble_term_IFS + local widget=${WIDGET%%["$_ble_term_IFS"]*} + if [[ $content == *$'\n'* || " $widget " == " ${_ble_keymap_vi_register_49_widget_list[*]} " ]]; then + local n + for ((n=9;n>=2;n--)); do + _ble_keymap_vi_register[48+n]=${_ble_keymap_vi_register[48+n-1]} + done + ble/keymap:vi/register#set 49 "$type" "$content" # "1 + else + ble/keymap:vi/register#set 45 "$type" "$content" # "- + fi + fi +} +function ble/keymap:vi/register#play { + local reg=$1 value + if [[ $reg ]] && ((reg!=34)); then + value=${_ble_keymap_vi_register[reg]} + if [[ $value == */* ]]; then + value=${value#*/} + else + value= + return 1 + fi + else + value=$_ble_edit_kill_ring + fi + local _ble_keymap_vi_register_onplay=1 + local ret; ble/decode/charlog#decode "$value" + ble/widget/.MACRO "${ret[@]}" + return 0 +} +function ble/keymap:vi/register#dump/escape { + local text=$1 + local out= i=0 iN=${#text} + while ((i=bleopt_keymap_vi_macro_depth)) || ble/util/is-stdin-ready; then + return 1 # 無限ループを防ぐため + fi + local _ble_keymap_vi_reg_record_play=$((depth+1)) + local key=$1 + local ret + if ble/keymap:vi/k2c "$key" && local c=$ret; then + ((65<=c&&c<91)) && ((c+=32)) # A-Z -> a-z + if ((48<=c&&c<58||97<=c&&c<123)); then # 0-9a-z + ble/keymap:vi/register#play "$c" && return 0 + fi + fi + ble/widget/vi-command/bell + return 1 +} +function ble/widget/vi-command/operator { + local ret opname=$1 + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + local ARG FLAG REG; ble/keymap:vi/get-arg '' + local a=$_ble_edit_ind b=$_ble_edit_mark + ((a<=b||(a=_ble_edit_mark,b=_ble_edit_ind))) + ble/widget/vi_xmap/.save-visual-state + local ble_keymap_vi_mark_active=$_ble_edit_mark_active # used in call-operator-blockwise + local mark_type=${_ble_edit_mark_active%+} + ble/widget/vi_xmap/exit + local ble_keymap_vi_opmode=$mark_type + if [[ $mark_type == vi_line ]]; then + ble/keymap:vi/call-operator-linewise "$opname" "$a" "$b" "$ARG" "$REG" + elif [[ $mark_type == vi_block ]]; then + ble/keymap:vi/call-operator-blockwise "$opname" "$a" "$b" "$ARG" "$REG" + else + local end=$b + ((end<${#_ble_edit_str}&&end++)) + ble/keymap:vi/call-operator-charwise "$opname" "$a" "$end" "$ARG" "$REG" + fi; local ext=$? + ((ext==147)) && return 147 + ((ext)) && ble/widget/.bell + ble/keymap:vi/adjust-command-mode + return "$ext" + elif [[ $_ble_decode_keymap == vi_nmap ]]; then + ble/decode/keymap/push vi_omap + _ble_keymap_vi_oparg=$_ble_edit_arg + _ble_keymap_vi_opfunc=$opname + _ble_edit_arg= + ble/keymap:vi/update-mode-name + elif [[ $_ble_decode_keymap == vi_omap ]]; then + local opname1=${_ble_keymap_vi_opfunc%%:*} + if [[ $opname == "$opname1" ]]; then + ble/widget/vi_nmap/linewise-operator "$_ble_keymap_vi_opfunc" + else + ble/keymap:vi/clear-arg + ble/widget/vi-command/bell + return 1 + fi + fi + return 0 +} +function ble/widget/vi_nmap/linewise-operator { + local opname=${1%%:*} opflags=${1#*:} + local ARG FLAG REG; ble/keymap:vi/get-arg 1 # _ble_edit_arg is consumed here + if ((ARG==1)) || [[ ${_ble_edit_str:_ble_edit_ind} == *$'\n'* ]]; then + if [[ :$opflags: == *:vi_char:* || :$opflags: == *:vi_block:* ]]; then + local beg=$_ble_edit_ind + local ret; ble-edit/content/find-logical-bol "$beg" $((ARG-1)); local end=$ret + ((beg<=end)) || local beg=$end end=$beg + if [[ :$opflags: == *:vi_block:* ]]; then + ble/keymap:vi/call-operator-blockwise "$opname" "$beg" "$end" '' "$REG" + else + ble/keymap:vi/call-operator-charwise "$opname" "$beg" "$end" '' "$REG" + fi + else + ble/keymap:vi/call-operator-linewise "$opname" "$_ble_edit_ind" "$_ble_edit_ind:$((ARG-1))" '' "$REG"; local ext=$? + fi + if ((ext==0)); then + ble/keymap:vi/adjust-command-mode + return 0 + elif ((ext==147)); then + return 147 + fi + fi + ble/widget/vi-command/bell + return 1 +} +function ble/widget/vi_nmap/copy-current-line { + ble/widget/vi_nmap/linewise-operator y +} +function ble/widget/vi_nmap/kill-current-line { + ble/widget/vi_nmap/linewise-operator d +} +function ble/widget/vi_nmap/kill-current-line-and-insert { + ble/widget/vi_nmap/linewise-operator c +} +function ble/widget/vi-command/beginning-of-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret; ble-edit/content/find-logical-bol; local beg=$ret + ble/widget/vi-command/exclusive-goto.impl "$beg" "$FLAG" "$REG" nobell +} +function ble/keymap:vi/call-operator { + ble/keymap:vi/mark/start-edit-area + local _ble_keymap_vi_mark_suppress_edit=1 + ble/keymap:vi/operator:"$@"; local ext=$? + ble/util/unlocal _ble_keymap_vi_mark_suppress_edit + ble/keymap:vi/mark/end-edit-area + if ((ext==0)); then + if ble/is-function ble/keymap:vi/operator:"$1".record; then + ble/keymap:vi/operator:"$1".record + else + ble/keymap:vi/repeat/record + fi + fi + return "$ext" +} +function ble/keymap:vi/call-operator-charwise { + local ch=$1 beg=$2 end=$3 arg=$4 reg=$5 + ((beg<=end||(beg=$3,end=$2))) + if ble/is-function ble/keymap:vi/operator:"$ch"; then + local ble_keymap_vi_operator_index= + ble/keymap:vi/call-operator "$ch" "$beg" "$end" char "$arg" "$reg"; local ext=$? + ((ext==147)) && return 147 + local index=${ble_keymap_vi_operator_index:-$beg} + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + _ble_edit_ind=$index + return 0 + else + return 1 + fi +} +function ble/keymap:vi/call-operator-linewise { + local ch=$1 a=$2 b=$3 arg=$4 reg=$5 ia=0 ib=0 + [[ $a == *:* ]] && local a=${a%%:*} ia=${a#*:} + [[ $b == *:* ]] && local b=${b%%:*} ib=${b#*:} + local ret + ble-edit/content/find-logical-bol "$a" "$ia"; local beg=$ret + ble-edit/content/find-logical-eol "$b" "$ib"; local end=$ret + if ble/is-function ble/keymap:vi/operator:"$ch"; then + local ble_keymap_vi_operator_index= + ((end<${#_ble_edit_str}&&end++)) + ble/keymap:vi/call-operator "$ch" "$beg" "$end" line "$arg" "$reg"; local ext=$? + ((ext==147)) && return 147 + if [[ $ble_keymap_vi_operator_index ]]; then + local index=$ble_keymap_vi_operator_index + else + ble-edit/content/find-logical-bol "$beg"; beg=$ret # operator 中で beg が変更されているかも + ble-edit/content/find-non-space "$beg"; local index=$ret + fi + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + _ble_edit_ind=$index + return 0 + else + return 1 + fi +} +function ble/keymap:vi/call-operator-blockwise { + local ch=$1 beg=$2 end=$3 arg=$4 reg=$5 + if ble/is-function ble/keymap:vi/operator:"$ch"; then + local mark_active=${ble_keymap_vi_mark_active:-vi_block} + local sub_ranges sub_x1 sub_x2 + _ble_edit_mark_active=$mark_active ble/keymap:vi/extract-block "$beg" "$end" + local nrange=${#sub_ranges[@]} + ((nrange)) || return 1 + local ble_keymap_vi_operator_index= + local beg=${sub_ranges[0]}; beg=${beg%%:*} + local end=${sub_ranges[nrange-1]}; end=${end#*:}; end=${end%%:*} + ble/keymap:vi/call-operator "$ch" "$beg" "$end" block "$arg" "$reg" + ((ext==147)) && return 147 + local index=${ble_keymap_vi_operator_index:-$beg} + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + _ble_edit_ind=$index + return 0 + else + return 1 + fi +} +function ble/keymap:vi/operator:d { + local context=$3 arg=$4 reg=$5 # beg end は上書きする + if [[ $context == line ]]; then + ble/keymap:vi/register#set-edit "$reg" L "${_ble_edit_str:beg:end-beg}" || return 1 + if ((end==${#_ble_edit_str}&&beg>0)); then + local ret + ((beg--)) + ble-edit/content/find-logical-bol "$beg" + ble-edit/content/find-non-space "$ret" + ble_keymap_vi_operator_index=$ret + fi + ble/widget/.delete-range "$beg" "$end" + elif [[ $context == block ]]; then + local -a afill=() atext=() arep=() + local sub shift=0 slpad0= + local smin smax slpad srpad sfill stext + for sub in "${sub_ranges[@]}"; do + stext=${sub#*:*:*:*:*:} + ble/string#split sub : "$sub" + smin=${sub[0]} smax=${sub[1]} + slpad=${sub[2]} srpad=${sub[3]} + sfill=${sub[4]} + [[ $slpad0 ]] || slpad0=$slpad # 最初の slpad + ble/array#push afill "$sfill" + ble/array#push atext "$stext" + local ret; ble/string#repeat ' ' $((slpad+srpad)) + ble/array#push arep $((smin+shift)):$((smax+shift)):"$ret" + ((shift+=(slpad+srpad)-(smax-smin))) + done + IFS=$'\n' builtin eval 'local yank_content="${atext[*]-}"' + local IFS=$_ble_term_IFS + local yank_type=B:"${afill[*]-}" + ble/keymap:vi/register#set-edit "$reg" "$yank_type" "$yank_content" || return 1 + local rep + for rep in "${arep[@]}"; do + smin=${rep%%:*}; rep=${rep:${#smin}+1} + smax=${rep%%:*}; rep=${rep:${#smax}+1} + ble/widget/.replace-range "$smin" "$smax" "$rep" + done + ((beg+=slpad)) # fix start position + else + if ((beg=width)); then + pad=$((c-width)) + nsp=$((smin+i+1)) + break + fi + done + local padding= + ((pad)) && { ble/string#repeat ' ' "$pad"; padding=$ret; } + ble/widget/.replace-range "$smin" "$nsp" "$padding" + done +} +function ble/keymap:vi/operator:indent.impl { + local delta=$1 context=$2 + ((delta)) || return 0 + if [[ $context == block ]]; then + if ((delta>=0)); then + ble/keymap:vi/operator:indent.impl/increase-block-indent "$delta" + elif ble/edit/use-textmap; then + ble/keymap:vi/operator:indent.impl/decrease-graphical-block-indent $((-delta)) + else + ble/keymap:vi/operator:indent.impl/decrease-logical-block-indent $((-delta)) + fi + else + [[ $context == char ]] && ble/keymap:vi/expand-range-for-linewise-operator + ((beg80&&(cols=80))) + ble/keymap:vi/operator:fold/.fold-paragraphwise "$old" "$cols"; local new=$ret + ble/widget/.replace-range "$beg" "$end" "$new" + if [[ :$opts: == *:preserve_point:* ]]; then + if ((end<=oind)); then + ble_keymap_vi_operator_index=$((beg+${#new})) + elif ((beg/dev/null'; then + ble/widget/vi-command/bell + return 1 + fi + new=${new%$'\n'}$'\n' + ble/widget/.replace-range "$beg" "$end" "$new" + _ble_edit_ind=$beg + if [[ $context == line ]]; then + ble/widget/vi-command/first-non-space + else + ble/keymap:vi/adjust-command-mode + fi + ble/keymap:vi/mark/set-previous-edit-area "$beg" $((beg+${#new})) + ble/keymap:vi/operator:filter/.record-repeat "$command" + return 0 +} +bleopt/declare -v keymap_vi_operatorfunc '' +function ble/keymap:vi/operator:map { + local context=$3 + if [[ $bleopt_keymap_vi_operatorfunc ]]; then + local opfunc=ble/keymap:vi/operator:$bleopt_keymap_vi_operatorfunc + if ble/is-function "$opfunc"; then + "$opfunc" "$@" + return "$?" + fi + fi + return 1 +} +function ble/widget/vi-command/exclusive-range.impl { + local src=$1 dst=$2 flag=$3 reg=$4 opts=$5 + if [[ $flag ]]; then + local opname=${flag%%:*} opflags=${flag#*:} + if [[ :$opflags: == *:vi_line:* ]]; then + local ble_keymap_vi_opmode=vi_line + ble/keymap:vi/call-operator-linewise "$opname" "$src" "$dst" '' "$reg"; local ext=$? + elif [[ :$opflags: == *:vi_block:* ]]; then + local ble_keymap_vi_opmode=vi_line + ble/keymap:vi/call-operator-blockwise "$opname" "$src" "$dst" '' "$reg"; local ext=$? + elif [[ :$opflags: == *:vi_char:* ]]; then + local ble_keymap_vi_opmode=vi_char + if [[ :$opts: == *:inclusive:* ]]; then + ((src=h)) && break + ((shift++)) + fi + done + [[ $shift ]] && + _ble_keymap_vi_mark_global[imark]=$((h-shift)):$v + done + ble/builtin/history/array#delete-hindex _ble_keymap_vi_mark_history "$@" + _ble_keymap_vi_mark_hindex= +} +function ble/keymap:vi/mark/history-insert.hook { + local beg=$1 len=$2 + for imark in "${!_ble_keymap_vi_mark_global[@]}"; do + local value=${_ble_keymap_vi_mark_global[imark]} + local h=${value%%:*} v=${value#*:} + ((h>=beg)) && _ble_keymap_vi_mark_global[imark]=$((h+len)):$v + done + ble/builtin/history/array#insert-range _ble_keymap_vi_mark_history "$@" + _ble_keymap_vi_mark_hindex= +} +function ble/keymap:vi/mark/shift-by-dirty-range { + local beg=$1 end=$2 end0=$3 reason=$4 + if [[ $4 == edit ]]; then + ble/dirty-range#update --prefix=_ble_keymap_vi_mark_edit_d "${@:1:3}" + ble/keymap:vi/xmap/update-dirty-range "$@" + ble/keymap:vi/mark/update-mark-history + local shift=$((end-end0)) + local imark + for imark in "${!_ble_keymap_vi_mark_local[@]}"; do + local value=${_ble_keymap_vi_mark_local[imark]} + local index=${value%%:*} rest=${value#*:} + ((indexlen&&(index=len))) + ble-edit/content/find-logical-bol "$index"; index=$ret + ble-edit/content/find-logical-eol "$index"; local eol=$ret + ((index+=bytes,index>eol&&(index=eol))) # ToDo: calculate by byte offset + ret=$index + return 0 +} +function ble/keymap:vi/mark/get-local-mark { + local c=$1 + ble/keymap:vi/mark/update-mark-history + local value=${_ble_keymap_vi_mark_local[c]} + [[ $value ]] || return 1 + local data + ble/string#split data : "$value" + ble/keymap:vi/mark/get-mark.impl "${data[0]}" "${data[1]}" # -> ret +} +_ble_keymap_vi_mark_suppress_edit= +function ble/keymap:vi/mark/set-previous-edit-area { + [[ $_ble_keymap_vi_mark_suppress_edit ]] && return 0 + local beg=$1 end=$2 + ((beg=0)) && ble/keymap:vi/mark/set-previous-edit-area "$beg" "$end" +} +function ble/keymap:vi/mark/set-jump { + ble/keymap:vi/mark/set-local-mark 96 "$_ble_edit_ind" +} +function ble/widget/vi-command/set-mark { + _ble_decode_key__hook="ble/widget/vi-command/set-mark.hook" + return 147 +} +function ble/widget/vi-command/set-mark.hook { + local key=$1 + ble/keymap:vi/clear-arg + local ret + if ble/keymap:vi/k2c "$key" && local c=$ret; then + if ((65<=c&&c<91)); then # A-Z + ble/keymap:vi/mark/set-global-mark "$c" "$_ble_edit_ind" + ble/keymap:vi/adjust-command-mode + return 0 + elif ((97<=c&&c<123||c==91||c==93||c==60||c==62||c==96||c==39)); then # a-z [ ] < > ` ' + ((c==39)) && c=96 # m' は m` に読み替える + ble/keymap:vi/mark/set-local-mark "$c" "$_ble_edit_ind" + ble/keymap:vi/adjust-command-mode + return 0 + fi + fi + ble/widget/vi-command/bell + return 1 +} +function ble/widget/vi-command/goto-mark.impl { + local index=$1 flag=$2 reg=$3 opts=$4 + [[ $flag ]] || ble/keymap:vi/mark/set-jump # `` + if [[ :$opts: == *:line:* ]]; then + ble/widget/vi-command/linewise-goto.impl "$index" "$flag" "$reg" + else + ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" nobell + fi +} +function ble/widget/vi-command/goto-local-mark.impl { + local c=$1 opts=$2 ret + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + if ble/keymap:vi/mark/get-local-mark "$c" && local index=$ret; then + ble/widget/vi-command/goto-mark.impl "$index" "$FLAG" "$REG" "$opts" + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/widget/vi-command/goto-global-mark.impl { + local c=$1 opts=$2 + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/keymap:vi/mark/update-mark-history + local value=${_ble_keymap_vi_mark_global[c]} + if [[ ! $value ]]; then + ble/widget/vi-command/bell + return 1 + fi + local data + ble/string#split data : "$value" + local index; ble/history/get-index + if ((index!=data[0])); then + if [[ $FLAG ]]; then + ble/widget/vi-command/bell + return 1 + fi + ble-edit/history/goto "${data[0]}" + fi + local ret + ble/keymap:vi/mark/get-mark.impl "${data[1]}" "${data[2]}" + ble/widget/vi-command/goto-mark.impl "$ret" "$FLAG" "$REG" "$opts" +} +function ble/widget/vi-command/goto-mark { + _ble_decode_key__hook="ble/widget/vi-command/goto-mark.hook ${1:-char}" + return 147 +} +function ble/widget/vi-command/goto-mark.hook { + local opts=$1 key=$2 + local ret + if ble/keymap:vi/k2c "$key" && local c=$ret; then + if ((65<=c&&c<91)); then # A-Z + ble/widget/vi-command/goto-global-mark.impl "$c" "$opts" + return "$?" + elif ((_ble_keymap_vi_mark_Offset<=c)); then + ((c==39)) && c=96 # `' は `` に読み替える + ble/widget/vi-command/goto-local-mark.impl "$c" "$opts" + return "$?" + fi + fi + ble/keymap:vi/clear-arg + ble/widget/vi-command/bell + return 1 +} +_ble_keymap_vi_repeat=() +_ble_keymap_vi_repeat_insert=() +_ble_keymap_vi_repeat_irepeat=() +_ble_keymap_vi_repeat_invoke= +function ble/keymap:vi/repeat/record-special { + [[ $_ble_keymap_vi_mark_suppress_edit ]] && return 0 + if [[ $_ble_keymap_vi_repeat_invoke ]]; then + [[ $repeat_arg ]] && _ble_keymap_vi_repeat[3]=$repeat_arg + [[ ! ${_ble_keymap_vi_repeat[5]} ]] && _ble_keymap_vi_repeat[5]=$repeat_reg + return 0 + fi + return 1 +} +function ble/keymap:vi/repeat/record-normal { + local IFS=$_ble_term_IFS + local -a repeat; repeat=("$KEYMAP" "${KEYS[*]-}" "$WIDGET" "$ARG" "$FLAG" "$REG" '') + if [[ $KEYMAP == vi_[xs]map ]]; then + repeat[6]=$_ble_keymap_vi_xmap_prev_edit + fi + if [[ $_ble_decode_keymap == vi_imap ]]; then + _ble_keymap_vi_repeat_insert=("${repeat[@]}") + else + _ble_keymap_vi_repeat=("${repeat[@]}") + _ble_keymap_vi_repeat_irepeat=() + fi +} +function ble/keymap:vi/repeat/record { + ble/keymap:vi/repeat/record-special && return 0 + ble/keymap:vi/repeat/record-normal +} +function ble/keymap:vi/repeat/record-insert { + ble/keymap:vi/repeat/record-special && return 0 + if [[ ${_ble_keymap_vi_repeat_insert-} ]]; then + _ble_keymap_vi_repeat=("${_ble_keymap_vi_repeat_insert[@]}") + _ble_keymap_vi_repeat_irepeat=("${_ble_keymap_vi_irepeat[@]}") + elif ((${#_ble_keymap_vi_irepeat[@]})); then + local IFS=$_ble_term_IFS + _ble_keymap_vi_repeat=(vi_nmap "${KEYS[*]-}" ble/widget/vi_nmap/insert-mode 1 '' '') + _ble_keymap_vi_repeat_irepeat=("${_ble_keymap_vi_irepeat[@]}") + fi + ble/keymap:vi/repeat/clear-insert +} +function ble/keymap:vi/repeat/clear-insert { + _ble_keymap_vi_repeat_insert=() +} +function ble/keymap:vi/repeat/invoke { + local repeat_arg=$_ble_edit_arg + local repeat_reg=$_ble_keymap_vi_reg + local KEYMAP=${_ble_keymap_vi_repeat[0]} + local -a KEYS; ble/string#split-words KEYS "${_ble_keymap_vi_repeat[1]}" + local WIDGET=${_ble_keymap_vi_repeat[2]} + if [[ $KEYMAP != vi_[onxs]map ]]; then + ble/widget/vi-command/bell + return 1 + elif [[ $KEYMAP == vi_omap ]]; then + ble/decode/keymap/push vi_omap + elif [[ $KEYMAP == vi_[xs]map ]]; then + local _ble_keymap_vi_xmap_prev_edit=${_ble_keymap_vi_repeat[6]} + ble/widget/vi_xmap/.restore-visual-state + ble/decode/keymap/push "$KEYMAP" + fi + _ble_edit_arg= + _ble_keymap_vi_oparg=${_ble_keymap_vi_repeat[3]} + _ble_keymap_vi_opfunc=${_ble_keymap_vi_repeat[4]} + [[ $repeat_arg ]] && _ble_keymap_vi_oparg=$repeat_arg + local REG=${_ble_keymap_vi_repeat[5]} + [[ $REG ]] && _ble_keymap_vi_reg=$REG + local _ble_keymap_vi_single_command{,_overwrite}= # single-command-mode は持続させる。 + local _ble_keymap_vi_repeat_invoke=1 + local LASTWIDGET=$_ble_decode_widget_last + _ble_decode_widget_last=$WIDGET + builtin eval -- "$WIDGET" + if [[ $_ble_decode_keymap == vi_imap ]]; then + ((_ble_keymap_vi_irepeat_count<=1?(_ble_keymap_vi_irepeat_count=2):_ble_keymap_vi_irepeat_count++)) + local -a _ble_keymap_vi_irepeat + _ble_keymap_vi_irepeat=("${_ble_keymap_vi_repeat_irepeat[@]}") + ble/array#push _ble_keymap_vi_irepeat '0:ble/widget/dummy' # Note: normal-mode が自分自身を pop しようとするので。 + ble/widget/vi_imap/normal-mode + fi + ble/util/unlocal _ble_keymap_vi_single_command{,_overwrite} +} +function ble/widget/vi_nmap/repeat { + ble/keymap:vi/repeat/invoke + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi-command/forward-char { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local index + if [[ $1 == wrap ]]; then + if [[ $FLAG || $_ble_decode_keymap == vi_[xs]map ]]; then + ((index=_ble_edit_ind+ARG, + index>${#_ble_edit_str}&&(index=${#_ble_edit_str}))) + else + local nl=$'\n' + local rex="^([^$nl]$nl?|$nl){0,$ARG}" + [[ ${_ble_edit_str:_ble_edit_ind} =~ $rex ]] + ((index=_ble_edit_ind+${#BASH_REMATCH})) + fi + else + local line=${_ble_edit_str:_ble_edit_ind:ARG} + line=${line%%$'\n'*} + ((index=_ble_edit_ind+${#line})) + fi + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" +} +function ble/widget/vi-command/backward-char { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local index + ((ARG>_ble_edit_ind&&(ARG=_ble_edit_ind))) + if [[ $1 == wrap ]]; then + if [[ $FLAG || $_ble_decode_keymap == vi_[xs]map ]]; then + ((index=_ble_edit_ind-ARG,index<0&&(index=0))) + else + local width=$ARG line + while ((width<=_ble_edit_ind)); do + line=${_ble_edit_str:_ble_edit_ind-width:width} + line=${line//[!$'\n']$'\n'/x} + ((${#line}>=ARG)) && break + ((width+=ARG-${#line})) + done + ((index=_ble_edit_ind-width,index<0&&(index=0))) + fi + else + local line=${_ble_edit_str:_ble_edit_ind-ARG:ARG} + line=${line##*$'\n'} + ((index=_ble_edit_ind-${#line})) + fi + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" +} +function ble/widget/vi_nmap/forward-char-toggle-case { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local line=${_ble_edit_str:_ble_edit_ind:ARG} + line=${line%%$'\n'*} + local len=${#line} + if ((len==0)); then + ble/widget/vi-command/bell + return 1 + fi + local index=$((_ble_edit_ind+len)) + local ret; ble/string#toggle-case "${_ble_edit_str:_ble_edit_ind:len}" + ble/widget/.replace-range "$_ble_edit_ind" "$index" "$ret" + ble/keymap:vi/mark/set-previous-edit-area "$_ble_edit_ind" "$index" + ble/keymap:vi/repeat/record + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + _ble_edit_ind=$index + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-command/.history-relative-line { + local offset=$1 + ((offset)) || return 0 + if [[ ! $_ble_history_prefix && ! $_ble_history_load_done ]]; then + ((offset<0)) || return 1 + ble/history/initialize # to use ble/history/get-index + fi + local index histsize + ble/history/get-index + ble/history/get-count -v histsize + local ret count=$((offset<0?-offset:offset)) exit=1 + ((count--)) + while ((count>=0)); do + if ((offset<0)); then + ((index>0)) || return "$exit" + ble/widget/history-prev + ret=${#_ble_edit_str} + ble/keymap:vi/needs-eol-fix "$ret" && ((ret--)) + _ble_edit_ind=$ret + else + ((indexe2y&&(x=e2x,y=e2y))) + ble/textmap#get-index-at "$x" "$y" # local variable "index" is set here + else + ble-edit/content/find-logical-eol "$bol2"; local eol2=$ret + ((index=bol2+ind-bol1,index>eol2&&(index=eol2))) + fi +} +function ble/widget/vi-command/relative-line.impl { + local offset=$1 flag=$2 reg=$3 opts=$4 + ((offset==0)) && return 0 + if [[ $flag ]]; then + ble/widget/vi-command/linewise-goto.impl "$_ble_edit_ind:$offset" "$flag" "$reg" preserve_column:require_multiline + return "$?" + fi + local count=$((offset<0?-offset:offset)) ret + if ((offset<0)); then + ble/string#count-char "${_ble_edit_str::_ble_edit_ind}" $'\n' + else + ble/string#count-char "${_ble_edit_str:_ble_edit_ind}" $'\n' + fi + ((count-=count=0?count:-count)) || ((nmove)); then + ble/keymap:vi/adjust-command-mode + return 0 + fi + fi + ble/widget/vi-command/bell + return 1 +} +function ble/widget/vi-command/forward-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/relative-line.impl "$ARG" "$FLAG" "$REG" history +} +function ble/widget/vi-command/backward-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/relative-line.impl $((-ARG)) "$FLAG" "$REG" history +} +function ble/widget/vi-command/graphical-relative-line.impl { + local offset=$1 flag=$2 reg=$3 opts=$4 + local index move + if ble/edit/use-textmap; then + local x y ax ay + ble/textmap#getxy.cur "$_ble_edit_ind" + ((ax=x,ay=y+offset, + ay<_ble_textmap_begy?(ay=_ble_textmap_begy): + (ay>_ble_textmap_endy?(ay=_ble_textmap_endy):0))) + ble/textmap#get-index-at "$ax" "$ay" + ble/textmap#getxy.cur --prefix=a "$index" + ((offset-=move=ay-y)) + else + local ret ind=$_ble_edit_ind + ble-edit/content/find-logical-bol "$ind" 0; local bol1=$ret + ble-edit/content/find-logical-bol "$ind" "$offset"; local bol2=$ret + ble-edit/content/find-logical-eol "$bol2"; local eol2=$ret + ((index=bol2+ind-bol1,index>eol2&&(index=eol2))) + if ((index>ind)); then + ble/string#count-char "${_ble_edit_str:ind:index-ind}" $'\n' + ((offset+=move=-ret)) + elif ((index=0?count:-count)); then + ble/widget/vi-command/first-non-space + elif ((nmove)); then + ble/keymap:vi/needs-eol-fix "$nolx" && ((nolx--)) + _ble_edit_ind=$nolx + ble/keymap:vi/adjust-command-mode + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/widget/vi-command/first-non-space { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/relative-first-non-space.impl 0 "$FLAG" "$REG" charwise:history +} +function ble/widget/vi-command/forward-first-non-space { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/relative-first-non-space.impl "$ARG" "$FLAG" "$REG" multiline:history +} +function ble/widget/vi-command/backward-first-non-space { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/relative-first-non-space.impl $((-ARG)) "$FLAG" "$REG" multiline:history +} +function ble/widget/vi-command/first-non-space-forward { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/relative-first-non-space.impl $((ARG-1)) "$FLAG" "$REG" history +} +function ble/widget/vi-command/forward-eol { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + if ((ARG>1)) && [[ ${_ble_edit_str:_ble_edit_ind} != *$'\n'* ]]; then + ble/widget/vi-command/bell + return 1 + fi + local ret index + ble-edit/content/find-logical-eol "$_ble_edit_ind" $((ARG-1)); index=$ret + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" nobell + [[ $_ble_decode_keymap == vi_[xs]map ]] && + ble/keymap:vi/xmap/add-eol-extension # 末尾拡張 +} +function ble/widget/vi-command/beginning-of-graphical-line { + if ble/edit/use-textmap; then + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local x y index + ble/textmap#getxy.cur "$_ble_edit_ind" + ble/textmap#get-index-at 0 "$y" + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" nobell + else + ble/widget/vi-command/beginning-of-line + fi +} +function ble/widget/vi-command/graphical-first-non-space { + if ble/edit/use-textmap; then + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local x y index ret + ble/textmap#getxy.cur "$_ble_edit_ind" + ble/textmap#get-index-at 0 "$y" + ble-edit/content/find-non-space "$index" + ble/keymap:vi/needs-eol-fix "$ret" && ((ret--)) + ble/widget/vi-command/exclusive-goto.impl "$ret" "$FLAG" "$REG" nobell + else + ble/widget/vi-command/first-non-space + fi +} +function ble/widget/vi-command/graphical-forward-eol { + if ble/edit/use-textmap; then + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local x y index + ble/textmap#getxy.cur "$_ble_edit_ind" + ble/textmap#get-index-at $((_ble_textmap_cols-1)) $((y+ARG-1)) + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" nobell + else + ble/widget/vi-command/forward-eol + fi +} +function ble/widget/vi-command/middle-of-graphical-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local index + if ble/edit/use-textmap; then + local x y + ble/textmap#getxy.cur "$_ble_edit_ind" + ble/textmap#get-index-at $((_ble_textmap_cols/2)) "$y" + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + else + local ret + ble-edit/content/find-logical-bol; local bol=$ret + ble-edit/content/find-logical-eol; local eol=$ret + ((index=(bol+${COLUMNS:-eol})/2, + index>eol&&(index=eol), + bol1)) && [[ ${_ble_edit_str:_ble_edit_ind:index-_ble_edit_ind} != *$'\n'* ]]; then + ble/widget/vi-command/bell + return 1 + fi + local rex=$'([^ \t\n]?[ \t]+|[^ \t\n])$' + [[ ${_ble_edit_str::index} =~ $rex ]] && ((index-=${#BASH_REMATCH})) + ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" nobell +} +_ble_keymap_vi_previous_scroll= +function ble/widget/vi_nmap/scroll.impl { + local opts=$1 + local height=${_ble_canvas_panel_height[_ble_textarea_panel]} + local ARG FLAG REG; ble/keymap:vi/get-arg "$_ble_keymap_vi_previous_scroll" + _ble_keymap_vi_previous_scroll=$ARG + [[ $ARG ]] || ((ARG=height/2)) + [[ :$opts: == *:backward:* ]] && ((ARG=-ARG)) + ble/widget/.update-textmap + if [[ :$opts: == *:cursor:* ]]; then + local x y index ret + ble/textmap#getxy.cur "$_ble_edit_ind" + ble/textmap#get-index-at 0 $((y+ARG)) + ble-edit/content/find-non-space "$index" + ble/keymap:vi/needs-eol-fix "$ret" && ((ret--)) + _ble_edit_ind=$ret + ble/keymap:vi/adjust-command-mode + ((_ble_textmap_endymax_scroll)); then + _ble_textarea_scroll_new=$max_scroll + fi + else + ((_ble_textmap_endymax_scroll)); then + _ble_textarea_scroll_new=$max_scroll + fi + local ay=$((_ble_textarea_scroll_new+_ble_textmap_begy)) + local by=$((_ble_textarea_scroll_new+height-1)) + ((_ble_textarea_scroll_new&&ay++)) + ((_ble_textarea_scroll_new!=0&&ayby?(y=by,1):0))); then + local index + ble/textmap#get-index-at "$x" "$y" + _ble_edit_ind=$index + fi + ble/keymap:vi/adjust-command-mode + fi +} +function ble/widget/vi_nmap/forward-line-scroll { + ble/widget/vi_nmap/scroll.impl forward:cursor +} +function ble/widget/vi_nmap/backward-line-scroll { + ble/widget/vi_nmap/scroll.impl backward:cursor +} +function ble/widget/vi_nmap/forward-scroll { + ble/widget/vi_nmap/scroll.impl forward +} +function ble/widget/vi_nmap/backward-scroll { + ble/widget/vi_nmap/scroll.impl backward +} +function ble/widget/vi_nmap/pagedown { + local height=${_ble_canvas_panel_height[_ble_textarea_panel]} + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/.update-textmap + local x y + ble/textmap#getxy.cur "$_ble_edit_ind" + if ((y==_ble_textmap_endy)); then + ble/widget/vi-command/bell + return 1 + fi + local vheight=$((height-_ble_textmap_begy-1)) + local ybase=$((_ble_textarea_scroll_new+height-1)) + local y1=$((ybase+(ARG-1)*(vheight-2))) + local index ret + ble/textmap#get-index-at 0 "$y1" + ble-edit/content/bolp "$index" && + ble-edit/content/find-non-space "$index"; index=$ret + _ble_edit_ind=$index + local max_scroll=$((_ble_textmap_endy+1-height)) + ble/textmap#getxy.cur "$_ble_edit_ind" + local scroll=$((y<=_ble_textmap_begy+1?0:(y-_ble_textmap_begy-1))) + ((scroll>max_scroll&&(scroll=max_scroll))) + _ble_textarea_scroll_new=$scroll + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi_nmap/pageup { + local height=${_ble_canvas_panel_height[_ble_textarea_panel]} + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/.update-textmap + if ((!_ble_textarea_scroll_new)); then + ble/widget/vi-command/bell + return 1 + fi + local vheight=$((height-_ble_textmap_begy-1)) + local ybase=$((_ble_textarea_scroll_new+_ble_textmap_begy+1)) + local y1=$((ybase-(ARG-1)*(vheight-2))) + ((y1<_ble_textmap_begy&&(y1=_ble_textmap_begy))) + local index ret + ble/textmap#get-index-at 0 "$y1" + ble-edit/content/bolp "$index" && + ble-edit/content/find-non-space "$index"; index=$ret + _ble_edit_ind=$index + local x y + ble/textmap#getxy.cur "$_ble_edit_ind" + local scroll=$((y-height+2)) + ((scroll<0&&(scroll=0))) + _ble_textarea_scroll_new=$scroll + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi_nmap/scroll-to-center.impl { + local opts=$1 + ble/widget/.update-textmap + local height=${_ble_canvas_panel_height[_ble_textarea_panel]} + local ARG FLAG REG; ble/keymap:vi/get-arg '' + if [[ ! $ARG && :$opts: == *:pagedown:* ]]; then + local y1=$((_ble_textarea_scroll_new+height)) + local index + ble/textmap#get-index-at 0 "$y1" + ((_ble_edit_ind=index)) + fi + local ret + ble-edit/content/find-logical-bol "$_ble_edit_ind"; local bol1=$ret + if [[ $ARG || :$opts: == *:nol:* ]]; then + if [[ $ARG ]]; then + ble-edit/content/find-logical-bol 0 $((ARG-1)); local bol2=$ret + else + local bol2=$bol1 + fi + if [[ :$opts: == *:nol:* ]]; then + ble-edit/content/find-non-space "$bol2" + _ble_edit_ind=$ret + elif ((bol1!=bol2)); then + local b1x b1y p1x p1y dx dy + ble/textmap#getxy.cur --prefix=b1 "$bol1" + ble/textmap#getxy.cur --prefix=p1 "$_ble_edit_ind" + ((dx=p1x,dy=p1y-b1y)) + local b2x b2y p2x p2y index + ble/textmap#getxy.cur --prefix=b2 "$bol2" + ((p2x=b2x,p2y=b2y+dy)) + ble/textmap#get-index-at "$p2x" "$p2y" + if ble-edit/content/find-logical-bol "$index"; ((ret==bol2)); then + _ble_edit_ind=$index + else + ble-edit/content/find-logical-eol "$bol2" + _ble_edit_ind=$ret + fi + fi + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + fi + if ((_ble_textmap_endy+1>height)); then + local max_scroll=$((_ble_textmap_endy+1-height)) + local b1x b1y + ble/textmap#getxy.cur --prefix=b1 "$bol1" + local scroll= + if [[ :$opts: == *:top:* ]]; then + ((scroll=b1y-(_ble_textmap_begy+2))) + elif [[ :$opts: == *:bottom:* ]]; then + ((scroll=b1y-(height-2))) + else + local vheight=$((height-_ble_textmap_begy-1)) + ((scroll=b1y-(_ble_textmap_begy+1+vheight/2))) + fi + if ((scroll<0)); then + scroll=0 + elif ((scroll>max_scroll)); then + scroll=$max_scroll + fi + _ble_textarea_scroll_new=$scroll + fi + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi_nmap/scroll-to-center-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl + ble/widget/redraw-line +} +function ble/widget/vi_nmap/scroll-to-top-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl top + ble/widget/redraw-line +} +function ble/widget/vi_nmap/scroll-to-bottom-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl bottom + ble/widget/redraw-line +} +function ble/widget/vi_nmap/scroll-to-center-non-space-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl nol + ble/widget/redraw-line +} +function ble/widget/vi_nmap/scroll-to-top-non-space-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl top:nol + ble/widget/redraw-line +} +function ble/widget/vi_nmap/scroll-to-bottom-non-space-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl bottom:nol + ble/widget/redraw-line +} +function ble/widget/vi_nmap/scroll-or-pagedown-and-redraw { + ble/widget/vi_nmap/scroll-to-center.impl top:nol:pagedown + ble/widget/redraw-line +} +function ble/widget/vi_nmap/paste.impl/block { + local arg=${1:-1} type=$2 + local graphical= + if [[ $type ]]; then + [[ $type == graphical ]] && graphical=1 + else + ble/edit/use-textmap && graphical=1 + fi + local ret cols=$_ble_textmap_cols + local -a afill; ble/string#split-words afill "${_ble_edit_kill_type:2}" + local atext; ble/string#split-lines atext "$_ble_edit_kill_ring" + local ntext=${#atext[@]} + if [[ $graphical ]]; then + ble-edit/content/find-logical-bol; local bol=$ret + local bx by x y c + ble/textmap#getxy.cur --prefix=b "$bol" + ble/textmap#getxy.cur "$_ble_edit_ind" + ((y-=by,c=y*cols+x)) + else + ble-edit/content/find-logical-bol; local bol=$ret + local c=$((_ble_edit_ind-bol)) + fi + local -a ins_beg=() ins_end=() ins_text=() + local i is_newline= + for ((i=0;i0)); then + ble-edit/content/find-logical-bol "$bol" 1 + if ((bol==ret)); then + is_newline=1 + else + bol=$ret + [[ $graphical ]] && ble/textmap#getxy.cur --prefix=b "$bol" + fi + fi + local text=${atext[i]} + local fill=$((afill[i])) + if ((arg>1)); then + ret= + ((fill)) && ble/string#repeat ' ' "$fill" + ble/string#repeat "$text$ret" "$arg" + text=${ret::${#ret}-fill} + fi + local index iend= + if [[ $is_newline ]]; then + index=${#_ble_edit_str} + ble/string#repeat ' ' "$c" + text=$'\n'$ret$text + elif [[ $graphical ]]; then + ble-edit/content/find-logical-eol "$bol"; local eol=$ret + ble/textmap#get-index-at "$x" $((by+y)); ((index>eol&&(index=eol))) + local ax ay ac; ble/textmap#getxy.out --prefix=a "$index" + ((ay-=by,ac=ay*cols+ax)) + if ((aceol)); then + ble/string#repeat ' ' $((index-eol)) + text=$ret$text + index=$eol + fi + fi + ble/array#push ins_beg "$index" + ble/array#push ins_end "${iend:-$index}" + ble/array#push ins_text "$text" + done + ble/keymap:vi/mark/start-edit-area + local i=${#ins_beg[@]} + while ((i--)); do + local ibeg=${ins_beg[i]} iend=${ins_end[i]} text=${ins_text[i]} + ble/widget/.replace-range "$ibeg" "$iend" "$text" + done + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi_nmap/paste.impl { + local arg=$1 reg=$2 is_after=$3 + if [[ $reg ]]; then + local _ble_edit_kill_ring _ble_edit_kill_type + ble/keymap:vi/register#load "$reg" + fi + [[ $_ble_edit_kill_ring ]] || return 0 + local ret + if [[ $_ble_edit_kill_type == L ]]; then + ble/string#repeat "$_ble_edit_kill_ring" "$arg" + local content=$ret + local index dbeg dend + if ((is_after)); then + ble-edit/content/find-logical-eol; index=$ret + if ((index==${#_ble_edit_str})); then + content=$'\n'${content%$'\n'} + ((dbeg=index+1,dend=index+${#content})) + else + ((index++,dbeg=index,dend=index+${#content}-1)) + fi + else + ble-edit/content/find-logical-bol + ((index=ret,dbeg=index,dend=index+${#content}-1)) + fi + ble/widget/.replace-range "$index" "$index" "$content" + _ble_edit_ind=$dbeg + ble/keymap:vi/mark/set-previous-edit-area "$dbeg" "$dend" + ble/keymap:vi/repeat/record + ble/widget/vi-command/first-non-space + elif [[ $_ble_edit_kill_type == B:* ]]; then + if ((is_after)) && ! ble-edit/content/eolp; then + ((_ble_edit_ind++)) + fi + ble/widget/vi_nmap/paste.impl/block "$arg" + else + if ((is_after)) && ! ble-edit/content/eolp; then + ((_ble_edit_ind++)) + fi + ble/string#repeat "$_ble_edit_kill_ring" "$arg" + local beg=$_ble_edit_ind + ble/widget/.insert-string "$ret" + local end=$_ble_edit_ind + ble/keymap:vi/mark/set-previous-edit-area "$beg" "$end" + ble/keymap:vi/repeat/record + [[ $_ble_keymap_vi_single_command ]] || ((_ble_edit_ind--)) + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/adjust-command-mode + fi + return 0 +} +function ble/widget/vi_nmap/paste-after { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/paste.impl "$ARG" "$REG" 1 +} +function ble/widget/vi_nmap/paste-before { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/paste.impl "$ARG" "$REG" 0 +} +function ble/widget/vi_nmap/kill-forward-char { + _ble_keymap_vi_opfunc=d + ble/widget/vi-command/forward-char +} +function ble/widget/vi_nmap/kill-forward-char-and-insert { + _ble_keymap_vi_opfunc=c + ble/widget/vi-command/forward-char +} +function ble/widget/vi_nmap/kill-backward-char { + _ble_keymap_vi_opfunc=d + ble/widget/vi-command/backward-char +} +function ble/widget/vi_nmap/kill-forward-line { + _ble_keymap_vi_opfunc=d + ble/widget/vi-command/forward-eol +} +function ble/widget/vi_nmap/kill-forward-line-and-insert { + _ble_keymap_vi_opfunc=c + ble/widget/vi-command/forward-eol +} +function ble/widget/vi-command/forward-word.impl { + local arg=$1 flag=$2 reg=$3 rex_word=$4 + local ifs=$_ble_term_IFS + if [[ $flag == c && ${_ble_edit_str:_ble_edit_ind:1} != [$ifs] ]]; then + ble/widget/vi-command/forward-word-end.impl "$arg" "$flag" "$reg" "$rex_word" allow_here + return "$?" + fi + local b=$'[ \t]' n=$'\n' + local rex="^((($rex_word)$n?|$b+$n?|$n)($b+$n)*$b*){0,$arg}" # 単語先頭または空行に止まる + [[ ${_ble_edit_str:_ble_edit_ind} =~ $rex ]] + local index=$((_ble_edit_ind+${#BASH_REMATCH})) + if [[ $flag ]]; then + local rematch1=${BASH_REMATCH[1]} + if local rex="$n$b*\$"; [[ $rematch1 =~ $rex ]]; then + local suffix_len=${#BASH_REMATCH} + ((suffix_len<${#rematch1})) && + ((index-=suffix_len)) + fi + fi + ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" +} +function ble/widget/vi-command/forward-word-end.impl { + local arg=$1 flag=$2 reg=$3 rex_word=$4 opts=$5 + local IFS=$_ble_term_IFS + local rex="^([$IFS]*($rex_word)?){0,$arg}" # 単語末端に止まる。空行には止まらない + local offset=1; [[ :$opts: == *:allow_here:* ]] && offset=0 + [[ ${_ble_edit_str:_ble_edit_ind+offset} =~ $rex ]] + local index=$((_ble_edit_ind+offset+${#BASH_REMATCH}-1)) + ((index<_ble_edit_ind&&(index=_ble_edit_ind))) + [[ ! $flag && $BASH_REMATCH && ${_ble_edit_str:index:1} == [$IFS] ]] && ble/widget/.bell + ble/widget/vi-command/inclusive-goto.impl "$index" "$flag" "$reg" +} +function ble/widget/vi-command/backward-word.impl { + local arg=$1 flag=$2 reg=$3 rex_word=$4 + local b=$'[ \t]' n=$'\n' + local rex="((($rex_word)$n?|$b+$n?|$n)($b+$n)*$b*){0,$arg}\$" # 単語先頭または空行に止まる + [[ ${_ble_edit_str::_ble_edit_ind} =~ $rex ]] + local index=$((_ble_edit_ind-${#BASH_REMATCH})) + ble/widget/vi-command/exclusive-goto.impl "$index" "$flag" "$reg" +} +function ble/widget/vi-command/backward-word-end.impl { + local arg=$1 flag=$2 reg=$3 rex_word=$4 + local i=$'[ \t\n]' b=$'[ \t]' n=$'\n' w="($rex_word)" + local rex1="(^|$w$n?|$n)($b+$n)*$b*" + local rex="($rex1)($rex1){$((arg-1))}($rex_word|$i)\$" # 単語末端または空行に止まる + [[ ${_ble_edit_str::_ble_edit_ind+1} =~ $rex ]] + local index=$((_ble_edit_ind+1-${#BASH_REMATCH})) + local rematch3=${BASH_REMATCH[3]} # 最初の ($rex_word) + [[ $rematch3 ]] && ((index+=${#rematch3}-1)) + ble/widget/vi-command/inclusive-goto.impl "$index" "$flag" "$reg" +} +function ble/widget/vi-command/forward-vword { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/forward-word.impl "$ARG" "$FLAG" "$REG" "$_ble_keymap_vi_REX_WORD" +} +function ble/widget/vi-command/forward-vword-end { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/forward-word-end.impl "$ARG" "$FLAG" "$REG" "$_ble_keymap_vi_REX_WORD" +} +function ble/widget/vi-command/backward-vword { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/backward-word.impl "$ARG" "$FLAG" "$REG" "$_ble_keymap_vi_REX_WORD" +} +function ble/widget/vi-command/backward-vword-end { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/backward-word-end.impl "$ARG" "$FLAG" "$REG" "$_ble_keymap_vi_REX_WORD" +} +function ble/widget/vi-command/forward-uword { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/forward-word.impl "$ARG" "$FLAG" "$REG" $'[^ \t\n]+' +} +function ble/widget/vi-command/forward-uword-end { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/forward-word-end.impl "$ARG" "$FLAG" "$REG" $'[^ \t\n]+' +} +function ble/widget/vi-command/backward-uword { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/backward-word.impl "$ARG" "$FLAG" "$REG" $'[^ \t\n]+' +} +function ble/widget/vi-command/backward-uword-end { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/backward-word-end.impl "$ARG" "$FLAG" "$REG" $'[^ \t\n]+' +} +function ble/widget/vi-command/nth-column { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret index + ble-edit/content/find-logical-bol; local bol=$ret + ble-edit/content/find-logical-eol; local eol=$ret + if ble/edit/use-textmap; then + local bx by; ble/textmap#getxy.cur --prefix=b "$bol" # Note: 先頭行はプロンプトにより bx!=0 + local ex ey; ble/textmap#getxy.cur --prefix=e "$eol" + local dstx=$((bx+ARG-1)) dsty=$by cols=${COLUMNS:-80} + ((dsty+=dstx/cols,dstx%=cols)) + ((dsty>ey&&(dsty=ey,dstx=ex))) + ble/textmap#get-index-at "$dstx" "$dsty" # local variable "index" is set here + [[ $_ble_decode_keymap != vi_[xs]map ]] && + ble-edit/content/nonbol-eolp "$index" && ((index--)) + else + [[ $_ble_decode_keymap != vi_[xs]map ]] && + ble-edit/content/nonbol-eolp "$eol" && ((eol--)) + ((index=bol+ARG-1,index>eol&&(index=eol))) + fi + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" nobell +} +function ble/widget/vi-command/nth-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` + ble/widget/vi-command/linewise-goto.impl 0:$((ARG-1)) "$FLAG" "$REG" +} +function ble/widget/vi-command/nth-last-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` + ble/widget/vi-command/linewise-goto.impl ${#_ble_edit_str}:$((-(ARG-1))) "$FLAG" "$REG" +} +function ble/widget/vi-command/history-beginning { + local ARG FLAG REG; ble/keymap:vi/get-arg 0 + if [[ $FLAG ]]; then + if ((ARG)); then + _ble_keymap_vi_oparg=$ARG + else + _ble_keymap_vi_oparg= + fi + _ble_keymap_vi_opfunc=$FLAG + _ble_keymap_vi_reg=$REG + ble/widget/vi-command/nth-line + return "$?" + fi + if ((ARG)); then + ble-edit/history/goto $((ARG-1)) + else + ble/widget/history-beginning + fi + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-command/history-end { + local ARG FLAG REG; ble/keymap:vi/get-arg 0 + if [[ $FLAG ]]; then + _ble_keymap_vi_opfunc=$FLAG + _ble_keymap_vi_reg=$REG + if ((ARG)); then + _ble_keymap_vi_oparg=$ARG + ble/widget/vi-command/nth-line + else + _ble_keymap_vi_oparg= + ble/widget/vi-command/nth-last-line + fi + return "$?" + fi + if ((ARG)); then + ble-edit/history/goto $((ARG-1)) + else + ble/widget/history-end + fi + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-command/last-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 0 + [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` + if ((ARG)); then + ble/widget/vi-command/linewise-goto.impl 0:$((ARG-1)) "$FLAG" "$REG" + else + ble/widget/vi-command/linewise-goto.impl ${#_ble_edit_str}:0 "$FLAG" "$REG" + fi +} +function ble/widget/vi-command/first-nol { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi-command/linewise-goto.impl 0:$((ARG-1)) "$FLAG" "$REG" +} +function ble/widget/vi-command/last-eol { + local ARG FLAG REG; ble/keymap:vi/get-arg '' + local ret index + if [[ $ARG ]]; then + ble-edit/content/find-logical-eol 0 $((ARG-1)); index=$ret + else + ble-edit/content/find-logical-eol ${#_ble_edit_str}; index=$ret + fi + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" nobell +} +function ble/widget/vi_nmap/replace-char.impl { + local key=$1 overwrite_mode=${2:-R} + _ble_edit_overwrite_mode= + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret + if ((key==(_ble_decode_Ctrl|91))); then # C-[ + ble/keymap:vi/adjust-command-mode + return 27 + elif ! ble/keymap:vi/k2c "$key"; then + ble/widget/vi-command/bell + return 1 + fi + local pos=$_ble_edit_ind + ble/keymap:vi/mark/start-edit-area + { + local -a KEYS; KEYS=("$ret") + local _ble_edit_arg=$ARG + local _ble_edit_overwrite_mode=$overwrite_mode + local ble_widget_self_insert_opts=nolineext + ble/widget/self-insert + ble/util/unlocal KEYS + } + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record + ((pos<_ble_edit_ind&&_ble_edit_ind--)) + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi_nmap/replace-char.hook { + ble/widget/vi_nmap/replace-char.impl "$1" R +} +function ble/widget/vi_nmap/replace-char { + _ble_edit_overwrite_mode=R + ble/keymap:vi/async-read-char ble/widget/vi_nmap/replace-char.hook +} +function ble/widget/vi_nmap/virtual-replace-char.hook { + ble/widget/vi_nmap/replace-char.impl "$1" 1 +} +function ble/widget/vi_nmap/virtual-replace-char { + _ble_edit_overwrite_mode=1 + ble/keymap:vi/async-read-char ble/widget/vi_nmap/virtual-replace-char.hook +} +function ble/widget/vi_nmap/connect-line-with-space { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret + ble-edit/content/find-logical-eol; local eol1=$ret + ble-edit/content/find-logical-eol "$_ble_edit_ind" $((ARG<=1?1:ARG-1)); local eol2=$ret + ble-edit/content/find-logical-bol "$eol2"; local bol2=$ret + if ((eol1 cancel + return 27 + else + ble/keymap:vi/k2c "$key" || return 1 + ble/util/c2s "$ret"; local c=$ret + fi + [[ $c ]] || return 1 + ((isrepeat)) || _ble_keymap_vi_char_search=$c$opts + local index + if [[ $opts == *b* ]]; then + ble-edit/content/find-logical-bol; local bol=$ret + local base=$_ble_edit_ind + ((isrepeat&&isprev&&base--,base>bol)) || return 1 + local line=${_ble_edit_str:bol:base-bol} + ble/string#last-index-of "$line" "$c" "$ARG" + ((ret>=0)) || return 1 + ((index=bol+ret,isprev&&index++)) + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" nobell + return "$?" + else + ble-edit/content/find-logical-eol; local eol=$ret + local base=$((_ble_edit_ind+1)) + ((isrepeat&&isprev&&base++,base=0)) || return 1 + ((index=base+ret,isprev&&index--)) + ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" nobell + return "$?" + fi +} +function ble/widget/vi-command/search-char.impl { + if ble/widget/vi-command/search-char.impl/core "$1" "$2"; then + ble/keymap:vi/adjust-command-mode + return 0 + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/widget/vi-command/search-forward-char { + ble/keymap:vi/async-read-char ble/widget/vi-command/search-char.impl f +} +function ble/widget/vi-command/search-forward-char-prev { + ble/keymap:vi/async-read-char ble/widget/vi-command/search-char.impl fp +} +function ble/widget/vi-command/search-backward-char { + ble/keymap:vi/async-read-char ble/widget/vi-command/search-char.impl b +} +function ble/widget/vi-command/search-backward-char-prev { + ble/keymap:vi/async-read-char ble/widget/vi-command/search-char.impl bp +} +function ble/widget/vi-command/search-char-repeat { + [[ $_ble_keymap_vi_char_search ]] || ble/widget/.bell + local c=${_ble_keymap_vi_char_search::1} opts=${_ble_keymap_vi_char_search:1} + ble/widget/vi-command/search-char.impl "r$opts" "$c" +} +function ble/widget/vi-command/search-char-reverse-repeat { + [[ $_ble_keymap_vi_char_search ]] || ble/widget/.bell + local c=${_ble_keymap_vi_char_search::1} opts=${_ble_keymap_vi_char_search:1} + if [[ $opts == *b* ]]; then + opts=f${opts//b} + else + opts=b${opts//f} + fi + ble/widget/vi-command/search-char.impl "r$opts" "$c" +} +function ble/widget/vi-command/search-matchpair/.search-forward { + ble/string#index-of-chars "$_ble_edit_str" "$ch1$ch2" $((index+1)) +} +function ble/widget/vi-command/search-matchpair/.search-backward { + ble/string#last-index-of-chars "$_ble_edit_str" "$ch1$ch2" "$index" +} +function ble/widget/vi-command/search-matchpair-or { + local ARG FLAG REG; ble/keymap:vi/get-arg -1 + if ((ARG>=0)); then + _ble_keymap_vi_oparg=$ARG + _ble_keymap_vi_opfunc=$FLAG + _ble_keymap_vi_reg=$REG + ble/widget/"$@" + return "$?" + fi + local open='({[' close=')}]' + local ret + ble-edit/content/find-logical-eol; local eol=$ret + if ! ble/string#index-of-chars "${_ble_edit_str::eol}" '(){}[]' "$_ble_edit_ind"; then + ble/keymap:vi/adjust-command-mode + return 1 + fi + local index1=$ret ch1=${_ble_edit_str:ret:1} + if [[ $ch1 == ["$open"] ]]; then + local i=${open%%"$ch"*}; i=${#i} + local ch2=${close:i:1} + local searcher=ble/widget/vi-command/search-matchpair/.search-forward + else + local i=${close%%"$ch"*}; i=${#i} + local ch2=${open:i:1} + local searcher=ble/widget/vi-command/search-matchpair/.search-backward + fi + local index=$index1 count=1 + while "$searcher"; do + index=$ret + if [[ ${_ble_edit_str:ret:1} == "$ch1" ]]; then + ((++count)) + else + ((--count==0)) && break + fi + done + if ((count)); then + ble/keymap:vi/adjust-command-mode + return 1 + fi + [[ $FLAG ]] || ble/keymap:vi/mark/set-jump # `` + ble/widget/vi-command/inclusive-goto.impl "$index" "$FLAG" "$REG" nobell +} +function ble/widget/vi-command/percentage-line { + local ARG FLAG REG; ble/keymap:vi/get-arg 0 + local ret; ble/string#count-char "$_ble_edit_str" $'\n'; local nline=$((ret+1)) + local iline=$(((ARG*nline+99)/100)) + ble/widget/vi-command/linewise-goto.impl 0:$((iline-1)) "$FLAG" "$REG" +} +function ble/widget/vi-command/nth-byte { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ((ARG--)) + local offset=0 text=$_ble_edit_str len=${#_ble_edit_str} + local left nleft ret + while ((ARG>0&&len>1)); do + left=${text::len/2} + ble/util/strlen "$left"; nleft=$ret + if ((ARG=2)); then + if [[ $type == i* ]]; then + [[ $match == ["$space"]* ]] && beg=1 + elif [[ $type == a* ]]; then + [[ $match == *[!"$ifs"] ]] && beg=1 + fi + fi + done + return 0 +} +function ble/keymap:vi/text-object/word.impl { + local arg=$1 flag=$2 reg=$3 type=$4 + local space=$' \t' nl=$'\n' ifs=$_ble_term_IFS + ((arg==0)) && return 0 + local rex_word + if [[ $type == ?W ]]; then + rex_word="[^$ifs]+" + else + rex_word=$_ble_keymap_vi_REX_WORD + fi + local index=$_ble_edit_ind + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + if ((index<_ble_edit_mark)); then + local beg=$index + if ble/keymap:vi/text-object/word.extend-backward; then + _ble_edit_ind=$beg + else + _ble_edit_ind=0 + ble/widget/.bell + fi + ble/keymap:vi/adjust-command-mode + return 0 + fi + fi + local beg=$index end=$index flags= + if ! ble/keymap:vi/text-object/word.extend-forward; then + index=${#_ble_edit_str} + ble-edit/content/nonbol-eolp "$index" && ((index--)) + _ble_edit_ind=$index + ble/widget/vi-command/bell + return 1 + fi + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + ((end--)) + ble-edit/content/nonbol-eolp "$end" && ((end--)) + ((beg<_ble_edit_mark)) && _ble_edit_mark=$beg + [[ $_ble_edit_mark_active == vi_line ]] && + _ble_edit_mark_active=vi_char + _ble_edit_ind=$end + ble/keymap:vi/adjust-command-mode + return 0 + else + ble/widget/vi-command/exclusive-range.impl "$beg" "$end" "$flag" "$reg" + fi +} +function ble/keymap:vi/text-object:quote/.next { + local index=${1:-$((_ble_edit_ind+1))} nl=$'\n' + local rex="^[^$nl$quote]*$quote" + [[ ${_ble_edit_str:index} =~ $rex ]] || return 1 + ((ret=index+${#BASH_REMATCH}-1)) + return 0 +} +function ble/keymap:vi/text-object:quote/.prev { + local index=${1:-_ble_edit_ind} nl=$'\n' + local rex="$quote[^$nl$quote]*\$" + [[ ${_ble_edit_str::index} =~ $rex ]] || return 1 + ((ret=index-${#BASH_REMATCH})) + return 0 +} +function ble/keymap:vi/text-object/quote.impl { + local arg=$1 flag=$2 reg=$3 type=$4 + local ret quote=${type:1} + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + if ble/keymap:vi/text-object:quote/.xmap; then + ble/keymap:vi/adjust-command-mode + return 0 + else + ble/widget/vi-command/bell + return 1 + fi + fi + local beg= end= + if [[ ${_ble_edit_str:_ble_edit_ind:1} == "$quote" ]]; then + ble-edit/content/find-logical-bol; local bol=$ret + ble/string#count-char "${_ble_edit_str:bol:_ble_edit_ind-bol}" "$quote" + if ((ret%2==1)); then + ((end=_ble_edit_ind+1)) + ble/keymap:vi/text-object:quote/.prev && beg=$ret + else + ((beg=_ble_edit_ind)) + ble/keymap:vi/text-object:quote/.next && end=$((ret+1)) + fi + elif ble/keymap:vi/text-object:quote/.prev && beg=$ret; then + ble/keymap:vi/text-object:quote/.next && end=$((ret+1)) + elif ble/keymap:vi/text-object:quote/.next && beg=$ret; then + ble/keymap:vi/text-object:quote/.next $((beg+1)) && end=$((ret+1)) + fi + if [[ $beg && $end ]]; then + [[ $type == i* || arg -gt 1 ]] && ((beg++,end--)) + ble/widget/vi-command/exclusive-range.impl "$beg" "$end" "$flag" "$reg" + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/keymap:vi/text-object:quote/.expand-xmap-range { + local inclusive=$1 + ((end++)) + if ((inclusive==2)); then + local rex + rex=$'^[ \t]+'; [[ ${_ble_edit_str:end} =~ $rex ]] && ((end+=${#BASH_REMATCH})) + elif ((inclusive==0&&end-beg>2)); then + ((beg++,end--)) + fi +} +function ble/keymap:vi/text-object:quote/.xmap { + local min=$_ble_edit_ind max=$_ble_edit_mark + ((min>max)) && local min=$max max=$min + [[ ${_ble_edit_str:min:max+1-min} == *$'\n'* ]] && return 1 + local inclusive=0 + if [[ $type == a* ]]; then + inclusive=2 + elif ((arg>1)); then + inclusive=1 + fi + local ret + if ((_ble_edit_ind==_ble_edit_mark)); then + ble/keymap:vi/text-object:quote/.prev $((_ble_edit_ind+1)) || + ble/keymap:vi/text-object:quote/.next $((_ble_edit_ind+1)) || return 1 + local beg=$ret + ble/keymap:vi/text-object:quote/.next $((beg+1)) || return 1 + local end=$ret + ble/keymap:vi/text-object:quote/.expand-xmap-range "$inclusive" + _ble_edit_mark=$beg + _ble_edit_ind=$((end-1)) + return 0 + elif ((_ble_edit_ind>_ble_edit_mark)); then + local updates_mark= + if [[ ${_ble_edit_str:_ble_edit_ind:1} == "$quote" ]]; then + ble/keymap:vi/text-object:quote/.next $((_ble_edit_ind+1)) || return 1; local beg=$ret + if ble/keymap:vi/text-object:quote/.next $((beg+1)); then + local end=$ret + else + local end=$beg beg=$_ble_edit_ind + fi + else + ble-edit/content/find-logical-bol; local bol=$ret + ble/string#count-char "${_ble_edit_str:bol:_ble_edit_ind-bol}" "$quote" + if ((ret%2==0)); then + ble/keymap:vi/text-object:quote/.next $((_ble_edit_ind+1)) || return 1; local beg=$ret + ble/keymap:vi/text-object:quote/.next $((beg+1)) || return 1; local end=$ret + else + ble/keymap:vi/text-object:quote/.prev "$_ble_edit_ind" || return 1; local beg=$ret + ble/keymap:vi/text-object:quote/.next $((_ble_edit_ind+1)) || return 1; local end=$ret + fi + local i1=$((_ble_edit_mark?_ble_edit_mark-1:0)) + [[ ${_ble_edit_str:i1:_ble_edit_ind-i1} != *"$quote"* ]] && updates_mark=1 + fi + ble/keymap:vi/text-object:quote/.expand-xmap-range "$inclusive" + [[ $updates_mark ]] && _ble_edit_mark=$beg + _ble_edit_ind=$((end-1)) + return 0 + else + ble-edit/content/find-logical-bol; local bol=$ret nl=$'\n' + local rex="^([^$nl$quote]*$quote[^$nl$quote]*$quote)*[^$nl$quote]*$quote" + [[ ${_ble_edit_str:bol:_ble_edit_ind-bol} =~ $rex ]] || return 1 + local beg=$((bol+${#BASH_REMATCH}-1)) + ble/keymap:vi/text-object:quote/.next $((beg+1)) || return 1 + local end=$ret + ble/keymap:vi/text-object:quote/.expand-xmap-range "$inclusive" + [[ ${_ble_edit_str:_ble_edit_ind:_ble_edit_mark+2-_ble_edit_ind} != *"$quote"* ]] && _ble_edit_mark=$((end-1)) + _ble_edit_ind=$beg + return 0 + fi +} +function ble/keymap:vi/text-object/block.impl { + local arg=$1 flag=$2 reg=$3 type=$4 + local ret paren=${type:1} lparen=${type:1:1} rparen=${type:2:1} + local axis=$_ble_edit_ind + [[ ${_ble_edit_str:axis:1} == "$lparen" ]] && ((axis++)) + local count=$arg beg=$axis + while ble/string#last-index-of-chars "$_ble_edit_str" "$paren" "$beg"; do + beg=$ret + if [[ ${_ble_edit_str:beg:1} == "$lparen" ]]; then + ((--count==0)) && break + else + ((++count)) + fi + done + if ((count)); then + ble/widget/vi-command/bell + return 1 + fi + local count=$arg end=$axis + while ble/string#index-of-chars "$_ble_edit_str" "$paren" "$end"; do + end=$((ret+1)) + if [[ ${_ble_edit_str:end-1:1} == "$rparen" ]]; then + ((--count==0)) && break + else + ((++count)) + fi + done + if ((count)); then + ble/widget/vi-command/bell + return 1 + fi + local linewise= + if [[ $type == *i* ]]; then + ((beg++,end--)) + [[ ${_ble_edit_str:beg:1} == $'\n' ]] && ((beg++)) + ((beg'; then + if rex='^<[^/][^>]*>' && [[ ${_ble_edit_str:ret} =~ $rex ]]; then + ((pivot=ret+${#BASH_REMATCH})) + else + ((pivot=ret+1)) + fi + fi + local ifs=$_ble_term_IFS + local beg=$pivot count=$arg + rex="<([^$ifs/>!]+([$ifs]+([^>]*[^/])?)?|/[^>]*)>\$" + while ble/string#last-index-of-chars "${_ble_edit_str::beg}" '>' && beg=$ret; do + [[ ${_ble_edit_str::beg+1} =~ $rex ]] || continue + ((beg-=${#BASH_REMATCH}-1)) + if [[ ${BASH_REMATCH::2} == ']*>'; [[ ${_ble_edit_str:beg:end-beg} =~ $rex ]] && ((beg+=${#BASH_REMATCH})) + rex='<[^>]*>$'; [[ ${_ble_edit_str:beg:end-beg} =~ $rex ]] && ((end-=${#BASH_REMATCH})) + fi + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + _ble_edit_mark=$beg + ble/widget/vi-command/exclusive-goto.impl "$end" + else + ble/widget/vi-command/exclusive-range.impl "$beg" "$end" "$flag" "$reg" + fi +} +function ble/keymap:vi/text-object:sentence/.beg { + beg= is_interval= + local pivot=$_ble_edit_ind rex= + if ble-edit/content/bolp && ble-edit/content/eolp; then + if rex=$'^\n+[^\n]'; [[ ${_ble_edit_str:pivot} =~ $rex ]]; then + beg=$((pivot+${#BASH_REMATCH}-2)) + else + if rex=$'\n+$'; [[ ${_ble_edit_str::pivot} =~ $rex ]]; then + ((pivot-=${#BASH_REMATCH})) + fi + fi + fi + if [[ ! $beg ]]; then + rex="^.*((^$LF?|$LF$LF)([ $HT]*)|[.!?][])'\"]*([ $HT$LF]+))" + if [[ ${_ble_edit_str::pivot+1} =~ $rex ]]; then + beg=${#BASH_REMATCH} + if ((pivot']) ble/keymap:vi/text-object/block.impl "$arg" "$flag" "$reg" "${type::1}<>" ;; + ([ia]['][']) ble/keymap:vi/text-object/block.impl "$arg" "$flag" "$reg" "${type::1}[]" ;; + ([ia]t) ble/keymap:vi/text-object/tag.impl "$arg" "$flag" "$reg" "$type" ;; + ([ia]s) ble/keymap:vi/text-object/sentence.impl "$arg" "$flag" "$reg" "$type" ;; + ([ia]p) ble/keymap:vi/text-object/paragraph.impl "$arg" "$flag" "$reg" "$type" ;; + (*) + ble/widget/vi-command/bell + return 1;; + esac +} +function ble/keymap:vi/text-object.hook { + local key=$1 + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + if ! ble-decode-key/ischar "$key"; then + ble/widget/vi-command/bell + return 1 + fi + local ret; ble/util/c2s "$key" + local type=$_ble_keymap_vi_text_object$ret + ble/keymap:vi/text-object.impl "$ARG" "$FLAG" "$REG" "$type" + return 0 +} +function ble/keymap:vi/.check-text-object { + local n=${#KEYS[@]}; ((n&&n--)) + ble-decode-key/ischar "${KEYS[n]}" || return 1 + local ret; ble/util/c2s "${KEYS[n]}"; local c=$ret + [[ $c == [ia] ]] || return 1 + [[ $_ble_keymap_vi_opfunc || $_ble_decode_keymap == vi_[xs]map ]] || return 1 + _ble_keymap_vi_text_object=$c + _ble_decode_key__hook=ble/keymap:vi/text-object.hook + return 0 +} +function ble/widget/vi-command/text-object { + ble/keymap:vi/.check-text-object && return 0 + ble/widget/vi-command/bell + return 1 +} +_ble_keymap_vi_commandline_history=() +_ble_keymap_vi_commandline_history_edit=() +_ble_keymap_vi_commandline_history_dirt=() +_ble_keymap_vi_commandline_history_index=0 +_ble_keymap_vi_cmap_is_cancel_key[63|_ble_decode_Ctrl]=1 # C-? +_ble_keymap_vi_cmap_is_cancel_key[127]=1 # DEL +_ble_keymap_vi_cmap_is_cancel_key[104|_ble_decode_Ctrl]=1 # C-h +_ble_keymap_vi_cmap_is_cancel_key[8]=1 # BS +function ble/keymap:vi/commandline/before-command.hook { + if [[ ! $_ble_edit_str ]] && ((_ble_keymap_vi_cmap_is_cancel_key[KEYS[0]])); then + ble/widget/vi_cmap/cancel + ble/decode/widget/suppress-widget + fi +} +function ble/widget/vi-command/commandline { + ble/keymap:vi/clear-arg + ble/keymap:vi/async-commandline-mode ble/widget/vi-command/commandline.hook + _ble_edit_PS1=: + ble/history/set-prefix _ble_keymap_vi_commandline + _ble_keymap_vi_cmap_before_command=ble/keymap:vi/commandline/before-command.hook + return 147 +} +function ble/widget/vi-command/commandline.hook { + local command + ble/string#split-words command "$1" + local cmd="ble/widget/vi-command:${command[0]}" + if ble/is-function "$cmd"; then + "$cmd" "${command[@]:1}"; local ext=$? + else + ble/widget/vi-command/bell "unknown command $1"; local ext=1 + fi + [[ $1 ]] && _ble_keymap_vi_register[58]=/$result # ": + return "$ext" +} +function ble/widget/vi-command:w { + if [[ $1 ]]; then + ble/builtin/history -a "$1" + local file=$1 + else + ble/builtin/history -a + local file=${HISTFILE:-'~/.bash_history'} + fi + local wc + ble/util/assign wc 'ble/bin/wc "$file"' + ble/string#split-words wc "$wc" + ble/edit/info/show text "\"$file\" ${wc[0]}L, ${wc[2]}C written" + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-command:q! { + ble/widget/exit force + return 1 +} +function ble/widget/vi-command:q { + ble/widget/exit + ble/keymap:vi/adjust-command-mode # ジョブがあるときは終了しないので。 + return 1 +} +function ble/widget/vi-command:wq { + ble/widget/vi-command:w "$@" + ble/widget/exit + ble/keymap:vi/adjust-command-mode + return 1 +} +_ble_keymap_vi_search_obackward= +_ble_keymap_vi_search_ohistory= +_ble_keymap_vi_search_needle= +_ble_keymap_vi_search_activate= +_ble_keymap_vi_search_matched= +_ble_keymap_vi_search_history=() +_ble_keymap_vi_search_history_edit=() +_ble_keymap_vi_search_history_dirt=() +_ble_keymap_vi_search_history_index=0 +bleopt/declare -v keymap_vi_search_match_current '' +function ble/highlight/layer:region/mark:vi_search/get-selection { + ble/highlight/layer:region/mark:vi_char/get-selection +} +function ble/keymap:vi/search/matched { + [[ $_ble_keymap_vi_search_matched || $_ble_edit_mark_active == vi_search || $_ble_keymap_vi_search_activate ]] +} +function ble/keymap:vi/search/clear-matched { + _ble_keymap_vi_search_activate= + _ble_keymap_vi_search_matched= + [[ $_ble_edit_mark_active == vi_search ]] && _ble_edit_mark_active= +} +function ble/keymap:vi/search/invoke-search { + local needle=$1 + local dir=+; ((opt_backward)) && dir=B + local ind=$_ble_edit_ind + if ((opt_optional_next)); then + if ((!opt_backward)); then + ((_ble_edit_ind<${#_ble_edit_str}&&_ble_edit_ind++)) + fi + elif ((opt_locate)) || ! ble/keymap:vi/search/matched; then + if ((opt_locate)) || [[ $bleopt_keymap_vi_search_match_current ]]; then + if ((opt_backward)); then + ble-edit/content/eolp || ((_ble_edit_ind++)) + fi + else + if ((!opt_backward)); then + ble-edit/content/eolp || ((_ble_edit_ind++)) + fi + fi + else + if ((!opt_backward)); then + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + if ble-edit/isearch/search "$@" && ((beg==_ble_edit_ind)); then + _ble_edit_ind=$end + else + ((_ble_edit_ind<${#_ble_edit_str}&&_ble_edit_ind++)) + fi + else + ((_ble_edit_ind=_ble_edit_mark)) + ble-edit/content/eolp || ((_ble_edit_ind++)) + fi + else + dir=- + fi + fi + ble-edit/isearch/search "$needle" "$dir":regex; local ret=$? + _ble_edit_ind=$ind + return "$ret" +} +function ble/widget/vi-command/search.core { + local beg= end= is_empty_match= + if ble/keymap:vi/search/invoke-search "$needle"; then + if ((beg'; [[ $word =~ $rex ]] && needle=$rex + if [[ $opts == backward ]]; then + ble/widget/vi-command/search.impl -:history "$needle" + else + local original_ind=$_ble_edit_ind + _ble_edit_ind=$((end-1)) + ble/widget/vi-command/search.impl +:history "$needle" && return 0 + _ble_edit_ind=$original_ind + return 1 + fi +} +function ble/widget/vi-command/search-word-forward { + ble/widget/vi-command/search-word.impl forward +} +function ble/widget/vi-command/search-word-backward { + ble/widget/vi-command/search-word.impl backward +} +function ble/widget/vi_nmap/command-help { + ble/keymap:vi/clear-arg + ble/widget/command-help; local ext=$? + ble/keymap:vi/adjust-command-mode + return "$ext" +} +function ble/widget/vi_xmap/command-help.core { + ble/keymap:vi/clear-arg + local get_selection=ble/highlight/layer:region/mark:$_ble_edit_mark_active/get-selection + ble/is-function "$get_selection" || return 1 + local selection + "$get_selection" || return 1 + ((${#selection[*]}==2)) || return 1 + local comp_cword=0 comp_line=$_ble_edit_str comp_point=$_ble_edit_ind + local -a comp_words; comp_words=("$cmd") + local cmd=${_ble_edit_str:selection[0]:selection[1]-selection[0]} + ble/widget/command-help.impl "$cmd"; local ext=$? + ble/keymap:vi/adjust-command-mode + return "$ext" +} +function ble/widget/vi_xmap/command-help { + if ! ble/widget/vi_xmap/command-help.core; then + ble/widget/vi-command/bell + return 1 + fi +} +function ble/keymap:vi/set-up-command-map { + ble-bind -f 0 vi-command/append-arg + ble-bind -f 1 vi-command/append-arg + ble-bind -f 2 vi-command/append-arg + ble-bind -f 3 vi-command/append-arg + ble-bind -f 4 vi-command/append-arg + ble-bind -f 5 vi-command/append-arg + ble-bind -f 6 vi-command/append-arg + ble-bind -f 7 vi-command/append-arg + ble-bind -f 8 vi-command/append-arg + ble-bind -f 9 vi-command/append-arg + ble-bind -f y 'vi-command/operator y' + ble-bind -f d 'vi-command/operator d' + ble-bind -f c 'vi-command/operator c' + ble-bind -f '<' 'vi-command/operator indent-left' + ble-bind -f '>' 'vi-command/operator indent-right' + ble-bind -f '!' 'vi-command/operator filter' + ble-bind -f 'g ~' 'vi-command/operator toggle_case' + ble-bind -f 'g u' 'vi-command/operator u' + ble-bind -f 'g U' 'vi-command/operator U' + ble-bind -f 'g ?' 'vi-command/operator rot13' + ble-bind -f 'g q' 'vi-command/operator fold' + ble-bind -f 'g w' 'vi-command/operator fold-preserve-point' + ble-bind -f 'g @' 'vi-command/operator map' + ble-bind -f paste_begin vi-command/bracketed-paste + ble-bind -f 'home' vi-command/beginning-of-line + ble-bind -f '$' vi-command/forward-eol + ble-bind -f 'end' vi-command/forward-eol + ble-bind -f '^' vi-command/first-non-space + ble-bind -f '_' vi-command/first-non-space-forward + ble-bind -f '+' vi-command/forward-first-non-space + ble-bind -f 'C-m' vi-command/forward-first-non-space + ble-bind -f 'RET' vi-command/forward-first-non-space + ble-bind -f '-' vi-command/backward-first-non-space + ble-bind -f 'g 0' vi-command/beginning-of-graphical-line + ble-bind -f 'g home' vi-command/beginning-of-graphical-line + ble-bind -f 'g ^' vi-command/graphical-first-non-space + ble-bind -f 'g $' vi-command/graphical-forward-eol + ble-bind -f 'g end' vi-command/graphical-forward-eol + ble-bind -f 'g m' vi-command/middle-of-graphical-line + ble-bind -f 'g _' vi-command/last-non-space + ble-bind -f h vi-command/backward-char + ble-bind -f l vi-command/forward-char + ble-bind -f left vi-command/backward-char + ble-bind -f right vi-command/forward-char + ble-bind -f 'C-?' 'vi-command/backward-char wrap' + ble-bind -f 'DEL' 'vi-command/backward-char wrap' + ble-bind -f 'C-h' 'vi-command/backward-char wrap' + ble-bind -f 'BS' 'vi-command/backward-char wrap' + ble-bind -f SP 'vi-command/forward-char wrap' + ble-bind -f j vi-command/forward-line + ble-bind -f down vi-command/forward-line + ble-bind -f C-n vi-command/forward-line + ble-bind -f C-j vi-command/forward-line + ble-bind -f k vi-command/backward-line + ble-bind -f up vi-command/backward-line + ble-bind -f C-p vi-command/backward-line + ble-bind -f 'g j' vi-command/graphical-forward-line + ble-bind -f 'g down' vi-command/graphical-forward-line + ble-bind -f 'g k' vi-command/graphical-backward-line + ble-bind -f 'g up' vi-command/graphical-backward-line + ble-bind -f w vi-command/forward-vword + ble-bind -f W vi-command/forward-uword + ble-bind -f b vi-command/backward-vword + ble-bind -f B vi-command/backward-uword + ble-bind -f e vi-command/forward-vword-end + ble-bind -f E vi-command/forward-uword-end + ble-bind -f 'g e' vi-command/backward-vword-end + ble-bind -f 'g E' vi-command/backward-uword-end + ble-bind -f C-right vi-command/forward-vword + ble-bind -f S-right vi-command/forward-vword + ble-bind -f C-left vi-command/backward-vword + ble-bind -f S-left vi-command/backward-vword + ble-bind -f 'g o' vi-command/nth-byte + ble-bind -f '|' vi-command/nth-column + ble-bind -f H vi-command/nth-line + ble-bind -f L vi-command/nth-last-line + ble-bind -f 'g g' vi-command/history-beginning + ble-bind -f G vi-command/history-end + ble-bind -f C-home vi-command/first-nol + ble-bind -f C-end vi-command/last-eol + ble-bind -f 'f' vi-command/search-forward-char + ble-bind -f 'F' vi-command/search-backward-char + ble-bind -f 't' vi-command/search-forward-char-prev + ble-bind -f 'T' vi-command/search-backward-char-prev + ble-bind -f ';' vi-command/search-char-repeat + ble-bind -f ',' vi-command/search-char-reverse-repeat + ble-bind -f '%' 'vi-command/search-matchpair-or vi-command/percentage-line' + ble-bind -f 'C-\ C-n' nop + ble-bind -f ':' vi-command/commandline + ble-bind -f '/' vi-command/search-forward + ble-bind -f '?' vi-command/search-backward + ble-bind -f 'n' vi-command/search-repeat + ble-bind -f 'N' vi-command/search-reverse-repeat + ble-bind -f '*' vi-command/search-word-forward + ble-bind -f '#' vi-command/search-word-backward + ble-bind -f '`' 'vi-command/goto-mark' + ble-bind -f \' 'vi-command/goto-mark line' + ble-bind -c 'C-z' fg +} +function ble/widget/vi_omap/operator-rot13-or-search-backward { + if [[ $_ble_keymap_vi_opfunc == rot13 ]]; then + ble/widget/vi-command/operator rot13 + else + ble/widget/vi-command/search-backward + fi +} +function ble/widget/vi_omap/switch-visual-mode.impl { + local new_mode=$1 + local old=$_ble_keymap_vi_opfunc + [[ $old ]] || return 1 + local new=$old: + new=${new/:vi_char:/:} + new=${new/:vi_line:/:} + new=${new/:vi_block:/:} + [[ $new_mode ]] && new=$new:$new_mode + _ble_keymap_vi_opfunc=$new +} +function ble/widget/vi_omap/switch-to-charwise { + ble/widget/vi_omap/switch-visual-mode.impl vi_char +} +function ble/widget/vi_omap/switch-to-linewise { + ble/widget/vi_omap/switch-visual-mode.impl vi_line +} +function ble/widget/vi_omap/switch-to-blockwise { + ble/widget/vi_omap/switch-visual-mode.impl vi_block +} +function ble-decode/keymap:vi_omap/define { + ble/keymap:vi/set-up-command-map + ble-bind -f __default__ vi_omap/__default__ + ble-bind -f __line_limit__ nop + ble-bind -f 'ESC' vi_omap/cancel + ble-bind -f 'C-[' vi_omap/cancel + ble-bind -f 'C-c' vi_omap/cancel + ble-bind -f a vi-command/text-object + ble-bind -f i vi-command/text-object + ble-bind -f v vi_omap/switch-to-charwise + ble-bind -f V vi_omap/switch-to-linewise + ble-bind -f C-v vi_omap/switch-to-blockwise + ble-bind -f C-q vi_omap/switch-to-blockwise + ble-bind -f '~' 'vi-command/operator toggle_case' + ble-bind -f 'u' 'vi-command/operator u' + ble-bind -f 'U' 'vi-command/operator U' + ble-bind -f '?' 'vi_omap/operator-rot13-or-search-backward' + ble-bind -f 'q' 'vi-command/operator fold' +} +function ble/widget/vi-command/exit-on-empty-line { + if [[ $_ble_edit_str ]]; then + ble/widget/vi_nmap/forward-scroll + return "$?" + else + ble/widget/exit + ble/keymap:vi/adjust-command-mode # ジョブがあるときは終了しないので。 + return 1 + fi +} +function ble/widget/vi-command/show-line-info { + local index count + ble/history/get-index -v index + ble/history/get-count -v count + local hist_ratio=$(((100*index+count-1)/count))% + local hist_stat=$'!\e[32m'$index$'\e[m / \e[32m'$count$'\e[m (\e[32m'$hist_ratio$'\e[m)' + local ret + ble/string#count-char "$_ble_edit_str" $'\n'; local nline=$((ret+1)) + ble/string#count-char "${_ble_edit_str::_ble_edit_ind}" $'\n'; local iline=$((ret+1)) + local line_ratio=$(((100*iline+nline-1)/nline))% + local line_stat=$'line \e[34m'$iline$'\e[m / \e[34m'$nline$'\e[m --\e[34m'$line_ratio$'\e[m--' + ble/edit/info/show ansi "\"$hist_stat\" $line_stat" + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-command/cancel { + if [[ $_ble_keymap_vi_single_command ]]; then + _ble_keymap_vi_single_command= + _ble_keymap_vi_single_command_overwrite= + ble/keymap:vi/update-mode-name + else + local joblist; ble/util/joblist + if ((${#joblist[*]})); then + ble/array#push joblist $'Type \e[35m:q!\e[m and press \e[35m\e[m to abandon all \e[31mjobs\e[m and exit Bash' + IFS=$'\n' builtin eval 'ble/edit/info/show ansi "${joblist[*]}"' + else + ble/edit/info/show ansi $'Type \e[35m:q\e[m and press \e[35m\e[m to exit Bash' + fi + fi + ble/widget/vi-command/bell + return 0 +} +bleopt/declare -v keymap_vi_imap_undo '' +_ble_keymap_vi_undo_suppress= +function ble/keymap:vi/undo/add { + [[ $_ble_keymap_vi_undo_suppress ]] && return 0 + [[ $1 == more && $bleopt_keymap_vi_imap_undo != more ]] && return 0 + ble-edit/undo/add +} +function ble/widget/vi_nmap/undo { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local _ble_keymap_vi_undo_suppress=1 + ble/keymap:vi/mark/start-edit-area + if ble-edit/undo/undo "$ARG"; then + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/adjust-command-mode + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/widget/vi_nmap/redo { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local _ble_keymap_vi_undo_suppress=1 + ble/keymap:vi/mark/start-edit-area + if ble-edit/undo/redo "$ARG"; then + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/adjust-command-mode + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/widget/vi_nmap/revert { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local _ble_keymap_vi_undo_suppress=1 + ble/keymap:vi/mark/start-edit-area + if ble-edit/undo/revert-toggle "$ARG"; then + ble/keymap:vi/needs-eol-fix && ((_ble_edit_ind--)) + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/adjust-command-mode + else + ble/widget/vi-command/bell + return 1 + fi +} +function ble/widget/vi_nmap/increment.impl { + local delta=$1 + ((delta==0)) && return 0 + local line=${_ble_edit_str:_ble_edit_ind} + line=${line%%$'\n'*} + local rex='^([^0-9]*)[0-9]+' + if ! [[ $line =~ $rex ]]; then + [[ $line ]] && ble/widget/.bell 'number not found' + ble/keymap:vi/adjust-command-mode + return 0 + fi + local rematch1=${BASH_REMATCH[1]} + local beg=$((_ble_edit_ind+${#rematch1})) + local end=$((_ble_edit_ind+${#BASH_REMATCH})) + rex='-?[0-9]*$'; [[ ${_ble_edit_str::beg} =~ $rex ]] + ((beg-=${#BASH_REMATCH})) + local number=${_ble_edit_str:beg:end-beg} + local abs=${number#-} + if [[ $abs == 0?* ]]; then + if [[ $number == -* ]]; then + number=-$((10#0$abs)) + else + number=$((10#0$abs)) + fi + fi + ((number+=delta)) + if [[ $abs == 0?* ]]; then + local wsign=$((number<0?1:0)) + local zpad=$((wsign+${#abs}-${#number})) + if ((zpad>0)); then + local ret; ble/string#repeat 0 "$zpad" + number=${number::wsign}$ret${number:wsign} + fi + fi + ble/widget/.replace-range "$beg" "$end" "$number" + ble/keymap:vi/mark/set-previous-edit-area "$beg" $((beg+${#number})) + ble/keymap:vi/repeat/record + _ble_edit_ind=$((beg+${#number}-1)) + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi_nmap/increment { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/increment.impl "$ARG" +} +function ble/widget/vi_nmap/decrement { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/widget/vi_nmap/increment.impl $((-ARG)) +} +function ble/widget/vi_nmap/__line_limit__.edit { + ble/keymap:vi/clear-arg + ble/widget/vi_nmap/.insert-mode + ble/keymap:vi/repeat/clear-insert + ble/widget/edit-and-execute-command.impl "$1" +} +function ble/widget/vi_nmap/__line_limit__ { + ble/widget/__line_limit__ vi_nmap/__line_limit__.edit +} +function ble-decode/keymap:vi_nmap/define { + ble/keymap:vi/set-up-command-map + ble-bind -f __default__ vi-command/decompose-meta + ble-bind -f __line_limit__ vi_nmap/__line_limit__ + ble-bind -f 'ESC' vi-command/bell + ble-bind -f 'C-[' vi-command/bell + ble-bind -f 'C-c' vi-command/cancel + ble-bind -f a vi_nmap/append-mode + ble-bind -f A vi_nmap/append-mode-at-end-of-line + ble-bind -f i vi_nmap/insert-mode + ble-bind -f insert vi_nmap/insert-mode + ble-bind -f I vi_nmap/insert-mode-at-first-non-space + ble-bind -f 'g I' vi_nmap/insert-mode-at-beginning-of-line + ble-bind -f o vi_nmap/insert-mode-at-forward-line + ble-bind -f O vi_nmap/insert-mode-at-backward-line + ble-bind -f R vi_nmap/replace-mode + ble-bind -f 'g R' vi_nmap/virtual-replace-mode + ble-bind -f 'g i' vi_nmap/insert-mode-at-previous-point + ble-bind -f '~' vi_nmap/forward-char-toggle-case + ble-bind -f Y vi_nmap/copy-current-line + ble-bind -f S vi_nmap/kill-current-line-and-insert + ble-bind -f D vi_nmap/kill-forward-line + ble-bind -f C vi_nmap/kill-forward-line-and-insert + ble-bind -f p vi_nmap/paste-after + ble-bind -f P vi_nmap/paste-before + ble-bind -f x vi_nmap/kill-forward-char + ble-bind -f s vi_nmap/kill-forward-char-and-insert + ble-bind -f X vi_nmap/kill-backward-char + ble-bind -f delete vi_nmap/kill-forward-char + ble-bind -f 'r' vi_nmap/replace-char + ble-bind -f 'g r' vi_nmap/virtual-replace-char # vim で実際に試すとこの機能はない + ble-bind -f J vi_nmap/connect-line-with-space + ble-bind -f 'g J' vi_nmap/connect-line + ble-bind -f v vi_nmap/charwise-visual-mode + ble-bind -f V vi_nmap/linewise-visual-mode + ble-bind -f C-v vi_nmap/blockwise-visual-mode + ble-bind -f C-q vi_nmap/blockwise-visual-mode + ble-bind -f 'g v' vi-command/previous-visual-area + ble-bind -f 'g h' vi_nmap/charwise-select-mode + ble-bind -f 'g H' vi_nmap/linewise-select-mode + ble-bind -f 'g C-h' vi_nmap/blockwise-select-mode + ble-bind -f . vi_nmap/repeat + ble-bind -f K vi_nmap/command-help + ble-bind -f f1 vi_nmap/command-help + ble-bind -f 'C-d' vi_nmap/forward-line-scroll + ble-bind -f 'C-u' vi_nmap/backward-line-scroll + ble-bind -f 'C-e' vi_nmap/forward-scroll + ble-bind -f 'C-y' vi_nmap/backward-scroll + ble-bind -f 'C-f' vi_nmap/pagedown + ble-bind -f 'next' vi_nmap/pagedown + ble-bind -f 'C-b' vi_nmap/pageup + ble-bind -f 'prior' vi_nmap/pageup + ble-bind -f 'z t' vi_nmap/scroll-to-top-and-redraw + ble-bind -f 'z z' vi_nmap/scroll-to-center-and-redraw + ble-bind -f 'z b' vi_nmap/scroll-to-bottom-and-redraw + ble-bind -f 'z RET' vi_nmap/scroll-to-top-non-space-and-redraw + ble-bind -f 'z C-m' vi_nmap/scroll-to-top-non-space-and-redraw + ble-bind -f 'z +' vi_nmap/scroll-or-pagedown-and-redraw + ble-bind -f 'z -' vi_nmap/scroll-to-bottom-non-space-and-redraw + ble-bind -f 'z .' vi_nmap/scroll-to-center-non-space-and-redraw + ble-bind -f m vi-command/set-mark + ble-bind -f '"' vi-command/register + ble-bind -f 'C-g' vi-command/show-line-info + ble-bind -f 'q' vi_nmap/record-register + ble-bind -f '@' vi_nmap/play-register + ble-bind -f u vi_nmap/undo + ble-bind -f C-r vi_nmap/redo + ble-bind -f U vi_nmap/revert + ble-bind -f C-a vi_nmap/increment + ble-bind -f C-x vi_nmap/decrement + ble-bind -f 'Z Z' 'vi-command:q' + ble-bind -f 'Z Q' 'vi-command:q' + ble-bind -f 'C-j' 'accept-line' + ble-bind -f 'C-RET' 'accept-line' + ble-bind -f 'C-m' 'accept-single-line-or vi-command/forward-first-non-space' + ble-bind -f 'RET' 'accept-single-line-or vi-command/forward-first-non-space' + ble-bind -f 'C-l' 'clear-screen' + ble-bind -f 'C-d' 'vi-command/exit-on-empty-line' # overwrites vi_nmap/forward-scroll + ble-bind -f 'auto_complete_enter' auto-complete-enter + ble-bind -f M-left 'vi-command/backward-vword' + ble-bind -f M-right 'vi-command/forward-vword' + ble-bind -f C-delete 'vi-rlfunc/kill-word' + ble-bind -f '#' 'vi-rlfunc/insert-comment' + ble-bind -f '&' 'vi_nmap/@edit tilde-expand' +} +function ble/widget/vi-rlfunc/.is-uppercase { + local n=${#KEYS[@]} + local code=$((KEYS[n?n-1:0]&_ble_decode_MaskChar)) + ((0x41<=code&&code<=0x5a)) +} +function ble/widget/vi-rlfunc/delete-to { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi_nmap/kill-forward-line + else + ble/widget/vi-command/operator d + fi +} +function ble/widget/vi-rlfunc/change-to { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi_nmap/kill-forward-line-and-insert + else + ble/widget/vi-command/operator c + fi +} +function ble/widget/vi-rlfunc/yank-to { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi_nmap/copy-current-line + else + ble/widget/vi-command/operator y + fi +} +function ble/widget/vi-rlfunc/char-search { + local n=${#KEYS[@]} + local code=$((KEYS[n?n-1:0]&_ble_decode_MaskChar)) + ((code==0)) && return 1 + ble/util/c2s "$code" + case $ret in + ('f') ble/widget/vi-command/search-forward-char ;; + ('F') ble/widget/vi-command/search-backward-char ;; + ('t') ble/widget/vi-command/search-forward-char-prev ;; + ('T') ble/widget/vi-command/search-backward-char-prev ;; + (';') ble/widget/vi-command/search-char-repeat ;; + (',') ble/widget/vi-command/search-char-reverse-repeat ;; + (*) return 1 ;; + esac +} +function ble/widget/vi-rlfunc/next-word { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi-command/forward-uword + else + ble/widget/vi-command/forward-vword + fi +} +function ble/widget/vi-rlfunc/prev-word { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi-command/backward-uword + else + ble/widget/vi-command/backward-vword + fi +} +function ble/widget/vi-rlfunc/end-word { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi-command/forward-uword-end + else + ble/widget/vi-command/forward-vword-end + fi +} +function ble/widget/vi-rlfunc/put { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi_nmap/paste-before + else + ble/widget/vi_nmap/paste-after + fi +} +function ble/widget/vi-rlfunc/search { + local n=${#KEYS[@]} + local code=$((KEYS[n?n-1:0]&_ble_decode_MaskChar)) + if ((code==63)); then + ble/widget/vi-command/search-backward + else + ble/widget/vi-command/search-forward + fi +} +function ble/widget/vi-rlfunc/search-again { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi-command/search-reverse-repeat + else + ble/widget/vi-command/search-repeat + fi +} +function ble/widget/vi-rlfunc/subst { + if ble/widget/vi-rlfunc/.is-uppercase; then + ble/widget/vi_nmap/kill-current-line-and-insert + else + ble/widget/vi_nmap/kill-forward-char-and-insert + fi +} +function ble/widget/vi-rlfunc/kill-word { + _ble_keymap_vi_opfunc=d + ble/widget/vi-command/forward-vword-end +} +function ble/widget/vi-rlfunc/unix-line-discard { + _ble_keymap_vi_opfunc=d + ble/widget/vi-command/beginning-of-line +} +function ble/widget/vi-rlfunc/insert-comment { + local ARG FLAG REG; ble/keymap:vi/get-arg '' + ble/keymap:vi/mark/start-edit-area + ble/widget/insert-comment/.insert "$ARG" + ble/keymap:vi/mark/end-edit-area + ble/widget/vi_nmap/accept-line +} +function ble/widget/vi-rlfunc/quoted-insert-char.hook { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/keymap:vi/mark/start-edit-area + _ble_edit_arg=$ARG ble/widget/quoted-insert-char.hook + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-rlfunc/quoted-insert-char { + _ble_edit_mark_active= + _ble_decode_char__hook=ble/widget/vi-rlfunc/quoted-insert-char.hook + return 147 +} +function ble/widget/vi-rlfunc/quoted-insert.hook { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/keymap:vi/mark/start-edit-area + _ble_edit_arg=$ARG ble/widget/quoted-insert.hook + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record + ble/keymap:vi/adjust-command-mode + return 0 +} +function ble/widget/vi-rlfunc/quoted-insert { + _ble_edit_mark_active= + _ble_decode_key__hook=ble/widget/vi-rlfunc/quoted-insert.hook + return 147 +} +function ble/widget/vi-rlfunc/eof-maybe { + if [[ ! $_ble_edit_str ]]; then + ble/widget/exit + ble/keymap:vi/adjust-command-mode # ジョブがあるときは終了しないので。 + return 1 + elif ble-edit/is-single-complete-line; then + ble/widget/vi_nmap/accept-line + else + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + ble/keymap:vi/mark/start-edit-area + _ble_edit_ind=${#_ble_edit_str} + _ble_edit_arg=$ARG + ble/widget/self-insert + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/adjust-command-mode + fi +} +function ble/widget/vi-rlfunc/yank-arg { + ble/widget/vi_nmap/append-mode + ble/keymap:vi/imap-repeat/reset + local -a KEYS; KEYS=(32) + ble/widget/self-insert + ble/util/unlocal KEYS + ble/widget/insert-last-argument + return "$?" +} +function ble/widget/vi-command/forward-byte { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local index=$_ble_edit_ind + ble/widget/.locate-forward-byte "$ARG" || [[ $FLAG ]] || ble/widget/.bell + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" +} +function ble/widget/vi-command/backward-byte { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local index=$_ble_edit_ind + ble/widget/.locate-forward-byte $((-ARG)) || [[ $FLAG ]] || ble/widget/.bell + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" +} +function ble/widget/vi_nmap/capitalize-XWORD { ble/widget/filter-word.impl XWORD ble/string#capitalize; } +function ble/widget/vi_nmap/downcase-XWORD { ble/widget/filter-word.impl XWORD ble/string#tolower; } +function ble/widget/vi_nmap/upcase-XWORD { ble/widget/filter-word.impl XWORD ble/string#toupper; } +function ble/widget/vi_nmap/@edit { + ble/keymap:vi/clear-arg + ble/keymap:vi/repeat/record + ble/keymap:vi/mark/start-edit-area + ble/widget/"$@" + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi_nmap/@adjust { + ble/keymap:vi/clear-arg + ble/widget/"$@" + ble/keymap:vi/adjust-command-mode +} +function ble/widget/vi_nmap/@motion { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local _ble_edit_ind=$_ble_edit_ind _ble_edit_arg=$ARG + if ble/widget/"$@"; then + local index=$_ble_edit_ind + ble/util/unlocal _ble_edit_ind + ble/widget/vi-command/exclusive-goto.impl "$index" "$FLAG" "$REG" nobell + else + ble/keymap:vi/adjust-command-mode + fi +} +function ble/keymap:vi/xmap/has-eol-extension { + [[ $_ble_edit_mark_active == *+ ]] +} +function ble/keymap:vi/xmap/add-eol-extension { + [[ $_ble_edit_mark_active ]] && + _ble_edit_mark_active=${_ble_edit_mark_active%+}+ +} +function ble/keymap:vi/xmap/remove-eol-extension { + [[ $_ble_edit_mark_active ]] && + _ble_edit_mark_active=${_ble_edit_mark_active%+} +} +function ble/keymap:vi/xmap/switch-type { + local suffix; [[ $_ble_edit_mark_active == *+ ]] && suffix=+ + _ble_edit_mark_active=$1$suffix +} +function ble/keymap:vi/get-graphical-rectangle { + local p=${1:-$_ble_edit_mark} q=${2:-$_ble_edit_ind} + local ret + ble-edit/content/find-logical-bol "$p"; p0=$ret + ble-edit/content/find-logical-bol "$q"; q0=$ret + local p0x p0y q0x q0y + ble/textmap#getxy.out --prefix=p0 "$p0" + ble/textmap#getxy.out --prefix=q0 "$q0" + local plx ply qlx qly + ble/textmap#getxy.cur --prefix=pl "$p" + ble/textmap#getxy.cur --prefix=ql "$q" + local prx=$plx pry=$ply qrx=$qlx qry=$qly + ble-edit/content/eolp "$p" && ((prx++)) || ble/textmap#getxy.out --prefix=pr $((p+1)) + ble-edit/content/eolp "$q" && ((qrx++)) || ble/textmap#getxy.out --prefix=qr $((q+1)) + ((ply-=p0y,qly-=q0y,pry-=p0y,qry-=q0y, + (plyqry||pry==qry&&prx>qrx)?(rx=prx,ry=pry):(rx=qrx,ry=qry))) +} +function ble/keymap:vi/get-logical-rectangle { + local p=${1:-$_ble_edit_mark} q=${2:-$_ble_edit_ind} + local ret + ble-edit/content/find-logical-bol "$p"; p0=$ret + ble-edit/content/find-logical-bol "$q"; q0=$ret + ((p-=p0,q-=q0,p<=q)) || local p=$q q=$p + lx=$p rx=$((q+1)) ly=0 ry=0 +} +function ble/keymap:vi/get-rectangle { + if ble/edit/use-textmap; then + ble/keymap:vi/get-graphical-rectangle "$@" + else + ble/keymap:vi/get-logical-rectangle "$@" + fi +} +function ble/keymap:vi/get-rectangle-height { + local p0 q0 lx ly rx ry + ble/keymap:vi/get-rectangle "$@" + ble/string#count-char "${_ble_edit_str:p0:q0-p0}" $'\n' + ((ret++)) + return 0 +} +function ble/keymap:vi/extract-graphical-block-by-geometry { + local bol1=$1 bol2=$2 x1=$3 x2=$4 y1=0 y2=0 opts=$5 + ((bol1<=bol2||(bol1=$2,bol2=$1))) + [[ $x1 == *:* ]] && local x1=${x1%%:*} y1=${x1#*:} + [[ $x2 == *:* ]] && local x2=${x2%%:*} y2=${x2#*:} + local cols=$_ble_textmap_cols + local c1=$((cols*y1+x1)) c2=$((cols*y2+x2)) + sub_x1=$c1 sub_x2=$c2 + local ret index lx ly rx ly + ble-edit/content/find-logical-eol "$bol2"; local eol2=$ret + local lines; ble/string#split-lines lines "${_ble_edit_str:bol1:eol2-bol1}" + sub_ranges=() + local min_sfill=0 + local line bol=$bol1 eol bolx boly + local c1l c1r c2l c2r + for line in "${lines[@]}"; do + ((eol=bol+${#line})) + if [[ :$opts: == *:first_line:* ]] && ((${#sub_ranges[@]})); then + ble/array#push sub_ranges ::::: + elif [[ :$opts: == *:skip_middle:* ]] && ((0<${#sub_ranges[@]}&&${#sub_ranges[@]}<${#lines[@]}-1)); then + ble/array#push sub_ranges ::::: + else + ble/textmap#getxy.out --prefix=bol "$bol" + ble/textmap#hit out "$x1" $((boly+y1)) "$bol" "$eol" + local smin=$index x1l=$lx y1l=$ly x1r=$rx y1r=$ry + if ble/keymap:vi/xmap/has-eol-extension; then + local eolx eoly; ble/textmap#getxy.out --prefix=eol "$eol" + local smax=$eol x2l=$eolx y2l=$eoly x2r=$eolx y2r=$eoly + else + ble/textmap#hit out "$x2" $((boly+y2)) "$bol" "$eol" + local smax=$index x2l=$lx y2l=$ly x2r=$rx y2r=$ry + fi + local sfill=0 slpad=0 srpad=0 + local stext=${_ble_edit_str:smin:smax-smin} + if ((sminc1))' || ((c1r=c1)) + ble/string#repeat ' ' $((c1r-c1)) + stext=$ret${stext:1} + fi + ((c2l=(y2l-boly)*cols+x2l)) + if ((c2lc2))' || ((c2r=c2)) + ((srpad=c2r-c2)) + fi + elif ((c2l>c2)); then + ((sfill=c2-c2l, + sfillc1)); then + ble/string#repeat ' ' $((c2-c1)) + stext=$ret${stext:1} + ((smax++)) + ((c1l=(y1l-boly)*cols+x1l,slpad=c1-c1l)) + ((c1r=(y1r-boly)*cols+x1r,srpad=c1r-c1)) + fi + fi + ble/array#push sub_ranges "$smin:$smax:$slpad:$srpad:$sfill:$stext" + fi + ((bol=eol+1)) + done + if ((min_sfill<0)); then + local isub=${#sub_ranges[@]} + while ((isub--)); do + local sub=${sub_ranges[isub]} + local sub45=${sub#*:*:*:*:} + local sfill=${sub45%%:*} + sub_ranges[isub]=${sub::${#sub}-${#sub45}}$((sfill-min_sfill))${sub45:${#sfill}} + done + fi +} +function ble/keymap:vi/extract-graphical-block { + local opts=$3 + local p0 q0 lx ly rx ry + ble/keymap:vi/get-graphical-rectangle "$@" + ble/keymap:vi/extract-graphical-block-by-geometry "$p0" "$q0" "$lx:$ly" "$rx:$ry" "$opts" +} +function ble/keymap:vi/extract-logical-block-by-geometry { + local bol1=$1 bol2=$2 x1=$3 x2=$4 opts=$5 + ((bol1<=bol2||(bol1=$2,bol2=$1))) + sub_x1=$c1 sub_x2=$c2 + local ret min_sfill=0 + local bol=$bol1 eol smin smax slpad srpad sfill + sub_ranges=() + while :; do + ble-edit/content/find-logical-eol "$bol"; eol=$ret + slpad=0 srpad=0 sfill=0 + ((smin=bol+x1,smin>eol&&(smin=eol))) + if ble/keymap:vi/xmap/has-eol-extension; then + ((smax=eol, + sfill=bol+x2-eol, + sfilleol&&(sfill=smax-eol,smax=eol))) + fi + local stext=${_ble_edit_str:smin:smax-smin} + ble/array#push sub_ranges "$smin:$smax:$slpad:$srpad:$sfill:$stext" + ((bol>=bol2)) && break + ble-edit/content/find-logical-bol "$bol" 1; bol=$ret + done + if ((min_sfill<0)); then + local isub=${#sub_ranges[@]} + while ((isub--)); do + local sub=${sub_ranges[isub]} + local sub45=${sub#*:*:*:*:} + local sfill=${sub45%%:*} + sub_ranges[isub]=${sub::${#sub}-${#sub45}}$((sfill-min_sfill))${sub45:${#sfill}} + done + fi +} +function ble/keymap:vi/extract-logical-block { + local opts=$3 + local p0 q0 lx ly rx ry + ble/keymap:vi/get-logical-rectangle "$@" + ble/keymap:vi/extract-logical-block-by-geometry "$p0" "$q0" "$lx" "$rx" "$opts" +} +function ble/keymap:vi/extract-block { + if ble/edit/use-textmap; then + ble/keymap:vi/extract-graphical-block "$@" + else + ble/keymap:vi/extract-logical-block "$@" + fi +} +function ble/highlight/layer:region/mark:vi_char/get-selection { + local rmin rmax + if ((_ble_edit_mark<_ble_edit_ind)); then + rmin=$_ble_edit_mark rmax=$_ble_edit_ind + else + rmin=$_ble_edit_ind rmax=$_ble_edit_mark + fi + ble-edit/content/eolp "$rmax" || ((rmax++)) + selection=("$rmin" "$rmax") +} +function ble/highlight/layer:region/mark:vi_line/get-selection { + local rmin rmax + if ((_ble_edit_mark<_ble_edit_ind)); then + rmin=$_ble_edit_mark rmax=$_ble_edit_ind + else + rmin=$_ble_edit_ind rmax=$_ble_edit_mark + fi + local ret + ble-edit/content/find-logical-bol "$rmin"; rmin=$ret + ble-edit/content/find-logical-eol "$rmax"; rmax=$ret + selection=("$rmin" "$rmax") +} +function ble/highlight/layer:region/mark:vi_block/get-selection { + local sub_ranges sub_x1 sub_x2 + ble/keymap:vi/extract-block + selection=() + local sub + for sub in "${sub_ranges[@]}"; do + ble/string#split sub : "$sub" + ((sub[0]0)) || arg=1 + local prev; ble/string#split prev : "$_ble_keymap_vi_xmap_prev_edit" + _ble_edit_mark_active=${prev[0]:-vi_char} + local nchar=${prev[1]:-1} + local nline=${prev[2]:-1} + ((nchar<1&&(nchar=1),nline<1&&(nline=1))) + local is_x_relative=0 + if [[ ${_ble_edit_mark_active%+} == vi_block ]]; then + ((is_x_relative=1,nchar*=arg,nline*=arg)) + elif [[ ${_ble_edit_mark_active%+} == vi_line ]]; then + ((nline*=arg,is_x_relative=1,nchar=1)) + else + ((nline==1?(is_x_relative=1,nchar*=arg):(nline*=arg))) + fi + ((nchar--,nline--)) + local index ret + ble-edit/content/find-logical-bol "$_ble_edit_ind" 0; local b1=$ret + ble-edit/content/find-logical-bol "$_ble_edit_ind" "$nline"; local b2=$ret + ble-edit/content/find-logical-eol "$b2"; local e2=$ret + if ble/keymap:vi/xmap/has-eol-extension; then + index=$e2 + elif ble/edit/use-textmap; then + local cols=$_ble_textmap_cols + local b1x b1y b2x b2y x y + ble/textmap#getxy.out --prefix=b1 "$b1" + ble/textmap#getxy.out --prefix=b2 "$b2" + if ((is_x_relative)); then + ble/textmap#getxy.out "$_ble_edit_ind" + local c=$((x+(y-b1y)*cols+nchar)) + else + local c=$nchar + fi + ((y=c/cols,x=c%cols)) + local lx ly rx ry + ble/textmap#hit out "$x" $((b2y+y)) "$b2" "$e2" + else + local c=$((is_x_relative?_ble_edit_ind-b1+nchar:nchar)) + ((index=b2+c,index>e2&&(index=e2))) + fi + _ble_edit_mark=$_ble_edit_ind + _ble_edit_ind=$index +} +_ble_keymap_vi_xmap_prev_visual= +ble/array#push _ble_textarea_local_VARNAMES \ + _ble_keymap_vi_xmap_prev_visual +function ble/keymap:vi/xmap/set-previous-visual-area { + local beg end + local mark_type=${_ble_edit_mark_active%+} + if [[ $mark_type == vi_block ]]; then + local sub_ranges sub_x1 sub_x2 + ble/keymap:vi/extract-block + local nrange=${#sub_ranges[*]} + ((nrange)) || return 1 + local beg=${sub_ranges[0]%%:*} + local sub2_slice1=${sub_ranges[nrange-1]#*:} + local end=${sub2_slice1%%:*} + ((beg +} +function ble/widget/vi-command/previous-visual-area { + local mark=$_ble_keymap_vi_xmap_prev_visual + local ret beg= end= + ble/keymap:vi/mark/get-local-mark 60 && beg=$ret # `< + ble/keymap:vi/mark/get-local-mark 62 && end=$ret # `> + [[ $beg && $end ]] || return 1 + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + ble/keymap:vi/clear-arg + ble/keymap:vi/xmap/set-previous-visual-area + _ble_edit_ind=$end + _ble_edit_mark=$beg + _ble_edit_mark_active=$mark + ble/keymap:vi/update-mode-name + else + ble/keymap:vi/clear-arg + ble/widget/vi-command/visual-mode.impl vi_xmap "$mark" + _ble_edit_ind=$end + _ble_edit_mark=$beg + fi + return 0 +} +function ble/widget/vi-command/visual-mode.impl { + local keymap=$1 visual_type=$2 + local ARG FLAG REG; ble/keymap:vi/get-arg 0 + if [[ $FLAG ]]; then + ble/widget/vi-command/bell + return 1 + fi + _ble_edit_overwrite_mode= + _ble_edit_mark=$_ble_edit_ind + _ble_edit_mark_active=$visual_type + _ble_keymap_vi_xmap_insert_data= # ※矩形挿入の途中で更に xmap に入ったときはキャンセル + ((ARG)) && ble/widget/vi_xmap/.restore-visual-state "$ARG" + ble/decode/keymap/push "$keymap" + ble/keymap:vi/update-mode-name + return 0 +} +function ble/widget/vi_nmap/charwise-visual-mode { + ble/widget/vi-command/visual-mode.impl vi_xmap vi_char +} +function ble/widget/vi_nmap/linewise-visual-mode { + ble/widget/vi-command/visual-mode.impl vi_xmap vi_line +} +function ble/widget/vi_nmap/blockwise-visual-mode { + ble/widget/vi-command/visual-mode.impl vi_xmap vi_block +} +function ble/widget/vi_nmap/charwise-select-mode { + ble/widget/vi-command/visual-mode.impl vi_smap vi_char +} +function ble/widget/vi_nmap/linewise-select-mode { + ble/widget/vi-command/visual-mode.impl vi_smap vi_line +} +function ble/widget/vi_nmap/blockwise-select-mode { + ble/widget/vi-command/visual-mode.impl vi_smap vi_block +} +function ble/widget/vi_xmap/exit { + if [[ $_ble_decode_keymap == vi_[xs]map ]]; then + ble/keymap:vi/xmap/set-previous-visual-area + _ble_edit_mark_active= + ble/decode/keymap/pop + ble/keymap:vi/update-mode-name + ble/keymap:vi/adjust-command-mode + fi + return 0 +} +function ble/widget/vi_xmap/cancel { + _ble_keymap_vi_single_command= + _ble_keymap_vi_single_command_overwrite= + ble-edit/content/nonbol-eolp && ((_ble_edit_ind--)) + ble/widget/vi_xmap/exit +} +function ble/widget/vi_xmap/switch-visual-mode.impl { + local visual_type=$1 + local ARG FLAG REG; ble/keymap:vi/get-arg 0 + if [[ $FLAG ]]; then + ble/widget/.bell + return 1 + fi + if [[ ${_ble_edit_mark_active%+} == "$visual_type" ]]; then + ble/widget/vi_xmap/cancel + else + ble/keymap:vi/xmap/switch-type "$visual_type" + ble/keymap:vi/update-mode-name + return 0 + fi +} +function ble/widget/vi_xmap/switch-to-charwise { + ble/widget/vi_xmap/switch-visual-mode.impl vi_char +} +function ble/widget/vi_xmap/switch-to-linewise { + ble/widget/vi_xmap/switch-visual-mode.impl vi_line +} +function ble/widget/vi_xmap/switch-to-blockwise { + ble/widget/vi_xmap/switch-visual-mode.impl vi_block +} +function ble/widget/vi_xmap/switch-to-select { + if [[ $_ble_decode_keymap == vi_xmap ]]; then + ble/decode/keymap/pop + ble/decode/keymap/push vi_smap + ble/keymap:vi/update-mode-name + fi +} +function ble/widget/vi_xmap/switch-to-visual { + if [[ $_ble_decode_keymap == vi_smap ]]; then + ble/decode/keymap/pop + ble/decode/keymap/push vi_xmap + ble/keymap:vi/update-mode-name + fi +} +function ble/widget/vi_xmap/switch-to-visual-blockwise { + if [[ $_ble_decode_keymap == vi_smap ]]; then + ble/decode/keymap/pop + ble/decode/keymap/push vi_xmap + fi + if [[ ${_ble_edit_mark_active%+} != vi_block ]]; then + ble/widget/vi_xmap/switch-to-blockwise + else + xble/keymap:vi/update-mode-name + fi +} +bleopt/declare -v keymap_vi_keymodel '' +function ble/widget/vi_smap/@nomarked { + [[ ,$bleopt_keymap_vi_keymodel, == *,stopsel,* ]] && + ble/widget/vi_xmap/exit + ble/widget/"$@" +} +function ble/widget/vi_smap/self-insert { + ble/widget/vi-command/operator c + ble/widget/self-insert +} +function ble/widget/vi_xmap/exchange-points { + ble/keymap:vi/xmap/remove-eol-extension + ble/widget/exchange-point-and-mark + return 0 +} +function ble/widget/vi_xmap/exchange-boundaries { + if [[ ${_ble_edit_mark_active%+} == vi_block ]]; then + ble/keymap:vi/xmap/remove-eol-extension + local sub_ranges sub_x1 sub_x2 + ble/keymap:vi/extract-block '' '' skip_middle + local nline=${#sub_ranges[@]} + ble/util/assert '((nline))' + local data1; ble/string#split data1 : "${sub_ranges[0]}" + local lpos1=${data1[0]} rpos1=$((data1[4]?data1[1]:data1[1]-1)) + if ((nline==1)); then + local lpos2=$lpos1 rpos2=$rpos1 + else + local data2; ble/string#split data2 : "${sub_ranges[nline-1]}" + local lpos2=${data2[0]} rpos2=$((data2[4]?data2[1]:data2[1]-1)) + fi + if ! ((lpos2<=_ble_edit_ind&&_ble_edit_ind<=rpos2)); then + local lpos1=$lpos2 lpos2=$lpos1 + local rpos1=$rpos2 rpos2=$rpos1 + fi + _ble_edit_mark=$((_ble_edit_mark==lpos1?rpos1:lpos1)) + _ble_edit_ind=$((_ble_edit_ind==lpos2?rpos2:lpos2)) + return 0 + else + ble/widget/vi_xmap/exchange-points + fi +} +function ble/widget/vi_xmap/visual-replace-char.hook { + local key=$1 + _ble_edit_overwrite_mode= + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local ret + if [[ $FLAG ]]; then + ble/widget/.bell + return 1 + elif ((key==(_ble_decode_Ctrl|91))); then # C-[ -> cancel + return 27 + elif ! ble/keymap:vi/k2c "$key"; then + ble/widget/.bell + return 1 + fi + local c=$ret + ble/util/c2s "$c"; local s=$ret + local old_mark_active=$_ble_edit_mark_active # save + local mark_type=${_ble_edit_mark_active%+} + ble/widget/vi_xmap/.save-visual-state + ble/widget/vi_xmap/exit # Note: _ble_edit_mark_active will be cleared here + if [[ $mark_type == vi_block ]]; then + ble/util/c2w "$c"; local w=$ret + ((w<=0)) && w=1 + local sub_ranges sub_x1 sub_x2 + _ble_edit_mark_active=$old_mark_active ble/keymap:vi/extract-block + local n=${#sub_ranges[@]} + if ((n==0)); then + ble/widget/.bell + return 1 + fi + local width=$((sub_x2-sub_x1)) + local count=$((width/w)) + ble/string#repeat "$s" "$count"; local ins=$ret + local pad=$((width-count*w)) + if ((pad)); then + ble/string#repeat ' ' "$pad"; ins=$ins$ret + fi + local i=$n sub smin=0 + ble/keymap:vi/mark/start-edit-area + while ((i--)); do + ble/string#split sub : "${sub_ranges[i]}" + local smin=${sub[0]} smax=${sub[1]} + local slpad=${sub[2]} srpad=${sub[3]} sfill=${sub[4]} + local ins1=$ins + ((sfill)) && ins1=${ins1::(width-sfill)/w} + ((slpad)) && { ble/string#repeat ' ' "$slpad"; ins1=$ret$ins1; } + ((srpad)) && { ble/string#repeat ' ' "$srpad"; ins1=$ins1$ret; } + ble/widget/.replace-range "$smin" "$smax" "$ins1" + done + local beg=$smin + ble/keymap:vi/needs-eol-fix "$beg" && ((beg--)) + _ble_edit_ind=$beg + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record + else + local beg=$_ble_edit_mark end=$_ble_edit_ind + ((beg<=end)) || local beg=$end end=$beg + if [[ $mark_type == vi_line ]]; then + ble-edit/content/find-logical-bol "$beg"; local beg=$ret + ble-edit/content/find-logical-eol "$end"; local end=$ret + else + ble-edit/content/eolp "$end" || ((end++)) + fi + local ins=${_ble_edit_str:beg:end-beg} + ins=${ins//[!$'\n']/"$s"} + ble/widget/.replace-range "$beg" "$end" "$ins" + ble/keymap:vi/needs-eol-fix "$beg" && ((beg--)) + _ble_edit_ind=$beg + ble/keymap:vi/mark/set-previous-edit-area "$beg" "$end" + ble/keymap:vi/repeat/record + fi + return 0 +} +function ble/widget/vi_xmap/visual-replace-char { + _ble_edit_overwrite_mode=R + ble/keymap:vi/async-read-char ble/widget/vi_xmap/visual-replace-char.hook +} +function ble/widget/vi_xmap/linewise-operator.impl { + local op=$1 opts=$2 + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + if [[ $FLAG ]]; then + ble/widget/.bell 'wrong keymap: xmap ではオペレータは設定されないはず' + return 1 + fi + local mark_type=${_ble_edit_mark_active%+} + local beg=$_ble_edit_mark end=$_ble_edit_ind + ((beg<=end)) || local beg=$end end=$beg + local call_operator= + if [[ :$opts: != *:force_line:* && $mark_type == vi_block ]]; then + call_operator=ble/keymap:vi/call-operator-blockwise + _ble_edit_mark_active=vi_block + [[ :$opts: == *:extend:* ]] && _ble_edit_mark_active=vi_block+ + else + call_operator=ble/keymap:vi/call-operator-linewise + _ble_edit_mark_active=vi_line + fi + local ble_keymap_vi_mark_active=$_ble_edit_mark_active + ble/widget/vi_xmap/.save-visual-state + ble/widget/vi_xmap/exit + "$call_operator" "$op" "$beg" "$end" "$ARG" "$REG"; local ext=$? + ((ext==147)) && return 147 + ((ext)) && ble/widget/.bell + ble/keymap:vi/adjust-command-mode + return "$ext" +} +function ble/widget/vi_xmap/replace-block-lines { ble/widget/vi_xmap/linewise-operator.impl c extend; } +function ble/widget/vi_xmap/delete-block-lines { ble/widget/vi_xmap/linewise-operator.impl d extend; } +function ble/widget/vi_xmap/delete-lines { ble/widget/vi_xmap/linewise-operator.impl d force_line; } +function ble/widget/vi_xmap/copy-block-or-lines { ble/widget/vi_xmap/linewise-operator.impl y; } +function ble/widget/vi_xmap/connect-line.impl { + local name=$1 + local ARG FLAG REG; ble/keymap:vi/get-arg 1 # ignored + local beg=$_ble_edit_mark end=$_ble_edit_ind + ((beg<=end)) || local beg=$end end=$beg + local ret; ble/string#count-char "${_ble_edit_str:beg:end-beg}" $'\n'; local nline=$((ret+1)) + ble/widget/vi_xmap/.save-visual-state + ble/widget/vi_xmap/exit # Note: _ble_edit_mark_active will be cleared here + _ble_edit_ind=$beg + _ble_edit_arg=$nline + _ble_keymap_vi_oparg= + _ble_keymap_vi_opfunc= + _ble_keymap_vi_reg= + "ble/widget/$name" +} +function ble/widget/vi_xmap/connect-line-with-space { + ble/widget/vi_xmap/connect-line.impl vi_nmap/connect-line-with-space +} +function ble/widget/vi_xmap/connect-line { + ble/widget/vi_xmap/connect-line.impl vi_nmap/connect-line +} +_ble_keymap_vi_xmap_insert_data= +_ble_keymap_vi_xmap_insert_dbeg=-1 +ble/array#push _ble_textarea_local_VARNAMES \ + _ble_keymap_vi_xmap_insert_data \ + _ble_keymap_vi_xmap_insert_dbeg +function ble/keymap:vi/xmap/update-dirty-range { + [[ $_ble_keymap_vi_insert_leave == ble/widget/vi_xmap/block-insert-mode.onleave ]] && + ((_ble_keymap_vi_xmap_insert_dbeg<0||beg<_ble_keymap_vi_xmap_insert_dbeg)) && + _ble_keymap_vi_xmap_insert_dbeg=$beg +} +function ble/widget/vi_xmap/block-insert-mode.impl { + local type=$1 + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local nline=${#sub_ranges[@]} + ble/util/assert '((nline))' + local index ins_x + if [[ $type == append ]]; then + local sub=${sub_ranges[0]#*:} + local smax=${sub%%:*} + index=$smax + if ble/keymap:vi/xmap/has-eol-extension; then + ins_x='$' + else + ins_x=$sub_x2 + fi + else + local sub=${sub_ranges[0]} + local smin=${sub%%:*} + index=$smin + ins_x=$sub_x1 + fi + ble/widget/vi_xmap/cancel + _ble_edit_ind=$index + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + ble/keymap:vi/mark/set-local-mark 1 "$_ble_edit_ind" + _ble_keymap_vi_xmap_insert_dbeg=-1 + local ret display_width + ble/string#count-char "${_ble_edit_str::_ble_edit_ind}" $'\n'; local iline=$ret + ble-edit/content/find-logical-bol; local bol=$ret + ble-edit/content/find-logical-eol; local eol=$ret + if ble/edit/use-textmap; then + local bx by ex ey + ble/textmap#getxy.out --prefix=b "$bol" + ble/textmap#getxy.out --prefix=e "$eol" + ((display_width=ex+_ble_textmap_cols*(ey-by))) + else + ((display_width=eol-bol)) + fi + _ble_keymap_vi_xmap_insert_data=$iline:$ins_x:$display_width:$nline + _ble_keymap_vi_insert_leave=ble/widget/vi_xmap/block-insert-mode.onleave + return 0 +} +function ble/widget/vi_xmap/block-insert-mode.onleave { + local data=$_ble_keymap_vi_xmap_insert_data + [[ $data ]] || continue + _ble_keymap_vi_xmap_insert_data= + ble/string#split data : "$data" + local ret + ble-edit/content/find-logical-bol; local bol=$ret + ble/string#count-char "${_ble_edit_str::bol}" $'\n'; ((ret==data[0])) || return 1 # 行番号 + ble/keymap:vi/mark/get-local-mark 1 || return 1; local mark=$ret # `[ + ble-edit/content/find-logical-bol "$mark"; ((bol==ret)) || return 1 # 記録行 `[ と同じか + local has_textmap= + if ble/edit/use-textmap; then + local cols=$_ble_textmap_cols + has_textmap=1 + fi + local new_width delta + ble-edit/content/find-logical-eol; local eol=$ret + if [[ $has_textmap ]]; then + local bx by ex ey + ble/textmap#getxy.out --prefix=b "$bol" + ble/textmap#getxy.out --prefix=e "$eol" + ((new_width=ex+cols*(ey-by))) + else + ((new_width=eol-bol)) + fi + ((delta=new_width-data[2])) + ((delta>0)) || return 1 # 縮んだ場合は処理しない + local x1=${data[1]} + [[ $x1 == '$' ]] && ((x1=data[2])) + ((x1>new_width&&(x1=new_width))) + if ((bol<=_ble_keymap_vi_xmap_insert_dbeg&&_ble_keymap_vi_xmap_insert_dbeg<=eol)); then + local px py + if [[ $has_textmap ]]; then + ble/textmap#getxy.out --prefix=p "$_ble_keymap_vi_xmap_insert_dbeg" + ((px+=cols*(py-by))) + else + ((px=_ble_keymap_vi_xmap_insert_dbeg-bol)) + fi + ((px>x1&&(x1=px))) + fi + local x2=$((x1+delta)) + local ins= p1 p2 + if [[ $has_textmap ]]; then + local index lx ly rx ry + ble/textmap#hit out $((x1%cols)) $((by+x1/cols)) "$bol" "$eol"; p1=$index + ble/textmap#hit out $((x2%cols)) $((by+x2/cols)) "$bol" "$eol"; p2=$index + ((lx+=(ly-by)*cols,rx+=(ry-by)*cols,lx!=rx&&p2++)) + else + ((p1=bol+x1,p2=bol+x2)) + fi + ins=${_ble_edit_str:p1:p2-p1} + local -a ins_beg=() ins_text=() + local iline=1 nline=${data[3]} strlen=${#_ble_edit_str} + for ((iline=1;iline index + local nfill + if ((index==eol&&(nfill=x1-lx+(ly-by)*cols)>0)); then + ble/string#repeat ' ' "$nfill"; lpad=$lpad$ret + fi + else + index=$((bol+x1)) + if ((index>eol)); then + ble/string#repeat ' ' $((index-eol)); lpad=$lpad$ret + ((index=eol)) + fi + fi + ble/array#push ins_beg "$index" + ble/array#push ins_text "$lpad$ins" + done + local i=${#ins_beg[@]} + ble/keymap:vi/mark/start-edit-area + ble/keymap:vi/mark/commit-edit-area "$p1" "$p2" + while ((i--)); do + local index=${ins_beg[i]} text=${ins_text[i]} + ble/widget/.replace-range "$index" "$index" "$text" + done + ble/keymap:vi/mark/end-edit-area + local index + if ble/keymap:vi/mark/get-local-mark 60 && index=$ret; then + ble/widget/vi-command/goto-mark.impl "$index" + else + ble-edit/content/find-logical-bol; index=$ret + fi + ble-edit/content/eolp || ((index++)) + _ble_edit_ind=$index + return 0 +} +function ble/widget/vi_xmap/insert-mode { + local mark_type=${_ble_edit_mark_active%+} + if [[ $mark_type == vi_block ]]; then + local sub_ranges sub_x1 sub_x2 + ble/keymap:vi/extract-block '' '' first_line + ble/widget/vi_xmap/block-insert-mode.impl insert + else + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local beg=$_ble_edit_mark end=$_ble_edit_ind + ((beg<=end)) || local beg=$end end=$beg + if [[ $mark_type == vi_line ]]; then + local ret + ble-edit/content/find-logical-bol "$beg"; beg=$ret + fi + ble/widget/vi_xmap/cancel + _ble_edit_ind=$beg + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 + fi +} +function ble/widget/vi_xmap/append-mode { + local mark_type=${_ble_edit_mark_active%+} + if [[ $mark_type == vi_block ]]; then + local sub_ranges sub_x1 sub_x2 + ble/keymap:vi/extract-block '' '' first_line + ble/widget/vi_xmap/block-insert-mode.impl append + else + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + local beg=$_ble_edit_mark end=$_ble_edit_ind + ((beg<=end)) || local beg=$end end=$beg + if [[ $mark_type == vi_line ]]; then + if ((_ble_edit_mark>_ble_edit_ind)); then + local ret + ble-edit/content/find-logical-bol "$end"; end=$ret + fi + fi + ble-edit/content/eolp "$end" || ((end++)) + ble/widget/vi_xmap/cancel + _ble_edit_ind=$end + ble/widget/vi_nmap/.insert-mode "$ARG" + ble/keymap:vi/repeat/record + return 0 + fi +} +function ble/widget/vi_xmap/paste.impl { + local opts=$1 + [[ :$opts: != *:after:* ]]; local is_after=$? + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + [[ $REG ]] && ble/keymap:vi/register#load "$REG" + local mark_type=${_ble_edit_mark_active%+} + local kill_ring=$_ble_edit_kill_ring + local kill_type=$_ble_edit_kill_type + local adjustment= + if [[ $mark_type == vi_block ]]; then + if [[ $kill_type == L ]]; then + if ((is_after)); then + local ret; ble/keymap:vi/get-rectangle-height; local nline=$ret + adjustment=lastline:$nline + fi + elif [[ $kill_type == B:* ]]; then + is_after=0 + else + is_after=0 + if [[ $kill_ring != *$'\n'* ]]; then + ((${#kill_ring}>=2)) && adjustment=index:$((${#kill_ring}*ARG-1)) + local ret; ble/keymap:vi/get-rectangle-height; local nline=$ret + ble/string#repeat "$kill_ring"$'\n' "$nline"; kill_ring=${ret%$'\n'} + ble/string#repeat '0 ' "$nline"; kill_type=B:${ret% } + fi + fi + elif [[ $mark_type == vi_line ]]; then + if [[ $kill_type == L ]]; then + is_after=0 + elif [[ $kill_type == B:* ]]; then + is_after=0 kill_type=L kill_ring=$kill_ring$'\n' + else + is_after=0 kill_type=L + [[ $kill_ring == *$'\n' ]] && kill_ring=$kill_ring$'\n' + fi + else + is_after=0 + [[ $kill_type == L ]] && adjustment=newline + fi + ble/keymap:vi/mark/start-edit-area + local _ble_keymap_vi_mark_suppress_edit=1 + { + ble/widget/vi-command/operator d; local ext=$? # _ble_edit_kill_{ring,type} is set here + if [[ $adjustment == newline ]]; then + local -a KEYS=(10) + ble/widget/self-insert + elif [[ $adjustment == lastline:* ]]; then + local ret + ble-edit/content/find-logical-bol "$_ble_edit_ind" $((${adjustment#*:}-1)) + _ble_edit_ind=$ret + fi + local _ble_edit_kill_ring=$kill_ring + local _ble_edit_kill_type=$kill_type + ble/widget/vi_nmap/paste.impl "$ARG" '' "$is_after" + if [[ $adjustment == index:* ]]; then + local index=$((_ble_edit_ind+${adjustment#*:})) + ((index>${#_ble_edit_str}&&(index=${#_ble_edit_str}))) + ble/keymap:vi/needs-eol-fix "$index" && ((index--)) + _ble_edit_ind=$index + fi + } + ble/util/unlocal _ble_keymap_vi_mark_suppress_edit + ble/keymap:vi/mark/end-edit-area + ble/keymap:vi/repeat/record + return "$ext" +} +function ble/widget/vi_xmap/paste-after { + ble/widget/vi_xmap/paste.impl after +} +function ble/widget/vi_xmap/paste-before { + ble/widget/vi_xmap/paste.impl before +} +function ble/widget/vi_xmap/increment.impl { + local opts=$1 + local ARG FLAG REG; ble/keymap:vi/get-arg 1 + if [[ $FLAG ]]; then + ble/widget/.bell + return 1 + fi + local delta=$ARG + [[ :$opts: == *:decrease:* ]] && ((delta=-delta)) + local progress=0 + [[ :$opts: == *:progressive:* ]] && progress=$delta + local old_mark_active=$_ble_edit_mark_active # save + local mark_type=${_ble_edit_mark_active%+} + ble/widget/vi_xmap/.save-visual-state + ble/widget/vi_xmap/exit # Note: _ble_edit_mark_active will be cleared here + if [[ $mark_type == vi_block ]]; then + local sub_ranges sub_x1 sub_x2 + _ble_edit_mark_active=$old_mark_active ble/keymap:vi/extract-block + if ((${#sub_ranges[@]}==0)); then + ble/widget/.bell + return 1 + fi + else + local beg=$_ble_edit_mark end=$_ble_edit_ind + ((beg<=end)) || local beg=$end end=$beg + if [[ $mark_type == vi_line ]]; then + local ret + ble-edit/content/find-logical-bol "$beg"; local beg=$ret + ble-edit/content/find-logical-eol "$end"; local end=$ret + else + ble-edit/content/eolp "$end" || ((end++)) + fi + local -a lines + ble/string#split-lines lines "${_ble_edit_str:beg:end-beg}" + local line index=$beg + local -a sub_ranges + for line in "${lines[@]}"; do + [[ $line ]] && ble/array#push sub_ranges "$index:::::$line" + ((index+=${#line}+1)) + done + ((${#sub_ranges[@]})) || return 0 + fi + local sub rex_number='^([^0-9]*)([0-9]+)' shift=0 dmin=-1 dmax=-1 + for sub in "${sub_ranges[@]}"; do + local stext=${sub#*:*:*:*:*:} + [[ $stext =~ $rex_number ]] || continue + local rematch1=${BASH_REMATCH[1]} + local rematch2=${BASH_REMATCH[2]} + local offset=${#rematch1} length=${#rematch2} + local number=$((10#0$rematch2)) + [[ $rematch1 == *- ]] && ((number=-number,offset--,length++)) + ((number+=delta,delta+=progress)) + if [[ $rematch2 == 0?* ]]; then + local wsign=$((number<0?1:0)) + local zpad=$((wsign+${#rematch2}-${#number})) + if ((zpad>0)); then + local ret; ble/string#repeat 0 "$zpad" + number=${number::wsign}$ret${number:wsign} + fi + fi + local smin=${sub%%:*} + local beg=$((shift+smin+offset)) + local end=$((beg+length)) + ble/widget/.replace-range "$beg" "$end" "$number" + ((shift+=${#number}-length, + dmin<0&&(dmin=beg), + dmax=beg+${#number})) + done + local beg=${sub_ranges[0]%%:*} + ble/keymap:vi/needs-eol-fix "$beg" && ((beg--)) + _ble_edit_ind=$beg + ((dmin>=0)) && ble/keymap:vi/mark/set-previous-edit-area "$dmin" "$dmax" + ble/keymap:vi/repeat/record + return 0 +} +function ble/widget/vi_xmap/increment { ble/widget/vi_xmap/increment.impl increase; } +function ble/widget/vi_xmap/decrement { ble/widget/vi_xmap/increment.impl decrease; } +function ble/widget/vi_xmap/progressive-increment { ble/widget/vi_xmap/increment.impl progressive:increase; } +function ble/widget/vi_xmap/progressive-decrement { ble/widget/vi_xmap/increment.impl progressive:decrease; } +function ble-decode/keymap:vi_xmap/define { + ble/keymap:vi/set-up-command-map + ble-bind -f __default__ vi-command/decompose-meta + ble-bind -f 'ESC' vi_xmap/exit + ble-bind -f 'C-[' vi_xmap/exit + ble-bind -f 'C-c' vi_xmap/cancel + ble-bind -f '"' vi-command/register + ble-bind -f a vi-command/text-object + ble-bind -f i vi-command/text-object + ble-bind -f 'C-\ C-n' vi_xmap/cancel + ble-bind -f 'C-\ C-g' vi_xmap/cancel + ble-bind -f v vi_xmap/switch-to-charwise + ble-bind -f V vi_xmap/switch-to-linewise + ble-bind -f C-v vi_xmap/switch-to-blockwise + ble-bind -f C-q vi_xmap/switch-to-blockwise + ble-bind -f 'g v' vi-command/previous-visual-area + ble-bind -f C-g vi_xmap/switch-to-select + ble-bind -f o vi_xmap/exchange-points + ble-bind -f O vi_xmap/exchange-boundaries + ble-bind -f '~' 'vi-command/operator toggle_case' + ble-bind -f 'u' 'vi-command/operator u' + ble-bind -f 'U' 'vi-command/operator U' + ble-bind -f 's' 'vi-command/operator c' + ble-bind -f 'x' 'vi-command/operator d' + ble-bind -f delete 'vi-command/operator d' + ble-bind -f r vi_xmap/visual-replace-char + ble-bind -f C vi_xmap/replace-block-lines + ble-bind -f D vi_xmap/delete-block-lines + ble-bind -f X vi_xmap/delete-block-lines + ble-bind -f S vi_xmap/delete-lines + ble-bind -f R vi_xmap/delete-lines + ble-bind -f Y vi_xmap/copy-block-or-lines + ble-bind -f J vi_xmap/connect-line-with-space + ble-bind -f 'g J' vi_xmap/connect-line + ble-bind -f I vi_xmap/insert-mode + ble-bind -f A vi_xmap/append-mode + ble-bind -f p vi_xmap/paste-after + ble-bind -f P vi_xmap/paste-before + ble-bind -f 'C-a' vi_xmap/increment + ble-bind -f 'C-x' vi_xmap/decrement + ble-bind -f 'g C-a' vi_xmap/progressive-increment + ble-bind -f 'g C-x' vi_xmap/progressive-decrement + ble-bind -f f1 vi_xmap/command-help + ble-bind -f K vi_xmap/command-help +} +function ble-decode/keymap:vi_smap/define { + ble-bind -f __default__ vi-command/decompose-meta + ble-bind -f 'ESC' vi_xmap/exit + ble-bind -f 'C-[' vi_xmap/exit + ble-bind -f 'C-c' vi_xmap/cancel + ble-bind -f 'C-\ C-n' nop + ble-bind -f 'C-\ C-n' vi_xmap/cancel + ble-bind -f 'C-\ C-g' vi_xmap/cancel + ble-bind -f C-v vi_xmap/switch-to-visual-blockwise + ble-bind -f C-q vi_xmap/switch-to-visual-blockwise + ble-bind -f C-g vi_xmap/switch-to-visual + ble-bind -f delete 'vi-command/operator d' + ble-bind -f 'C-?' 'vi-command/operator d' + ble-bind -f 'DEL' 'vi-command/operator d' + ble-bind -f 'C-h' 'vi-command/operator d' + ble-bind -f 'BS' 'vi-command/operator d' + ble-bind -f __defchar__ vi_smap/self-insert + ble-bind -f paste_begin vi-command/bracketed-paste + ble-bind -f 'C-a' vi_xmap/increment + ble-bind -f 'C-x' vi_xmap/decrement + ble-bind -f f1 vi_xmap/command-help + ble-bind -c 'C-z' fg + ble-bind -f home 'vi_smap/@nomarked vi-command/beginning-of-line' + ble-bind -f end 'vi_smap/@nomarked vi-command/forward-eol' + ble-bind -f C-m 'vi_smap/@nomarked vi-command/forward-first-non-space' + ble-bind -f RET 'vi_smap/@nomarked vi-command/forward-first-non-space' + ble-bind -f S-home 'vi-command/beginning-of-line' + ble-bind -f S-end 'vi-command/forward-eol' + ble-bind -f S-C-m 'vi-command/forward-first-non-space' + ble-bind -f S-RET 'vi-command/forward-first-non-space' + ble-bind -f C-right 'vi_smap/@nomarked vi-command/forward-vword' + ble-bind -f C-left 'vi_smap/@nomarked vi-command/backward-vword' + ble-bind -f S-C-right 'vi-command/forward-vword' + ble-bind -f S-C-left 'vi-command/backward-vword' + ble-bind -f left 'vi_smap/@nomarked vi-command/backward-char' + ble-bind -f right 'vi_smap/@nomarked vi-command/forward-char' + ble-bind -f 'C-?' 'vi_smap/@nomarked vi-command/backward-char wrap' + ble-bind -f 'DEL' 'vi_smap/@nomarked vi-command/backward-char wrap' + ble-bind -f 'C-h' 'vi_smap/@nomarked vi-command/backward-char wrap' + ble-bind -f 'BS' 'vi_smap/@nomarked vi-command/backward-char wrap' + ble-bind -f SP 'vi_smap/@nomarked vi-command/forward-char wrap' + ble-bind -f S-left 'vi-command/backward-char' + ble-bind -f S-right 'vi-command/forward-char' + ble-bind -f 'S-C-?' 'vi-command/backward-char wrap' + ble-bind -f 'S-DEL' 'vi-command/backward-char wrap' + ble-bind -f 'S-C-h' 'vi-command/backward-char wrap' + ble-bind -f 'S-BS' 'vi-command/backward-char wrap' + ble-bind -f S-SP 'vi-command/forward-char wrap' + ble-bind -f down 'vi_smap/@nomarked vi-command/forward-line' + ble-bind -f C-n 'vi_smap/@nomarked vi-command/forward-line' + ble-bind -f C-j 'vi_smap/@nomarked vi-command/forward-line' + ble-bind -f up 'vi_smap/@nomarked vi-command/backward-line' + ble-bind -f C-p 'vi_smap/@nomarked vi-command/backward-line' + ble-bind -f C-home 'vi_smap/@nomarked vi-command/first-nol' + ble-bind -f C-end 'vi_smap/@nomarked vi-command/last-eol' + ble-bind -f S-down 'vi-command/forward-line' + ble-bind -f S-C-n 'vi-command/forward-line' + ble-bind -f S-C-j 'vi-command/forward-line' + ble-bind -f S-up 'vi-command/backward-line' + ble-bind -f S-C-p 'vi-command/backward-line' + ble-bind -f S-C-home 'vi-command/first-nol' + ble-bind -f S-C-end 'vi-command/last-eol' +} +function ble/widget/vi_imap/__attach__ { + ble/keymap:vi/update-mode-name + return 0 +} +function ble/widget/vi_imap/__detach__ { + ble/edit/info/default clear + ble/keymap:vi/clear-arg + ble/keymap:vi/search/clear-matched + return 0 +} +function ble/widget/vi_imap/accept-single-line-or { + if ble-edit/is-single-complete-line; then + ble/keymap:vi/imap-repeat/reset + ble/widget/accept-line + else + ble/widget/"$@" + fi +} +function ble/widget/vi_imap/delete-region-or { + if [[ $_ble_edit_mark_active ]]; then + ble/keymap:vi/imap-repeat/reset + if ((_ble_edit_ind!=_ble_edit_mark)); then + ble/keymap:vi/undo/add more + ble/widget/delete-region + ble/keymap:vi/undo/add more + fi + else + ble/widget/"$@" + fi +} +function ble/widget/vi_imap/overwrite-mode { + ble-edit/content/clear-arg + if [[ $_ble_edit_overwrite_mode ]]; then + _ble_edit_overwrite_mode= + else + _ble_edit_overwrite_mode=${_ble_keymap_vi_insert_overwrite:-R} + fi + ble/keymap:vi/update-mode-name + return 0 +} +function ble/widget/vi_imap/delete-backward-word { + local space=$' \t' nl=$'\n' + local rex="($_ble_keymap_vi_REX_WORD)[$space]*\$|[$space]+\$|$nl\$" + if [[ ${_ble_edit_str::_ble_edit_ind} =~ $rex ]]; then + local index=$((_ble_edit_ind-${#BASH_REMATCH})) + if ((index!=_ble_edit_ind)); then + ble/keymap:vi/undo/add more + ble/widget/.delete-range "$index" "$_ble_edit_ind" + ble/keymap:vi/undo/add more + fi + return 0 + else + ble/widget/.bell + return 1 + fi +} +function ble/widget/vi_imap/quoted-insert-char { + ble/keymap:vi/imap-repeat/pop + _ble_edit_mark_active= + _ble_decode_char__hook=ble/widget/vi_imap/quoted-insert-char.hook + return 147 +} +function ble/widget/vi_imap/quoted-insert-char.hook { + ble/keymap:vi/imap/invoke-widget ble/widget/self-insert "$1" +} +function ble/widget/vi_imap/quoted-insert { + ble/keymap:vi/imap-repeat/pop + _ble_edit_mark_active= + _ble_decode_key__hook=ble/widget/vi_imap/quoted-insert.hook + return 147 +} +function ble/widget/vi_imap/quoted-insert.hook { + ble/keymap:vi/imap/invoke-widget ble/widget/quoted-insert.hook "$1" +} +function ble/widget/vi_imap/bracketed-paste { + ble/keymap:vi/imap-repeat/pop + ble/widget/bracketed-paste + _ble_edit_bracketed_paste_proc=ble/widget/vi_imap/bracketed-paste.proc + return 147 +} +function ble/widget/vi_imap/bracketed-paste.proc { + local WIDGET=ble/widget/batch-insert + local -a KEYS; KEYS=("$@") + ble/keymap:vi/imap-repeat/push + builtin eval -- "$WIDGET" +} +_ble_keymap_vi_brackated_paste_mark_active= +function ble/widget/vi-command/bracketed-paste { + local ARG FLAG REG; ble/keymap:vi/get-arg 1 # discard args + _ble_keymap_vi_brackated_paste_mark_active=$_ble_edit_mark_active + _ble_edit_mark_active= + ble/widget/bracketed-paste + _ble_edit_bracketed_paste_proc=ble/widget/vi-command/bracketed-paste.proc + return 147 +} +function ble/widget/vi-command/bracketed-paste.proc { + if [[ $_ble_decode_keymap == vi_nmap ]]; then + local isbol index=$_ble_edit_ind + ble-edit/content/bolp && isbol=1 + ble/decode/widget/call-interactively 'ble/widget/vi_nmap/append-mode' 97 + [[ $isbol ]] && ((_ble_edit_ind=index)) # 行頭にいたときは戻る + ble/widget/vi_imap/bracketed-paste.proc "$@" + ble/keymap:vi/imap/invoke-widget \ + ble/widget/vi_imap/normal-mode $((_ble_decode_Ctrl|0x5b)) + elif [[ $_ble_decode_keymap == vi_[xs]map ]]; then + local _ble_edit_mark_active=$_ble_keymap_vi_brackated_paste_mark_active + ble/decode/widget/call-interactively 'ble/widget/vi-command/operator c' 99 || return 1 + ble/widget/vi_imap/bracketed-paste.proc "$@" + ble/keymap:vi/imap/invoke-widget \ + ble/widget/vi_imap/normal-mode $((_ble_decode_Ctrl|0x5b)) + elif [[ $_ble_decode_keymap == vi_omap ]]; then + ble/widget/vi_omap/cancel + ble/widget/.bell + return 1 + else # vi_omap + ble/widget/.bell + return 1 + fi +} +function ble/widget/vi_imap/insert-digraph.hook { + local -a KEYS; KEYS=("$1") + ble/widget/self-insert +} +function ble/widget/vi_imap/insert-digraph { + ble/decode/keymap/push vi_digraph + _ble_keymap_vi_digraph__hook=ble/widget/vi_imap/insert-digraph.hook + return 0 +} +function ble/widget/vi_imap/newline { + local ret + ble-edit/content/find-logical-bol; local bol=$ret + ble-edit/content/find-non-space "$bol"; local nol=$ret + ble/widget/default/newline + ((bol' 'history-end' + ble-bind -f 'M-.' 'insert-last-argument' + ble-bind -f 'M-_' 'insert-last-argument' + ble-bind -f 'M-C-y' 'insert-nth-argument' + ble-bind -f 'M-?' 'complete show_menu' + ble-bind -f 'M-*' 'complete insert_all' + ble-bind -f 'M-{' 'complete insert_braces' + ble-bind -f 'M-/' 'complete context=filename' + ble-bind -f 'M-~' 'complete context=username' + ble-bind -f 'M-$' 'complete context=variable' + ble-bind -f 'M-@' 'complete context=hostname' + ble-bind -f 'M-!' 'complete context=command' + ble-bind -f "M-'" 'sabbrev-expand' + ble-bind -f 'M-g' 'complete context=glob' + ble-bind -f 'M-C-i' 'complete context=dynamic-history' + ble-bind -f 'M-TAB' 'complete context=dynamic-history' +} +_ble_keymap_vi_cmap_hook= +_ble_keymap_vi_cmap_cancel_hook= +_ble_keymap_vi_cmap_before_command= +_ble_keymap_vi_cmap_history=() +_ble_keymap_vi_cmap_history_edit=() +_ble_keymap_vi_cmap_history_dirt=() +_ble_keymap_vi_cmap_history_index=0 +function ble/keymap:vi/async-commandline-mode { + local hook=$1 + _ble_keymap_vi_cmap_hook=$hook + _ble_keymap_vi_cmap_cancel_hook= + _ble_keymap_vi_cmap_before_command= + ble/textarea#render + ble/textarea#save-state _ble_keymap_vi_cmap + ble/util/save-vars _ble_keymap_vi_cmap _ble_canvas_panel_focus + _ble_keymap_vi_cmap_history_prefix=$_ble_history_prefix + ble/decode/keymap/push vi_cmap + ble/keymap:vi/update-mode-name + _ble_textarea_panel=1 + _ble_canvas_panel_focus=1 + ble/textarea#invalidate + _ble_edit_PS1=$PS2 + _ble_prompt_ps1_data=(0 '' '' 0 0 0 32 0 '' '') + _ble_edit_dirty_observer=() + ble/widget/.newline/clear-content + _ble_edit_arg= + ble-edit/undo/clear-all + ble/history/set-prefix _ble_keymap_vi_cmap + _ble_syntax_lang=text + _ble_highlight_layer__list=(plain region overwrite_mode) +} +function ble/widget/vi_cmap/accept { + local hook=${_ble_keymap_vi_cmap_hook} + _ble_keymap_vi_cmap_hook= + local result=$_ble_edit_str + [[ $result ]] && ble/history/add "$result" # Note: cancel でも登録する + local -a DRAW_BUFF=() + ble/canvas/panel#set-height.draw "$_ble_textarea_panel" 0 + ble/canvas/bflush.draw + ble/textarea#restore-state _ble_keymap_vi_cmap + ble/textarea#clear-state _ble_keymap_vi_cmap + ble/util/restore-vars _ble_keymap_vi_cmap _ble_canvas_panel_focus + [[ $_ble_edit_overwrite_mode ]] && ble/util/buffer "$_ble_term_civis" + ble/history/set-prefix "$_ble_keymap_vi_cmap_history_prefix" + ble/decode/keymap/pop + ble/keymap:vi/update-mode-name + if [[ $hook ]]; then + builtin eval -- "$hook \"\$result\"" + else + ble/keymap:vi/adjust-command-mode + return 0 + fi +} +function ble/widget/vi_cmap/cancel { + _ble_keymap_vi_cmap_hook=$_ble_keymap_vi_cmap_cancel_hook + ble/widget/vi_cmap/accept +} +function ble/widget/vi_cmap/__before_widget__ { + if [[ $_ble_keymap_vi_cmap_before_command ]]; then + builtin eval -- "$_ble_keymap_vi_cmap_before_command" + fi +} +function ble/widget/vi_cmap/__line_limit__.edit { + local content=$1 + ble/widget/edit-and-execute-command.edit "$content" no-newline; local ext=$? + ((ext==127)) && return "$ext" + ble-edit/content/reset "$ret" + ble/widget/vi_cmap/accept +} +function ble/widget/vi_cmap/__line_limit__ { + ble/widget/__line_limit__ vi_cmap/__line_limit__.edit +} +function ble-decode/keymap:vi_cmap/define { + local ble_bind_nometa= + ble-decode/keymap:safe/bind-common + ble-decode/keymap:safe/bind-history + ble-decode/keymap:safe/bind-complete + ble-bind -f __before_widget__ vi_cmap/__before_widget__ + ble-bind -f __line_limit__ vi_cmap/__line_limit__ + ble-bind -f 'ESC' vi_cmap/cancel + ble-bind -f 'C-[' vi_cmap/cancel + ble-bind -f 'C-c' vi_cmap/cancel + ble-bind -f 'C-m' vi_cmap/accept + ble-bind -f 'RET' vi_cmap/accept + ble-bind -f 'C-j' vi_cmap/accept + ble-bind -f 'C-g' bell + ble-bind -f 'C-x C-g' bell + ble-bind -f 'C-M-g' bell + ble-bind -f 'C-l' redraw-line + ble-bind -f 'C-M-l' redraw-line + ble-bind -f 'C-x C-v' display-shell-version + ble-bind -f 'C-\' bell + ble-bind -f 'C-^' bell +} +function ble-decode/keymap:vi/initialize { + local fname_keymap_cache=$_ble_base_cache/keymap.vi + if [[ -s $fname_keymap_cache && + $fname_keymap_cache -nt $_ble_base/keymap/vi.sh && + $fname_keymap_cache -nt $_ble_base/lib/init-cmap.sh ]]; then + source "$fname_keymap_cache" && return 0 + fi + ble/edit/info/immediate-show text "ble.sh: updating cache/keymap.vi..." + { + ble/decode/keymap#load isearch dump + ble/decode/keymap#load nsearch dump + ble/decode/keymap#load vi_imap dump + ble/decode/keymap#load vi_nmap dump + ble/decode/keymap#load vi_omap dump + ble/decode/keymap#load vi_xmap dump + ble/decode/keymap#load vi_cmap dump + } 3>| "$fname_keymap_cache" + ble/edit/info/immediate-show text "ble.sh: updating cache/keymap.vi... done" +} +ble-decode/keymap:vi/initialize +blehook/invoke keymap_load +blehook/invoke keymap_vi_load +return 0 -- cgit v1.2.3