사용자 정의 위젯에서 vi 운영자 일시 중지 모드 후에 zsh 커서를 이동하는 방법은 무엇입니까?

사용자 정의 위젯에서 vi 운영자 일시 중지 모드 후에 zsh 커서를 이동하는 방법은 무엇입니까?

나는zsh 플러그인이것은 vi 에뮬레이션 모드에서 zsh의 vim-easymotion 포트입니다. zsh 줄 편집기는 여러 줄을 지원하므로 줄 이동( j및 )에 대한 k지원을 추가했습니다 . 플러그인은 vi 운영자 일시 중지 모드(예: 삭제 모드)에서도 작동해야 하므로 zsh MARKCURSOR변수를 사용하여 사용자 선택을 전체 행으로 확장했습니다. 따라서 행 동작은 항상 행의 일부가 아닌 전체 행을 삭제하거나 변경합니다. ) 어느). 이는 vim 사용자가 기대하는 동작입니다. 그런데 변경/삭제 동작 후 커서 위치가 틀립니다. 커서는 다음 줄의 첫 번째 단어에 있어야 합니다.뒤쪽에행 블록이 삭제되었습니다. 대신 커서는 마지막 줄의 끝에 있습니다.앞으로행 블록. 커서 변경 사항은 선택한 운영자 영역의 일부가 되므로 운영자 일시 중지 모드 후에 커서를 변경할 가능성이 없습니다.

내 질문은: zsh 사용자 정의 위젯에서 커서 위치를 변경하는 방법을 아는 사람이 있습니까?뒤쪽에vi 연산자가 실행되었나요?

고쳐 쓰다:

문제를 이해하기 쉽게 만들기 위해 문제에 대한 최소한의 예를 만들려고 합니다.

이 작은 zsh 스크립트의 소스는 다음과 같습니다.

function test-widget () {
    MARK=3
    CURSOR=6
}

zle -N test-widget

bindkey -M vicmd ' ' test-widget

zsh의 vicmd/normal 모드에 있는 경우( bindkey -vvi 에뮬레이션을 활성화하고 <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

$NUMERIC1이 아닐 때는 어떻게 해야 할지 고민해야 할 수도 있습니다 .

관련 정보