Como quebrar longas filas no vim?

12

Eu tenho um arquivo de texto bastante grande formado por blocos como

Short line.
Really long line.
Short line.

separados por linhas vazias, e eu gostaria de usar o vim (no Linux) para quebrar as linhas longas e obter blocos como

Short line.
This was
part of
a long line.
Short line.

Meu problema com gq(e gw) é que ele reflecte cada bloco como um parágrafo inteiro, ou seja, não preserva as duas quebras de linha dentro de cada bloco e, de acordo com :help fo-tablenenhuma das gqopções de formato, me permite fazer o que quero. Também pensei que poderia alcançar meu objetivo se pudesse definir caracteres de nova linha como delimitadores de parágrafos, mas, de acordo com :help paragrapheles, são codificados.

Editar: eu sei que poderia usar gqou gwformatar cada linha longa, uma a uma, mas como meu arquivo é executado em alguns milhares de linhas, estou procurando uma maneira de conseguir isso automaticamente.

AP
fonte
A propósito: procurei soluções para o meu problema na documentação do vim, aqui no SU e na web, aparecendo vazia. Terei o prazer de excluir esta pergunta se ignorar algo óbvio.
AP
Can I justificar o texto no vim? em vi.sx .
Restabeleça Monica - M. Schröder
@ MartinSchröder: Fico feliz em saber que há um vi SE! Essas respostas não abordam meu problema, já que eu já sabia gqe gw. Também estou feliz por não ter parado por aí, caso contrário não teria aprendido sobre o :gcomando. :)
AP

Respostas:

16
:%norm! gww

Isso aplica o normalcomando gww(que formata a linha atual como em gw) em todo o buffer, sem levar em consideração os mapeamentos personalizados (para evitar problemas se, por exemplo, gwtiver sido mapeado para outra coisa).

Vejo

  • :help :%
  • :help :norm
  • :help gww

Essa alternativa é conforme a sugestão de Ben nos comentários e é mais direta que a solução original, que é salva abaixo, pois pode se encaixar melhor em outras circunstâncias semelhantes devido à capacidade de correspondência de expressões regulares. No caso "combinar todas as linhas", porém, é desnecessariamente bruto.


Aplicando gwwem cada linha individual no buffer programaticamente:

:g/^/norm gww

Veja :help :ge :help norm. ^coincide com o início de uma linha, o que, na prática, faz essa correspondência com todas as linhas.

Pode-se também optar por selecionar apenas linhas maiores que, por exemplo, 60 caracteres com

:g/\%>60v/norm gww

(veja :help \%<), mas, na prática gww, reformatará apenas as linhas por mais tempo do que textwidthqualquer outra forma; portanto, isso pode não importar muito em velocidade ou resultado.

(Estou usando va "coluna virtual" em vez de ca "coluna", pois a última calcula realmente um certo número de bytes na linha. Isso pode levar a resultados inesperados ao usar codificações multibyte, o que geralmente é um motivo para ser cauteloso. Na prática, não é um problema real pelo mesmo motivo acima, pois gwwisso não reformatará as linhas mais curtas do que nunca textwidth.)

Daniel Andersson
fonte
Aparentemente :gfalha sem um padrão, então :g//norm gwwnão funciona, mas :g/.*/norm gwwfunciona.
AP
@AP: Huh, funciona para mim. Estou usando o Vim 7.4.488-6 do Debian Unstable.
Daniel Andersson
4
:g//reutiliza o último padrão de pesquisa; se não houver, falhará. Use :g/^/para aplicar a todas as linhas.
Ingo Karkat
@IngoKarkat: Ah, faz sentido, já que meu último padrão durante os testes foi o tamanho da linha que eu demonstrei mais tarde. Vou atualizar a resposta. Você sabe onde, na ajuda, esse comportamento de "padrão vazio" é mencionado? Não consigo encontrá-lo trivialmente.
Daniel Andersson
Examinando o manual, provavelmente está implícito que as informações fornecidas na :help last-patternpesquisa normal também se aplicam ao :globalcomando.
Daniel Andersson
4

Desde que você já leu o manual para os gqe gwcomandos, eu acho que você provavelmente vai querer algo mais conveniente do que mudar manualmente para as longas filas e, em seguida, usando gw0, gw$ou de outro gwcomando para formatar apenas a linha atual.

Não conheço uma maneira fácil de quebrar linhas longas no Vim em um bloco de texto. No entanto, desde que você mencionou que está usando o Vim em um sistema GNU / Linux, sugiro filtrar seu texto através do fmtcomando GNU .

Para o arquivo inteiro:

:%!fmt --width=75 --split-only

Para o parágrafo atual (usando opções curtas):

:'{,'}!fmt -75 -s

As explicações das fmtopções relevantes são:

  • -w, --width=WIDTH- largura máxima da linha (padrão de 75 colunas). A opção -WIDTHé uma forma abreviada de --width=DIGITS(se estiver usando esta versão abreviada, deve ser a primeira opção).

  • -s, --split-only- dividir palangres, mas não reabastecer; esta é a opção que preserva as quebras de linha rígida pré-existentes.

Anthony Geoghegan
fonte
Obrigado por mencionar fmt. Eu preferi aceitar a outra resposta, no entanto, porque ela requer apenas o vim.
AP
@AP Não se preocupe. É uma ótima resposta e eu mesma teria aceitado. Tanto ele quanto sua pergunta merecem votos positivos.
Anthony Geoghegan
1

A partir de:

Short line.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Short line.

Colocando o marcador na linha "lorem ipsum" e pressionando os gwwrendimentos (com textwidth=40clareza):

Short line.
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Short line.

o que para mim parece o que você está pedindo. Caso contrário, fique à vontade para esclarecer.

Daniel Andersson
fonte