我用过的答案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+绑定Backspace到backward-kill-line
命令(即删除光标和行开头之间的所有内容)。
但是,当我输入Ctrl+ C Ctrl+ Shift+时Backspace,我的提示仅显示— 即与+^H
相同的组合键。CtrlBackspace
答案1
Ctrl您的终端为+ Shift+发送Backspace与Ctrl+相同的转义序列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,而不是面向性能的语言)编写的包装器。