답변:
아마도 더 간단한 방법이 있지만 다음을 시도해 볼 수 있습니다.
레지스터 q
를 사용 하여 재귀 매크로를 기록 한다고 가정 해 봅시다 .
기록의 맨 처음에 다음을 입력하십시오.
:let a = line('.')
그런 다음 기록의 마지막에 @q
매크로를 재귀 적으로 만들기 위해 누르는 대신 다음 명령을 입력하십시오.
:if line('.') == a | exe 'norm @q' | endif
로 매크로 기록을 종료하십시오 q
.
마지막으로 입력 한 명령은 매크로 q
( exe 'norm @q'
)를 재생 하지만 현재 행 번호 ( line('.')
)가 처음에 variable에 저장된 명령과 동일한 경우에만 재생 됩니다 a
.
이 :normal
명령을 사용하면 @q
Ex 모드에서 일반 명령 ( 예 :) 을 입력 할 수 있습니다 .
그리고 명령이 문자열로 래핑되고 명령에 의해 실행되는 이유 는 나머지 명령 ( )을 사용 (타이핑)하는 :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
qqq
q
매크로 정의 중에 처음 호출 할 때 방해하지 않도록 레지스터의 내용을 지 웁니다.qq
녹음을 시작합니다:let a=line('.')
변수 안에 현재 줄 번호를 저장합니다 a
w
커서를 다음 숫자로 이동:if line('.')==a|exe 'norm @q'|endif
행 번호가 변경되지 않은 경우에만 매크로를 호출합니다.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
레지스터에 현재 포함 된 키 입력 전후에 두 개의 문자열을 연결하기 만하면됩니다 .
let @q =
레지스터 내용을 재정의 q
":let a=line('.')\r"
a
매크로가 \r
Enter 키를 누르고 명령을 실행하도록 Vim에 지시 하는 작업을 수행하기 전에 변수에 현재 줄 번호를 저장합니다. :help expr-quote
유사한 특수 문자 목록을 참조하십시오 . . @q .
q
레지스터 의 현재 내용을 이전 문자열과 다음 문자열로 연결합니다 .":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
qq
레지스터 내에서 매크로 기록을 시작합니다 q
<C-a>
커서 아래 숫자를 증가시킵니다w
커서를 다음 숫자로 이동q
녹음을 종료합니다:RecursiveMacro q 0
레지스터 안에 저장된 매크로를 q
재귀 적이지만 줄 끝까지 만 (두 번째 인수 때문에 0
)3G
커서를 임의의 줄로 이동합니다 (예 : 3)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
1 2 3 4 5 6 7 8 9 10
얻습니다 . 왜 그런지 모르겠습니다. 어쨌든 그것은 내 간단한 접근 방식보다 더 정교 해 보이며 매크로가 커서를 움직여야하는 위치 와이 방법으로는 결코 본 적이없는 위치 목록을 설명하는 정규식이 필요합니다. 나는 그것을 많이 좋아! 2 3 4 5 6 7 8 9 10 12
2 3 4 5 6 7 8 9 10 11
\d\+
. 여러 자리 숫자를 설명하는 데 사용해야 했습니다.
:lv ...
명령 후에는 명령을 :lla
사용하여 마지막 일치 항목으로 :lp
건너 뛰고 명령을 사용하여 일치 항목을 역순으로 진행할 수 있습니다.
재귀 매크로는 실패한 명령이 발생하자마자 중지됩니다. 따라서 줄 끝에서 멈추려면 줄 끝에서 실패하는 명령이 필요합니다.
기본적으로 * l
명령은 이러한 명령이므로 재귀 매크로를 중지하는 데 사용할 수 있습니다. 커서가 줄의 끝에 있지 않으면 명령을 사용하여 나중에 커서를 다시 이동하면됩니다 h
.
따라서 saginaw와 동일한 예제 매크로를 사용하십시오 .
qqqqq<c-a>lhw@qq
세분화 :
qqq
: q 레지스터를 지우십시오.qq
: q
레지스터 에서 매크로 기록을 시작합니다.<c-a>
: 커서 아래의 숫자를 증가시킵니다.lh
: 줄 끝에 있으면 매크로를 중단합니다. 그렇지 않으면 아무것도하지 마십시오.w
: 줄의 다음 단어로 넘어갑니다.@q
: 되풀이q
: 녹화를 중지합니다.그런 다음 0@q
saginaw에서 설명한 것과 동일한 명령으로 매크로를 실행할 수 있습니다 .
*이 'whichwrap'
옵션을 사용하면 줄의 시작 또는 끝 부분에있을 때 다음 줄로 감쌀 이동 키를 정의 할 수 있습니다 (참조 :help 'whichwrap'
). l
이 옵션 을 설정 하면 위에서 설명한 해결 방법이 중단됩니다.
그러나, 당신은 단지 하나의 문자를 발전의 세 가지 기본 정상 모드 명령 중 하나를 사용 (가능성이 <Space>
, l
그리고 <Right>
당신이 그렇다면) l
당신에 포함 된 'whichwrap'
설정, 당신은 당신이 것을 하나 제거 할 수 없는 으로부터 사용을 'whichwrap'
옵션, 예 <Space>
:
:set whichwrap-=s
그런 다음 l
매크로의 4 단계 에서 명령을 명령으로 바꿀 수 있습니다 <Space>
.
virtualedit=onemore
은 l
행 끝을 감지하는 데 사용 하는 데 방해가 되지만 심각하지는 않습니다 whichwrap=l
.
've'
:lv /\%3l\d/g %<CR>qqqqq<C-a>:lne<CR>@qq@q
행 3의 모든 숫자가 증가 하는 경우) 위치 목록을 사용하여 매크로에서 검색 일치를 진행하는 데 사용할 수 있습니다 .