Come inserire testo ripetitivo con lievi differenze in vim?


11

Voglio inserire un testo come questo:

similar text wordA similar text ...
similar text wordB similar text ...
similar text wordC similar text ...

So di poter incollare il testo molte volte, quindi utilizzare la sostituzione per modificare una singola parola per ogni riga, tuttavia trovo ancora questo metodo molto scomodo.

C'è un modo per salvare una parola o un elenco di parole in una "variabile" e quindi utilizzare questa variabile per generare un testo simile?


EDIT Ho fatto qualcosa di poco chiaro nella domanda originale, in effetti sto cercando di fare alcune definizioni di funzioni molto simili, quindi wordA wordB... può apparire molte volte in ogni clone di testo e il testo può contenere molte righe. il modello è esattamente così:

similar_text1 wordA similar_text2 wordA similar_text3 ...
similar_text1 wordB similar_text2 wordB similar_text3 ...
similar_text1 wordC similar_text2 wordC similar_text3 ...

(il testo può contenere nuove righe e la parola A, la parola B ... possono esistere molte volte)


2 ° EDIT Le parti "similar_text" possono essere diverse ogni volta che eseguo tale lavoro, quindi è meglio riusare la soluzione per questo lavoro. Perché sto cercando di creare definizioni di funzioni molto simili o una stringa per la tabella di mapping delle funzioni.

Dopo aver letto le risposte e un po 'di pratica, trovo che sia più conveniente pensare a questo lavoro come una sorta di sostituzione, perché separare "part1", "part2" ... "partN" che può contenere newline è difficile da scrivere, quindi scrivere prima un modello:

similar_text1 $WORD similar_text2 $WORD similar_text3 ...
(text may contain <ENTER>, make sure $WORD not exist in "similar_text" parts )

Quindi provare a mettere cloni del testo ma sostituire $ WORD con un elenco di parole è più semplice pensare.

Quindi sembra che il mio problema sia cambiato in "come clonare un blocco di testo molte volte, ma ogni volta sostituendo una parola chiave con una parola da un elenco?"


Ecco perché vengono utilizzati i registri. È possibile copiare (copiare) il testo in un registro e quindi utilizzare quel registro. Le macro possono essere utilizzate per svolgere attività simili e ripetitive.
SibiCoder

Risposte:


7

È possibile utilizzare la seguente funzione:

function! GenerateLines()
    let firstpart="similar text part 1"
    let secondpart="similar text part 2"

    let words=["wordA","wordB","wordC","wordD","wordE"]

    for word in words
        let line = firstpart . word . secondpart
        call append(line('.')+1, line)
        normal j
    endfor
endfunction

Nelle variabili firstparte secondpartmetti il ​​testo da ripetere prima e dopo le parole e nella lista wordsinserisci le parole che dovrebbero cambiare.

Quindi il loop creerà il contenuto della riga per ogni parola dell'elenco, inserirà la riga nel buffer e passerà a questa nuova riga.

Si può poi semplicemente chiamare la funzione: call GenerateLines().


Modifica Per semplificare la manipolazione, puoi anche passare le diverse parti come argomenti, la funzione dovrebbe apparire così:

function! GenerateLines(firstpart, secondpart, words)
    for word in a:words
        call append(line('.')+1, a:firstpart . word . a:secondpart)
        normal j
    endfor
endfunction

E puoi chiamarlo così:

call GenerateLines("first part", "second part", ["wordA","wordB","wordC","wordD","wordE"])

È possibile evitare il ciclo con call map(a:words, 'a:firstpart . v:val . a:secondpart')e call append(line('.'), a:words).
Antony,

Dato che faccio spesso questo tipo di modifica con "firstpart" e "secondpart" molto lunghi, anche "thirdpart", e queste parti possono contenere righe, sembra essere troppo lungo per digitare così tanto in modalità comando, quindi forse è più conveniente inserire il testo nei registri, quindi utilizzare le funzioni per generare testo dai registri?
social_loser

Ho modificato la domanda, cambia molto, mi dispiace per l'inconveniente.
social_loser

5

La mia strategia in questi casi può variare, ma spesso segue i seguenti passaggi:

  1. Scrivi le parole uniche, ad es

    wordA
    wordB
    ...
    wordK
    
  2. O

    a) fare una ricerca e sostituire, ad es

    :%s/\w\+/similar text \0 similar text .../
    

    b) o utilizzare la modalità blocco visivo, vedere :h blockwise-visual. In particolare, selezionerò le parole e le uso Iper inserire un testo simile davanti o Aper aggiungere un testo simile dopo.

Direi che questa strategia ha senso quando esegui questo tipo di attività di modifica relativamente di rado. Tuttavia, se trovi che devi farlo spesso, allora dovresti seguire il suggerimento di @ statox con una funzione che espande l'elenco delle parole.


Penso che la soluzione dipenda da dove proviene l'elenco di parole. Se proviene da un file, :readseguito dalla sostituzione ha molto senso.
Antony,

la tua soluzione è facile da fare e risolvi facilmente il problema che ho posto nella domanda originale. Tuttavia ci sono alcuni errori nel mio post originale, ho fatto 2 modifiche e cambia molto, grazie per la risposta, scusate il mio inglese mutevole e cattivo :)
social_loser

@social_loser puoi adattare questa soluzione usando "\ r" per
indicare

2

Sosterrò che questo è un lavoro per il blocco visivo ( Ctrl+ v). Per prima cosa scrivo tutte le parole distinte:

wordA
wordB
wordC
wordD
wordE

Iniziando con il cursore sul primo, weseguirò quindi:

<c-v>5j$yA <esc>pA <esc>p

Posso controllare quante colonne mi servono premendo A <esc>pquante volte voglio. Supponiamo che avessi bisogno di tre colonne proprio come mostra il comando sopra. Ora abbiamo questo:

wordA wordA wordA
wordB wordB wordB
wordC wordC wordC
wordD wordD wordD
wordE wordE wordE

E il cursore si trova all'inizio del 3 ° wordAnella prima riga. Successivamente vorrei bloccare selezionare la colonna di spazio tra le colonne andando indietro e aggiungendo il testo in mezzo. Dalla posizione corrente del cursore:

h<c-v>5jI similar text 3<esc>

Ciò si traduce in (la% indica la posizione del cursore):

wordA wordA%similar text 3 wordA
wordB wordB similar text 3 wordB
wordC wordC similar text 3 wordC
wordD wordD similar text 3 wordD
wordE wordE similar text 3 wordE

Ripeti per la colonna successiva:

bh<c-v>5jI similar text 2<esc>

E l'ultima / prima colonna (quella sul lato sinistro):

b<c-v>5jIsimilar text 1 <esc>

Alla fine risulta in:

similar text 1 wordA similar text 2 wordA similar text 3 wordA
similar text 1 wordB similar text 2 wordB similar text 3 wordB
similar text 1 wordC similar text 2 wordC similar text 3 wordC
similar text 1 wordD similar text 2 wordD similar text 3 wordD
similar text 1 wordE similar text 2 wordE similar text 3 wordE

Aggiornamento: aggiunto uno screencast

inserisci qui la descrizione dell'immagine


Sembra che ci sia molta digitazione, ma in realtà è molto facile abituarsi. Ti dà la libertà di cambiare il numero di parole, il numero di colonne e persino la spaziatura tra le colonne.

Lo svantaggio è che devi conoscere il numero di parole distinte che stai usando. Ho un 5hardcoded in tutti i comandi sopra perché è il numero di righe su cui stanno operando i comandi.

Nota di debug: tutti i comandi iniziano e finiscono in modalità normale, se ti trovi in ​​modalità visiva o di inserimento alla fine di un comando stai facendo qualcosa di sbagliato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.