¿Cómo romper largas colas en vim?

12

Tengo un archivo de texto bastante grande formado por bloques como

Short line.
Really long line.
Short line.

separados por líneas vacías, y me gustaría usar vim (en Linux) para dividir las líneas largas y obtener bloques como

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

Mi problema con gq(y gw) es que redistribuye cada bloque como un párrafo completo, es decir, no conserva los dos saltos de línea dentro de cada bloque, y de acuerdo con :help fo-tableninguna de gqlas opciones de formato me permitiría hacer lo que quiero. También pensé que podría lograr mi objetivo si pudiera definir caracteres de nueva línea como delimitadores de párrafo, pero de acuerdo con :help paragraphellos están codificados.

Editar: Sé que podría usar gqo gwformatear cada línea larga una por una, pero dado que mi archivo se ejecuta en unos pocos miles de líneas, estoy buscando una manera de lograr esto automáticamente.

AP
fuente
Por cierto: busqué soluciones a mi problema en la documentación de vim, aquí en SU, y en la web, que aparecían vacías. Con gusto eliminaré esta pregunta si pasé por alto algo obvio.
AP
Hay ¿Puedo justificar texto en Vim? en vi.sx .
Restablecer Monica - M. Schröder
@ MartinSchröder: ¡Me alegra saber que hay un vi SE! Sin embargo, esas respuestas no abordan mi problema, ya que ya sabía gqy gw. También me alegro de no haberme detenido allí, de lo contrario no habría aprendido sobre el :gcomando. :)
AP

Respuestas:

16
:%norm! gww

Esto aplica el normalcomando gww(que formatea la línea actual como con gw) en todo el búfer, sin tener en cuenta las asignaciones personalizadas (para evitar problemas si, por ejemplo, gwse ha asignado a otra cosa).

Ver

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

Esta alternativa es según la sugerencia de Ben en los comentarios, y es más sencilla que la solución original, que se guarda a continuación, ya que podría encajar mejor en otras circunstancias similares debido a la capacidad de coincidencia de expresiones regulares. Sin embargo, en el caso de "coincidir todas las líneas", es innecesariamente bruto.


Aplicando gwwen cada línea individual en el búfer mediante programación:

:g/^/norm gww

Ver :help :gy :help norm. ^coincide con el comienzo de una línea, que en la práctica hace que coincida con cada línea.

También se puede optar por seleccionar solo líneas de más de, por ejemplo, 60 caracteres con

:g/\%>60v/norm gww

(ver :help \%<), pero en la práctica gwwsolo formateará las líneas más tiempo que de textwidthtodos modos, por lo que puede que no importe mucho ni en velocidad ni en resultado.

(Estoy usando vpara "columna virtual" en lugar de c"columna", ya que este último realmente calcula un cierto número de bytes en la línea. Esto puede conducir a resultados inesperados cuando se usan codificaciones multibyte, lo que a menudo es una razón para desconfiar. En la práctica, no es un problema real por la misma razón que antes, ya que gwwno formateará las líneas más cortas que de textwidthtodos modos).

Daniel Andersson
fuente
Aparentemente :gfalla sin un patrón, por lo :g//norm gwwque no funciona pero :g/.*/norm gwwsí.
AP
@AP: Eh, funciona para mí. Estoy usando Vim 7.4.488-6 de Debian Unstable.
Daniel Andersson
44
:g//reutiliza el último patrón de búsqueda; Si no hay ninguno, falla. Use :g/^/para aplicar a todas las líneas.
Ingo Karkat
@IngoKarkat: Ah, tiene sentido, ya que mi último patrón durante las pruebas fue el de la longitud de línea que demostré más tarde. Actualizaré la respuesta. ¿Sabes en qué parte de la ayuda se menciona este comportamiento de "patrón vacío"? No puedo encontrarlo trivialmente.
Daniel Andersson
Al revisar el manual, es probable que la información proporcionada :help last-patternpara la búsqueda normal se aplique también al :globalcomando.
Daniel Andersson
4

Dado que ya ha leído el manual de las gqy gwlos comandos, supongo que es probable que desee algo más conveniente que mover manualmente a las largas filas y luego utilizando gw0, gw$u otro gwcomando sólo para dar formato a la línea actual.

No conozco una manera fácil de romper largas líneas en Vim sobre un bloque de texto. Sin embargo, como ha mencionado que está usando Vim en un sistema GNU / Linux, le sugiero que filtre su texto a través del fmtcomando GNU .

Para todo el archivo:

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

Para el párrafo actual (usando opciones cortas):

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

La explicación de las fmtopciones relevantes son:

  • -w, --width=WIDTH- ancho de línea máximo (predeterminado de 75 columnas). La opción -WIDTHes una forma abreviada de --width=DIGITS(si usa esta versión abreviada, debe ser la primera opción).

  • -s, --split-only- dividir líneas largas, pero no rellenar; Esta es la opción que conserva los saltos de línea dura preexistentes.

Anthony Geoghegan
fuente
Gracias por mencionar fmt. Sin embargo, preferí aceptar la otra respuesta, porque solo requiere vim.
AP
@AP No te preocupes. Es una gran respuesta y yo misma la hubiera aceptado. Tanto él como tu pregunta merecen votos positivos.
Anthony Geoghegan
1

Desde:

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.

Poniendo el marcador en la línea "lorem ipsum" y presionando los gwwrendimientos (con textwidth=40mayor claridad):

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.

que a mí me parece lo que estás pidiendo. Si no, no dude en aclarar.

Daniel Andersson
fuente