rhysd / clever-f.vim

Extended f, F, t and T key mappings for Vim.
https://rhysd.github.io/clever-f.vim
1.01k stars 44 forks source link

日本語限定:カーソル行に同じ全角英字が二つ以上ある場合にエラーが出る #80

Open s-kiraku opened 1 month ago

s-kiraku commented 1 month ago

環境

Vim: 8.2 OS: Ubuntu ロケール: 日本語環境(enc=utf-8)

事象

以下のオプションが設定されているかつカーソル行に全角の大文字が重複して存在する場合、 f/F/t/T の何れかを実行すると clever_f#_mark_direct 関数にてエラー(E716: Key not present in Dictionary)が発生する。

具体的には、xBB という行に対して x の位置で :call clever_f#find_with('f') を実行すると、エラーE716: Key not present in Dictionary: "b" が発生する。

原因

clever_f#_mark_direct 関数には g:clever_f_smart_case が有効な時は tolower 関数を用いて大文字を小文字とみなす処理が入っていますが、それが全角英字のケースを想定していないためだと思われます。tolower 関数は全角の大文字も全角の小文字に変換する(tolower('B') = 'b')のに対して、大文字かどうかを判定する処理(正規表現 \u )が全角の大文字に対応していないことが不具合の中心かと。

具体的には autoload/clever_f.vim の 176 行目からの処理が次のようになります:

" ch = 'B' とすると、ch_lower = 'b' となる
let ch_lower = tolower(ch)

let char_count[ch] = get(char_count, ch, 0) + 1
" 'B' =~# '\u' == 0 なので char_count['b'] は設定されない
if g:clever_f_smart_case && ch =~# '\u'
    " uppercase characters are doubly counted
    let char_count[ch_lower] = get(char_count, ch_lower, 0) + 1
endif

" char_count['b'] が未設定なので E716 が発生
if char_count[ch] == a:count ||
    \ (g:clever_f_smart_case && char_count[ch_lower] == a:count)

対応?

とりあえず自分の環境では UTF-8 しか使わないので、

if g:clever_f_smart_case && ch =~# '\u\|[A-Z]'

として問題を回避しました。

rhysd commented 1 month ago

詳細な報告ありがとうございます.大変助かります.時間がある時に見てみます.