Comment déplacer du texte d'un registre vers un nombre arbitraire de registres?

10

Existe-t-il un moyen de «diriger» du texte d'un registre vers un autre registre ou ensemble de registres? Par exemple, passez "qaux registres "1via "5.

Je souhaite souvent créer des versions légèrement différentes de la même macro, il est donc utile de pouvoir copier une macro «modèle» dans plusieurs registres, puis de modifier chacun d'eux en place.

Pour donner un exemple pratique, voici le problème qui a suscité cette question pour moi.

J'ai besoin de transformer la ligne suivante d'un langage de description matérielle en plusieurs blocs répétés,

RAM64(in=in, load=load0, address=address[0..5], out=out1);

à

RAM64(in=in, load=load1, address=address[0..5], out=out2);
RAM64(in=in, load=load2, address=address[0..5], out=out3);
RAM64(in=in, load=load3, address=address[0..5], out=out4);
RAM64(in=in, load=load4, address=address[0..5], out=out5);

J'ai une macro qui effectue cela, en utilisant la fonction d'incrémentation, yypW^At)^Aque j'ai stockée dans le registre "a.

Parfois, j'ai besoin que le modèle d'incrémentation soit légèrement différent, tel que

RAM512(in=in, load=load1, address=address[0..8], out=out2);
RAM512(in=in, load=load2, address=address[0..8], out=out4);
RAM512(in=in, load=load3, address=address[0..8], out=out6);
RAM512(in=in, load=load4, address=address[0..8], out=out8);

où la macro en registre "bserait yypW^At)^A^A.

Je veux un registre pour ce faire, mais pour chaque incrément de 1 à 5. Le registre "apourrait (d'une manière ou d'une autre) être copié dans les registres b à e. Ensuite, je collais chaque registre dans la mémoire tampon, apportais la modification requise (ajoutais de termes, changeais le caractère qui suit le tmouvement, etc.) et retirais l'expression modifiée dans le registre. Idéalement, cette dernière étape pourrait même être incluse dans la ou les commandes pour copier les registres

Cela m'évite de répéter tous les caractères de la macro qui ne nécessitent PAS de modification. Pour mon exemple, cela peut être trivial, mais je peux prévoir des moments où il pourrait être très utile de faire ce que je demande.

Trousse
la source
5
En passant, je ne recommanderais pas d'utiliser les registres numérotés. Les seuls registres "sûrs" sont les registres alphabétiques. Tous les autres registres sont automatiquement définis par Vim.
jamessan

Réponses:

7

Les macros ne sont que du texte.

Ouvrez un nouveau tampon vide et placez-y votre macro. Vous pouvez dupliquer les lignes, changer une chose ici et autre chose ailleurs, puis tirer une ligne et l'utiliser immédiatement avec @".

Pas besoin de polluer vos registres, en particulier les registres de numéros qui servent un but entièrement différent.

-- Éditer --

Votre question est plus facile à comprendre maintenant que vous avez ajouté quelques explications.

En fait, il vous suffit de modifier votre enregistrement initial pour atteindre votre objectif, sans jouer avec les registres comme s'il s'agissait de variables:

:let i = 1                     " define variable i
qa                             " start recording in register a
yy                             " yank the line
p                              " paste it
W                              " move to next WORD
<C-v><C-a>                     " increment number
t)                             " jump to the other number to increment
:norm <C-r>=i<CR><C-v><C-a>    " increment the number by i
q                              " stop recording

Pour créer 5 copies de la ligne en cours avec le dernier numéro incrémenté de 2:

:let i = 2|norm 5@a

ou 12 exemplaires, le dernier chiffre étant incrémenté de 23:

:let i = 23|norm 12@a
romainl
la source
D'accord sur les registres numériques - mais que se passe-t-il si vous souhaitez utiliser ceci dans une commande et que vous avez besoin de registres qui commencent les mêmes mais deviennent différents?
wchargin
@WChargin, veuillez expliquer.
romainl
Comme dans, peut - être que je veux faire quelque chose avec des copies ayant subi une rotation d'une chaîne, donc si abcdeest @q, alors je veux @x="bcdea", @y="abcde"et @z="eabcd". Je pourrais commencer par laisser @x, @yet @ztous égaux @qpuis les modifier au besoin. Évidemment, je viens de l'inventer, mais il semble qu'il puisse y avoir des cas où quelque chose de similaire pourrait être utile.
wchargin
2
@Kit, je suis un peu préoccupé par le manque d'exemple pratique dans votre question qui le fait immédiatement sentir comme XY. Je suis presque certain que vous utilisez les registres à mauvais escient, j'aimerais donc lire une explication de ce que vous essayez de faire.
romainl
1
@Kit, c'est l'un des nombreux problèmes avec les problèmes de problèmes XY. La réponse la plus votée est une réponse directe de haute qualité à votre question mais finalement inutile dans le contexte de votre problème réel alors que ma réponse moins votée est une solution réelle à votre problème sous-jacent. Les deux réponses sont correctes mais elles répondent à des questions différentes, ce qui rend difficile la décision. Si c'était moi, j'accepterais la réponse qui répond à mon problème principal… mais c'est juste moi.
romainl
6

Utilisation de getregetsetreg

Pour copier à partir qde registres 1- 5:

let src=getreg('q', 1)
for i in range(1, 5)
    call setreg(i, src)
endfor

Pour copier dans une liste plus générale:

let src=getreg('q', 1)
for i in ['a', 'c', 'e']
    call setreg(i, src)
endfor

En utilisant execute

Pour copier à partir qde registres 1- 5:

for i in range(1, 5)
   execute 'let @' . i . '=@a'
endfor

Pour copier dans une liste plus générale:

for i in ['a', 'c', 'e']
    execute 'let @' . i . '=@a'
endfor

Explication. La commande letpeut être utilisée en tant let @x=@yque copie ypour s'inscrire x. Essentiellement, nous construisons simplement ces commandes en boucle (en changeant la valeur de xdans le formulaire ci-dessus) et executeen les ing.

wchargin
la source
1
Il n'est pas nécessaire d'utiliser :exeici. Les fonctions getreg()et setreg()seraient plus propres.
jamessan
@jamessan Belle suggestion, merci - est-ce que je les utilise correctement?
wchargin
Je l'ai édité pour ajouter le deuxième argument facultatif à getreg () car cela renvoie le contenu du registre plutôt qu'une éventuelle évaluation de celui-ci.
jamessan
1

Pour répondre directement à la question, si vous souhaitez copier rapidement et facilement le contenu d'un registre dans un autre, vous pouvez mettre ce qui suit dans votre .vimrc. Vous pouvez ensuite exécuter <leader>rcabpour copier le contenu du registre apour vous inscrire b. A titre d'exemple, j'ai choisi <leader>rcde représenter «copie d'enregistrement»

function! s:CopyRegister()
    let sourceReg = nr2char(getchar())

    if sourceReg !~# '\v^[a-z0-9]'
        echo "Invalid register given: " . sourceReg
        return
    endif

    let destinationReg = nr2char(getchar())

    if destinationReg !~# '\v^[a-z0-9]'
        echo "Invalid register given: " . destinationReg
        return
    endif

    call setreg(destinationReg, getreg(sourceReg, 1))
    echo "Replaced register '". destinationReg ."' with contents of register '". sourceReg ."'"
endfunction

" rc = register copy
nnoremap <leader>rc :call <sid>CopyRegister()<cr>
Steve Vermeulen
la source
1
Je recommanderais getreg(sourceReg, 1).
jamessan
Ah ouais, c'est vrai. Fixé.
Steve Vermeulen