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). 실제로 동일한 동작을 갖는 두 가지 함수가 있습니다.

  • 뒤로 단어 삭제
  • 단어를 거꾸로 죽여라

또한 이러한 함수를 재정의할 수도 있습니다 zle -N <func>. 어떻게 작동하는지 완전히 확신할 수는 없지만 코드를 읽어보면 어쨌든 작동한다는 것을 이해할 수 있을 것입니다.

기본적으로 Ctrl + W및 둘 다 .so Ctrl + Alt + H에 매핑되므로 재정의한 다음 다음에 바인딩 할 수 있습니다 .backward-kill-wordbackward-delete-wordCtrl + 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

관련 정보