Bagaimana cara mengomentari serangkaian garis yang dipilih dalam mode visual?

35

Bagaimana cara saya mengomentari banyak dalam mode visual yang dipilih baris? Bagaimana cara membuatnya khusus bahasa?

Misalnya, jika 4 baris pertama dipilih:

def foo(a,b):
    for each in (a,b):
        print each
    return a+b
print "2"

Pengoperasian perintah / makro harus menghasilkan ini (dalam python):

#def foo(a,b):
#    for each in (a,b):
#        print each
#    return a+b
print "2"
John HK
sumber

Jawaban:

31

Jika Anda ingin berkomentar khusus bahasa, Anda memerlukan plugin seperti nerdcommenter .

Atau, meskipun itu tidak menjawab pertanyaan Anda yang sebenarnya, Anda dapat menggunakan tindakan builtin vim dan pengetahuan Anda tentang karakter komentar masing-masing bahasa ...

Opsi # 1: Blok-V

  1. :1 Enter (Lanjutkan ke baris 1)
  2. Ctrl-V (mode V-Block)
  3. jjj (Turun 3 baris lagi)
  4. Shift-I (Masuk ke mode insert sebelum blok)
  5. # (Sisipkan '#')
  6. Esc (Kembali ke mode normal)

Opsi # 2: Pergantian

:1,4s/^/#/

Kerusakan:

  1. : Perintah Ex berikut
  2. 1,4 pada garis dari 1 hingga 4
  3. s pengganti
  4. /pemisah untuk potongan-potongan perintah substitusi.
    (Anda juga dapat menggunakan karakter yang berbeda, misalnya :)
  5. ^ mulai dari garis
  6. / pemisah
  7. # karakter komentar untuk python
  8. / pemisah akhir

Opsi # 3: Ulangi aplikasi makro ( sumber )

  1. :1 Enter (Lanjutkan ke baris 1)
  2. qa(Mulai merekam saat mendaftar a)
  3. Shift-I (Masuk ke mode insert di awal baris
  4. # (Tambahkan '#' di awal baris)
  5. Esc (Kembali ke mode normal)
  6. q (Berhenti merekam)

  7. :2,4 normal @a(jalankan kembali makro yang direkam untuk mendaftar adi jalur antara 2 dan 4)

    ATAU

    Anda dapat memilih garis dalam mode visual dan tekan :untuk secara otomatis mengisi baris Ex dengan :'<,'>(rentang dari awal hingga akhir pemilihan visual) kemudian ketik normal @adan tekan Enter( sumber ).

Sekarang, setiap kali Anda ingin mengomentari beberapa baris, jalankan kembali makro yang direkam untuk mendaftar apada baris-baris itu:

:9,22 normal @a (comment out lines 9-22)
bsmith89
sumber
1
Opsi 4: Plugin
Polling Cody
Saya tidak mengerti mengapa Anda menggunakan makro untuk perintah tunggal, ketika Anda bisa melakukan :9,22 normal I#sesuai jawaban saya.
Ben
Mengapa Anda menggunakan: 1 <enter> saat Anda dapat menggunakan gg?
Tanath
@Tanath Mengomentari dari baris pertama khusus untuk contoh ini. Jika penulis ingin berkomentar dari baris 9 hingga 22 mereka tidak akan dapat menggunakan gg.
bsmith89
@Ben aku tidak tahu apa-apa tentang normalperintah sebelum menulis jawaban ini. Kamu benar; :9,22 normal I#akan bekerja juga.
bsmith89
26

Menggunakan mode Blok Visual ( CtrlV), pilih awal garis. Lalu tekan I#(itu huruf kapital I) untuk memasukkan karakter hash pada setiap baris tersebut. Kemudian tekan Escuntuk kembali dari Sisipkan Mode ke Mode Normal.

200_sukses
sumber
Itu tidak bekerja untuk saya. Itu menyisipkan komentar hanya di baris pertama.
gon1332
Apakah Anda mendorong ctrl? Karena ctrl+vitu hal yang berbeda dari adil v.
Polling Cody
@CodyPoll saya tahu. Semuanya baik-baik saja I. Ketika saya menekan I, maka #akan ditempatkan hanya di depan baris pertama.
gon1332
@CodyPoll Oke .. Saya baru saja rawat inap. Saya tidak menekan Escsetelah prosedur yang dijelaskan.
gon1332
@ gon1332 sejauh yang saya tahu Anda harus menekan Escpada akhirnya.
Gonçalo Ribeiro
18

Jika Anda hanya memerlukan solusi cepat untuk bahasa apa pun yang Anda gunakan saat ini, dan Anda sudah memilih teks dalam mode visual, maka

:norm 0i#

melakukan pekerjaan. (Untuk setiap baris, dalam mode normal, buka kolom pertama dan masukkan #. Menggunakan :norm I#akan memasukkannya sebelum karakter non-spasi pertama, yang mungkin bukan yang Anda inginkan.) Menggunakan :norm i#juga akan berfungsi, karena :normdimulai pada awal dari baris, tetapi kurang eksplisit dan kurang jelas jika Anda tidak tahu itu.

Tentu saja, jika Anda sering melakukan ini, Anda ingin mengatur pemetaan atau mencari plugin.

wchargin
sumber
1
0 tidak diperlukan karena secara default, normalperintah dijalankan dengan kursor pada awal baris.
nitishch
1
Tentu saja, nomor baris,%, tanda dapat diawali dengan perintah ini. Contoh:: 1,5norm i # (atau): 'a,' bnorm i # (atau): norma 10% i #
SibiCoder
9

Melakukannya secara otomatis akan mengharuskan Anda untuk menambahkan sesuatu seperti berikut ini ke vimrcfile Anda ( sumber ):

au FileType haskell,vhdl,ada let b:comment_leader = '-- '
au FileType vim let b:comment_leader = '" '
au FileType c,cpp,java let b:comment_leader = '// '
au FileType sh,make let b:comment_leader = '# '
au FileType tex let b:comment_leader = '% '
noremap <silent> ,c :<C-B>sil <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:noh<CR>
noremap <silent> ,u :<C-B>sil <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:noh<CR>

Menggunakan ,cuntuk mengomentari suatu wilayah dan ,umembatalkan komentar suatu daerah. Ini secara manual menetapkan simbol komentar untuk berbagai bahasa.

Opsi kedua adalah menggunakan plugin seperti tcomment , vim-commentary atau comments.vim . Saya menggunakan tcomment sendiri. Tolong, baca instruksi tentang penggunaan dan instalasi di halaman mereka, karena saya percaya itu di luar topik pertanyaan.

Saya sarankan Anda menggunakan plugin (salah satu yang ditautkan di atas atau yang lain) karena itu jauh lebih mudah daripada mempertahankan sepotong kode di vimrcfile Anda .

Sunting: Saya menghapus cara manual karena pertanyaannya diubah dan juga cara yang benar dijawab oleh 200_success.

tokoyami
sumber
Saran plugin tambahan: NERD Commenter - vim.org/scripts/script.php?script_id=1218
giveen
Catatan: ini hanya mendukung komentar yang ada di baris. Misalnya, ANSI C tidak mengenali //(hanya /* */).
wchargin
Sementara saya menyukai pendekatan ini, Apakah ada cara untuk membuatnya beralih komentar?
ideasman42
1
@ ideasman42 Anda harus membuat fungsi dan memeriksa apakah baris saat ini dimulai dengan komentar dan kemudian tergantung pada panggilan itu salah satu :sperintah yang ditunjukkan dalam kutipan dalam jawaban. Cek itu sendiri akan seperti getline('.') =~ "^" . escape(b:comment_leader, '\/'). Jika itu benar tanda komentar, sebaliknya komentar. Ini tidak diuji dan hanya berfungsi sebagai contoh.
tokoyami
5

Saya menggunakan scrooloose / nerdcommenter untuk ini.

Dengan plugin ini, Anda dapat secara visual memilih baris dan tekan leader+ cuntuk mengganti komentar. Tergantung pada jenis file itu akan menggunakan simbol yang berbeda untuk berkomentar.

OrangeTux
sumber
5

Setelah Anda memilih garis, cukup ketik

:norm I#

:akan secara otomatis memakai '<,'>baris perintah Anda, yang merupakan rentang dari awal pilihan Anda hingga akhir; normmengeksekusi perintah mode normal, dan akan bertindak pada rentang itu; I#adalah perintah mode normal yang memasukkan '#' di awal baris.

Ben
sumber
4

Saya penggemar TComment untuk ini; saya tidak hanya dapat melakukan gaya komentar spesifik tipe file, tetapi bahkan menentukan blok vs per-baris untuk bahasa yang mendukung komentar blok.

    gc{motion}   :: Toggle comments (for small comments within one line 
                    the &filetype_inline style will be used, if 
                    defined)
    gcc          :: Toggle comment for the current line

Explicit commenting/uncommenting:

    g<{motion}   :: Uncomment region
    g<c          :: Uncomment the current line
    g<b          :: Uncomment the current region as block

    g>{motion}   :: Comment region
    g>c          :: Comment the current line
    g>b          :: Comment the current region as block

In visual mode:

    gc           :: Toggle comments
    gC           :: Comment selected text
Collin Grady
sumber
Terima kasih atas jawaban anda! Bisakah Anda mengembangkannya? Memberikan jawaban plugin baik-baik saja, tetapi sekarang ini hanya tautan ke plugin. Paling tidak, deskripsi dasar tentang apa yang dilakukannya dan bagaimana menggunakannya diharapkan dalam jawabannya. juga lihat posting meta ini .
Martin Tournoij
Tampaknya konyol untuk menyalin / menempelkan keybinds tetapi begitulah; Saya sudah menjelaskan apa fungsinya.
Collin Grady
3

Saya menemukan plugin vim-commentary sejauh ini merupakan cara termudah untuk melakukan ini. Pilih rentang garis, lalu tekan saja gc. Ini akan menggunakan karakter komentar yang sesuai untuk tipe file yang Anda buka. Bahkan mungkin tanpa pemilihan visual untuk menghilangkan komentar pada baris komentar yang berdekatan dengan gcuatau gcgc.

Andrew Ferrier
sumber
2

Dengan asumsi Anda ingin menambahkan awalan ke 5 baris di awal baris, maka Anda dapat menggunakannya Cari dan ganti :

:.,+5s/^/prefix_/g

atau di akhir baris:

:.,+5s/$/suffix_/g

Atau gunakan mode visual ( Ctrl+v ) untuk memilih blok teks vertikal, lalu masukkan mode sisipkan ( I) dan ketik sesuatu dan tekan Escuntuk mengonfirmasi dan menerapkan perubahan ke baris lain.

Terkait:

kenorb
sumber
2

Jawaban ini ada di sini untuk 1) menunjukkan kode yang benar untuk ditempelkan ke .vimrc untuk vim 7.4+melakukan blok komentar / komentar sambil menjaga tingkat lekukan dengan 1 pintasan dalam mode visual dan 2) untuk menjelaskannya.

Ini kodenya:

let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.[ch]    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.cpp    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.py    let b:commentChar='#'
autocmd BufNewFile,BufReadPost *.*sh    let b:commentChar='#'
function! Docomment ()
  "make comments on all the lines we've grabbed
  execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e'
endfunction
function! Uncomment ()
  "uncomment on all our lines
  execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e'
endfunction
function! Comment ()
  "does the first line begin with a comment?
  let l:line=getpos("'<")[1]
  "if there's a match
  if match(getline(l:line), '^\s*'.b:commentChar)>-1
    call Uncomment()
  else
    call Docomment()
  endif
endfunction
vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>

Bagaimana itu bekerja:

  • let b:commentChar='//': Ini menciptakan variabel dalam vim. di bsini merujuk pada ruang lingkup, yang dalam hal ini terkandung ke buffer, yang berarti file yang sedang dibuka. Karakter komentar Anda adalah string dan perlu dibungkus dengan tanda kutip, tanda kutip itu bukan bagian dari apa yang akan diganti ketika bertukar komentar.

  • autocmd BufNewFile,BufReadPost *...: Perintah otomatis memicu pada hal-hal yang berbeda, dalam hal ini, ini memicu ketika file baru atau file yang dibaca berakhir dengan ekstensi tertentu. Setelah dipicu, jalankan perintah berikut, yang memungkinkan kita untuk mengubahcommentChar tergantung pada tipe file. Ada cara lain untuk melakukan ini, tetapi mereka lebih membingungkan bagi pemula (seperti saya).

  • function! Docomment(): Fungsi dideklarasikan dengan mulai functiondan diakhiri dengan endfunction. Fungsi harus dimulai dengan modal. itu !memastikan bahwa fungsi ini menimpa setiap fungsi sebelumnya yang didefinisikan Docomment()dengan versi ini Docomment(). Tanpa itu !, saya punya kesalahan, tapi itu mungkin karena saya mendefinisikan fungsi baru melalui baris perintah vim.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': Jalankan panggilan perintah. Dalam hal ini, kami mengeksekusi substitute, yang dapat mengambil rentang (secara default ini adalah baris saat ini) seperti %untuk seluruh buffer atau '<,'>untuk bagian yang disorot. ^\s*adalah regex untuk mencocokkan awal baris diikuti oleh jumlah spasi, yang kemudian ditambahkan ke (karena &). Di .sini digunakan untuk penggabungan string, karena escape()tidak dapat dibungkus dengan tanda kutip. escape()memungkinkan Anda untuk keluar dari karakter commentCharyang cocok dengan argumen (dalam hal ini, \dan /) dengan menambahkannya dengan a \. Setelah ini, kami menyatukan lagi dengan ujung substitutestring kami , yang memilikiebendera. Bendera ini memungkinkan kami gagal secara diam-diam, artinya jika kami tidak menemukan kecocokan pada baris yang diberikan, kami tidak akan berteriak tentang hal itu. Secara keseluruhan, baris ini memungkinkan kita menempatkan karakter komentar diikuti oleh spasi tepat sebelum teks pertama, yang berarti kita menjaga tingkat lekukan kita.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e': Ini mirip dengan perintah besar terakhir kami. Unik untuk yang satu ini, kami punya \v, yang memastikan bahwa kami tidak harus melarikan diri dari kami (), dan 1, yang mengacu pada grup yang kami buat dengan kami (). Pada dasarnya, kami mencocokkan garis yang dimulai dengan jumlah spasi putih apa pun dan kemudian karakter komentar kami diikuti oleh jumlah spasi putih apa pun, dan kami hanya menyimpan set spasi putih pertama. Sekali lagi, emari kita gagal secara diam-diam jika kita tidak memiliki karakter komentar di baris itu.

  • let l:line=getpos("'<")[1]: ini menetapkan variabel seperti yang kami lakukan dengan karakter komentar kami, tetapi lmerujuk ke lingkup lokal (lokal ke fungsi ini). getpos()mendapat posisi, dalam hal ini, awal dari penyorotan kami, dan [1]sarana kami hanya peduli dengan nomor baris, bukan hal-hal lain seperti nomor kolom.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1: Anda tahu cara ifkerjanya. match()memeriksa apakah hal pertama berisi hal kedua, jadi kami mengambil garis yang kami mulai sorot kami, dan memeriksa apakah itu dimulai dengan spasi putih diikuti oleh karakter komentar kami. match()mengembalikan indeks di mana ini benar, dan -1jika tidak ada kecocokan yang ditemukan. Karena ifmengevaluasi semua angka bukan nol menjadi benar, kita harus membandingkan output kita untuk melihat apakah itu lebih besar dari -1. Perbandingan dalam vimpengembalian 0 jika salah dan 1 jika benar, yang ifingin dilihat untuk mengevaluasi dengan benar.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapberarti memetakan perintah berikut dalam mode visual, tetapi jangan memetakannya secara rekursif (artinya tidak mengubah perintah lain yang mungkin digunakan dengan cara lain). Pada dasarnya, jika Anda seorang pemula, selalu gunakan noremapuntuk memastikan Anda tidak merusak barang-barang. <silent>berarti "Saya tidak ingin kata-kata Anda, hanya tindakan Anda" dan mengatakan itu untuk tidak mencetak apa pun ke baris perintah. <C-r>adalah hal yang kami pemetaan, yaitu ctrl + r dalam hal ini (perhatikan bahwa Anda masih dapat menggunakan Cr secara normal untuk "redo" dalam mode normal dengan pemetaan ini). C-uagak membingungkan, tetapi pada dasarnya itu memastikan Anda tidak kehilangan jejak penyorotan visual Anda (menurut jawaban ini membuat perintah Anda mulai dengan '<,'>yang kami inginkan).call sini hanya memberitahu vim untuk menjalankan fungsi yang kami beri nama, dan <cr>mengacu pada memukulentertombol. Kita harus menekannya sekali untuk benar-benar memanggil fungsi (jika tidak kita baru saja mengetik call function()pada baris perintah, dan kita harus menekannya lagi untuk mendapatkan pengganti kita untuk pergi sepanjang jalan (tidak benar-benar yakin mengapa, tapi apa pun).

Bagaimanapun, semoga ini membantu. Ini akan mengambil apa pun yang disorot dengan v,, Vatau C-v, periksa apakah baris pertama dikomentari, jika ya, coba batalkan komentar pada semua baris yang disorot, dan jika tidak, tambahkan lapisan karakter komentar tambahan untuk setiap baris. Inilah perilaku yang saya inginkan; Saya tidak hanya ingin beralih apakah setiap baris di blok dikomentari atau tidak, jadi itu berfungsi dengan baik bagi saya setelah mengajukan beberapa pertanyaan pada subjek.

profil jeremys
sumber