zsh의 vi 모드를 bash의 vi 모드처럼 동작하게하려면 어떻게해야합니까?


24

나는 zsh의 일반적인 속도를 정말로 좋아하지만, 두 가지가 나에게 짜증나게한다.

  1. 히스토리 검색에 도달하기 위해 탈출을 치고 슬래시를 치는 사이에 잠시 기다려야합니다 (슬래시를 너무 빨리 칠 경우 zsh: do you wish to see all 514 possibilities (172 lines))
  2. a또는 로 인해 삽입 모드로 들어간 후 삽입 모드로 들어간 A지점을지나 백 스페이스로 이동할 수 없습니다.

나는 2가 클래식 vi와 같다는 것을 알고 있지만 vim 스타일이 더 좋습니다.


누군가가 이중 이스케이프 문제로 인해 i두 번 눌러 삽입 모드로 돌아 가야하는 경우이 수정 프로그램을 사용 하는 것이 좋습니다 .
cchamberlain 님

여기에 좋은 요약이 있습니다 : dougblack.io/words/zsh-vi-mode.html
jackcogdill

답변:


22

(1). : 어떤 이유로, bindkey 동작합니다 이상한 그것은 "/"에 관해서 <esc>신속하게 다음 /과 같이 해석됩니다 <esc-/>. (다른 요일에이 동작을 관찰했습니다. 원인이 무엇인지 잘 모르겠습니다.) 이것이 버그인지 또는 기능인지, 기능이 해제 가능한지 기능인지는 알 수 없지만 상당히 쉽게 해결할 수 있습니다. .

이 키 콤보는에 바인딩되어 _history-complete-older있어 원하지 않는 결과를 생성 할 수 있습니다 bindkey -L.이 경우를 확인하는 데 사용할 수 있습니다 .

어쨌든 실제 <esc-/> (코드로 함께 눌려 짐) 바인딩을 희생하지 않으려는 경우 vi 모드 기록 검색 명령에 다시 바인딩 할 수 있으므로 입력 <esc>후 입력 /할 때마다 동일한 작업을 수행 할 수 있습니다 속도. =)

이 코드는 코드로 취급되므로 vi 명령 모드에 처음 들어가는 효과가 없으므로 먼저 발생하는지 확인해야합니다. 먼저 함수를 정의해야합니다. 사용하면 어딘가에 fpath넣거나 .zshrc에 넣으십시오.

vi-search-fix() {
zle vi-cmd-mode
zle .vi-history-search-backward
}

나머지는 .zshrc에 넣습니다.

autoload vi-search-fix
zle -N vi-search-fix
bindkey -M viins '\e/' vi-search-fix

잘 가야합니다.

(2). 다음과 같이 백 스페이스 키를 수정할 수 있습니다.

`bindkey "^?" backward-delete-char`

또한 다른 vi 스타일 명령에 대해 비슷한 동작을 원할 경우 :

bindkey "^W" backward-kill-word 
bindkey "^H" backward-delete-char      # Control-h also deletes the previous char
bindkey "^U" backward-kill-line            

그것은 ^[/아니지만 \e/, 둘 다 탈출을 말하는 유효한 방법입니다. 변화는 완벽하게 작동합니다. 이제 더 완벽하게 놀고 있기 때문에 bash와 비교하여 zsh의 vi 모드가 빨라 보입니다 (적어도 기본적으로 완전히 구성되어 있지는 않습니다). 이에 대한 한 가지 예는 검색 기록 후에 삽입 모드로 전환된다는 사실입니다. 다음 검색 항목을 찾으려면 n을 누르려면 명령 모드로 돌아 가야합니다.
Chas. Owens

1
글쎄, 다른 예가 있는지는 모르겠지만 언급 한 것은 zsh가 아니라 내 잘못입니다. =) 무슨 일이 있었는지 vi 삽입 모드에서 vi-cmd 모드 편집기 명령을 바인딩했습니다.이 명령은 쉘이 이미 cmd 모드에있을 것으로 예상하고 그에 따라 동작합니다. 먼저 "enter cmd mode"명령을 호출 한 다음 실행 하는 편집기 명령을 작성해야합니다 .vi-history-search-backward. 작성하고 답변을 편집하겠습니다. 나중에 다시 확인하십시오.
Marshall Eubanks

좋아, 나는 대답을 업데이트했다. 사용해보십시오.
Marshall Eubanks

(2)와 관련하여 내가 bindkey | grep <searchterm>어떤 용어 든 할 때는 모두 앞에 접두사가 붙습니다 vi-. bindkey접두사가 붙지 않은 명령 을 설정해야 vi-합니까?
adam_0

1
고맙습니다. 이러한 핵 (및 아래 wjv의 핵)도 zsh의 vi 모드를 거의 사용할 수없는 수준에서 우수한 수준으로 만듭니다. 투표 할 수 있도록 수퍼 유저 계정을 만들었습니다. :-)
ctrueden

14

나는 질문 (1) 만 다룰 것입니다.

문제가 KEYTIMEOUT입니다. zshzle (1)에서 인용합니다.

ZLE은 터미널에서 명령을 읽을 때 일부 명령에 바인딩 된 시퀀스를 읽을 수 있으며 더 긴 바인딩 된 문자열의 접두사이기도합니다. 이 경우 ZLE는 더 많은 문자가 입력되었는지 확인하기 위해 특정 시간 동안 대기하며, 그렇지 않으면 (또는 더 이상 문자열과 일치하지 않는 경우) 바인딩을 실행합니다. 이 시간 종료는 KEYTIMEOUT 매개 변수에 의해 정의됩니다. 기본값은 0.4 초입니다. 접두사 문자열 자체가 명령에 바인딩되지 않은 경우 시간 초과가 없습니다.

0.4 초는 ESC를 친 후 겪는 지연입니다. 수정 사항은 셸 시작 파일 중 하나에서 KEYTIMEOUT을 0.01 이하로 설정하는 것입니다.

export KEYTIMEOUT=1

불행히도 이것은 두드리는 효과가 있습니다. 다른 일이 잘못되기 시작합니다…

먼저 vi 명령 모드에 문제가 있습니다. ESC를 입력하면 커서가 정지되고 다음에 입력하는 문자가 모두 삼켜집니다. vi 명령 모드에서는 ESC가 기본적으로 어떤 것에도 바인딩되어 있지 않기 때문에 ESC (커서 키!)로 시작하는 다중 문자 위젯이 있습니다. 따라서 ESC를 누르면 ZLE가 다음 문자를 기다렸다가 소비합니다.

해결 방법은 명령 모드에서 ESC를 무언가 에 바인딩하여 $ KEYTIMEOUT 센티 초 후에 무언가 가 ZLE로 전달 되도록하는 입니다. 이제 우리는 이러한 나쁜 영향없이 명령 모드에서 ESC로 시작하는 바인딩을 유지할 수 있습니다. 나는 ESC를 벨 문자에 묶습니다.이 문자는 자기 삽입보다 덜 방해 적입니다 (그리고 내 껍질은 침묵합니다).

bindkey -sM vicmd '^[' '^G'

2017 년 업데이트 :

ESC 바인딩을위한 더 나은 솔루션 인 undefined-key위젯 을 찾았습니다 . 원래이 답변을 쓸 때이 위젯이 zsh에서 사용 가능한지 확실하지 않습니다.

bindkey -M vicmd '^[' undefined-key

다음 문제 : 기본적으로 vi 삽입 모드에서 ^ X로 시작하는 일부 두 개의 키 위젯이 있습니다. $ KEYTIMEOUT을 끝까지 설정하면 사용할 수 없게됩니다. 내가하는 일은 vi 삽입 모드에서 ^ X를 바인드 해제하는 것입니다 (기본적으로 자체 삽입입니다). 이를 통해 두 키 위젯이 계속 작동 할 수 있습니다.

bindkey -rM viins '^X'

자체 삽입에 대한 바인딩을 잃어 버렸지 만 물론 다른 것에 바인딩 할 수 있습니다. (나는 그것을 사용하지 않기 때문에, 나는하지 않습니다.)

마지막 문제 (지금까지 찾았습니다) : $ KEYTIMEOUT을 아래로 설정하여 "손실"할 몇 가지 기본 키 바인딩이 있습니다. 커서 키 가 아닌 vi 삽입 모드에서 ESC로 시작하는 키. 대신 ^ X로 시작하도록 개인적으로 리 바인드했습니다.

bindkey -M viins '^X,' _history-complete-newer \
                 '^X/' _history-complete-older \
                 '^X`' _bash_complete-word

2018 업데이트 :

위의 전체 섹션 ( "2017 업데이트"이후)이 반드시 필요한 것은 아닙니다. 다음을 사용하여 키보드 매핑에서 META 키를 ESC와 동일하게 설정할 수 있습니다.

bindkey -mv

따라서 ^ X를 바인드 해제 하지 말고 대신 META를 리더로 사용하여 ESC에서 시작하는 키 바인딩에 액세스 할 수 있습니다 (현대 키보드에서는 ALT 또는 OPT).

Kiddle et al.의 Bash에서 Z Shell 로 책을 열람 할 수 있다면 , 키 바인딩에서 ESC와 META의 동등성에 대해서는 78-79 페이지의 4 장 사이드 바에서 설명합니다.


고맙습니다. 이러한 핵 (그리고 위의 마샬)도 해킹을 통해 zsh의 vi 모드를 거의 사용할 수없는 수준에서 우수한 수준으로 변경했습니다. 투표 할 수 있도록 수퍼 유저 계정을 만들었습니다. :-)
ctrueden

1
감사! 이 시간이 지난 후에도 핵심 zsh 기능을 사용할 수 있도록 해킹과 해결 방법이 여전히 필요하다는 점이 조금 걱정됩니다.
wjv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.