Как изменить отмену гранулярности в Vim?

11

В какой-то момент мой Vim отменит целое слово, когда я нажму u.

[i]typing some words[C-c][u]

Приведет к

typing some

Однако отмена детализации, похоже, изменилась на удаление одной буквы за раз.

[i]typing some words[C-c][u]

Результаты в

typing some word

Я помню, как читал кое-что о настройке отмены детализации в Practical Vim, но не могу вспомнить, как это контролировать. Любая помощь приветствуется!

Дэн Принц
источник
2
Возможно, в вашем vimrc есть что-то, что делает это. Я не могу скопировать его и ничего не могу найти в :helpфайлах об этом ... См .: Как мне отладить мой файл vimrc? ... Кроме того, использование <C-c>для выхода из режима вставки может иметь побочные эффекты ( см. Это ) и может быть частью проблемы ... Я бы предложил использовать Escили <C-[>( см. Это )
Martin Tournoij

Ответы:

11

Ручное нарушение последовательности отмены

Вы можете вручную прервать последовательность отмен в режиме вставки с помощью <C-G>u. Из справки :

CTRL-G u        break undo sequence, start new change

пример

iHello<C-G>u world!<Esc>u

Это оставит вас с текстом

Hello

Разбивка команд

i                           " Enter Insert mode
 Hello                      " Type 'Hello'
      <C-G>u                " Break the undo sequence
             world!         " Type ' world!'
                   <Esc>    " Return to Normal mode
                        u   " Undo

Автоматическое решение

Более тонкий контроль уровня отмены

Вот небольшой фрагмент VimScript, который используется <C-G>uдля создания разрывов отмены, когда вы начинаете удалять текст, а также когда вы начинаете вводить текст снова после удаления.

function! s:start_delete(key)
    let l:result = a:key
    if !s:deleting
        let l:result = "\<C-G>u".l:result
    endif
    let s:deleting = 1
    return l:result
endfunction

function! s:check_undo_break(char)
    if s:deleting
        let s:deleting = 0
        call feedkeys("\<BS>\<C-G>u".a:char, 'n')
    endif
endfunction

augroup smartundo
    autocmd!
    autocmd InsertEnter * let s:deleting = 0
    autocmd InsertCharPre * call s:check_undo_break(v:char)
augroup END

inoremap <expr> <BS> <SID>start_delete("\<BS>")
inoremap <expr> <C-W> <SID>start_delete("\<C-W>")
inoremap <expr> <C-U> <SID>start_delete("\<C-U>")

Ноты

Это будет работать для <BS>, <C-W>(удалить слово), и <C-U>(удаление в начале строки). Если в режиме вставки есть другие способы удаления, их можно поддержать, добавив дополнительные inoremapвызовы в конце.

tommcdo
источник
4
Единственная проблема в том, что вы не предвидите, что будете удалять позже (иначе вы не будете делать это в первую очередь). Таким образом, вы обычно сталкиваетесь с ситуацией, в которой вы хотели бы использовать ее <C-G>u, что уже слишком поздно.
Шахбаз
4
Да. На самом деле, я что-то упустил сам, это. Иногда я делаю это с iпоследующим длинным предложением с последующим пробелом, чтобы удалить часть того, что я написал (все в режиме вставки). Тогда я понимаю, что не должен был отступать, и то, что я написал, было в порядке. Я отменяю, но затем весь вставленный текст отменяется. Так что либо у меня нет ни одного длинного предложения, ни части, которая не стоит на заднем плане. Невозможно вернуть часть с возвратом назад. Есть ли способ сказать Vim, чтобы прервать последовательность отмены после возврата? (Теперь, когда я это говорю, mapконечно , можно использовать ing backspace).
Шахбаз
2
Для будущих посетителей я также добавил, inoremap <CR> <C-G>u<CR>что каждая отмена содержится в одной строке (больше не нужно отменять весь абзац, который вы набирали без перерыва).
Шахбаз
1
@Shahbaz, абсолютно :)
Tommcdo
1
@ Shahbaz "Разрешено ли мне копировать?" См. Ссылку внизу страницы: «Пользовательские вклады лицензируются в соответствии с cc by-sa 3.0 с указанием авторства»