Simile alla risposta su https://vi.stackexchange.com/a/818/227 , è possibile utilizzare il comando globale.
Con esso puoi istruire Vim a cercare linee che corrispondono a un modello, e quindi eseguire comandi su di esso.
Nel tuo caso, desideri anteporre il testo alle righe che iniziano con "Livello N:", quindi il nostro comando globale potrebbe essere
:g/^Level \d:/{COMMANDS}
Utilizzo del comando sostitutivo (sostituzione di espressioni regolari) per il comando
I comandi sono più divertenti. Di solito mi piace fare una sostituzione delle espressioni regolari per cose come questa, poiché è facile usare le variabili.
Esempio per la tua domanda
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Come funziona
Nella sezione di sostituzione di un comando di sostituzione può essere presente un'espressione.
La prima cosa che faremo è impostare una variabile i
come numero iniziale. Ho scelto 1, ma qualsiasi numero lo farà.let i = 1
Quindi eseguiamo il nostro comando globale, che ci imposta per fare un'azione su linee abbinate. g/^Level \d:/
Avremo il nostro comando globale inserire il valore e incrementare il nostro contatore usando il comando di sostituzione e il comando let. s/^/\=printf("%02d ", i)/ | let i = i+1
L'espressione regolare del comando di sostituzione trova l'inizio della riga ^
e la sostituisce con un'espressione e la nostra espressione sarà il risultato di una stampa formattata. Come nel linguaggio C, printf di vim accetta parametri di formattazione. %02d
significa convertire un argomento come se fosse un numero decimale d
, occupando almeno 2 spazi 2
e pad con 0 0
. Per dettagli e altre opzioni di conversione (inclusa la formattazione in virgola mobile), vedere :help printf
. Diamo a printf la nostra variabile di conteggio i
e ci dà 01
la prima volta, 02
la seconda volta, ecc. Questo viene utilizzato dal comando di sostituzione per sostituire l'inizio della riga, inserendo efficacemente il risultato della stampa all'inizio.
Nota che ho messo uno spazio dopo la d: "%02d "
. Non l'hai chiesto nella domanda (e non ho visto l'output di esempio), ma sospettavo che volessi separare il numero dalla parola "Livello". Rimuovere lo spazio dalla stringa assegnata a printf per avere il numero inserito proprio accanto alla L in Level.
Infine, questo let i = i + 1
aumenta il nostro contatore dopo ogni sostituzione.
Questo può essere applicato generalmente per sostituire parti di linee che sono soddisfatte da altri criteri con dati funzionali arbitrari.
Utilizzo dei comandi normali combinati
Questo è utile per inserimenti semplici o modifiche complesse. Come con sostituto, useremo global per abbinare, ma invece della sostituzione di espressioni regolari, eseguiremo una serie di operazioni come se fossero state digitate dall'utente.
Esempio per la tua domanda
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Come funziona
I valori utilizzati sono molto simili al sostituto (stiamo ancora usando printf per formattare il nostro numero per renderlo 0 riempito con 2 cifre), ma l'operazione è diversa.
Qui usiamo il comando execute, che accetta una stringa ed esegue la stringa come un comando ex ( :help :exe
). Costruiamo una stringa che combina "normale! I" con i nostri dati, che sarà "normale! I01" la prima volta e "normale! I02" la seconda volta, ecc.
Il normal
comando esegue le operazioni come in modalità normale. In questo esempio, il nostro normale comando è I
, che viene inserito all'inizio della riga. Se lo avessimo usato dd
, eliminerebbe la riga, o
aprirà una nuova riga dopo la riga corrispondente. È come se tu I
stessi digitando (o qualsiasi altra operazione) in modalità normale. usiamo il !
after normal
per assicurarci che nessuna mappatura ci ostacoli. Vedere :help :normal
.
Ciò che viene inserito è quindi il valore del nostro printf, come nel primo esempio di utilizzo di sostituto.
Questo metodo può essere più elaborato di regex, perché puoi fare cose del genere execute "normal! ^2wy" . i . "th$p"
, che andranno all'inizio del testo ^
, avanzano di 2 parole 2w
, tirano fino al carattere ith 'h' y" . i . "th
, si spostano alla fine della riga $
e incollano p
.
È quasi come eseguire una macro, ma in realtà non utilizza un registro e può combinare stringhe da qualsiasi espressione. Trovo che questo sia molto potente.
Approccio in cui ogni livello ha il proprio contatore
Potresti desiderare che ogni livello ottenga il proprio contatore. Se si conosce il numero massimo di livelli in anticipo, è possibile effettuare le seguenti operazioni (l'aggiunta di un codice aggiuntivo per trovare il livello più grande potrebbe non essere troppo difficile, ma renderebbe questa risposta troppo lunga. Si sta allungando così com'è).
Innanzitutto, liberiamo i, nel caso in cui l'abbiamo già usato come numero intero. Non possiamo convertire i in un elenco, dobbiamo crearlo in questo modo.
:unlet! i
Quindi, consente di impostare i come elenco contenente il numero di livelli. Hai mostrato 2 nella tua domanda, ma supponiamo che 10 si divertano. Poiché l'indicizzazione dell'elenco è basata su 0 e non voglio preoccuparmi di correggerla per 1 in base al tuo elenco, creeremo solo elementi sufficienti (11) e non utilizzeremo mai l'indice 0.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
Successivamente, abbiamo bisogno di un modo per ottenere il numero di livello. Fortunatamente, sostituto è disponibile anche come funzione, quindi gli daremo la nostra linea ed estrarremo il numero di livellosubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Poiché i è ora un elenco di 11 1
s (ogni indice è il contatore per il nostro livello), ora possiamo regolare uno degli esempi sopra per utilizzare il risultato di questa sostituzione:
Tramite comando sostitutivo:
: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
Tramite comando normale:
: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
Esempio di input:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Esempio di output:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More