Beh, avere una funzione di eseguire solo una volta in un intervallo, aggiungere la parola chiave range
. Per esempio.
fun Foo() range
...
endfun
Allora la vostra funzione può prendersi cura del campo di se stesso con i parametri speciali a: Firstline e un: lastLine. (Vedere :help a:firstline
per i dettagli.)
però penso che in questo caso le vostre esigenze sono solo circa abbastanza semplice da realizzare con un one-liner utilizzando :global
.
Potremmo fare davvero meglio con input e output specificati. Ma assumendo un file contenente
Item a: <total>
Subitem: 10 min
Subitem 2: 20 min
Item b: <total>
Subitem: 10 min
Subitem 2: 23 min
Item c: <total>
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
e una funzione definita come
fun! Sum(n)
let g:s += a:n
return a:n
endfun
allora questo sommare gli elementi secondari (una sola riga)
:g/^Item/ let g:s = 0 | mark a | +,-/\nItem\|\%$/ s/\v(\d+)\ze\s+min$/\=Sum(submatch(0))/g | 'a s/<total>/\=(g:s . ' min')/
e produrre questo output
Item a: 30 min
Subitem: 10 min
Subitem 2: 20 min
Item b: 33 min
Subitem: 10 min
Subitem 2: 23 min
Item c: 76 min
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
A proposito, il comando precedente agisce sull'intero buffer. Se si evidenzia prima un intervallo e poi si preme la chiave :
, vim aggiungerà automaticamente il comando con '<,'>
, il che significa che il comando seguente funzionerà dall'inizio alla fine dell'intervallo evidenziato.
E.g. evidenziando linee da 1 a 5 e poi eseguendo il comando (:'<,'> g/...
) produce questo risultato
Item a: 30 min
Subitem: 10 min
Subitem 2: 20 min
Item b: 33 min
Subitem: 10 min
Subitem 2: 23 min
Item c: <total>
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
Una nota finale. Se uno dei gruppi non ha elementi secondari, ad es.
Item a: <total>
Subitem: 10 min
Subitem 2: 20 min
Item b: <total>
Item c: <total>
Subitem: 10 min
Subitem 2: 23 min
Subitem 3: 43 min
il comando si interrompe con un errore 'intervallo valido' quando raggiunge il secondo elemento. Puoi fare in modo che Vim ignori questo e continui a prescindere anteponendo l'intero comando a :silent!
.
EDIT
Solo una breve spiegazione del mio flusso di lavoro e perché il lungo one-liner.
- Mi piace
:g
ed ex comandi molto.
- Ho sviluppato il comando in modo interattivo utilizzando la cronologia della riga di comando e la finestra della riga di comando per la modifica.
- Quando ho finito, incollo comandi singoli come questo nel buffer: ho una mappatura per eseguire la riga corrente come un comando ex. In questo modo il comando è sempre facilmente disponibile quando ne ho bisogno. Per un uso più regolare si potrebbe desiderare un comando, una funzione o un ftplugin.
è ... bello ... Scherzi a parte, grazie per il miglior SO rispondere Probabilmente ho mai ricevuto. –
Btw, per chiunque pensi che il comando: g sopra sembra complesso, non lo è davvero. La sintassi è molto concisa e potrebbe dargli quell'aspetto, ma le operazioni sono davvero piuttosto semplici; non ci sono trucchi intelligenti. Basta cercare i bit che non si trovano nella meravigliosa documentazione, o chiedere a SO o al gruppo vim_use di Google. – 1983
Mi c'è voluto molto tempo per capire ... ecco la spiegazione: : g avvia un comando globale /^ Articolo/il comando viene eseguito in ogni riga che corrisponde^Articolo Sia G: s = 0 contrassegna a Memorizza la posizione del cursore in un +, -/\ nItem \ | \% $/s/\ v (\ d +) \ ze \ s + min $/\ = Sum (submatch (0))/g Questa è una bestia enorme di un comando sostitutivo. La parte fino alla prima "s" è la gamma, la parte tra "s" e "$" è il modello e la chiamata di funzione è la sostituzione (nulla viene effettivamente sostituito) 'a tornare alla posizione contrassegnato con s//\ = (g: s. 'min')/ sostituire infine lo –