Como comentar um conjunto de linhas selecionadas no modo visual?

35

Como faço para comentar várias linhas selecionadas no modo visual? Como faço para tornar o idioma específico?

Por exemplo, se as 4 primeiras linhas estiverem selecionadas:

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

A operação de um comando / macro deve resultar no seguinte (em python):

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

Respostas:

31

Se você quiser comentar um idioma específico, precisará de um plugin como o nerdcommenter .

Como alternativa, embora não responda à sua pergunta real, você pode usar ações internas do vim e seu conhecimento dos caracteres de comentário de cada idioma ...

Opção 1: blocos em V

  1. :1 Enter (Vá para a linha 1)
  2. Ctrl-V (modo V-Block)
  3. jjj (Abaixo mais 3 linhas)
  4. Shift-I (Entre no modo de inserção antes do bloco)
  5. # (Insira um '#')
  6. Esc (Voltar ao modo normal)

Opção 2: Substituição

:1,4s/^/#/

Demolir:

  1. : O comando ex segue
  2. 1,4 nas linhas de 1 a 4
  3. s substituto
  4. /separador para partes do comando de substituição.
    (Você também pode usar um caractere diferente, por exemplo :)
  5. ^ começo da linha
  6. / separador
  7. # o caractere de comentário para python
  8. / separador final

Opção 3: repetir a aplicação de uma macro ( origem )

  1. :1 Enter (Vá para a linha 1)
  2. qa(Comece a gravar no registro a)
  3. Shift-I (Entre no modo de inserção no início da linha
  4. # (Adicione um '#' no início da linha)
  5. Esc (Voltar ao modo normal)
  6. q (Pare de gravar)

  7. :2,4 normal @a(execute novamente a macro gravada para registrar anas linhas entre 2 e 4)

    OU

    você pode selecionar as linhas no modo visual e pressionar :para preencher automaticamente a linha Ex com :'<,'>(um intervalo do início ao final da seleção visual) e digitar normal @ae pressionar Enter( fonte ).

Agora, sempre que você quiser comentar algumas linhas, basta executar novamente a macro gravada para se registrar anessas linhas:

:9,22 normal @a (comment out lines 9-22)
bsmith89
fonte
11
Opção 4: Plug-in
Cody Poll
Não entendo por que você usa uma macro para um único comando, quando pode fazer :9,22 normal I#conforme minha resposta.
Ben
Por que você usaria: 1 <enter> quando você pode usar o gg?
19415 Tanath
Os comentários da primeira linha foram específicos para este exemplo. Se o autor quisesse comentar das linhas 9 a 22, não seria capaz de usar gg.
bsmith89
@ Ben Eu não sabia nada sobre o normalcomando antes de escrever esta resposta. Você está certo; :9,22 normal I#irá funcionar também.
precisa saber é o seguinte
26

Usando o modo Visual Block ( CtrlV), selecione o início das linhas. Em seguida, pressione I#(que é uma letra maiúscula I) para inserir o caractere de hash em cada uma dessas linhas. Em seguida, pressione Escpara retornar do modo de inserção para o modo normal.

200_success
fonte
Isto não funciona para mim. Ele insere um comentário apenas na primeira linha.
gon1332
Você está empurrando ctrl? Porque ctrl+vé uma coisa diferente de apenas v.
Cody Poll
@CodyPoll eu sei. Tudo está bem até I. Quando eu pressionar I, o #item será colocado apenas na frente da primeira linha.
precisa saber é o seguinte
@CodyPoll Ok .. Eu estava apenas internado. Não pressionei Escapós o procedimento descrito.
precisa saber é o seguinte
@ gon1332, tanto quanto eu sei que você precisa pressionar Escno final.
Gonçalo Ribeiro
18

Se você só precisa de uma solução rápida para o idioma em que está atualmente e já tem o texto selecionado no modo visual,

:norm 0i#

faz o trabalho. (Para cada linha, no modo normal, vá para a primeira coluna e insira #. O uso :norm I#será inserido antes do primeiro caractere que não seja um espaço em branco, que pode não ser o que você deseja.) O uso :norm i#também funcionará, porque :normcomeça no início do linha, mas é menos explícito e menos claro se você não sabe disso.

Obviamente, se você pretende fazer isso com frequência, convém configurar um mapeamento ou procurar um plug-in.

wchargin
fonte
11
0 não é necessário, pois, por padrão, o normalcomando é executado com o cursor no início da linha.
Nitishch
11
Obviamente, números de linha,%, marcas podem ser prefixados com este comando. Exemplo:: 1,5norm i # (ou): 'a', bnorm i # (ou): 10%
nor
9

Para fazer isso automaticamente, você deve adicionar algo como o seguinte ao seu vimrcarquivo ( fonte ):

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>

Usando ,cpara comentar uma região e ,udescomentar uma região. Isso define manualmente os símbolos de comentários para diferentes idiomas.

A segunda opção é usar um plugin como tcomment , vim-commentary ou comments.vim . Eu mesmo uso esse comentário. Por favor, leia as instruções sobre uso e instalação em suas páginas, pois acredito que estão além do tópico da pergunta.

Eu sugiro que você use um plug-in (um dos links acima ou outro), pois isso é muito mais fácil do que manter um pedaço de código em seu vimrcarquivo.

Edit: Eu removi a maneira manual, pois a pergunta foi alterada e a maneira correta foi respondida por 200_success.

tokoyami
fonte
Uma sugestão adicional para o plug-in: NERD Commenter - vim.org/scripts/script.php?script_id=1218
concedida em 3/02/15
Nota: isso suporta apenas comentários em linha. Por exemplo, ANSI C não reconhece //(apenas /* */).
wchargin
Enquanto eu gosto dessa abordagem, existe uma maneira de alternar os comentários?
precisa saber é o seguinte
11
@ ideasman42 Em vez disso, você teria que criar uma função e verificar se a linha atual começa com um comentário e, dependendo dessa chamada, um dos :scomandos mostrados no trecho da resposta. O cheque em si seria algo parecido getline('.') =~ "^" . escape(b:comment_leader, '\/'). Se for realmente descomentado, comente. Isso não foi testado e deve servir apenas como exemplo.
tokoyami
5

Eu uso scrooloose / nerdcommenter para isso.

Com este plugin, você pode selecionar visualmente suas linhas e pressionar leader+ cpara alternar os comentários. Dependendo do tipo de arquivo, ele usará símbolos diferentes para comentar.

OrangeTux
fonte
5

Depois de selecionar as linhas, basta digitar

:norm I#

:colocará automaticamente '<,'>na sua linha de comando, que é um intervalo desde o início da sua seleção até o final; normexecuta um comando no modo normal e atua nesse intervalo; I#é o comando do modo normal que insere um '#' no início da linha.

Ben
fonte
4

Sou um grande fã do TComment por isso; não só posso criar estilos de comentários específicos do tipo de arquivo, mas também especificar bloco x por linha para idiomas que suportam comentários em bloco.

    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
fonte
Obrigado pela sua resposta! Você poderia talvez expandi-lo? Fornecer respostas para plugins é bom, mas agora é apenas um link para um plug-in. No mínimo, uma descrição básica do que ele faz e como usá-lo é esperada na resposta. veja também este meta post .
Martin Tournoij
Parece bobagem copiar / colar combinações de teclas, mas lá está você; Eu já descrevi o que faz.
Collin Grady
3

Acho que o plugin vim-commentary é de longe a maneira mais fácil de fazer isso. Selecione um intervalo de linhas e pressione gc. Ele usará um caractere de comentário apropriado para o tipo de arquivo que você abriu. É possível, mesmo sem nenhuma seleção visual, descomentar as linhas comentadas adjacentes com gcuou gcgc.

Andrew Ferrier
fonte
2

Supondo que você queira adicionar prefixo a 5 linhas no início da linha, use a opção Pesquisar e substituir :

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

ou no final das linhas:

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

Ou use o modo visual (Ctrl + v) para selecionar o bloco vertical de texto, entre no modo de inserção ( I) e digite algo e pressione Escpara confirmar e aplicar as alterações em outras linhas.

Palavras-chave:

kenorb
fonte
2

Esta resposta está aqui para 1) mostrar o código correto para colar em um .vimrcpara obtervim 7.4+ fazer bloco comentando / descomentando mantendo nível de recuo com um atalho no modo visual e 2) para explicá-lo.

Aqui está o código:

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>

Como funciona:

  • let b:commentChar='//': Isso cria uma variável no vim. o baqui refere-se ao âmbito de aplicação, que neste caso está contido no tampão, o que significa que o ficheiro que está aberto. Os caracteres de seu comentário são cadeias de caracteres e precisam ser colocados entre aspas; as aspas não fazem parte do que será substituído ao alternar os comentários.

  • autocmd BufNewFile,BufReadPost *...: Os comandos automáticos são acionados em diferentes coisas; nesse caso, são acionadas quando um novo arquivo ou o arquivo lido termina com uma certa extensão. Uma vez acionado, execute o seguinte comando, o que nos permite alterar ocommentChar tipo de arquivo dependendo. Existem outras maneiras de fazer isso, mas elas são mais confusas para iniciantes (como eu).

  • function! Docomment(): As funções são declaradas iniciando functione terminando com endfunction. As funções devem começar com uma capital. os !garante que esta função substitui qualquer funções anteriores como definidos Docomment()com esta versão Docomment(). Sem o !, tive erros, mas isso pode ser porque eu estava definindo novas funções através da linha de comando do vim.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': Executar chama um comando. Nesse caso, estamos executando substitute, o que pode assumir um intervalo (por padrão, esta é a linha atual), como %para todo o buffer ou '<,'>para a seção destacada. ^\s*é regex para corresponder ao início de uma linha seguida por qualquer quantidade de espaço em branco, que é então anexado a (devido a &). O .aqui é usado para concatenação de cadeias, pois escape()não pode ser colocado entre aspas. escape()permite que você escape um caractere commentCharque corresponda aos argumentos (nesse caso, \e/ ), acrescentando-os com a \. Depois disso, concatenamos novamente com o final da nossa substitutestring, que tem oebandeira. Essa bandeira nos deixa falhar silenciosamente, o que significa que, se não encontrarmos uma correspondência em uma determinada linha, não gritaremos sobre isso. Como um todo, essa linha nos permite colocar um caractere de comentário seguido por um espaço antes do primeiro texto, o que significa que mantemos nosso nível de indentação.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e': Isso é semelhante ao nosso último grande e longo comando. Exclusivo para este, temos \v, o que garante que não temos que escapar do nosso (), e 1, que se refere ao grupo que fizemos com o nosso (). Basicamente, estamos combinando uma linha que começa com qualquer quantidade de espaço em branco e, em seguida, nosso caractere de comentário seguido por qualquer quantidade de espaço em branco, e estamos mantendo apenas o primeiro conjunto de espaços em branco. Novamente, evamos falhar silenciosamente se não tivermos um caractere de comentário nessa linha.

  • let l:line=getpos("'<")[1]: define uma variável como fizemos com o nosso caractere de comentário, mas lrefere-se ao escopo local (local para esta função). getpos()obtém a posição de, neste caso, o início de nosso destaque e o[1] meios que nos importam apenas com o número da linha, e não com outras coisas como o número da coluna.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1: você sabe como iffunciona. match()verifica se a primeira coisa contém a segunda, então pegamos a linha na qual começamos o destaque e verificamos se ela começa com espaço em branco seguido pelo caractere de comentário. match()retorna o índice onde isso é verdade e -1se nenhuma correspondência foi encontrada. Como ifavalia todos os números diferentes de zero como verdadeiros, precisamos comparar nossa saída para ver se é maior que -1. Comparação nos vimretornos 0 se falso e 1 se verdadeiro, que é o que ifdeseja ver para avaliar corretamente.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapsignifica mapear o seguinte comando no modo visual, mas não o mapeie recursivamente (ou seja, não altere nenhum outro comando que possa ser usado de outras maneiras). Basicamente, se você é um novato em vim, sempre use noremappara se certificar de não quebrar as coisas. <silent>significa "Não quero suas palavras, apenas suas ações" e diz para não imprimir nada na linha de comando. <C-r>é o que estamos mapeando, que é ctrl + r nesse caso (observe que você ainda pode usar Cr normalmente para "refazer" no modo normal com esse mapeamento). C-ué meio confuso, mas basicamente garante que você não perca o realce visual (de acordo com esta resposta , o comando começa com '<,'>o que queremos).call aqui, basta dizer ao vim para executar a função que chamamos e <cr>refere-se a pressionar oenterbotão. Temos que apertar uma vez para realmente chamar a função (caso contrário, apenas digitamos call function()na linha de comando, e temos que apertá-la novamente para que nossos substitutos passem por todo o caminho (não sei ao certo por que, mas tanto faz).

Enfim, espero que isso ajude. Isso vai levar nada destacou com v, Vou C-v, cheque se a primeira linha é comentada, se sim, tentar tire todas as linhas destacadas, e se não, adicionar uma camada extra de caracteres de comentário para cada linha. Este é o meu comportamento desejado; Eu não queria apenas alternar se cada linha do bloco era comentada ou não, por isso funciona perfeitamente para mim depois de fazer várias perguntas sobre o assunto.

jeremysprofile
fonte