Similar a la respuesta en https://vi.stackexchange.com/a/818/227 , puede usar el comando global.
Con él, puede indicar a vim que busque líneas que coincidan con un patrón y luego ejecutar comandos en él.
En su caso, desea anteponer texto a las líneas que comienzan con "Nivel N:", por lo que nuestro comando global podría ser
:g/^Level \d:/{COMMANDS}
Usar el comando sustituto (reemplazo de expresión regular) para el comando
Los comandos son más divertidos. Por lo general, me gusta hacer un reemplazo de expresión regular para cosas como esta, ya que es fácil de usar variables.
Ejemplo para tu pregunta
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Cómo funciona
En la sección de reemplazo de un comando de sustitución puede ser una expresión.
Lo primero que haremos es establecer una variable i
para que sea el número inicial. Elegí 1, pero cualquier número servirá.let i = 1
Luego ejecutamos nuestro comando global, que nos prepara para hacer una acción en líneas coincidentes. g/^Level \d:/
Haremos que nuestro comando global inserte el valor e incremente nuestro contador usando el comando de sustitución y el comando let. s/^/\=printf("%02d ", i)/ | let i = i+1
La expresión regular del comando de sustitución encuentra el comienzo de la línea ^
y la reemplaza con una expresión, y nuestra expresión será el resultado de una impresión formateada. Al igual que en el lenguaje C, el printf de vim toma parámetros de formato. %02d
significa convertir un argumento como si fuera un número decimal d
, ocupando al menos 2 espacios 2
y rellenar con 0 0
. Para obtener detalles y otras opciones de conversión (incluido el formato de punto flotante), consulte :help printf
. Le damos a printf nuestra variable de conteo i
y nos da 01
la primera vez, 02
la segunda, etc. Esto se usa mediante el comando de sustitución para reemplazar el comienzo de la línea, insertando efectivamente el resultado de printf al principio.
Nota que puse un espacio después de la d: "%02d "
. No lo solicitó en la pregunta (y no vi resultados de ejemplo), pero sospeché que deseaba separar el número de la palabra "Nivel". Elimine el espacio de la cadena dada a printf para tener el número insertado justo al lado de la L en el Nivel.
Finalmente, eso let i = i + 1
incrementa nuestro contador después de cada sustitución.
Esto se puede aplicar generalmente para reemplazar partes de líneas que coinciden con otros criterios con datos funcionales arbitrarios.
Usar comandos normales combinados
Esto es bueno para inserciones simples o edición compleja. Al igual que con el sustituto, usaremos global para coincidir, pero en lugar de la sustitución de expresiones regulares, ejecutaremos una serie de operaciones como si fueran escritas por el usuario.
Ejemplo para tu pregunta
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Cómo funciona
Los valores utilizados son muy similares al sustituto (todavía estamos usando printf para formatear nuestro número para que sea 0 rellenado con 2 dígitos), pero la operación es diferente.
Aquí usamos el comando execute, que toma una cadena y la ejecuta como un comando ex ( :help :exe
). Construimos una cadena que combina "normal! I" con nuestros datos, que será "normal! I01" la primera vez y "normal! I02" la segunda vez, etc.
El normal
comando realiza operaciones como si estuviera en modo normal. En este ejemplo, nuestro comando normal es I
, que se inserta al comienzo de la línea. Si lo hubiéramos usado dd
, eliminaría la línea, o
abriría una nueva línea después de la línea coincidente. Es como si escribiera I
(o cualquier otra operación) usted mismo en modo normal. Usamos el !
after normal
para asegurarnos de que no haya mapeos en nuestro camino. Ver :help :normal
.
Lo que se inserta entonces es el valor de nuestra printf, como en el primer ejemplo de uso de sustituto.
Este método puede ser más sofisticado que regex, porque puede hacer cosas como execute "normal! ^2wy" . i . "th$p"
ir al principio del texto ^
, avanzar 2 palabras 2w
, tirar hasta el carácter de la 'h' y" . i . "th
, moverse al final de la línea $
y pegar p
.
Esto es casi como ejecutar una macro, pero en realidad no usa un registro y puede combinar cadenas de cualquier expresión. Esto me parece muy poderoso.
Enfoque donde cada nivel tiene su propio contador
Es posible que desee que cada nivel obtenga su propio contador. Si conoce el número máximo de niveles con anticipación, puede hacer lo siguiente (agregar código adicional para encontrar el nivel más alto podría no ser demasiado difícil, pero haría que esta respuesta fuera demasiado larga. Esto es cada vez más larga).
Primero, liberemos i, en caso de que ya lo hayamos usado como un entero. No podemos convertir i en una lista, tenemos que crearlo de esa manera.
:unlet! i
A continuación, establezcamos i como una lista que contiene el número de niveles. Mostraste 2 en tu pregunta, pero supongamos 10 por diversión. Dado que la indexación de la lista está basada en 0, y no quiero molestarme en corregir 1 basada en su lista, crearemos suficientes elementos (11) y nunca usaremos el índice 0.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
A continuación, necesitamos una forma de obtener el número de nivel. Afortunadamente, el sustituto también está disponible como una función, por lo que le daremos nuestra línea y extraeremos el número de nivelsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Como ahora es una lista de 11 1
s (cada índice es el contador de nuestro nivel), ahora podemos ajustar cualquiera de los ejemplos anteriores para usar el resultado de esta sustitución:
Mediante comando sustituto:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Por comando normal:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Entrada de ejemplo:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Salida de ejemplo:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More