나는zsh 플러그인이것은 vi 에뮬레이션 모드에서 zsh의 vim-easymotion 포트입니다. zsh 줄 편집기는 여러 줄을 지원하므로 줄 이동( j
및 )에 대한 k
지원을 추가했습니다 . 플러그인은 vi 운영자 일시 중지 모드(예: 삭제 모드)에서도 작동해야 하므로 zsh MARK
와 CURSOR
변수를 사용하여 사용자 선택을 전체 행으로 확장했습니다. 따라서 행 동작은 항상 행의 일부가 아닌 전체 행을 삭제하거나 변경합니다. ) 어느). 이는 vim 사용자가 기대하는 동작입니다. 그런데 변경/삭제 동작 후 커서 위치가 틀립니다. 커서는 다음 줄의 첫 번째 단어에 있어야 합니다.뒤쪽에행 블록이 삭제되었습니다. 대신 커서는 마지막 줄의 끝에 있습니다.앞으로행 블록. 커서 변경 사항은 선택한 운영자 영역의 일부가 되므로 운영자 일시 중지 모드 후에 커서를 변경할 가능성이 없습니다.
내 질문은: zsh 사용자 정의 위젯에서 커서 위치를 변경하는 방법을 아는 사람이 있습니까?뒤쪽에vi 연산자가 실행되었나요?
고쳐 쓰다:
문제를 이해하기 쉽게 만들기 위해 문제에 대한 최소한의 예를 만들려고 합니다.
이 작은 zsh 스크립트의 소스는 다음과 같습니다.
function test-widget () {
MARK=3
CURSOR=6
}
zle -N test-widget
bindkey -M vicmd ' ' test-widget
zsh의 vicmd/normal 모드에 있는 경우( bindkey -v
vi 에뮬레이션을 활성화하고 <esc>
명령 모드로 들어가기) 이제 키를 눌러 <space>
커서를 현재 편집 버퍼의 6번째 문자로 설정할 수 있습니다. vi 연산자( d
뒤에 ) 를 입력하면 <space>
세 번째부터 여섯 번째 문자까지 모두 삭제됩니다(변수 설정으로 인해 MARK
).
삭제 예: 편집 버퍼가 다음과 같다고 가정합니다(커서 위치는 로 표시됨 []
).
[a]bc def ghi
그런 다음 버튼을 누르면 d<space>
다음을 얻습니다.
abc[f] ghi
그러나 동일한 위젯 호출에서 삭제 작업 후에 커서 위치를 변경하고 싶습니다. 예를 들면 다음과 같습니다.
abcf [g]hi
CURSOR
모든 변경 사항이 삭제된 텍스트의 범위에 영향을 미치기 때문에 이것이 어떻게 가능한지 모르겠습니다 .
삭제 작업 + 커서 위치 지정을 구현하는 방법은 무엇입니까?
답변1
d
, c
, y
, gu
, gU
, ...에 바인딩된 g~
위젯 과 같이 작업을 수행하는 위젯을 다시 정의해야 할 것 같습니다.
그것은 다음과 같습니다:
test-widget () {
MARK=3
CURSOR=6
MOVE_AFTER_MOTION=2
}
zle -N test-widget
bindkey -M vicmd ' ' test-widget
for widget in vi-{delete,change,yank,{down,oper-swap,up}-case}; do
$widget () {
local ret
zle ".$WIDGET"; ret=$?
if (($+MOVE_AFTER_MOTION)); then
(( CURSOR += MOVE_AFTER_MOTION ))
unset MOVE_AFTER_MOTION
fi
return "$ret"
}
zle -N $widget
done
$NUMERIC
1이 아닐 때는 어떻게 해야 할지 고민해야 할 수도 있습니다 .