Comment insérer du texte répétitif avec une différence mineure dans vim?

11

Je veux insérer du texte comme ceci:

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

Je sais que je peux coller le texte plusieurs fois puis utiliser la substitution pour changer un seul mot pour chaque ligne, mais je trouve toujours cette méthode très gênante.

Existe-t-il un moyen d'enregistrer un mot ou une liste de mots dans une "variable" puis d'utiliser cette variable pour générer un texte similaire?


EDIT J'ai rendu quelque chose de peu clair dans la question d'origine, en fait j'essaie de faire des définitions de fonctions très similaires, donc wordA wordB... peut apparaître plusieurs fois dans chaque clone de texte et le texte peut contenir plusieurs lignes. le motif est exactement comme ceci:

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

(le texte peut contenir de nouvelles lignes, et le mot A, le mot B ... peuvent exister plusieurs fois)


2nd EDIT Les parties "similar_text" peuvent être différentes à chaque fois que je fais un tel travail, donc la solution pour ce travail est préférable d'être réutilisable. Parce que j'essaie de faire des définitions de fonctions très similaires, ou une chaîne de table de mappage de fonctions.

Après avoir lu les réponses et un peu de pratique, je trouve qu'il est plus pratique de penser que ce travail est une sorte de substitution, parce que "part1", "part2" ... "partN" qui peut contenir des retours à la ligne est difficile à écrire, alors écrivez un modèle d'abord:

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

Ensuite, essayer de mettre des clones du texte, mais remplacer $ WORD par une liste de mots est une pensée plus simple.

Il semble donc que mon problème ait changé: "comment cloner un bloc de texte plusieurs fois, mais à chaque fois en y substituant un mot-clé par un mot d'une liste?"

social_loser
la source
C'est pourquoi les registres sont utilisés. Vous pouvez extraire (copier) du texte dans un registre, puis utiliser ce registre. Les macros peuvent être utilisées pour effectuer des tâches similaires et répétitives.
SibiCoder

Réponses:

7

Vous pouvez utiliser la fonction suivante:

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

Dans les variables firstpartet secondpartmettez le texte à répéter avant et après les mots et dans la liste wordsmettez les mots qui doivent changer.

Ensuite, la boucle créera le contenu de la ligne pour chaque mot de la liste, insérera la ligne dans le tampon et ira à cette nouvelle ligne.

Vous pouvez ensuite appeler simplement la fonction: call GenerateLines().


Modifier Pour faciliter la manipulation, vous pouvez également passer les différentes parties en arguments, la fonction devrait ressembler à ceci:

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

Et vous pouvez l'appeler comme ceci:

call GenerateLines("first part", "second part", ["wordA","wordB","wordC","wordD","wordE"])
statox
la source
Vous pourriez éviter la boucle avec call map(a:words, 'a:firstpart . v:val . a:secondpart')et call append(line('.'), a:words).
Antony
Étant donné que je fais souvent ce type d'édition avec de très longues "première partie" et "deuxième partie", voire "troisième partie", et que ces parties peuvent contenir des nouvelles lignes, il semble trop long de taper autant en mode commande, donc c'est peut-être plus pratique tirer du texte dans les registres, puis utiliser des fonctions pour générer du texte à partir des registres?
social_loser
J'ai édité la question, ça change beaucoup, désolé pour le dérangement.
social_loser
5

Ma stratégie dans de tels cas variera, mais elle suit souvent les étapes suivantes:

  1. Écrivez le ou les mots uniques, par exemple

    wordA
    wordB
    ...
    wordK
    
  2. Soit

    a) faire une recherche et remplacer, par exemple

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

    b) ou utilisez le mode de blocage visuel, voir :h blockwise-visual. En particulier, je sélectionnerais les mots et utiliserais Ipour insérer un texte similaire devant ou Apour ajouter un texte similaire après.

Je dirais que cette stratégie est logique lorsque vous effectuez ce genre de tâche d'édition relativement rarement. Cependant, si vous trouvez que vous devez le faire souvent, vous devez suivre la suggestion de @ statox avec une fonction qui étend la liste des mots.

Karl Yngve Lervåg
la source
Je pense que la solution dépend de la provenance de la liste de mots. Si c'est à partir d'un fichier, :readsuivi de votre substitution, cela a beaucoup de sens.
Antony
votre solution est facile à faire et résout facilement le problème que j'ai posé dans la question d'origine. Cependant il y a quelques erreurs dans mon post d'origine, j'ai fait 2 modifications et ça change beaucoup, merci pour la réponse, désolé pour mon anglais changeant et mauvais :)
social_loser
@social_loser vous pouvez adapter cette solution en utilisant "\ r" pour représenter une nouvelle ligne dans la partie de remplacement de la substitution
frangio
2

Je dirai que c'est un travail pour le bloc visuel ( Ctrl+ v). J'écrirais d'abord tous les mots distincts:

wordA
wordB
wordC
wordD
wordE

En commençant par le curseur sur le premier, wje ferais ensuite:

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

Je peux contrôler le nombre de colonnes dont j'ai besoin en appuyant A <esc>pautant de fois que je le souhaite. Supposons que j'avais besoin de trois colonnes, comme le montre la commande ci-dessus. Maintenant, nous avons ceci:

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

Et le curseur est au début du 3ème wordAdans la première ligne. Ensuite, je bloquerais la sélection de la colonne d'espaces entre les colonnes en arrière et en ajoutant le texte entre les deux. Depuis l'emplacement actuel du curseur:

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

Il en résulte (le% marque la position du curseur):

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

Répétez pour la colonne suivante:

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

Et la dernière / première (celle du côté gauche):

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

Il en résulte finalement:

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

Mise à jour: ajout d'un screencast

entrez la description de l'image ici


Cela semble être beaucoup de frappe, mais il est en fait très facile de s'y habituer. Il vous offre la liberté de modifier le nombre de mots, le nombre de colonnes et même l'espacement entre les colonnes.

L'inconvénient est que vous devez connaître le nombre de mots distincts que vous utilisez. J'ai 5codé en dur dans toutes les commandes ci-dessus car c'est le nombre de lignes sur lesquelles les commandes fonctionnent.

Note de débogage: toutes les commandes démarrent et se terminent en mode normal, si vous vous trouvez en mode visuel ou inséré à la fin d'une commande, vous faites quelque chose de mal.

grochmal
la source