diff --git a/blerc.template b/blerc.template index 16fc666c..bec69c39 100644 --- a/blerc.template +++ b/blerc.template @@ -119,6 +119,14 @@ #bleopt edit_magic_expand=history:sabbrev +## This option configures the detailed behavior of the widget "magic-space" +## with a colon-separated list. If the field "inline-sabbrev-no-insert" is +## specified, the insertion of "SP" is skipped when the inline sabbrev is +## performed by "magic-space". + +#bleopt edit_magic_opts= + + ## The following option controls the position of the info pane where completion ## menu, mode names, and other information are shown. When the value "top" is ## specified, the info pane is shown just below the command line. When the diff --git a/contrib b/contrib index dde8b8f2..b4978f81 160000 --- a/contrib +++ b/contrib @@ -1 +1 @@ -Subproject commit dde8b8f206daf37652af1427316586e66f6a972f +Subproject commit b4978f8126bcd478e5fb5657be7806e2a672b217 diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index c8005f4e..671346a5 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -137,6 +137,7 @@ - edit: support a user command `ble append-line` (requested by mozirilla213) `#D2001` 2a524f34 - decode: accept isolated ESC \ (requested by mozirilla213) `#D2004` xxxxxxxx - sabbrev: add widget `magic-slash` to approximate Zsh named directories (motivated by mozirilla213) `#D2008` xxxxxxxx +- sabbrev: support inline and linewise sabbre with `ble-sabbrev -il` `#D2012` xxxxxxxx ## Changes diff --git a/lib/core-complete-def.sh b/lib/core-complete-def.sh index 295b8708..fc60409f 100644 --- a/lib/core-complete-def.sh +++ b/lib/core-complete-def.sh @@ -30,10 +30,13 @@ function ble-sabbrev { blehook/eval-after-load complete "$ret" } -if ! declare -p _ble_complete_sabbrev &>/dev/null; then # reload #D0875 - builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_complete_sabbrev}" +if ! declare -p _ble_complete_sabbrev_wordwise &>/dev/null; then # reload #D0875 + builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_complete_sabbrev_wordwise}" fi +declare -p _ble_complete_sabbrev_literal &>/dev/null || + builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_complete_sabbrev_literal}" + #------------------------------------------------------------------------------ # 設定変数 diff --git a/lib/core-complete.sh b/lib/core-complete.sh index 5869837c..d524b8ec 100644 --- a/lib/core-complete.sh +++ b/lib/core-complete.sh @@ -38,6 +38,19 @@ function ble/complete/string#common-suffix-prefix { fi } +## @fn ble/complete/string#match-patterns str patterns... +## 指定した文字列が patterns 集合の何れかのパターンに一致するか検査します。 +## @param[in] str +## @param[in] patterns +## @exit +function ble/complete/string#match-patterns { + local s=$1 pattern found= + for pattern in "${patterns[@]}"; do + [[ $s == $pattern ]] && return 0 + done + return 1 +} + ## @fn ble/complete/get-wordbreaks ## @var[out] wordbreaks function ble/complete/get-wordbreaks { @@ -8203,6 +8216,11 @@ function ble-decode/keymap:auto_complete/define { # sabbrev # +# The following are variables defined in core-complete-def.sh: +# +# @var _ble_complete_sabbrev_wordwise +# @var _ble_complete_sabbrev_literal + function ble/complete/sabbrev/.initialize-print { sgr0= sgr1= sgr2= sgr3= sgro= if [[ $flags == *c* || $flags != *n* && -t 1 ]]; then @@ -8217,7 +8235,7 @@ function ble/complete/sabbrev/.initialize-print { function ble/complete/sabbrev/.print-definition { local key=$1 type=${2%%:*} value=${2#*:} local option= - [[ $type == m ]] && option=$sgro'-m'$sgr0' ' + [[ $type != w ]] && option=$sgro'-'$type$sgr0' ' local ret ble/string#quote-word "$key" quote-empty:sgrq="$sgr3":sgr0="$sgr2" @@ -8231,30 +8249,55 @@ function ble/complete/sabbrev/.print-definition { ## 静的略語展開を登録します。 ## @param[in] key value ## -## @fn ble/complete/sabbrev/list [keys...] +## @fn ble/complete/sabbrev/list type [keys...] ## 登録されている静的略語展開の一覧を表示します。 ## @var[in] flags ## -## @fn ble/complete/sabbrev/reset [keys...] +## @fn ble/complete/sabbrev/reset type [keys...] ## 登録されている静的略語展開を削除します。 ## @var[in] flags ## -## @fn ble/complete/sabbrev/get key +## @fn ble/complete/sabbrev/wordwise.get key ## 静的略語展開の展開値を取得します。 ## @param[in] key ## @var[out] ret ## -# Note: _ble_complete_sabbrev は core-complete-def.sh で定義 +# Note: _ble_complete_sabbrev_wordwise は core-complete-def.sh で定義 function ble/complete/sabbrev/register { local key=$1 value=$2 - ble/gdict#set _ble_complete_sabbrev "$key" "$value" + if [[ $value == [il]:* ]]; then + ble/gdict#set _ble_complete_sabbrev_literal "$key" "$value" + ble/gdict#unset _ble_complete_sabbrev_wordwise "$key" + else + ble/gdict#set _ble_complete_sabbrev_wordwise "$key" "$value" + ble/gdict#unset _ble_complete_sabbrev_literal "$key" + fi } function ble/complete/sabbrev/list { + local type=$1; shift local keys ret; keys=("$@") if ((${#keys[@]}==0)); then - ble/gdict#keys _ble_complete_sabbrev - keys=("${ret[@]}") + if [[ $type ]]; then + # type が指定されている時は、その type の sabbrev だけ表示する + local dict=_ble_complete_sabbrev_wordwise + case $type in + ([wm]) dict=_ble_complete_sabbrev_wordwise ;; + ([il]) dict=_ble_complete_sabbrev_literal ;; + esac + + local ret key + ble/gdict#keys "$dict" + for key in "${ret[@]}"; do + ble/gdict#get "$dict" "$key" && [[ $ret == "$type":* ]] || continue + ble/array#push keys "$key" + done + else + ble/gdict#keys _ble_complete_sabbrev_wordwise + keys=("${ret[@]}") + ble/gdict#keys _ble_complete_sabbrev_literal + ble/array#push keys "${ret[@]}" + fi ((${#keys[@]})) || return 0 fi @@ -8263,43 +8306,130 @@ function ble/complete/sabbrev/list { local key ext=0 for key in "${keys[@]}"; do - if ble/gdict#get _ble_complete_sabbrev "$key"; then + if ble/gdict#get _ble_complete_sabbrev_wordwise "$key"; then + ble/complete/sabbrev/.print-definition "$key" "$ret" + elif ble/gdict#get _ble_complete_sabbrev_literal "$key"; then ble/complete/sabbrev/.print-definition "$key" "$ret" else ble/util/print "ble-sabbrev: $key: not found." >&2 ext=1 fi done + return "$ext" } function ble/complete/sabbrev/reset { + local type=$1; shift if (($#)); then local key for key; do - ble/gdict#unset _ble_complete_sabbrev "$key" + ble/gdict#unset _ble_complete_sabbrev_wordwise "$key" + ble/gdict#unset _ble_complete_sabbrev_literal "$key" + done + elif [[ $type ]]; then + # type が指定されている時は、その type の sabbrev だけ削除する + + local dict=_ble_complete_sabbrev_wordwise + case $type in + ([wm]) dict=_ble_complete_sabbrev_wordwise ;; + ([il]) dict=_ble_complete_sabbrev_literal ;; + esac + + local ret key + ble/gdict#keys "$dict" + for key in "${ret[@]}"; do + ble/gdict#get "$dict" "$key" && [[ $ret == "$type":* ]] || continue + ble/gdict#unset "$dict" "$key" done else - ble/gdict#clear _ble_complete_sabbrev + ble/gdict#clear _ble_complete_sabbrev_wordwise + ble/gdict#clear _ble_complete_sabbrev_literal fi return 0 } -function ble/complete/sabbrev/get { +function ble/complete/sabbrev/wordwise.get { local key=$1 - ble/gdict#get _ble_complete_sabbrev "$key" + ble/gdict#get _ble_complete_sabbrev_wordwise "$key" } -function ble/complete/sabbrev/get-keys { +function ble/complete/sabbrev/wordwise.get-keys { local ret - ble/gdict#keys _ble_complete_sabbrev + ble/gdict#keys _ble_complete_sabbrev_wordwise keys=("${ret[@]}") } +## @fn ble/complete/sabbrev/literal.find str [opts] +## 最長一致するリテラル略語とその値を取得します。 +## @param[in] str +## @param[in,opt] opts +## コロン区切りのオプションです。 +## +## filter-by-patterns +## patterns 配列に指定されているパターンに一致する sabbrev だけを一致対象 +## とします。 +## @arr[in] patterns +## +## @var[out] key +## @var[out] ret +## +function ble/complete/sabbrev/literal.find { + key= + local ent= opts=$2 key1 ent1 + ble/gdict#keys _ble_complete_sabbrev_literal + for key1 in "${ret[@]}"; do + ((${#key1}>${#key})) || continue + + ble/gdict#get _ble_complete_sabbrev_literal "$key1" || continue; ent1=$ret + [[ $1 == *"$key1" ]] || continue + if [[ $ent1 == l:* ]]; then + ble/string#match "${1%"$key1"}" $'(^|\n)[ \t]*$' || continue + fi + + [[ :$opts: == *:filter-by-patterns:* ]] && + ((${#patterns[@]})) && + ! ble/complete/string#match-patterns "$key1" "${patterns[@]}" && + continue + + key=$key1 ent=$ent1 + done + + ret=$ent + [[ $key ]] +} + +## @fn ble/complete/sabbrev/read-arguments/.set-type opt +## @var[in,out] flags type +function ble/complete/sabbrev/read-arguments/.set-type { + local new_type + case $1 in + (--type=wordwise | -w) new_type=w ;; + (--type=dynamic | -m) new_type=m ;; + (--type=inline | -i) new_type=i ;; + (--type=linewise | -l) new_type=l ;; + (*) + ble/util/print "ble-sabbrev: unknown sabbrev type '${1#--type=}'." >&2 + flags=E$flags + return 1 ;; + esac + + if [[ $type && $type != "$new_type" ]]; then + ble/util/print "ble-sabbrev: arg $1: a conflicting sabbrev type (-$type) has already been specified." >&2 + flags=E$flags + fi + type=$new_type +} + +## @fn ble/complete/sabbrev/read-arguments args... +## @arr[out] specs print +## @var[out] flags type function ble/complete/sabbrev/read-arguments { + specs=() print=() + flags= type= while (($#)); do local arg=$1; shift - if [[ $arg == ?*=* ]]; then - ble/array#push specs "s:$arg" - else + if [[ $flags != L && $arg == -* ]]; then case $arg in + (--) + flags=L$flags ;; (--help) flags=H$flags ;; (--reset) @@ -8310,66 +8440,88 @@ function ble/complete/sabbrev/read-arguments { flags=n${flags//[cn]} ;; (--color=auto) flags=${flags//[cn]} ;; + (--color=*) + ble/util/print "ble-sabbrev: unknown color type '$arg'." >&2 + flags=E$flags ;; + (--type=*) + ble/complete/sabbrev/read-arguments/.set-type "$arg" ;; + (--type) + if ((!$#)); then + ble/util/print "ble-sabbrev: option argument for '$arg' is missing" >&2 + flags=E$flags + else + ble/complete/sabbrev/read-arguments/.set-type "--type=$1"; shift + fi ;; + (--*) + ble/util/print "ble-sabbrev: unknown option '$arg'." >&2 + flags=E$flags ;; (-*) local i n=${#arg} c for ((i=1;i&2 - flags=E$flags - elif [[ $1 != ?*=* ]]; then - ble/util/print "ble-sabbrev: invalid option argument '-$c $1' (expected form: '-$c key=value')" >&2 - flags=E$flags - else - ble/array#push specs "$c:$1"; shift - fi ;; - (r) - flags=r$flags ;; + ([wmil]) ble/complete/sabbrev/read-arguments/.set-type "-$c" ;; + (r) flags=r$flags ;; (*) ble/util/print "ble-sabbrev: unknown option '-$c'." >&2 flags=E$flags ;; esac done ;; - (*) - ble/array#push print "$arg" ;; esac + else + if [[ $arg == ?*=* ]]; then + ble/array#push specs "$arg" + else + ble/array#push print "$arg" + fi fi done + return 0 } ## @fn ble-sabbrev key=value ## 静的略語展開を登録します。 function ble-sabbrev { - local -a specs=() print=() - local flags= + local flags type specs print ble/complete/sabbrev/read-arguments "$@" if [[ $flags == *H* || $flags == *E* ]]; then [[ $flags == *E* ]] && ble/util/print ble/util/print-lines \ - 'usage: ble-sabbrev [KEY=VALUE|-m KEY=FUNCTION]...' \ - 'usage: ble-sabbrev [-r|--reset] [KEY...]' \ + 'usage: ble-sabbrev [--type=TYPE|-wmil] [KEY=VALUE]...' \ + 'usage: ble-sabbrev [-r|--reset] [--type=TYPE|-wmil|KEY...]' \ + 'usage: ble-sabbrev [--color[=auto|always|never]] [--type=TYPE|-wmil|KEY...]' \ 'usage: ble-sabbrev --help' \ - ' Register sabbrev expansion.' + ' Register sabbrev expansion.' \ + '' \ + 'OPTIONS' \ + ' -w, --type=wordwise replace matching word.' \ + ' -m, --type=dynamic run command and replace matching word.' \ + ' -i, --type=inline replace matching suffix.' \ + ' -l, --type=linewise replace matching line.' \ + '' \ + ' -r, --reset remove specified set of sabbrev.' \ + '' \ + ' --color=always enable color output.' \ + ' --color=never disable color output.' \ + ' --color, --color=auto automatically determine color output (default).' \ + '' [[ ! $flags == *E* ]]; return "$?" fi local ext=0 if ((${#specs[@]}==0||${#print[@]})); then if [[ $flags == *r* ]]; then - ble/complete/sabbrev/reset "${print[@]}" + ble/complete/sabbrev/reset "$type" "${print[@]}" else - ble/complete/sabbrev/list "${print[@]}" + ble/complete/sabbrev/list "$type" "${print[@]}" fi || ext=$? fi - local spec key type value + local spec key value for spec in "${specs[@]}"; do - # spec は t:key=value の形式 - type=${spec::1} spec=${spec:2} + # spec は key=value の形式 key=${spec%%=*} value=${spec#*=} - ble/complete/sabbrev/register "$key" "$type:$value" + ble/complete/sabbrev/register "$key" "${type:-w}:$value" done return "$ext" } @@ -8415,6 +8567,11 @@ function ble/complete/sabbrev/locate-key { ## @param[in,opt] opts ## コロン区切りのオプションです。 ## +## wordwise +## literal +## それぞれ wordwise sabbrev および literal sabbrev (line, inline) の展開 +## を実行します。どちらも指定されていない場合は両方実行します。 +## ## pattern=PATTERN ## これが一つ以上指定されていた時は何れかの PATTERN で指定された名前を持 ## つ sabbrev だけ有効にします。 @@ -8422,27 +8579,55 @@ function ble/complete/sabbrev/locate-key { ## strip-slash ## 展開後の末尾に含まれる / を削除します。 ## +## type-status +## 実行した sabbrev の種類を終了ステータスで返します。 +## function ble/complete/sabbrev/expand { - local pos comp_index=$_ble_edit_ind comp_text=$_ble_edit_str opts=$1 - ble/complete/sabbrev/locate-key 'file|command|argument|variable:w|wordlist:.*|sabbrev|rhs' || return 1 + local opts=$1 + local comp_index=$_ble_edit_ind comp_text=$_ble_edit_str + + [[ :$opts: == *:wordwise:* || :$opts: == *:literal:* ]] || + opts=$opts:wordwise:literal + + local -a patterns=() + ble/opts#extract-all-optargs "$opts" pattern && + patterns=("${ret[@]}") + + # wordwise sabbrev と literal sabbrev を両方検索しより長い一致を選択する + local key1= ent1= key2= ent2= + if [[ :$opts: == *:wordwise:* ]]; then + local pos key ret + ble/complete/sabbrev/locate-key 'file|command|argument|variable:w|wordlist:.*|sabbrev|rhs' && + key=${_ble_edit_str:pos:comp_index-pos} && + ble/complete/sabbrev/wordwise.get "$key" && + { ((${#patterns[@]}==0)) || ble/complete/string#match-patterns "$key" "${patterns[@]}"; } && + key1=$key ent1=$ret + fi + if [[ :$opts: == *:literal:* ]]; then + local key ret + ble/complete/sabbrev/literal.find "${_ble_edit_str::comp_index}" filter-by-patterns && + key2=$key ent2=$ret + fi + if ((${#key1}>=${#key2})); then + local key=$key1 ent=$ent1 + else + local key=$key2 ent=$ent2 + fi + [[ $key ]] || return 1 - local key=${_ble_edit_str:pos:comp_index-pos} - local ret; ble/complete/sabbrev/get "$key" || return 1; local ent=$ret + local type=${ent%%:*} value=${ent#*:} - if ble/opts#extract-all-optargs "$opts" pattern; then - local pattern found= - for pattern in "${ret[@]}"; do - [[ $key == $pattern ]] || continue - found=1 - break - done - [[ $found ]] || return 1 + local exit=0 + if [[ :$opts: == *:type-status:* ]]; then + local ret + ble/util/s2c "$type" + exit=$ret fi - local type=${ent%%:*} value=${ent#*:} case $type in - (s) + ([wil]) [[ :$opts: == *:strip-slash:* ]] && value=${value%/} + local pos=$((comp_index-${#key})) ble/widget/.replace-range "$pos" "$comp_index" "$value" ((_ble_edit_ind=pos+${#value})) ;; (m) @@ -8482,7 +8667,7 @@ function ble/complete/sabbrev/expand { [[ :$opts: == *:strip-slash:* ]] && value=${value%/} ble/widget/.replace-range "$pos" "$comp_index" "$value" ((_ble_edit_ind=pos+${#value})) - return 0 + return "$exit" fi # Note: 既存の内容 (key) は削除する @@ -8496,7 +8681,7 @@ function ble/complete/sabbrev/expand { return 147 ;; (*) return 1 ;; esac - return 0 + return "$exit" } function ble/widget/sabbrev-expand { if ! ble/complete/sabbrev/expand; then @@ -8513,11 +8698,11 @@ function ble/complete/action:sabbrev/init-menu-item { show=$INSERT } function ble/complete/action:sabbrev/get-desc { - local ret; ble/complete/sabbrev/get "$INSERT" + local ret; ble/complete/sabbrev/wordwise.get "$INSERT" desc="$desc_sgrt(sabbrev)$desc_sgr0 $ret" } function ble/complete/source:sabbrev { - local keys; ble/complete/sabbrev/get-keys + local keys; ble/complete/sabbrev/wordwise.get-keys "$opts" local filter_type=$comp_filter_type [[ $filter_type == none ]] && filter_type=head diff --git a/make_command.sh b/make_command.sh index f30ecca4..6b5f2144 100755 --- a/make_command.sh +++ b/make_command.sh @@ -1184,6 +1184,7 @@ function sub:scan/bash404-no-argument-return { \Zif \(REQ == "[A-Z]+"\)Zd \Z\(return\|ret\)Zd \Z_ble_trap_done=return$Zd + \Z\bwe return\bZd g' } diff --git a/note.txt b/note.txt index da201239..2b30bc10 100644 --- a/note.txt +++ b/note.txt @@ -3513,10 +3513,6 @@ bash_tips 2021-05-19 - * sabbrev: 単語でなくても任意の文脈で発動する sabbrev が欲しい。\ 等で前置す - れば特に問題ないのではないか? 然し、その為には全ての場合について一致するか - どうか確認する必要がある。 - * complete: [TAB] 補完の場合には、ユーザー入力があった時に即座にキャンセルす るのではなくて timeout があっても良いのかもしれない。 @@ -6630,6 +6626,151 @@ bash_tips 2023-03-08 + * 2021-05-19 sabbrev: 単語でなくても任意の文脈で発動する sabbrev が欲しい [#D2012] + + \ 等で前置すれば特に問題ないのではないか? 然し、その為には全ての場合につい + て一致するかどうか確認する必要がある。 + + 2023-03-08 どうも実際に \ に色々割り当てて使おうとしている人がいる様だ。こ + の用途だと実際に単語でしか発動しないというのは困るのではないだろうか。 + https://github.com/akinomyoga/ble.sh/discussions/288#discussioncomment-5226973 + + 例えば ble-sabbrev --literal 的なオプションにするのはどうだろうか。通常の + sabbrev が見つからない場合に --literal sabbrev を試みる。literal sabbrev に + 関しては -m は対応しなくて良い (もしかしたら最終的に実装する可能性もあるが + 今ではない)。 + + ? resolved: 取り敢えず literal という名前で実装したが本当にそれで良いのか。 + + % literal というと -m の反対という気もするし、そもそも sabbrev 自体が + % literal である。元々伝えたかったのは文法情報等を無視した sabbrev という + % 事だった。例えば context-free sabbrev expansions 等の方が自然の気がする。 + % 然し、context-free を表現するオプション名として適切な物が思い浮かばない。 + % + % a 何も考えなければ頭文字の -c だが、実際は context 依存の逆という事なの + % で変な気がする。 + % + % 或いは漢字変換的な使い方を想定して conversion の頭文字と取る事もでき + % る? 然し漢字変換というとどういう名前だろうか。IME と考えて -i とする + % か。然しそれだと i は input の i なので一般的すぎて微妙? 否、input 専 + % 用と思えばやはり良い? 然しオプション名が例えば input-no-insert だとよ + % く分からない。やはり実際の呼称と紐づいたオプション文字にしたいと考え + % ると呼称自体から丁寧に決めたい。 + % + % b context に依存しないという意味でやはり literal 的な要素があって、そう + % 思うと -l でも良い様な気もしてくる。 + % + % c -c の逆という事で -C 等を使うという可能性もある? がやはり分かりにくい + % 気がする。 + % + % d -f はどうだろうか。ble-bind -f (bindable Function) という既存の例があっ + % てその印象があるが、それを抜きにすれば悪くない気はする。然し、やはり + % 自然かというと疑問が残る。 + % + % e 英小文字にしたい。という事を考えると片っ端から可能な物を列挙して考え + % てみても良いのかもしれない。zsh alias で既に使われているオプションは + % 避けたい。 + % + % zsh alias で使われているのは gmrsL である。grs はそれぞれ alias の種 + % 類を指定する為のオプションで、-g はグローバル alias (ble-sabbrev に対 + % 応)、-s は suffix alias (拡張子展開)、-r は通常 alias である。-m + % PATTERN はまとめて複数の alias を glob で指定するのに使う。-L は現在 + % の alias の定義を出力するのに使われる。 + % + % ble-sabbrev では -P を出力に使いたい気がする。 + % + % * -a は grep の -a の様に文字列 (ascii) をそのまま解釈するという意味 + % に使えるかもしれない。 + % + % 或いは anywhere という意味にも取れる。これが良い気がする (anywhere + % という意味に取れば every where -e もありかもしれないが -e はより色々 + % な意味に取れそう)。でも anywhere というのも微妙なのは、anywhere と + % 言いつつカーソルの直前で起こる必要があるという事。何処からスタート + % しても良いという意味での anywhere であるが、それを表現するのに丁度 + % 良い別の表現はあるだろうか。 + % + % * -b は backward? + % * -i は inplace という漢字がするけれど違う気もする。 + % * -djkwyz ??? + % x -e は grep の様に次に通常のパターンが来るという意味の引数に使えるか + % もしれないが、それはいま目的としている物とは違う気がする。 + % x -gs は既に zsh で別用途に使われているので混乱の元 + % x -n は特別な効果を全て削除しているという雰囲気が出るかもしれない? で + % もやはり変な気がする + % x -o はオプションを指定しそうな気がする。 + % x -p は出力という漢字がする。 + % x -q は quoted という感じがするが現在の目的からすると混乱の元 + % x -t は tail という意味に取れる気もするがそもそも sabbrev は常に末尾 + % にカーソルがある時に発火している。これは context-free sabbrev 特有 + % の特徴ではない。類似の考えで -h (here) 的なものも駄目。 + % x -u は変更のある項目の選択に使いそう? でも ble-sabbrev に既存設定や + % 既定値などない為、登録されている全ての物が変更ありになるのでこのオ + % プションをその意味で使っても意味がない。 + % x -v も literal 的なものを想起する。C-v 関係だろう。然し、これも現在 + % の用途に合っているかというと微妙な気がする。 + % x -x は何か実行しそう。 + % + % 長い呼称を先に決めてからそれの短縮オプション文字を決めるのが良さそう。 + % + % literal-no-insert, conversion-no-insert, contextfree-no-insert, + % inplace-no-insert, inword-no-insert 等。うーん。inword が良い気がしてき + % た。類似の物として inword subword, substr, substring, suffix, 等。 + % inword だと空白も含む略語展開に合わないし、丁度単語に一致している時も変 + % な気がする。代わりに inline というのも良いのかもしれない、と思ったが + % sabbrev 自体既にある意味で inline なので混乱の元かもしれない。唯の置換 + % と思えば substitute だとか replace だとかもありなのだろうか。然し、これ + % も sabbrev 一般の性質を表して言えるのに過ぎない。 + + うーん。コマンド行全体に作用する sabbrev も定義したくなって来た。それも定 + 義すれば全体として consistent になる気がする。 + + →結局 -l (--linewise) 及び -i (--inline) を両方定義する事にした。これが + インターフェイス的にも分かりやすい。 + + * done: 取り敢えず実装仕掛けた literal は inline に変更する。と思ったが、-il + をまとめて linewise と呼ぶ事にする。 + + * done: wordwise vs literal は最長一致に変更する。呼び出し元で一々指定しな + くて良い様にする。同時にどの種類の展開が起こったのかを取得できる仕組みを + 作る。文字で返すのが良い? もしくは終了ステータス? + + * done: 現在の実装では inline も単語で切ってから判定しているが + _ble_edit_str 全体に対して適用するべきの気がする。 + + * done: 呼び出し元に展開の種類を返す機能。 + + * done: ble-sabbrev の -mil は全体に作用する様にインターフェイスを変更する。 + + * done: ble-sabbrev に long option を用意する事にする。 + + * done: wiki: ble-sabbrev -il + + * done: wiki: edit_magic_opts + * done: blerc: edit_magic_opts + + * done: -w で通常の sabbrev の種類を選択できる様にする。通常の sabbrev を選 + 択するのに毎回 --type=wordwise としなければならないのは不便である。 + + ? resolved: linewise は本当に linewise と呼んで良いのか? コマンドライン全体 + に一致するのだから bufferwise とか whole とか all とか exact とかにするべ + きなのでは。或いは実際に linewise に一致する様に変更した方が便利? その時 + にはインデントも許す様にする。extglob を一時的に有効にしないと面倒だろう + か。 + + [[ $1 == "$key" || $1 == *$'\n'*(["$sp"])"$key" ]] + + 或いは $'\n' で切断して trim しても良いかもしれないと思ったがそうすると今 + 度は key に改行や空白が含まれていた場合に都合が悪い。それに trim は regex + を使っているので別に extglob よりも早いとも限らない。 + + extglob は実装の問題から遅くなる可能性があるがそれは気にしない事にする? + と思ったが現在の codebase では extglob はほぼ使っていない。というか確認し + てみたらユーザーの提供したパターンなどを評価するときを除いて全く使用して + いない。なので、ここでも使わない実装を目指したい様な気もする。 + + というか最初に末尾が $key に一致するか確かめてその上で残っている文字列に + 対して regex で確認を行えば良いだけなのでは? その様に実装する事にする。 + * 2023-03-02 complete (source:argument): sabbrev 候補が気になるのは最初に表示されるから? (motivated by mozirilla213) [#D2011] https://github.com/akinomyoga/ble.sh/discussions/288 diff --git a/src/edit.sh b/src/edit.sh index 8100471f..a0fcc400 100644 --- a/src/edit.sh +++ b/src/edit.sh @@ -95,6 +95,7 @@ bleopt/declare -v undo_point end bleopt/declare -n edit_forced_textmap 1 bleopt/declare -n edit_magic_expand history:sabbrev +bleopt/declare -v edit_magic_opts '' function ble/edit/use-textmap { ble/textmap#is-up-to-date && return 0 @@ -7819,19 +7820,23 @@ function ble/widget/magic-space { local oind=$_ble_edit_ind ostr=$_ble_edit_str local arg; ble-edit/content/get-arg '' + local opts=$bleopt_edit_magic_opts - local expanded= + local expanded= opt_noinsert= # (1) history expansion if [[ :$bleopt_edit_magic_expand: == *:history:* ]]; then ble/widget/history-expand-backward-line && expanded=1 fi # (2) sabbrev expansion if [[ ! $expanded && :$bleopt_edit_magic_expand: == *:sabbrev:* ]]; then - ble/complete/sabbrev/expand; local ext=$? - if ((ext==147)); then - return 147 # sabbrev/expand の中でメニュー補完に入った時など。 - elif ((ext==0)); then + ble/complete/sabbrev/expand type-status; local ext=$? + if ((ext==0||32<=ext&&ext<=126)); then expanded=1 + ((ext==105)) && # 105 = 'i' (inline sabbrev) + [[ :$opts: == *:inline-sabbrev-no-insert:* ]] && + opt_noinsert=1 + elif ((ext==147)); then + return 147 # メニュー補完に入った時 fi fi # (3) alias expansion @@ -7840,18 +7845,19 @@ function ble/widget/magic-space { fi # keymap/vi.sh - [[ $_ble_decode_keymap == vi_imap ]] && - if [[ $ostr != "$_ble_edit_str" ]]; then - _ble_edit_ind=$oind _ble_edit_str=$ostr ble/keymap:vi/undo/add more - ble/keymap:vi/undo/add more - fi + if [[ $_ble_decode_keymap == vi_imap && $ostr != "$_ble_edit_str" ]]; then + _ble_edit_ind=$oind _ble_edit_str=$ostr ble/keymap:vi/undo/add more + ble/keymap:vi/undo/add more + fi - local -a KEYS=(32) - _ble_edit_arg=$arg - ble/widget/self-insert + if [[ ! $opt_noinsert ]]; then + local -a KEYS=(32) + _ble_edit_arg=$arg + ble/widget/self-insert + fi } function ble/widget/magic-slash { - ble/complete/sabbrev/expand pattern='~*':strip-slash + ble/complete/sabbrev/expand wordwise:pattern='~*':strip-slash (($?==147)) && return 147 # sabbrev/expand の中でメニュー補完に入った時など。 local -a KEYS=(47) # /