編集:
関数を単純化し、質問を明確にしました。
元の質問は、ページの下の方にまだあります。vim_dev メーリング リストへの相互投稿: https://groups.google.com/forum/#!topic/vim_dev/_Rz3uVXbwsQ
Neovim にバグとして報告:
https://github.com/neovim/neovim/issues/6276
次の 2 つの例で、カーソルの位置が異なるのはなぜですか。
[正しいカーソル位置] 置換の結果は、バッファー内の前の変更 (3 行目の追加) に結合され、カーソル位置はバッファー内の 2 行目に正しく復元されます。
normal ggiline one is full of aaaa set undolevels=10 " splits the change into separate undo blocks normal Goline two is full of bbbb set undolevels=10 normal Goline three is full of cccc set undolevels=10 undojoin keepjumps %s/aaaa/zzzz/ normal u
[INCORRECT CURSOR POSITION] 置換の結果はバッファ内の前の変更 (行 4 の追加) に結合され、カーソル位置はバッファ内の最初の行 (行 3 である必要があります) に誤って復元されます。
normal ggiline one is bull of aaaa set undolevels=10 " splits the change into separate undo blocks normal Goline two is full of bbbb set undolevels=10 normal Goline three is full of cccc set undolevels=10 normal Goline four is full of aaaa's again set undolevels=10 undojoin keepjumps %s/aaaa/zzzz/ normal u
元の質問
私のVIMの設定方法、バッファをファイルに保存すると、カスタムStripTrailingSpaces()関数がトリガーされます(質問の最後に添付されています):
autocmd BufWritePre,FileWritePre,FileAppendPre,FilterWritePre <buffer>
\ :keepjumps call StripTrailingSpaces(0)
スクリプトによって行われたテキスト変更を元に戻した後にカーソル位置を復元するのを見た後、StripTrailingSpaces() 関数によって作成された元に戻すレコードを前の変更の最後にマージすることにより、元に戻す履歴から私の StripTrailingSpaces() 関数によって行われた変更を除外するというアイデアを得ましたバッファ。
この方法では、変更を元に戻すときに、関数が独自の元に戻すレコードをまったく作成していないように見えます。
私のアイデアを検証するために、単純なテスト ケースを使用しました。クリーン バッファを作成し、次のコマンドを手動で入力するか、次のブロックをファイルとして保存し、次の方法でソースを取得します。
vim +"source <saved-filename-here>"
normal ggiline one is full of aaaa
set undolevels=10 " splits the change into separate undo blocks
normal Goline two is full of bbbb
set undolevels=10
normal Goline three is full of cccc
set undolevels=10
undojoin
keepjumps %s/aaaa/zzzz/
normal u
ご覧のとおり、バッファ内の最後の変更を取り消した後、つまり 3 行目を作成すると、カーソルはファイルの 2 行目に正しく戻ります。
テストがうまくいったのでundojoin
、StripTrailingSpaces() にほぼ同じものを実装しました。ただし、関数の実行後に最後の変更を元に戻すと、カーソルはファイルの一番上の変更に戻ります。これは多くの場合、取り除かれたスペースであり、私が変更した位置ではありませんundojoin
。
これがなぜなのか、誰でも考えられますか?さらに良いことに、誰かが修正を提案できますか?
function! StripTrailingSpaces(number_of_allowed_spaces)
" Match all trailing spaces in a file
let l:regex = [
\ '\^\zs\s\{1,\}\$',
\ '\S\s\{' . a:number_of_allowed_spaces . '\}\zs\s\{1,\}\$',
\ ]
" Join trailing spaces regex into a single, non-magic string
let l:regex_str = '\V\(' . join(l:regex, '\|') . '\)'
" Save current window state
let l:last_search=@/
let l:winview = winsaveview()
try
" Append the comming change onto the end of the previous change
" NOTE: Fails if previous change doesn't exist
undojoin
catch
endtry
" Substitute all trailing spaces
if v:version > 704 || v:version == 704 && has('patch155')
execute 'keepjumps keeppatterns %s/' . l:regex_str . '//e'
else
execute 'keepjumps %s/' . l:regex_str . '//e'
call histdel('search', -1)
endif
" Restore current window state
call winrestview(l:winview)
let @/=l:last_search
endfunction