10

編集:


次の 2 つの例で、カーソルの位置が異なるのはなぜですか。

  1. [正しいカーソル位置] 置換の結果は、バッファー内の前の変更 (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
    
  2. [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
4

1 に答える 1