Bagaimana cara mengubah membatalkan granularitas di Vim?

11

Pada titik tertentu Vim saya akan membatalkan seluruh kata ketika saya menekan u.

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

Akan menghasilkan

typing some

Namun, membatalkan perincian tampaknya telah berubah untuk menghapus satu huruf sekaligus.

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

Hasil dalam

typing some word

Saya ingat pernah membaca sesuatu tentang menyesuaikan undian granularity di Practical Vim, tetapi saya tidak ingat bagaimana cara mengendalikannya. Bantuan apa pun dihargai!

Dan Prince
sumber
2
Mungkin ada sesuatu di vimrc Anda yang melakukan ini. Saya tidak dapat mereplikasi, dan tidak dapat menemukan apa pun di :helpfile tentang itu ... Lihat: Bagaimana cara saya debug file vimrc saya? ... Juga, menggunakan <C-c>untuk keluar dari mode penyisipan mungkin memiliki efek samping ( lihat ini ) dan mungkin menjadi bagian dari masalah ... Saya akan menyarankan menggunakan Escatau <C-[>( lihat ini )
Martin Tournoij

Jawaban:

11

Memecah urutan undo secara manual

Anda dapat memecahkan urutan undo secara manual dalam mode Insert with <C-G>u. Dari bantuan :

CTRL-G u        break undo sequence, start new change

Contoh

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

Ini akan meninggalkan Anda dengan teks

Hello

Kerusakan perintah

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

Solusi otomatis

Kontrol undo-level berbutir halus

Berikut ini adalah potongan kecil VimScript yang digunakan <C-G>uuntuk membuat jeda ketika Anda mulai menghapus teks, dan juga ketika Anda mulai memasukkan teks lagi setelah penghapusan.

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>")

Catatan

Ini akan berfungsi untuk <BS>, <C-W>(menghapus kata), dan <C-U>(hapus ke awal baris). Jika ada lebih banyak cara untuk menghapus dalam mode Sisipkan, mereka dapat didukung dengan menambahkan inoremappanggilan tambahan di akhir.

tommcdo
sumber
4
Satu-satunya masalah adalah, Anda tidak melihat bahwa Anda akan kehancuran nanti (jika tidak, Anda tidak akan melakukannya di tempat pertama). Jadi Anda biasanya berakhir dengan situasi di mana Anda berharap telah menggunakan <C-G>u, yang sudah terlambat.
Shahbaz
4
Iya. Sebenarnya sesuatu yang saya rindukan adalah ini. Kadang-kadang saya melakukan ini idiikuti oleh kalimat panjang diikuti oleh backspace untuk menghapus bagian dari apa yang saya tulis (semua dalam mode insert). Kemudian saya menyadari bahwa saya seharusnya tidak mundur dan apa yang saya tulis baik-baik saja. Saya membatalkan, tetapi kemudian seluruh teks yang dimasukkan dibatalkan. Jadi entah saya tidak memiliki kalimat yang panjang, atau bagian yang tidak mundur. Tidak mungkin mendapatkan bagian backspace kembali. Apakah ada cara untuk memberitahu vim untuk memutus urutan undo pada backspace? (Sekarang saya katakan itu, mapbackspace adalah pilihan tentu saja).
Shahbaz
2
Untuk pengunjung yang akan datang, saya juga menambahkan inoremap <CR> <C-G>u<CR>agar setiap undo dimuat dalam satu baris (tidak lagi membatalkan seluruh paragraf yang Anda ketikkan tanpa henti).
Shahbaz
1
@ Shahbaz, tentu saja :)
tommcdo
1
@ Shahbaz, "Apakah saya diizinkan menyalin?" Lihat tautan di bagian bawah halaman: "kontribusi pengguna dilisensikan di bawah cc by-sa 3.0 dengan atribusi yang diperlukan"