如何使用 shift 选择部分命令行(像在许多文本编辑器中一样)?
答案1
一种方法是
- 定义新的小部件来激活移动运动键上的标记,
- 重新定义所有操作部件以在该区域进行操作(如果有的话),并且
- 重新定义所有默认运动小部件以停用标记。
这是(针对的)概念证明xterm
,适用于:
Shift-Left
和Shift-Right
:分别开始向左/向右选择,Left
,Right
:取消选择并分别向左/向右移动,Delete
:如果有选择则删除,否则删除光标下的字符。
适用通常的免责声明(可能有其他更好的方法,您的猫可能会吃您的烤面包机等)。
bindkey -e
function zle-line-init {
marking=0
}
zle -N zle-line-init
function select-char-right {
if (( $marking != 1 ))
then
marking=1
zle set-mark-command
fi
zle .forward-char
}
zle -N select-char-right
function select-char-left {
if (( $marking != 1 ))
then
marking=1
zle set-mark-command
fi
zle .backward-char
}
zle -N select-char-left
function forward-char {
if (( $marking == 1 ))
then
marking=0
NUMERIC=-1 zle set-mark-command
fi
zle .forward-char
}
zle -N forward-char
function backward-char {
if (( $marking == 1 ))
then
marking=0
NUMERIC=-1 zle set-mark-command
fi
zle .backward-char
}
zle -N backward-char
function delete-char {
if (( $marking == 1 ))
then
zle kill-region
marking=0
else
zle .delete-char
fi
}
zle -N delete-char
bindkey '^[[1;2D' select-char-left # assuming xterm
bindkey '^[[1;2C' select-char-right # assuming xterm
答案2
对于 Windows 和西弗吉尼亚海岸用户。
这是其他作者对他们的回答的组合,经过修改以适用于 WSL窗口终端. 行为与标准一致电源外壳:ctrl+shift+箭头选择,ctrl+x、c、v、a等。即使这是重复的Zsh zle 换档选择
# zsh-shift-select https://stackoverflow.com/a/30899296
r-delregion() {
if ((REGION_ACTIVE)) then
zle kill-region
else
local widget_name=$1
shift
zle $widget_name -- $@
fi
}
r-deselect() {
((REGION_ACTIVE = 0))
local widget_name=$1
shift
zle $widget_name -- $@
}
r-select() {
((REGION_ACTIVE)) || zle set-mark-command
local widget_name=$1
shift
zle $widget_name -- $@
}
for key kcap seq mode widget (
sleft kLFT $'\e[1;2D' select backward-char
sright kRIT $'\e[1;2C' select forward-char
sup kri $'\e[1;2A' select up-line-or-history
sdown kind $'\e[1;2B' select down-line-or-history
send kEND $'\E[1;2F' select end-of-line
send2 x $'\E[4;2~' select end-of-line
shome kHOM $'\E[1;2H' select beginning-of-line
shome2 x $'\E[1;2~' select beginning-of-line
left kcub1 $'\EOD' deselect backward-char
right kcuf1 $'\EOC' deselect forward-char
end kend $'\EOF' deselect end-of-line
end2 x $'\E4~' deselect end-of-line
home khome $'\EOH' deselect beginning-of-line
home2 x $'\E1~' deselect beginning-of-line
csleft x $'\E[1;6D' select backward-word
csright x $'\E[1;6C' select forward-word
csend x $'\E[1;6F' select end-of-line
cshome x $'\E[1;6H' select beginning-of-line
cleft x $'\E[1;5D' deselect backward-word
cright x $'\E[1;5C' deselect forward-word
del kdch1 $'\E[3~' delregion delete-char
bs x $'^?' delregion backward-delete-char
) {
eval "key-$key() {
r-$mode $widget \$@
}"
zle -N key-$key
bindkey ${terminfo[$kcap]-$seq} key-$key
}
# Fix zsh-autosuggestions https://stackoverflow.com/a/30899296
export ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
key-right
)
# ctrl+x,c,v https://unix.stackexchange.com/a/634916/424080
function zle-clipboard-cut {
if ((REGION_ACTIVE)); then
zle copy-region-as-kill
print -rn -- $CUTBUFFER | clip.exe
zle kill-region
fi
}
zle -N zle-clipboard-cut
function zle-clipboard-copy {
if ((REGION_ACTIVE)); then
zle copy-region-as-kill
print -rn -- $CUTBUFFER | clip.exe
else
zle send-break
fi
}
zle -N zle-clipboard-copy
function zle-clipboard-paste {
if ((REGION_ACTIVE)); then
zle kill-region
fi
LBUFFER+="$(cat clip.exe)"
}
zle -N zle-clipboard-paste
function zle-pre-cmd {
stty intr "^@"
}
precmd_functions=("zle-pre-cmd" ${precmd_functions[@]})
function zle-pre-exec {
stty intr "^C"
}
preexec_functions=("zle-pre-exec" ${preexec_functions[@]})
for key kcap seq widget arg (
cx _ $'^X' zle-clipboard-cut _
cc _ $'^C' zle-clipboard-copy _
cv _ $'^V' zle-clipboard-paste _
) {
if [ "${arg}" = "_" ]; then
eval "key-$key() {
zle $widget
}"
else
eval "key-$key() {
zle-$widget $arg \$@
}"
fi
zle -N key-$key
bindkey ${terminfo[$kcap]-$seq} key-$key
}
# Select entire prompt https://stackoverflow.com/a/68987551/13658418
function widget::select-all() {
local buflen=$(echo -n "$BUFFER" | wc -m | bc)
CURSOR=$buflen
zle set-mark-command
while [[ $CURSOR > 0 ]]; do
zle beginning-of-line
done
}
zle -N widget::select-all
bindkey '^a' widget::select-all
在 WSL2“Linux 5.15.79.1-microsoft-standard-WSL2”上使用 Windows 终端“1.15.3466.0”进行测试。