问题

问题

我用过的答案zsh 杀 Ctrl + 退格键、Ctrl + 删除配置以下键绑定:

  • Ctrl+ Backspace:删除直到当前单词的开头,
  • Ctrl+ Delete:删除直到当前单词末尾,
  • Ctrl+ Shift+ Delete:删除直到行尾。

这是使用以下命令完成的:

$ bindkey -M emacs '^[[3;5~' kill-word
$ bindkey -M emacs '^H' backward-kill-word 
$ bindkey -M emacs '^[[3;6~' kill-line  

为了了解如何对键(即^[[3;5~部分)进行编码,我使用了答案中详细介绍的“技巧”:“输入Ctrl+ C Ctrl+Delete查看您系统上的值”

问题

我想将Ctrl+ Shift+绑定Backspacebackward-kill-line命令(即删除光标和行开头之间的所有内容)。

但是,当我输入Ctrl+ C Ctrl+ Shift+时Backspace,我的提示仅显示— 即与+^H相同的组合键。CtrlBackspace

答案1

Ctrl您的终端为+ Shift+发送BackspaceCtrl+相同的转义序列Backspace,因此 zsh 无法区分两者。唯一的解决方案是配置您的终端以发送不同的转义序列。并非所有终端都允许这样做。

某些终端(例如 xterm、rxvt、iTerm2 和 Emacs term)允许您手动为每个键和弦配置转义序列。请查阅您的终端文档。

例如,对于 xterm,您可以将下面的代码片段放入您的.Xresources.加载它xrdb -merge ~/.Xresources。许多环境会在您登录时加载此内容;如果您的没有,请将此命令添加到您的 X11 启动文件中。

XTerm.VT100.translations: #override \
    Ctrl Shift <Key>BackSpace: string("\033[27;6;8~") \n

然后你可以使用这个转义序列:

bindkey -M emacs '^[[27;6;8~' backward-kill-word 

终端基于静脉血栓栓塞,包括 Gnome-terminal、Guake 和 Terminator,你运气不好。他们没有任何方法来配置键绑定。他们可能愿意为特定密钥添加临时支持尽管。

1我选择这个序列是为了兼容xterm 的modifyOtherKeys模式。我通常建议启用modifyOtherKeys,这主要是向后兼容的,但是您想要的特定键和弦只能在级别 2 上启用,这是一个很难处理的问题(例如 Ctrl+字母不会发送相应的控制字符)。

答案2

对于 X11 终端模拟器,Ctrl+Shift+Backspace发送与 和 相同的内容,Backspace并且不提供任何更改它的方法(如果你绝望的话),作为一种肮脏的黑客行为,你可以劫持终端模拟器和 X 服务器之间的通信,并且例如,当按住和时,将发送到终端仿真器的 X11 事件消息中的Backspace(keycode 22) 替换为(keybode 96) 。F12BackspaceShiftCtrl

顺便说一句,zsh这使得它相对容易,因为它具有内置的 Unix 域和 TCP 套接字 API。运行以下脚本:

that-script guake

并添加到您的~/.zshrc

if [ -n "$WRAPPED_DISPLAY" ]; then
  export DISPLAY="$WRAPPED_DISPLAY"
  unset DISPLAY
fi

(以避免在该终端内启动的其他应用程序通过该包装器)。

并绑定:

bindkey -M emacs '^[[24;6~' backward-kill-word

其中至少是按下VTE\e[24;6~时发送的序列。Ctrl+Shift+F12xterm

#! /bin/zsh -

die() {
  (($# == 0)) || print -ru2 -- "$@"
  exit 1
}

case $DISPLAY in
  (:<->(.<->|))
    mode=unix;;
  ((localhost|127.0.0.1|"[::1]"):<->(.<->|))
    mode=tcp
    zmodload zsh/net/tcp || die;;
  (*)
    die "Unsupported display: $DISPLAY";;
esac

conn=${DISPLAY##*:}
port=${conn%%.*}
screennumber=${conn#$port}
(($# > 0)) || argv=(gnome-terminal --wait)

unset -v listen_fd
typeset -A clients

tcp_connect() ztcp -v localhost $((port + 6000))
unix_connect() zsocket /tmp/.X11-unix/X$port

zmodload zsh/net/socket || die
zmodload zsh/system || die
zmodload zsh/zselect || die

new_port=20
until
  new_socket_path=/tmp/.X11-unix/X$new_port
  zsocket -l $new_socket_path 2> /dev/null
do
  ((new_port++))
done
listen_fd=$REPLY

unset -v pid
trap '
  kill "$pid" 2> /dev/null
  wait "$pid"; ret=$?
  rm -f $new_socket_path
  exit "$ret"' EXIT INT TERM HUP
{
  coproc {
    export WRAPPED_DISPLAY=$DISPLAY DISPLAY=:$new_port$screennumber
    xauth list "$WRAPPED_DISPLAY" |
      awk '{$1 = "add " ENVIRON["DISPLAY"];print}' |
      xauth -q -
    "$@" <&3 3>&1 >&4 4>&- {listen_fd}<&-
  }
} 3<&0 4>&1
pid=$!
exec {child_monitor}<&p
coproc :

LC_ALL=C
set -o extendedglob

tear() {
  exec {1}>&- {2}>&-
  unset "clients[$1]"
}

typeset -A ready
while zselect -A ready -r $listen_fd $child_monitor ${(kv)clients}; do
  [[ $ready[$child_monitor] ]] && exit
  if [[ $ready[$listen_fd] ]]; then
    zsocket -a $listen_fd || die
    fd=$REPLY
    ${mode}_connect || die
    clients[$fd]=$REPLY
  fi
  for client server (${(kv)clients}) {
    for from fdin fdout (
      client $client $server
      server $server $client
    ) if [[ $ready[$fdin] ]]; then
        if sysread -s 65536 -i $fdin buf; then
          if [[ $from = server ]]; then
            if [[ $buf[1,2] = $'\x23\x83' ]]; then
              offsets=(9 17 73) # Generic XInputExtension Event 
            else
              offsets=(1 2 29)  # Normal Event
            fi
            if
              [[ $buf[offsets[1]] = ($'\x2'|$'\x3') ]] && # KeyPress or KeyRelease
                [[ $buf[offsets[2]] = $'\x16' ]] && # keycode 22, Backspace
                printf -v modifiers %d "'$buf[offsets[3]]" &&
                ((modifiers & 5 == 5)) # Shift+Ctrl
            then
              buf[offsets[2]]=$'\x60' # keycode 96, F12
            fi
          fi
          syswrite -o $fdout -- $buf || tear $client $server
        else
          tear $client $server
        fi
      fi
  }
done

请注意,我们没有在那里进行完整的 X11 协议解释,并假设按键事件显示为完整消息。如果您在终端正忙于与 X 服务器通信时按下该组合键,则可能会错过它。它还会对性能产生影响,因为所有 X11 流量都必须经过用zsh(shell,而不是面向性能的语言)编写的包装器。

相关内容