modifiche:VIM annulla: Perché il cursore salta nella posizione sbagliata quando si annulla il `annullamento '?
Ho semplificato la funzione e chiarito la questione.
La domanda originale è ancora disponibile più in basso nella pagina.Crosspost sul vim_dev lista: https://groups.google.com/forum/#!topic/vim_dev/_Rz3uVXbwsQ
riportato come un insetto di Neovim:
https://github.com/neovim/neovim/issues/6276
Perché il cursore posizionato diverso nei due seguenti esempi :
[CORRETTO POSIZIONE CURSORE] Il seguente test produce la variazione sostituzione risultato atteso è unito alla modifica precedente nel buffer (aggiunta di linea 3), la posizione del cursore è correttamente ripristinato alla seconda linea nel buffer .
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
[INESATTA POSIZIONE CURSORE] Il seguente test produce un risultato inatteso: modifica sostituzione è unito alla modifica precedente nel buffer (aggiunta di linea 4), la posizione del cursore è erroneamente ripristinato alla prima linea nel buffer (dovrebbe essere la riga 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
domanda iniziale
Il modo in cui la mia VIM è impostato, il salvataggio di un buffer per un file innesca una StripTrailingSpaces personalizzati() la funzione (in allegato alla fine della questione):
autocmd BufWritePre,FileWritePre,FileAppendPre,FilterWritePre <buffer>
\ :keepjumps call UmkaDK#StripTrailingSpaces(0)
Dopo aver visto Restore the cursor position after undoing text change made by a script, mi è venuta un'idea per escludere le modifiche apportate dai miei StripTrailingSpaces() funzione dalla cronologia degli annullamenti unendo il record di annullamento creato dalla funzione alla fine della modifica precedente nel buffer.
In questo modo, quando si annullano le modifiche, sembra che la funzione non abbia creato il proprio record di annullamento.
Per convalidare la mia idea ho usato un semplice caso di test: creare un buffer pulito e immettere i seguenti comandi manualmente, o salvare il seguente blocco come un file e la fonte tramite:
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
Come si può vedere, dopo aver annullato l'ultima modifica nel buffer, che sta creando la terza riga, il cursore viene correttamente restituito alla seconda riga del file.
Poiché il mio test ha funzionato, ho implementato un identico undojoin
nel mio StripTrailingSpaces(). Tuttavia, quando annullo l'ultima modifica dopo l'esecuzione della funzione, il cursore viene riportato all'inizio della maggior parte delle modifiche nel file. Questo è spesso uno spazio vuoto ed è non la posizione della modifica I undojoin
-ed a.
Qualcuno può pensare perché questo sarebbe? Meglio ancora, qualcuno può suggerire una correzione?
function! UmkaDK#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:[email protected]/
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
Ci dispiace, ma qual è la differenza tra queste 75 righe e ':% s/\ s * $ /'? – steffen
@steffen: Beh ... le sue 74 righe e 2866 caratteri più a lungo ... ha anche commenti descrittivi, conserva la cronologia delle ricerche e l'ultima stringa di ricerca, non cambia i segni "" "," "." E "^", non aggiunge un nuovo record 'jumplist' e' changelist', conserva la vista e la posizione del cursore e * dovrebbe * creare un'esperienza di annullamento del fumo. (Anche se l'ultimo punto è soggettivo ed è la ragione per cui questa domanda è qui.) – UmkaDK
La posizione del cursore viene ricordata prima di apportare modifiche e quindi ripristinata dopo aver annullato le modifiche. –