Plegado por patrón de búsqueda regex

13

Obtuve un archivo de texto sin formato con columnas de valores separadas por espacios en blanco. Me gusta esto:

AU 3030 .... ... ....  
AU 3031 .... ... ....  
AU 3032 .... ... .... 
AU 3033 .... ... .... 
IT 48100 ... .. .....
IT 40100 ... .. .....
IT 48123 ... .. .....
UK 3333 ... ... ..... 
UK 4444 ... ... .....
UK 5555 ... ... .....

También obtuve esta expresión regular que coincidirá con cualquier línea adyacente con el mismo valor en la primera columna (suponga que el archivo está ordenado en la primera columna) excepto la última:

/^\(\([A-Z0-9]\+\)\s\+.*\n\)\(\2\)\@=

(o para hacerlo menos "peludo"):

/^\v([A-Z0-9]+)\s+.*\n(\1)@=

¿Es posible doblar líneas sobre la línea que no coincide? Teniendo este resultado:

+-- 4 lines AU ....
+-- 3 lines IT ....
+-- 3 lines UK ....
guido
fuente

Respuestas:

14

Haga set foldmethod=expry use 'foldexpr'para establecer una expresión de script vim que definirá los puntos de inicio de plegado.

set foldmethod=expr
set foldexpr=get(split(getline(v:lnum-1)),0,'')!=get(split(getline(v:lnum)),0,'')?'>1':'='

Esto parece más complicado de lo que es, porque no podemos usar espacios fácilmente :set, pero con espacios y una nueva línea o 2, se ve así:

get(split(getline(v:lnum - 1)), 0, '') != get(split(getline(v:lnum)), 0, '')
    \ ? '>1'
    \ : '='

Visión general

Básicamente, esto compara la primera palabra de cada línea con la línea anterior. Si las palabras son diferentes entonces la línea es empezar del pliegue, >1. De lo contrario, se mantiene el mismo nivel pliegue, =.

Gloria de detalles

  • set foldmethod=expr decirle a Vim que use una expresión de script vim para determinar los pliegues
  • 'foldexpr' la opción contiene la expresión de script vim
  • Evaluar la condición con un ternario que regresa >1cuando un pliegue debe comenzar y =cuando el nivel del pliegue debe continuar
  • v:lnumes la línea actual que se 'foldexpr'está ejecutando para actualizar los pliegues
  • Obtenga los contenidos de la línea actual ( v:lnum) y la línea anterior ( v:lnum - 1) a través degetline()
  • Divide cada línea en palabras a través de split()
  • Use get()para obtener el primer índice de las palabras recién divididas
  • Utilice un valor predeterminado de ''en caso de una línea en blanco. p.ejget(words, 0, '')
  • Compare la primera palabra de la línea actual con la primera palabra de la línea anterior en la porción de condición del ternario

Nota: este método puede tener algunos problemas de rendimiento con documentos muy grandes

Para más ayuda ver:

:h 'foldmethod'
:h 'foldexpr'
:h getline(
:h v:lnum
:h split(
:h get(
Peter Rincker
fuente