¿Cómo configurar Vim para que funcione con una oración por línea?

17

Actualmente estoy escribiendo una gran cantidad de texto sin formato (y LaTeX con un formato mínimo en los párrafos), y sería bueno si pudiera configurar vim para mantener cada oración (por simplicidad, el texto termina con un '.', '!' , o '?'; es una puntuación de terminación seguida de un espacio para evitar romper los números decimales) en su propia línea, por lo que las diferencias de VCS serán más útiles.

Como mínimo, me gustaría gqformatear el texto de:

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

A:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

Pero sería bueno si vim también realizara este formateo mientras escribo (como lo hace con el reflujo de ancho de texto). es posible?

Mi solución actual es unir un párrafo Jy luego ejecutarlo, lo :'<,'>s/\. /.\r/gcual es bastante bueno ya que hay pocos signos de exclamación y de interrogación, pero sería mucho mejor si pudiera hacer que gq sea un poco más inteligente.

Alex
fuente

Respuestas:

23

La 'formatexpr'opcion

Puede lograr esto usando la 'formatexpr'opción. De la ayuda:

Expresión que se evalúa para formatear un rango de líneas para el operador gq o el formateo automático (ver 'formatoptions'). Cuando esta opción está vacía, se usa 'formatprg'.

Configurarlo 'formatexpr'correctamente funcionará tanto al usar gqcomo al insertar texto.

Un simple ejemplo

Aquí hay una función VimScript simple y el 'formatexpr'valor correspondiente que debería hacer el trabajo. No lo he probado en todos los casos límite, pero funcionó muy bien para mis pruebas simples.

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

Explicación

La expresión es una llamada a la función MyFormatExpr(), pasando las líneas inicial y final sobre las cuales se aplicará el formato. Estas líneas se calculan utilizando las variables rellenadas automáticamente v:lnum(la primera línea que se formateará) y v:count(el número de líneas que se formatearán).

La MyFormatExpr()función construye un :substitutecomando con el pasado en el rango, en lugar de un espacio en blanco después de una marca de puntuacion de fin de frase ( ., !o ?) con una nueva línea ( \r).

Advertencias

  • La MyFormatExpr()función no conserva la sangría inicial. Se necesitaría una lógica más sofisticada para arreglar eso.
  • Puede haber otros casos extremos donde esto se desmorona. ¡Pruébelo y ajústelo según sea necesario!
tommcdo
fuente
Oh, sí, este es el camino a seguir, ignora mi respuesta.
Sukima
¡Esto es asombroso! Lo que desearía poder hacer es que la función ejecute una macro, como "avanzar a la siguiente oración )e insertar una nueva línea; repetir hasta llegar al final del rango". Entonces, presumiblemente, aplicaría cualquier regla de sangría. Pero mi Vim-fu es demasiado débil para eso. :)
Nathan Long
Esto se divide en e.g. blah, por ejemplo , y Blah et al. 2018que es un poco molesto. Puede desunir patrones como ese con algo así 's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'. Simplemente agregue más patrones al primer grupo para evitar otras cosas en las que no desea dividirse. De lo contrario, esto es súper útil, gracias. No me había encontrado gqantes, y gqipes muy útil para formatear el texto que los editores de texto del coautor han destrozado.
naught101
¿Hay alguna manera de agregar este comportamiento al comportamiento predeterminado? Me gustaría poder ajustar a un ancho de texto dado, así como dividir al final de las oraciones ..
naught101
1

Bueno, puedes configurar algunos mapas y comandos automáticos:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

Luego, simplemente configure el tipo de archivo en texto personalizado o llame a la AddSentenceMapsfunción manualmente.

Sukima
fuente
0

Quiero agregar mis pensamientos sobre este tema. Por lo general, las personas desean este tipo de característica debido a que saltan las líneas envueltas cuando navegan por el código jy los kcomandos, que es el comportamiento predeterminado de Vim. Para la navegación a través de líneas envueltas, uso gj- mover hacia abajo y gk- mover hacia arriba. También existe la posibilidad de reasignar el estándar jy el kcomando en las contrapartes con prefijo g, pero en mi humilde opinión, sería excesivo.

Alexander Myshov
fuente
o tener una clave para hacer esa reasignación de jy khacia gjy gkcuando lo desee ;-)
anthony
0

No responde a su pregunta específica sobre el formateo, pero 'set wrap' junto con 'set linebreak' puede hacer que editar líneas largas sea mucho más agradable. Combina esto con gj y gk para navegar dentro de líneas envueltas. Mapeo las flechas hacia arriba y hacia abajo a gj y gk, respectivamente, para poder elegir entre subir y bajar líneas reales o líneas visuales. Como sabio para Inicio / Fin a g0 / g $.

Dibujó
fuente