Vim: komentar otomatis di baris baru

9

Vim secara otomatis memasukkan komentar ketika saya memulai baris baru dari baris komentar, karena saya telah menetapkan formatoptions=tcroql. Misalnya (kursor adalah *):

// this is a comment*

dan setelah memukul <Enter>(masukkan mode) atau o(mode normal) saya dibiarkan dengan:

// this is a comment
// *

Fitur ini sangat berguna ketika menulis komentar multi-baris yang panjang, tetapi seringkali saya hanya ingin komentar satu baris. Sekarang jika saya ingin mengakhiri seri komentar saya memiliki beberapa opsi:

  • memukul <Esc>S
  • tekan <BS>tiga kali

Keduanya mampu melakukan tiga kali penekanan tombol, secara bersamaan dengan <Enter>ini berarti empat penekanan tombol untuk baris baru, yang menurut saya terlalu banyak. Idealnya, saya hanya ingin melakukan <Enter>yang kedua kalinya:

// this is a comment
*

Penting bahwa solusinya juga akan bekerja dengan tingkat indentasi yang berbeda, yaitu

int main(void) {
    // this is a comment*
}

memukul <Enter>

int main(void) {
    // this is a comment
    // *
}

memukul <Enter>

int main(void) {
    // this is a comment
    *
}

Saya pikir saya telah melihat fitur ini di beberapa editor teks beberapa tahun yang lalu tetapi saya tidak ingat yang mana itu. Adakah yang mengetahui solusi yang akan melakukan ini untuk saya di Vim? Pointer ke arah yang benar tentang cara menggulung solusi saya sendiri juga sangat disambut.

Patrick Oscity
sumber
3
Anda dapat menggunakan ctrl-u dalam mode sisipkan untuk menghapus penanda komentar yang dimasukkan secara otomatis dalam satu kunci-kunci.
Etan Reisner
1
@EtanReisner itu sebenarnya lebih baik, tetapi masih satu keystroke terlalu banyak bagi saya karena itu adalah kasus penggunaan umum :)
Patrick Oscity
Anda menyarankan Anda ingin dapat menekan enter lagi untuk mendapatkan perilaku yang Anda inginkan tetapi ctrl-u terlalu banyak? Anda dapat mencoba memetakan <enter> <enter> dalam mode sisipkan untuk secara otomatis melakukan ctrl-u untuk Anda tetapi itu akan menyebabkan penundaan jika Anda menekan <enter> sekali saja (tanpa mengenai apa pun).
Etan Reisner
Yah selain itu, seharusnya hanya memicu jika baris komentar kosong. Penundaan nyata saat memukul <Enter> juga tidak dapat diterima.
Patrick Oscity
Ini hanya akan menunda jika Anda tidak menekan tombol lain yang saya percaya karena vim perlu menunggu untuk memastikan Anda tidak berencana untuk menekan tombol lain. Anda dapat menggunakan fungsi untuk melakukan pemeriksaan itu juga saya pikir meskipun mungkin tidak terlalu mudah untuk dilakukan.
Etan Reisner

Jawaban:

4

Coba ini:

function! EnterEnter()
  if getline(".") =~ '^\s*\(//\|#\|"\)\s*$'
    return "\<C-u>"
  else
    return "\<CR>"
  endif
endfunction

imap <expr> <CR> EnterEnter()
romainl
sumber
Terima kasih terlihat hebat! Akan mencoba ketika aku sampai di rumah. Apakah Anda tahu cara memperluas regex agar cocok dengan bahasa penanda komentar secara independen? Informasi itu harus ada di file sintaks atau sesuatu. Mungkin saya dapat memanfaatkan fitur sintaksis untuk ini ...
Patrick Oscity
Maksud saya di C itu harus cocok dengan // dan / * dan * (komentar multiline) dan di ruby ​​# dan seterusnya
Patrick Oscity
Jelas, fungsi ini sama sekali tidak generik. Lihat :h 'comment'dan :h format-comment'.
romainl
Fungsi dimodifikasi untuk bekerja dengan #ruby dan "vimscript di samping klasik //. Tidak masuk akal untuk melakukan apa pun untuk *komentar multiline gaya-C karena itu harus diakhiri dengan yang lain */.
romainl
Hmm, mungkin <CR><CR>bisa digunakan untuk menyelesaikan komentar multiline ...
romainl
3

Saya memperluas jawaban @ romainl untuk bekerja dengan bahasa yang berubah-ubah dengan membuat regex dari Vim &commentstring:

function! s:IsOnlyComment(getlineArg)
  let commentRegex='^\s*'.substitute(&commentstring,'%s','\\s*','').'$'
  return strlen(matchstr(getline(a:getlineArg), commentRegex)) > 0
endfunction

function! SmartEnter()
  if s:IsOnlyComment('.')
    return "\<Esc>S"
  else
    return "\<CR>"
  endif
endfunction

inoremap <expr> <CR> SmartEnter()

Namun, sepertinya saya tidak bisa memetakan lagi <CR>, ini tidak akan berhasil. Untuk saat ini, saya menggunakan <CR><CR>sampai masalah ini terpecahkan.

Patrick Oscity
sumber
1
Mengapa <Esc>S? <C-u>melakukan hal yang sama tanpa meninggalkan mode sisipkan. Ngomong-ngomong, saya punya fungsi khusus yang melakukan banyak hal <CR>dan menamainya SmartEnter()baru kemarin setelah saya memposting jawaban saya ;-). Juga saya tidak yakin &commentstringadalah pilihan yang tepat karena umumnya hanya berisi satu bentuk dan mungkin "linewise" atau "blockwise" ( /*%s*/dalam C, //%sdalam Javascript, dll).
romainl
2

Hapus r dari 'formatoptions. Itulah yang dilakukan opsi itu. Menonaktifkannya akan berarti Anda tidak pernah melakukan hal itu untuk Anda yang berarti Anda perlu menambahkan penanda komentar terkemuka ketika Anda benar-benar menginginkannya tetapi itu adalah kompromi.

Etan Reisner
sumber
2
Saya sebenarnya ingin Vim menambahkan penanda komentar untuk saya, saya suka ini. Tetapi saya juga ingin cara cepat untuk keluar dari komentar. Terima kasih atas jawaban Anda.
Patrick Oscity
Untuk mode normal 'o' perintah, salah satu harus menghapus 'r' dariformatoptions
elig