правок:VIM undo: Почему курсор переходит в неправильное положение при отмене `undojoin`?
Я упрощены функции и осветленные вопрос.
Оригинальный вопрос по-прежнему доступен далее по странице.Crossposted на список vim_dev рассылки: https://groups.google.com/forum/#!topic/vim_dev/_Rz3uVXbwsQ
Сообщается как об ошибке Neovim:
https://github.com/neovim/neovim/issues/6276
Почему курсор позиционируется по-разному в двух следующих примерах :
[ПРАВИЛЬНАЯ позиции курсора] Следующий тест производит ожидаемое изменение результата замещения присоединилось к предыдущему изменению в буфере (добавление строки 3), позиция курсора находится правильно восстановлен во второй строке в буфере ,
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
[НЕПРАВИЛЬНЫЕ позиции курсора] Следующий тест дает неожиданный результат: изменение замены присоединяются к предыдущему изменению в буфере (добавление линии 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 UmkaDK#StripTrailingSpaces(0)
Осмотрев Restore the cursor position after undoing text change made by a script, я получил представление о том, чтобы исключить изменения, сделанные мой 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
Как вы можете видеть, после отмены последнего изменения в буфере, который создает третью строку, курсор правильно возвращается ко второй строке файла.
С момента моего тестирования я реализовал почти идентичный undojoin
в своем StripTrailingSpaces(). Однако, когда я отменю последнее изменение после запуска функции, курсор возвращается к самому большому изменению файла. Это часто разделенное пространство и составляет не позиция изменения I undojoin
-ed to.
Может кто-нибудь подумать, почему это было бы? Еще лучше, может ли кто-нибудь предложить исправить?
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
Извините, но какая разница между этими 75 строками и ':% s/\ s * $ /'? – steffen
@steffen: Ну ... его 74 строки и 2866 символов длиннее ... он также содержит описательные комментарии, сохраняет историю поиска и последнюю строку поиска, не изменяет ваши метки '' '', ''. 'И' '^', не добавляет новую запись 'jumplist' и' changelist', сохраняет ваш взгляд и позицию курсора, а * должен * создавать более гладкий случай отмены. (Хотя последний пункт субъективен и является причиной этого вопроса.) – UmkaDK
Позиция курсора запоминается перед внесением изменений, а затем восстанавливается после отмены изменений. –