Secara otomatis membuat kawat gigi yang cocok di vim


17

Bagaimana cara saya secara otomatis membuat kawat gigi yang cocok di vim?

Ini harus berfungsi sebagai berikut: Jika saya memasukkan brace terbuka, yang penutup akan muncul secara otomatis dan kursor harus ditempatkan di antaranya. Untuk melompat keluar dari pasangan kurung kombinasi Ctrl-jdigunakan.

Ada banyak plugin yang menyediakan penyisipan penjepit otomatis. Tapi mereka

  • baik menggunakan kombinasi tombol yang berbeda dari Ctrl-juntuk melompat keluar dari pasangan penjepit atau
  • mengganggu ikatan kunci UltiSnips .

Berikut ini berfungsi seperti yang diharapkan

:inoremap ( ()<Esc>:let leavechar=")"<CR>i
:imap <C-j> <Esc>:exec "normal f" . leavechar<CR>a

Tetapi dengan pengaturan ini, cuplikan UltiSnips tidak berfungsi lagi. Jadi saya menggunakan UltiSnips untuk memasukkan kurung kurawal:

inoremap ( (<C-R>=UltiSnips_Anon('($1)$0', '(')<CR>

Ini hampir berhasil. Penjepit yang cocok dimasukkan dan saya bisa melewati yang penutup dengan Ctrl-j. Namun, ini hanya berfungsi jika ada ruang di depan brace terbuka.

main () // works, the closing parentheses is added
main(   // fails without a space

Solusi saya memerlukan pengikatan kunci yang berbeda untuk melompati penjepit penutup atau membutuhkan ruang di depan yang terbuka. Bagaimana cara memperbaikinya?

Catatan: Saya menggunakan tanda kurung sebagai contoh. Ini harus bekerja dengan tanda kurung, kurung kurawal, tanda kurung dan tanda kurang dari dan tidak mengganggu plugin UltiSnips.


1
Sudahkah Anda mencoba autoclose ? Anda dapat melompat keluar dari pasangan dengan ), memetakan kembali c-juntuk yang mungkin berhasil.
Kevin

Jawaban:


4

Bagaimana cara saya secara otomatis membuat kawat gigi yang cocok di vim?

Masalah ini tidak sepele, seperti yang akan Anda lihat. Jawaban sederhananya adalah: Gunakan plugin, seperti autoclose atau smartinput . Dengan naif memetakan kembali ([.. tombol akan memberi Anda edgecases dalam beberapa baris, itu sebabnya plugin ini dibuat, dan mengapa mereka biasanya cukup kompleks (jika mereka ada gunanya).

Jadi saya menggunakan UltiSnips untuk memasukkan kurung kurawal

Anda dapat mencoba ini sebagai gantinya (yang berbeda dari saran asli saya):

inoremap ( ()<CR>=UltiSnips_Anon('$1)$0', ')')<CR>

Di mana UltiSnips akan membagi garis (bukannya memasukkan maindalam pertandingan. Masalah dengan menggunakan plugin snippet untuk ini adalah mereka (biasanya) tidak mendukung nesting, sehingga mereka akan melupakan posisi lompatan ketika snippet (nested) berikutnya dimasukkan.

Untuk melompat keluar dari pasangan kurung kombinasi Ctrl-jdigunakan.

Anda dapat memetakan ulang Ctrl-juntuk UltiSnips atau plugin yang bertentangan. Jika pemetaan tidak tercantum dalam dokumentasi, Anda dapat menggunakan :map/imap/nmap <key>untuk menampilkan pemetaan. Jika Anda ingin Ctrl-jmemilih dan melakukan pekerjaan kedua plugin, Anda meminta:

  1. sesuatu yang jauh lebih maju daripada yang saya kira Anda mungkin berpikir
  2. sesuatu yang saya curigai tidak Anda inginkan

Pertimbangkan bash loop ini:

while (( ${arr1[i]} < ${arr2[i<CURSOR>]} )); do
  [next_snippet_position_marker]
done

Dalam hal ini, Anda harus menekan Ctrl-j5 kali untuk sampai ke badan loop. Menggunakan kawat gigi penutup untuk melompat keluar dari pasangan yang sesuai memberi Anda lebih banyak kontrol di mana Anda ingin kursor bergerak. Anda bisa menerapkan tumpukan untuk melacak pasangan yang dimasukkan dan digunakan Ctrl-juntuk meloncat dan bergerak, tetapi kemudian Anda akan mengalami masalah jika Anda mulai menghapus secara manual kawat gigi tanpa melepaskannya dari tumpukan. Jadi Anda akan mulai memecahkan masalah yang coba diatasi oleh brace-plugins. Ini adalah roda yang sulit untuk diciptakan kembali.

Memperluas hal ini, Anda bisa mendapatkan apa yang awalnya Anda minta, gunakan Ctrl-juntuk melompat keluar dari kawat gigi dan potongan. Jika Anda menggunakan beberapa nilai dummy untuk mewakili posisi snippet dan mendorongnya ke dalam stack selain dari kurung kurawal, dengan pemetaan ulang dinamis Ctrl-juntuk berhubungan dengan penyerahan snipet atau kurung kurawal. Tetapi kemudian Anda perlu menerapkan beberapa heuristik yang cukup canggih untuk mencari tahu keajaiban apa yang harus terjadi, karena Anda pada dasarnya mengambil dua masalah sekaligus, yang saat ini sedang diselesaikan oleh pembuat plugins penyisipan snippet dan brace matching plugins secara terpisah, dan menyelesaikan kembali masalah-masalah ini lagi, di atas solusi mereka , untuk mencapai kenyamanan dan, yah, sulap.

Itu datang untuk mengontrol vs kenyamanan. Saya pikir kontrol akan melayani Anda lebih baik dalam hal ini, yang berarti Anda harus menjaga masalah ini dan plugin terkait dan pemetaan kunci terpisah. Jika Anda masih menginginkan kenyamanan, itu bisa dilakukan, tetapi sulit.


1

Saya pikir delimitMate melakukan apa yang Anda butuhkan.

Secara otomatis menutup tanda kurung atau kutipan dan menempatkan kursor di antaranya. Untuk melompat keluar dari pasangan tanda kurung (saat berada dalam mode sisipan) Anda akan melakukan Ctrl-g+ gtetapi Anda dapat memetakannya Ctrl-jdengan menambahkan ini ke vimrc:

% Jump out of a block of parentheses (uses delimitMate)
imap <C-j> <C-g>g

Lebih baik memberikan rincian lebih lanjut di sini, dan menggunakan tautan sebagai referensi untuk bacaan lebih lanjut. Dengan begitu jawaban Anda tidak kehilangan semua nilainya saat tautan menjadi tidak valid.
Anthon

1

Saya telah menemukan autoclose menambahkan sedikit lag, dan juga mengganggu pengaturan saya (Ultisnips dan Supertab), tapi saya suka pendekatannya meniru Eclipse CDT.

Saya menggunakan delimitMate dengan peta berikut untuk membantu navigasi dan lekukan, mencoba untuk mendapatkan hasil yang sama:

imap <C-F> <C-G>g           " To jump out brackets in same line.
inoremap <C-K> <ESC>ki<TAB> " To move and insert an indent on the line before the current cursor (assuming empty line)

Saya menggunakannya dengan cara ini: masukkan pembukaan { <CR><CR><C-K>dan mulailah menulis di baris dalam yang terindentasi.


Saya menemukan delimitMate menambahkan sedikit lag juga
icc97

1

Secara pribadi saya menggunakan smartinput untuk memasukkan kurung dan kutipan secara otomatis. Misalnya mengetik di {mana saja akan menghasilkan {}dengan kursor Anda di tengah. Untuk meninggalkan {grup braket Anda cukup ketik }kapan di sebelah dimasukkan }.

Namun ini mendukung kebutuhan Anda akan tabstop dan melompat ke luar braket. Ini juga tidak membuat yang baru di antara tanda kurung Anda, tetapi Anda hanya perlu satu kunci tambahan untuk itu - <CR>.

Anda dapat memetakan <C-J>untuk melompat ke baris berikutnya ke bawah:

:inoremap <C-J> <C-O>j

atau jika Anda ingin pindah ke awal baris berikutnya:

:inoremap <C-J> <C-O>+

0

Sesuatu seperti ini mungkin berhasil untuk Anda.

inoremap {      {}<Left>
inoremap {<CR>  {<CR>}<Esc>O
inoremap {{     {
inoremap {}     {}

Apa yang Anda sarankan adalah pemetaan sederhana yang tidak memungkinkan untuk melompati penjepit penutup.
Marco

0

Sebenarnya, Ultisnips dapat melakukannya dengan hampir sempurna (ini mungkin baru). Sedikit memodifikasi jawaban yang diberikan di atas, saya berhasil dengan baik

inoremap () ()<C-R>=UltiSnips#Anon('($1)$0', '()', 'double parentheses', 'i')<CR>

Kita harus mengetik () yang menemukan lebih baik tetapi itu bisa diubah (juga. Kemudian, argumen opsional tambahan UltiSnips#Anonadalah deskripsi dan pengubah iyang memungkinkan perluasan kata.

Melompat keluar dari tanda kurung dengan <c-j>karya, juga bersarang di dalam cuplikan lainnya. Namun, menerapkan ()tanda kurung bersarang tampaknya merusak fitur ini, yang bukan masalah besar.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.