Jak można przenieść tekst z jednego rejestru do dowolnej liczby rejestrów?

10

Czy istnieje sposób na przeniesienie tekstu z rejestru do innego rejestru lub zestawu rejestrów? Na przykład przejdź "qdo rejestrów "1przez "5.

Często chcę tworzyć nieco inne wersje tego samego makra, więc warto skopiować makro „szablonu” do kilku rejestrów, a następnie zmodyfikować każde z nich na miejscu.

Aby dać praktyczny przykład, oto problem, który skłonił mnie do tego pytania.

Muszę przekształcić następujący wiersz z języka opisu sprzętu w wiele powtarzających się bloków,

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

do

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);

Mam makro, które wykonuje to, używając funkcji przyrostowej, yypW^At)^Aktórą zapisałem w rejestrze "a.

Czasami potrzebuję, aby wzorzec przyrostu był nieco inny, np

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);

gdzie "bbyłoby makro w rejestrze yypW^At)^A^A.

Chcę, aby rejestr to zrobił, ale dla każdego przyrostu od 1-5. Rejestr "amożna (w jakiś sposób) skopiować do rejestrów od b do e. Następnie wkleiłem każdy rejestr do bufora, dokonałem wymaganej modyfikacji (dodałem więcej terminów, zmieniłem znak następujący po truchu itp.) I wcisnąłem zmodyfikowane wyrażenie z powrotem do rejestru. Idealnie ten ostatni krok mógłby nawet zostać zawarty w poleceniu (-ach), aby skopiować rejestry

To oszczędza mi powtarzania wszystkich znaków w makrze, które NIE wymagają zmiany. W moim przykładzie może to być trywialne, ale mogę przewidzieć czasy, w których zrobienie tego, o co proszę, może być bardzo pomocne.

Zestaw
źródło
5
Nawiasem mówiąc, nie zalecałbym używania rejestrów numerowanych. Jedynymi „bezpiecznymi” rejestrami są rejestry alfabetyczne. Wszystkie inne rejestry są ustawiane automatycznie przez Vima.
jamessan

Odpowiedzi:

7

Makra to tylko tekst.

Otwórz nowy pusty bufor i umieść tam swoje makro. Możesz powielić linie, zmienić jedną rzecz tutaj i coś innego w innym miejscu, a następnie zerwać linię i użyć jej od razu @".

Nie ma potrzeby zanieczyszczania rejestrów, zwłaszcza rejestrów numerów, które służą zupełnie innym celom.

-- edytować --

Twoje pytanie jest łatwiejsze do zrozumienia, gdy dodałeś jakieś wyjaśnienie.

Jak się okazuje, wystarczy zmienić początkowe nagranie, aby osiągnąć cel, bez grania rejestrami tak, jakby były zmiennymi:

: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

Aby utworzyć 5 kopii bieżącego wiersza z ostatnim numerem zwiększonym o 2:

:let i = 2|norm 5@a

lub 12 kopii, z ostatnią liczbą powiększoną o 23:

:let i = 23|norm 12@a
romainl
źródło
Zgadzam się co do rejestrów numerycznych - ale co, jeśli chcesz użyć tego w poleceniu i potrzebujesz rejestrów, które zaczynają się tak samo, ale stają się inne?
wchargin
@WChargin, proszę wyjaśnić.
romainl
Jak w, może chcę zrobić coś z obróconych kopii sznurku, więc jeśli abcdejest @q, to chcę @x="bcdea", @y="abcde"i @z="eabcd". Mógłbym zacząć od pozwalania @x, @yi @zwszystko równe, @qa następnie modyfikowanie ich w razie potrzeby. Oczywiście, właśnie to, ale wydaje się, że mogą istnieć pewne sytuacje, w których coś podobnego może być przydatne.
wchargin
2
@Kit, jestem trochę zaniepokojony brakiem praktycznego przykładu w twoim pytaniu, które natychmiast sprawia, że ​​pachnie jak XY. Jestem prawie pewien, że niewłaściwie używasz rejestrów, więc chciałbym przeczytać wyjaśnienie tego, co próbujesz zrobić.
romainl
1
@Kit, to jeden z wielu problemów z problemami z XY. Najbardziej pozytywną odpowiedzią jest wysokiej jakości bezpośrednia odpowiedź na twoje pytanie, ale ostatecznie bezużyteczna w kontekście twojego prawdziwego problemu, podczas gdy moja mniej pozytywna odpowiedź jest rzeczywistym rozwiązaniem podstawowego problemu. Obie odpowiedzi są poprawne, ale odpowiadają na różne pytania, co utrudnia podjęcie decyzji. Gdybym to był ja, zaakceptowałbym odpowiedź dotyczącą mojego podstawowego problemu… ale to tylko ja.
romainl
6

Korzystanie getregisetreg

Aby skopiować z qdo rejestrów 1- 5:

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

Aby skopiować na bardziej ogólną listę:

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

Za pomocą execute

Aby skopiować z qdo rejestrów 1- 5:

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

Aby skopiować na bardziej ogólną listę:

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

Wyjaśnienie. Polecenia letmożna użyć jako let @x=@y, które kopie rejestrują się ydo zarejestrowania x. Zasadniczo konstruujemy te polecenia w pętli (zmieniając wartość xw powyższej formie) i executeje przetwarzamy.

wchargin
źródło
1
Nie ma tu potrzeby używania :exe. Funkcje getreg()i setreg()byłyby czystsze.
jamessan
@jamessan Ładna sugestia, dzięki - czy używam ich poprawnie?
wchargin
Zredagowałem go, aby dodać opcjonalny drugi argument do getreg (), ponieważ zwraca on zawartość rejestru zamiast możliwej oceny.
jamessan
1

Aby bezpośrednio odpowiedzieć na pytanie, jeśli chcesz szybko i łatwo skopiować zawartość jednego rejestru do drugiego, możesz umieścić w .vimrc następujące elementy. Następnie można wykonać, <leader>rcababy skopiować zawartość rejestru ado rejestracji b. Jako przykład wybrałem opcję <leader>rc„zarejestruj kopię”

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
źródło
1
Polecam getreg(sourceReg, 1).
jamessan
Ach tak, prawda. Naprawiony.
Steve Vermeulen,