zsh에서 `Ctrl + W` 및 `Ctrl + Alt + H`가 bash에서와 동일하게 작동하도록 만들기

zsh에서 `Ctrl + W` 및 `Ctrl + Alt + H`가 bash에서와 동일하게 작동하도록 만들기

Bash에서의 동작은 다음과 같습니다:

  • Ctrl+ W커서 뒤에 있는 단어를 다음 공백까지 삭제합니다.
  • Ctrl++ , , 등과 같은 다음 구분 문자까지 커서 뒤의 단어를 삭제 Alt합니다 .H.,-/

+ 및 ++ zsh모두 에서 의 후자처럼 동작합니다 .CtrlWCtrlAltHbash

에서와 동일한 동작을 원합니다 bash.

답변1

이는 에 있는 내용에 관계없이 원하는 작업을 수행 $WORDCHARS하고 삭제된 단어를 다음에서 사용할 수 있게 만듭니다 yank.

# Create a new widget.
zle -N backward-kill-space-word
backward-kill-space-word() {
  # Inform the line editor that this widget will kill text.
  zle -f kill

  # Set $WORDCHARS for this command only. 
  WORDCHARS='*?_-.[]~=/&;!#$%^(){}<>' zle .backward-kill-word
}

# See comments above.
zle -N backward-kill-bash-word
backward-kill-bash-word() {
  zle -f kill
  WORDCHARS='' zle .backward-kill-word
}

# Bind the widgets to keys.
bindkey   '^W' backward-kill-space-word
bindkey '^[^H' backward-kill-bash-word

대안으로, 나는플러그인이 호출되었습니다.zsh-edit, 이러한 키 바인딩의 보다 정교한 버전이 제공됩니다.

답변2

변수를 사용하여 단어의 일부로 간주되는 특수 문자를 설정할 수 있습니다 WORDCHARS. 이는 다음에 의해 단어가 삭제되는 방식에 영향을 미칩니다 Ctrl + W.

WORDCHARS='~!#$%^&*(){}[]<>?.+;-_/\|=@`'

그러나 에도 영향을 미칩니다 Ctrl + Alt + H. 우리는 이 동작이 에만 적용되기를 원합니다 Ctrl + W. 하지만 우리가 할 수 있는 비결이 있습니다. 설명하겠습니다.

키 조합을 다른 기능에 다시 바인딩할 수 있습니다( 참조 man zshzle). 그리고 실제로 동일한 동작을 하는 2개의 함수가 있습니다.

  • 뒤로 삭제 단어
  • 뒤로 죽이는 단어

를 사용하여 이러한 기능을 재정의할 수도 있습니다 zle -N <func>. 어떻게 작동하는지 완전히 확신할 수는 없지만 코드를 읽으면 아이디어를 얻을 수 있습니다. 어쨌든 트릭을 수행합니다.

기본적으로 Ctrl + W및 는 모두 Ctrl + Alt + H에 매핑됩니다 backward-kill-word. 따라서 backward-delete-word이를 재정의한 다음 다음과 같이 바인딩 할 수 있습니다 Ctrl + W.

# Make `Ctrl + W` behave like it does in Bash, deleting words separated by
# spaces. We do this by redefining the `backward-delete-word` function and bind
# that to `Ctrl + W`.
SPACE_WORDCHARS='~!#$%^&*(){}[]<>?.+;-_/\|=@`'
backward-delete-word() WORDCHARS=$SPACE_WORDCHARS zle .$WIDGET
zle -N backward-delete-word
bindkey "^W" backward-delete-word

예, 이제 ! Ctrl + W보다 더 큰 단어를 삭제합니다 Ctrl + Alt + H.

편집하다:

매우 슬프게도 저는 이제 이 접근 방식에 일부 기능이 부족하다는 사실을 발견했습니다. 단어를 삭제할 때 붙여넣기 버퍼(Ctrl + Y)에 붙여넣지 않습니다. 아직 그에 대한 해결책을 찾지 못했습니다..

답변3

나는 궁극적으로 다음 바인딩을 통해 원하는 동작을 찾았습니다.

# Configures bindings for jumping/deleting full and sub-words, similar to
# the keybindings in bash.

# Jumping:
# Alt + B                Backward sub-word
# Ctrl + Alt + B         Backward full-word
# Alt + F                Forward sub-word
# Ctrl + Alt + F         Forward full-word

# Deleting:
# Ctrl + W               Backward delete full-word
# Ctrl + Alt + H         Backward delete sub-word
# Alt + D                Forward delete sub-word
# Ctrl + Alt + D         Forward delete full-word

# Which characters, besides letters and numbers, that are jumped over by a
# full-word jump:
FULLWORDCHARS="*?_-.,[]~=/&:;!#$%^(){}<>'\""

backward-full-word() { WORDCHARS=$FULLWORDCHARS zle .backward-word ; }
backward-sub-word() { WORDCHARS="" zle .backward-word ; }
forward-full-word() { WORDCHARS=$FULLWORDCHARS zle .forward-word ; }
backward-kill-full-word() { WORDCHARS=$FULLWORDCHARS zle .backward-kill-word ; }
backward-kill-sub-word() { WORDCHARS="" zle .backward-kill-word ; }
forward-kill-full-word() { WORDCHARS=$FULLWORDCHARS zle .kill-word ; }
forward-kill-sub-word() { WORDCHARS="" zle .kill-word ; }

zle -N backward-full-word
zle -N backward-sub-word
zle -N forward-full-word
zle -N backward-kill-full-word
zle -N backward-kill-sub-word
zle -N forward-kill-full-word
zle -N forward-kill-sub-word

# For `forward-sub-word` we use the built-in `emacs-forward-word` widget,
# because that simulates bash behavior.
zle -A emacs-forward-word forward-sub-word

bindkey "^[b" backward-sub-word
bindkey "^[^b" backward-full-word
bindkey "^[f" forward-sub-word
bindkey "^[^f" forward-full-word
bindkey "^[^h" backward-kill-sub-word
bindkey "^w" backward-kill-full-word
bindkey "^[d" forward-kill-sub-word
bindkey "^[^d" forward-kill-full-word

관련 정보