# 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