Modification:Annuler VIM: pourquoi le curseur saute-t-il à la mauvaise position en annulant `undojoin`?
J'ai simplifié la fonction et a explicité la question.
La question initiale est toujours disponible plus bas sur la page.Crossposted sur la liste de diffusion de vim_dev: https://groups.google.com/forum/#!topic/vim_dev/_Rz3uVXbwsQ
Rapporté comme un bug à Neovim:
https://github.com/neovim/neovim/issues/6276
Pourquoi le curseur positionné différemment dans les deux exemples suivants :
[POSITION CORRECT CURSOR] Le test suivant produit le changement de substitution de résultat attendu est relié au changement précédent dans le tampon (addition de la ligne 3), la position du curseur est correctement restauré à la seconde ligne dans la mémoire tampon .
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
[CURSOR position incorrecte] Le test suivant produit un résultat inattendu: le changement de substitution est relié au changement précédent dans le tampon (addition de la ligne 4), la position du curseur est incorrectement restauré à la première ligne dans le tampon (devrait être la ligne 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
Original Question
La façon dont mon VIM est mis en place, la sauvegarde d'un tampon à un fichier déclenche une fonction StripTrailingSpaces personnalisés() (ci-joint à la fin de la question):
autocmd BufWritePre,FileWritePre,FileAppendPre,FilterWritePre <buffer>
\ :keepjumps call UmkaDK#StripTrailingSpaces(0)
Après avoir vu Restore the cursor position after undoing text change made by a script, j'ai eu une idée d'exclure les modifications apportées par mes StripTrailingSpaces() fonctionne à partir de l'historique d'annulation en fusionnant l'enregistrement d'annulation créé par la fonction à la fin de la modification précédente dans le tampon. De cette façon, lorsque vous annulez des modifications, il semble que la fonction n'ait pas du tout créé son propre enregistrement d'annulation.
Pour valider mon idée que je l'ai utilisé un exemple simple de test: créer un tampon propre et entrez les commandes suivantes manuellement ou enregistrer le bloc suivant dans un fichier et de la source via:
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
Comme vous pouvez le voir, après avoir annulé la dernière modification dans le tampon, c'est-à-dire en créant la troisième ligne, le curseur est correctement renvoyé à la deuxième ligne du fichier.
Depuis que mon test a fonctionné, j'ai implémenté un undojoin
presque identique dans mes StripTrailingSpaces(). Toutefois, lorsque j'annule la dernière modification après l'exécution de la fonction, le curseur est renvoyé à la plus grande modification du fichier. Ceci est souvent un espace dénudé et n'est pas la position de la modification I undojoin
-ed à.
Quelqu'un peut-il penser à pourquoi ce serait? Mieux encore, quelqu'un peut-il suggérer une solution?
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
Désolé, mais quelle est la différence entre ces 75 lignes et ':% s/\ s * $ /'? – steffen
@steffen: Eh bien ... ses 74 lignes et 2866 caractères de plus ... il a aussi des commentaires descriptifs, préserve votre historique de recherche et la dernière chaîne de recherche, ne change pas vos marques ''' ','' .' et ''^', n'ajoute pas un nouvel enregistrement 'jumplist' et' changelist', préserve la position de votre vue et du curseur, et * devrait * créer une expérience d'annulation plus douce. (Bien que le dernier point soit subjectif et la raison pour laquelle cette question est ici.) – UmkaDK
La position du curseur est mémorisée avant d'effectuer des modifications, puis restaurée après avoir annulé les modifications. –