줄 끝에서 재귀 매크로를 어떻게 중지합니까?


13

줄 끝까지 만 실행되도록 재귀 매크로를 어떻게 만들 수 있습니까?

또는 줄 끝까지 만 재귀 매크로를 실행하는 방법은 무엇입니까?

답변:


11

아마도 더 간단한 방법이 있지만 다음을 시도해 볼 수 있습니다.

레지스터 q를 사용 하여 재귀 매크로를 기록 한다고 가정 해 봅시다 .

기록의 맨 처음에 다음을 입력하십시오.

:let a = line('.')

그런 다음 기록의 마지막에 @q매크로를 재귀 적으로 만들기 위해 누르는 대신 다음 명령을 입력하십시오.

:if line('.') == a | exe 'norm @q' | endif

로 매크로 기록을 종료하십시오 q.

마지막으로 입력 한 명령은 매크로 q( exe 'norm @q')를 재생 하지만 현재 행 번호 ( line('.'))가 처음에 variable에 저장된 명령과 동일한 경우에만 재생 됩니다 a.

:normal명령을 사용하면 @qEx 모드에서 일반 명령 ( 예 :) 을 입력 할 수 있습니다 .
그리고 명령이 문자열로 래핑되고 명령에 의해 실행되는 이유 는 나머지 명령 ( )을 사용 (타이핑)하는 :execute것을 방지하기 위해서 :normal입니다 |endif.


사용 예.

다음과 같은 버퍼가 있다고 가정 해 봅시다.

1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4

그리고 재귀 매크로를 사용하여 임의의 줄에서 모든 숫자를 증가시키고 싶습니다.

당신은 입력 할 수 0다음 매크로 기록을 시작 줄의 시작 부분으로 커서를 이동합니다 :

qqq
qq
:let a=line('.')
<C-a>
w
:if line('.')==a|exe 'norm @q'|endif
q
  1. qqqq매크로 정의 중에 처음 호출 할 때 방해하지 않도록 레지스터의 내용을 지 웁니다.
  2. qq 녹음을 시작합니다
  3. :let a=line('.') 변수 안에 현재 줄 번호를 저장합니다 a
  4. Ctrl+ a커서 아래 숫자를 증가시킵니다
  5. w 커서를 다음 숫자로 이동
  6. :if line('.')==a|exe 'norm @q'|endif 행 번호가 변경되지 않은 경우에만 매크로를 호출합니다.
  7. q 녹음을 중지

매크로를 정의하고 나면 커서를 세 번째 줄에 놓고 커서를 눌러 줄 0의 시작 부분으로 이동 한 다음 @q을 눌러 매크로를 재생 q하면 다른 줄이 아닌 현재 줄에만 영향을 미칩니다.

1 2 3 4
1 2 3 4
2 3 4 5
1 2 3 4

기록 후 매크로 재귀 만들기

원하는 경우 매크로를 레지스터 내부의 문자열에 저장하고 도트 .연산자로 두 개의 문자열을 연결할 수 있다는 사실을 사용하여 기록 후 매크로를 재귀 적으로 만들 수 있습니다 .

이렇게하면 몇 가지 이점이 있습니다.

  • 문자 @q가 정의 된 후 매크로에 추가되고 이전 내용이 무엇이든 덮어 쓴 후 기록 전에 레지스터를 지우지 않아도 됩니다.
  • 녹화 중에 특이한 것을 입력 할 필요없이 간단하고 작동하는 매크로를 만드는 데 집중할 수 있습니다.
  • 재귀 적으로 만들기 전에 테스트하여 테스트하는 방법

매크로를 평소와 같이 (재귀 적으로) 기록하지 않으면 다음 명령을 사용하여 매크로를 재귀 적으로 만들 수 있습니다.

let @q = @q . "@q"

또는 더 짧습니다 : let @q .= "@q"
.=문자열을 다른 문자열에 추가 할 수있는 연산자입니다.

이것은 @q레지스터 안에 저장된 일련의 키 스트로크 끝에 2 개의 문자 를 추가해야합니다 q. 사용자 정의 명령을 정의 할 수도 있습니다.

command! -register RecursiveMacro let @<reg> .= "@<reg>"

:RecursiveMacro레지스터의 이름을 인수로 기다리는 명령 을 정의합니다 (에 -register전달 된 속성 때문에 :command).
이전과 동일한 명령이며, 모든 차이점은로 대체한다는 것 q입니다 <reg>. 명령이 실행될 때 Vim은 <reg>사용자가 제공 한 레지스터 이름 으로 모든 항목을 자동으로 확장합니다 .

이제는 평소와 같이 매크로를 비재 귀적으로 기록한 다음 :RecursiveMacro q레지스터 내부에 저장된 매크로를 q재귀 적 으로 만들려면 입력 하십시오 .


현재 행에있는 조건에서 매크로를 재귀 적으로 만들기 위해 동일한 작업을 수행 할 수 있습니다.

let @q = ":let a=line('.')\r" . @q . ":if line('.')==a|exe 'norm @q'|endif\r"

이번에는 녹음 후 수행하는 것을 제외하고 게시물 시작 부분에 설명 된 것과 똑같습니다. q레지스터에 현재 포함 된 키 입력 전후에 두 개의 문자열을 연결하기 만하면됩니다 .

  1. let @q = 레지스터 내용을 재정의 q
  2. ":let a=line('.')\r"a매크로가
    \rEnter 키를 누르고 명령을 실행하도록 Vim에 지시 하는 작업을 수행하기 전에 변수에 현재 줄 번호를 저장합니다. :help expr-quote유사한 특수 문자 목록을 참조하십시오 .
  3. . @q .q레지스터 의 현재 내용을 이전 문자열과 다음 문자열로 연결합니다 .
  4. ":if line('.')==a|exe 'norm @q'|endif\r"q라인이 변경되지 않은 상태 에서 매크로 를 호출합니다.

다시 한 번 키 입력을 저장하기 위해 다음 사용자 정의 명령을 정의하여 프로세스를 자동화 할 수 있습니다.

command! -register RecursiveMacroOnLine let @<reg> = ":let a=line('.')\r" . @<reg> . ":if line('.')==a|exe 'norm @<reg>'|endif\r"

다시 말하지만, 평소와 같이 매크로를 비재 귀적으로 기록한 다음 :RecursiveMacroOnLine q레지스터에 저장된 매크로를 q현재 줄에 유지되는 상태에서 재귀 적으로 만들려면 입력 하십시오.


두 명령을 병합

또한 :RecursiveMacro두 가지 경우를 다루 도록 조정할 수 있습니다 .

  • 매크로를 무조건 재귀 적으로 만듭니다.
  • 현재 줄에있는 상태에서 매크로를 재귀 적으로 만듭니다.

이렇게하려면에 두 번째 인수를 전달하면됩니다 :RecursiveMacro. 후자는 단순히 값을 테스트하고 값에 따라 두 개의 이전 명령 중 하나를 실행합니다. 그것은 다음과 같은 것을 줄 것입니다 :

command! -register -nargs=1 RecursiveMacro if <args> | let @<reg> .= "@<reg>" | else | let @<reg> = ":let a=line('.')\r" . @<reg> . ":if line('.')==a|exe 'norm @<reg>'|endif\r" | endif

또는 (행 연속 / 백 슬래시를 사용하여 좀 더 읽기 쉽게) :

command! -register -nargs=1 RecursiveMacro
           \ if <args> |
           \     let @<reg> .= "@<reg>" |
           \ else |
           \     let @<reg> = ":let a = line('.')\r" .
           \                  @<reg> .
           \                  ":if line('.')==a | exe 'norm @<reg>' | endif\r" |
           \ endif

이번에는 :RecursiveMacro( -nargs=1속성 때문에) 두 번째 인수를 제공해야한다는 점을 제외하면 이전과 동일합니다 .
이 새 명령이 실행될 때 Vim은 <args>사용자가 제공 한 값 으로 자동 확장 됩니다.
이 두 번째 인수가 0이 아닌 값 (true if <args>) 이면 명령의 첫 번째 버전이 실행되고 (매크로를 무조건 재귀 적으로 작성하는 버전), 그렇지 않으면 0이 아닌 경우 두 번째 버전이 실행됩니다 ( 현재 줄에 머물러있는 조건에서 매크로 재귀).

이전 예제로 돌아 가면 다음과 같은 결과가 나타납니다.

qq
<C-a>
w
q
:RecursiveMacro q 0
3G
0@q
  1. qq 레지스터 내에서 매크로 기록을 시작합니다 q
  2. <C-a> 커서 아래 숫자를 증가시킵니다
  3. w 커서를 다음 숫자로 이동
  4. q 녹음을 종료합니다
  5. :RecursiveMacro q 0레지스터 안에 저장된 매크로를 q 재귀 적이지만 줄 끝까지 만 (두 번째 인수 때문에 0)
  6. 3G 커서를 임의의 줄로 이동합니다 (예 : 3)
  7. 0@q 줄의 처음부터 재귀 매크로를 재생합니다

이전과 동일한 결과를 제공해야합니다.

1 2 3 4
1 2 3 4
2 3 4 5
1 2 3 4

그러나 이번에는 매크로를 기록하는 동안주의를 산만하게 입력 할 필요가 없었습니다.

그리고 5 단계에서 0이 아닌 인수를 명령에 전달한 경우, 즉 :RecursiveMacro q 1대신을 입력 :RecursiveMacro q 0하면 매크로 q가 무조건 재귀가되어 다음과 같은 버퍼를 갖게됩니다.

1 2 3 4
1 2 3 4
2 3 4 5
2 3 4 5

이번에는 매크로가 세 번째 줄의 끝이 아니라 버퍼의 끝에서 멈췄을 것입니다.


자세한 내용은 다음을 참조하십시오.

:help line()
:help :normal
:help :execute
:help :command-nargs
:help :command-register

2
매크로가 일치하는 위치를 변경하지 않는 한 (예 : :lv /\%3l\d/g %<CR>qqqqq<C-a>:lne<CR>@qq@q행 3의 모든 숫자가 증가 하는 경우) 위치 목록을 사용하여 매크로에서 검색 일치를 진행하는 데 사용할 수 있습니다 .
djjcast

@ djjcast 당신은 답변으로 게시 할 수 있습니다, 나는 그것을 시도하고 정말 훌륭하게 작동합니다. 내가 이해하지 못하는 단 하나의 사례가 있습니다. 다음 줄에서 매크로를 실행할 때 대신을 1 2 3 4 5 6 7 8 9 10얻습니다 . 왜 그런지 모르겠습니다. 어쨌든 그것은 내 간단한 접근 방식보다 더 정교 해 보이며 매크로가 커서를 움직여야하는 위치 와이 방법으로는 결코 본 적이없는 위치 목록을 설명하는 정규식이 필요합니다. 나는 그것을 많이 좋아! 2 3 4 5 6 7 8 9 10 122 3 4 5 6 7 8 9 10 11
saginaw

@ djjcast 죄송합니다, 방금 이해했습니다. 문제는 단순히 정규식에서 나왔습니다 \d\+. 여러 자리 숫자를 설명하는 데 사용해야 했습니다.
saginaw

@ djjcast Ah 이제 매크로가 일치하는 위치를 변경해서는 안된다고 말했을 때의 의미를 이해합니다. 그러나이 문제를 해결하는 방법을 모르겠습니다. 매크로 내부에서 위치 목록을 업데이트하는 것이 유일한 아이디어이지만 위치 목록에 익숙하지 않습니다. 매우 복잡합니다. 정말 미안합니다.
saginaw

1
@saginaw 일치하는 항목을 역순으로 반복하면 매크로가 이전 일치하는 위치를 변경할 가능성이 적기 때문에 대부분의 경우 문제를 해결하는 것처럼 보입니다. 따라서 :lv ...명령 후에는 명령을 :lla사용하여 마지막 일치 항목으로 :lp건너 뛰고 명령을 사용하여 일치 항목을 역순으로 진행할 수 있습니다.
djjcast

9

재귀 매크로는 실패한 명령이 발생하자마자 중지됩니다. 따라서 줄 끝에서 멈추려면 줄 끝에서 실패하는 명령이 필요합니다.

기본적으로 * l명령은 이러한 명령이므로 재귀 매크로를 중지하는 데 사용할 수 있습니다. 커서가 줄의 끝에 있지 않으면 명령을 사용하여 나중에 커서를 다시 이동하면됩니다 h.

따라서 saginaw와 동일한 예제 매크로를 사용하십시오 .

qqqqq<c-a>lhw@qq

세분화 :

  1. qqq: q 레지스터를 지우십시오.
  2. qq: q레지스터 에서 매크로 기록을 시작합니다.
  3. <c-a>: 커서 아래의 숫자를 증가시킵니다.
  4. lh: 줄 끝에 있으면 매크로를 중단합니다. 그렇지 않으면 아무것도하지 마십시오.
  5. w: 줄의 다음 단어로 넘어갑니다.
  6. @q: 되풀이
  7. q: 녹화를 중지합니다.

그런 다음 0@qsaginaw에서 설명한 것과 동일한 명령으로 매크로를 실행할 수 있습니다 .


*이 'whichwrap'옵션을 사용하면 줄의 시작 또는 끝 부분에있을 때 다음 줄로 감쌀 이동 키를 정의 할 수 있습니다 (참조 :help 'whichwrap'). l이 옵션 을 설정 하면 위에서 설명한 해결 방법이 중단됩니다.

그러나, 당신은 단지 하나의 문자를 발전의 세 가지 기본 정상 모드 명령 중 하나를 사용 (가능성이 <Space>, l그리고 <Right>당신이 그렇다면) l당신에 포함 된 'whichwrap'설정, 당신은 당신이 것을 하나 제거 할 수 없는 으로부터 사용을 'whichwrap'옵션, 예 <Space>:

:set whichwrap-=s

그런 다음 l매크로의 4 단계 에서 명령을 명령으로 바꿀 수 있습니다 <Space>.


1
또한 설정 virtualedit=onemorel행 끝을 감지하는 데 사용 하는 데 방해가 되지만 심각하지는 않습니다 whichwrap=l.
Kevin

@ 케빈 좋은 지적! 언급하도록 답변을 업데이트하겠습니다've'
Rich
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.