Come commentare una serie di linee che sono selezionate in modalità visiva?


35

Come posso commentare più righe selezionate in modalità visiva? Come posso renderlo specifico per la lingua?

Ad esempio, se sono selezionate le prime 4 righe:

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

L'operazione di un comando / macro dovrebbe comportare questo (in Python):

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

Risposte:


31

Se vuoi un commento specifico sulla lingua avrai bisogno di un plugin come nerdcommenter .

In alternativa, anche se non risponde alla tua vera domanda, puoi usare le azioni di vim integrate e la tua conoscenza dei caratteri di commento di ogni lingua ...

Opzione n. 1: blocchi a V.

  1. :1 Enter (Vai alla linea 1)
  2. Ctrl-V (modalità V-Block)
  3. jjj (Giù altre 3 righe)
  4. Shift-I (Entra nella modalità di inserimento prima del blocco)
  5. # (Inserisci un '#')
  6. Esc (Torna alla modalità normale)

Opzione 2: sostituzione

:1,4s/^/#/

Abbattersi:

  1. : Segue il comando Ex
  2. 1,4 sulle linee da 1 a 4
  3. s sostituire
  4. /separatore per pezzi del comando di sostituzione.
    (Puoi anche usare un carattere diverso, ad es. :)
  5. ^ inizio della riga
  6. / separatore
  7. # il carattere di commento per Python
  8. / separatore finale

Opzione n. 3: ripetere l'applicazione di una macro ( sorgente )

  1. :1 Enter (Vai alla linea 1)
  2. qa(Avviare la registrazione sul registro a)
  3. Shift-I (Entra nella modalità di inserimento all'inizio della riga
  4. # (Aggiungi un '#' all'inizio della riga)
  5. Esc (Torna alla modalità normale)
  6. q (Interrompi registrazione)

  7. :2,4 normal @a(rieseguire la macro registrata per registrarsi asu righe tra 2 e 4)

    O

    puoi selezionare le linee in modalità visiva e premere :per popolare automaticamente la linea Ex con :'<,'>(un intervallo dall'inizio alla fine della selezione visiva), quindi digitare normal @ae premere Enter( sorgente ).

Ora, ogni volta che vuoi commentare alcune righe, esegui nuovamente la macro registrata per registrarti asu quelle righe:

:9,22 normal @a (comment out lines 9-22)

1
Opzione 4: Plugin
Cody Poll

Non capisco perché usi una macro per comando singolo, quando puoi fare :9,22 normal I#secondo la mia risposta.
Ben

Perché dovresti usare: 1 <invio> quando puoi usare gg?
Tanath,

@Tanath I commenti dalla prima riga erano specifici di questo esempio. Se l'autore volesse commentare dalle righe 9 a 22 non sarebbero in grado di usare gg.
bsmith89,

@Ben Non sapevo nulla del normalcomando prima di scrivere questa risposta. Hai ragione; :9,22 normal I#funzionerà pure.
bsmith89,

26

Utilizzando la modalità Visual Block ( CtrlV), selezionare l'inizio delle righe. Quindi premi I#(che è una lettera maiuscola I) per inserire il carattere hash su ciascuna di quelle righe. Quindi premere Escper tornare dalla modalità di inserimento alla modalità normale.


Per me non funziona. Inserisce un commento solo nella prima riga.
gon1332,

Stai spingendo ctrl? Perché ctrl+vè una cosa diversa dal giusto v.
Cody Poll

@CodyPoll Lo so. Va tutto bene I. Quando premo I, quindi #verrà posizionato solo davanti alla prima riga.
gon1332,

@CodyPoll Ok .. Ero solo ricoverato. Non ho premuto Escdopo la procedura descritta.
gon1332,

@ gon1332 per quanto ne so è necessario premere Escalla fine.
Gonçalo Ribeiro,

18

Se hai solo bisogno di una soluzione rapida per la lingua in cui ti trovi attualmente e hai già selezionato il testo in modalità visiva, allora

:norm 0i#

fa il lavoro. (Per ogni riga, in modalità normale, vai alla prima colonna e inserisci #. L'utilizzo :norm I#lo inserirà prima del primo carattere non bianco, che potrebbe non essere quello che desideri.) Anche l'uso :norm i#funzionerà, perché :norminizia all'inizio del linea, ma è meno esplicito e meno chiaro se non lo sai.

Naturalmente, se hai intenzione di farlo di frequente, ti consigliamo di impostare una mappatura o cercare un plugin.


1
0 non è necessario poiché, per impostazione predefinita, il normalcomando viene eseguito con il cursore all'inizio della riga.
nitishch,

1
Naturalmente, con questo comando è possibile aggiungere il prefisso per numeri di riga,%, segni. Esempio: 1,5norm i # (o): 'a,' bnorm i # (o): 10% norm i #
SibiCoder,

9

Farlo automaticamente richiederebbe di aggiungere qualcosa di simile al seguente al tuo vimrcfile ( sorgente ):

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>

Utilizzo ,cper commentare una regione e ,urimuovere il commento da una regione. Ciò imposta manualmente i simboli di commento per diverse lingue.

La seconda opzione è utilizzare un plugin come tcomment , vim-commentary o commenti.vim . Uso il tcomment me stesso. Per favore, leggi le istruzioni sull'uso e l'installazione alle loro pagine, poiché credo che sia al di là dell'argomento della domanda.

Ti suggerirei di utilizzare un plug-in (uno dei collegamenti sopra o un altro) in quanto è molto più semplice che mantenere un pezzo di codice nel tuo vimrcfile.

Modifica: ho rimosso il modo manuale poiché la domanda è stata modificata e anche il modo corretto è stato risposto con 200_success.


Un suggerimento aggiuntivo per il plugin: NERD Commenter - vim.org/scripts/script.php?script_id=1218
dato il

Nota: supporta solo commenti a livello di riga. Ad esempio, ANSI C non riconosce //(solo /* */).
mercoledì

Mentre mi piace questo approccio, c'è un modo per farlo attivare o disattivare i commenti?
ideasman42

1
@ ideasman42 Dovresti invece fare una funzione e verificare se la riga corrente inizia con un commento e quindi a seconda di quella chiamata uno dei :scomandi mostrati nell'estratto nella risposta. Il controllo stesso sarebbe qualcosa di simile getline('.') =~ "^" . escape(b:comment_leader, '\/'). Se è un vero commento, altrimenti commenta. Questo non è testato e dovrebbe servire solo come esempio.
Tokoyami,

5

Per questo uso scrooloose / nerdcommenter .

Con questo plugin puoi selezionare visivamente le tue linee e premere leader+ cper attivare o disattivare i commenti. A seconda del tipo di file, verranno utilizzati simboli diversi per i commenti.


5

Dopo aver selezionato le linee, digita semplicemente

:norm I#

:inserirà automaticamente '<,'>la riga di comando, che è un intervallo dall'inizio della selezione alla fine; normesegue un comando in modalità normale e agirà su tale intervallo; I#è il comando in modalità normale che inserisce un '#' all'inizio della riga.


4

Sono un grande fan di TComment per questo; non solo posso creare stili di commento specifici per il tipo di file, ma anche specificare blocco vs per riga per le lingue che supportano i commenti di blocco.

    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

Grazie per la tua risposta! Potresti forse espanderlo? Fornire risposte al plugin va bene, ma in questo momento è solo un collegamento a un plugin. Come minimo, nella risposta è prevista una descrizione di base di ciò che fa e di come utilizzarlo. vedi anche questo meta post .
Martin Tournoij,

Sembra sciocco copiare / incollare i tasti ma ci sei; Ho già descritto cosa fa.
Collin Grady,

3

Trovo che il plugin vim-commentary sia di gran lunga il modo più semplice per farlo. Seleziona un intervallo di linee, quindi premi gc. Utilizzerà un carattere di commento appropriato per il tipo di file che hai aperto. È anche possibile senza alcuna selezione visiva separare le righe commentate adiacenti con gcuo gcgc.


2

Supponendo che desideri aggiungere il prefisso a 5 righe all'inizio della riga, puoi utilizzare Cerca e sostituisci :

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

o alla fine delle linee:

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

Oppure usa la modalità visiva ( Ctrl+ v) per selezionare il blocco di testo verticale, quindi inserisci la modalità di inserimento ( I) e digita qualcosa e premi Escper confermare e applicare le modifiche ad altre righe.

Relazionato:


2

Questa risposta è qui per 1) mostra il codice corretto da incollare in a .vimrcper ottenerevim 7.4+ per fare in modo da bloccare i commenti / i commenti, mantenendo il livello di rientro con 1 scorciatoia in modalità visiva e 2) per spiegarlo.

Ecco il codice:

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>

Come funziona:

  • let b:commentChar='//': Questo crea una variabile in vim. il bqui si riferisce al campo di applicazione, che in questo caso è contenuto al buffer, cioè il file aperto. I tuoi caratteri di commento sono stringhe e devono essere racchiusi tra virgolette, le virgolette non fanno parte di ciò che verrà sostituito quando si attivano o disattivano i commenti.

  • autocmd BufNewFile,BufReadPost *...: I comandi automatici si attivano su cose diverse, in questo caso si attivano quando un nuovo file o il file letto termina con una determinata estensione. Una volta attivato, esegui il seguente comando, che ci consente di modificare il commentCharsecondo tipo di file. Ci sono altri modi per farlo, ma sono più confusi per i principianti (come me).

  • function! Docomment(): Le funzioni vengono dichiarate iniziando con functione terminando con endfunction. Le funzioni devono iniziare con un capitale. le !assicura che questa funzione sovrascrive qualsiasi precedenti funzioni definite Docomment()con questa versione di Docomment(). Senza il !, ho avuto errori, ma ciò potrebbe essere dovuto al fatto che stavo definendo nuove funzioni tramite la riga di comando di vim.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': Esegui chiama un comando. In questo caso, stiamo eseguendo substitute, che può assumere un intervallo (per impostazione predefinita questa è la riga corrente) come %per l'intero buffer o '<,'>per la sezione evidenziata. ^\s*è regex in modo che corrisponda all'inizio di una riga seguita da qualsiasi quantità di spazio bianco, che viene quindi aggiunto (a causa di &). Il .qui è usato per la concatenazione di stringhe, poiché escape()non può essere racchiuso tra virgolette. escape()ti permette di sfuggire al carattere commentCharche corrisponde agli argomenti (in questo caso \e /) anteponendoli con a\ . Dopo questo, ci concateniamo di nuovo con la fine della nostra substitutestringa, che ha ilebandiera. Questa bandiera ci consente di fallire silenziosamente, il che significa che se non troviamo una corrispondenza su una determinata linea, non urleremo al riguardo. Nel complesso, questa riga ci consente di inserire un carattere di commento seguito da uno spazio appena prima del primo testo, il che significa che manteniamo il nostro livello di rientro.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e': Questo è simile al nostro ultimo enorme comando lungo. Unico a questo, abbiamo \v, il che ci assicura che non dobbiamo sfuggire al nostro (), e 1che si riferisce al gruppo che abbiamo fatto con il nostro (). Fondamentalmente, stiamo abbinando una linea che inizia con qualsiasi quantità di spazio bianco e quindi il nostro carattere di commento seguito da qualsiasi quantità di spazio bianco e manteniamo solo il primo set di spazi bianchi. Ancora una volta, epossiamo fallire silenziosamente se non abbiamo un carattere di commento su quella riga.

  • let l:line=getpos("'<")[1]: imposta una variabile come abbiamo fatto con il nostro carattere di commento, ma si lriferisce all'ambito locale (locale a questa funzione). getpos()ottiene la posizione, in questo caso, l'inizio della nostra evidenziazione e i [1]mezzi che ci interessano solo del numero di riga, non di altre cose come il numero di colonna.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1: sai come iffunziona. match()controlla se la prima cosa contiene la seconda cosa, quindi prendiamo la linea su cui abbiamo iniziato la nostra evidenziazione e controlliamo se inizia con uno spazio bianco seguito dal nostro carattere di commento. match()restituisce l'indice dove questo è vero e -1se non sono state trovate corrispondenze. Poiché ifvaluta che tutti i numeri diversi da zero sono veri, dobbiamo confrontare il nostro output per vedere se è maggiore di -1. Il confronto tra vimrestituisce 0 se falso e 1 se vero, che è ciò che ifvuole vedere per valutare correttamente.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapsignifica mappare il seguente comando in modalità visiva, ma non mapparlo in modo ricorsivo (il che significa che non cambia altri comandi che potrebbero essere utilizzati in altri modi). Fondamentalmente, se sei un principiante, usa sempre noremapper assicurarti di non rompere le cose. <silent>significa "Non voglio le tue parole, solo le tue azioni" e gli dice di non stampare nulla sulla riga di comando. <C-r>è la cosa che stiamo mappando, che in questo caso è ctrl + r (nota che puoi sempre usare Cr normalmente per "ripetere" in modalità normale con questa mappatura). C-uè un po 'confuso, ma fondamentalmente si assicura che non si perda traccia dell'evidenziazione visiva (secondo questa risposta fa iniziare il comando con '<,'>quale è quello che vogliamo).call qui dice solo a Vim di eseguire la funzione che abbiamo nominato e si <cr>riferisce a colpire ilenterpulsante. Dobbiamo premerlo una volta per chiamare effettivamente la funzione (altrimenti abbiamo appena digitato call function()sulla riga di comando e dobbiamo premerlo di nuovo per fare in modo che i nostri sostituti procedano fino in fondo (non sono sicuro del perché, ma qualunque cosa).

Comunque, si spera che questo aiuti. Ciò richiederà qualsiasi cosa evidenziata con v, Vo C-v, controlla se la prima riga è commentata, in caso affermativo, prova a rimuovere il commento da tutte le linee evidenziate e, in caso contrario, aggiungi un ulteriore livello di caratteri di commento a ciascuna riga. Questo è il mio comportamento desiderato; Non volevo solo cambiare se ogni riga del blocco è stata commentata o meno, quindi funziona perfettamente per me dopo aver fatto più domande sull'argomento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.