How to use shift to select part of the commandline (like in many text editors) ?
Zsh Shift Select Mode. Emacs shift-select mode for Zsh – select text in the command line using Shift as in many text editors, browsers and other GUI programs. This plugin does not override any existing widgets and binds only shifted keys (see Key Bindings).
The Zsh Line Editor (ZLE) is simply your command prompt. It's your interface to the shell interpreter, allowing you to write and edit your mind-blowing commands. It also allows you to use keystrokes to execute ZLE commands, more commonly called widgets.
Expanding on Stephane's excellent answer from almost 3 years ago, I added some more bindings to make the behaviour (almost) completely consistent with all of Windows' standard keyboard behaviour:
Backspace
and Del
delete an active selectionCtrl+Shift+Left
/Ctrl+Shift+Right
Shift+Home
and Shift+End
extend the selection to the beginning and end of line respectively. Ctrl+Shift+Home
and Ctrl+Shift+End
do the same.Two things that are not exactly the same:
Note that the default mintty behaviour is to bind Shift+End
and Shift+Home
to access the scroll back buffer. This supercedes the zsh configuration; the keys never get passed through. In order for these to work, you will need to configure a different key (or disable scroll back) in /etc/minttyrc
or ~/.minttyrc
. See "modifier for scrolling" here - the simplest solution is just set ScrollMod=2
to bind it to Alt
instead of Shift
.
So everything:
ScrollMod=2
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
}
This covers keycodes from several different keyboard configurations I have used.
Note: the values in the "key" column don't mean anything, they are just used to build a named reference for zle. They could be anything. What is important is the seq
, mode
and widget
columns.
Note 2: You can bind pretty much any keys you want, you just need the key codes used in your console emulator. Open a regular console (without running zsh) and type Ctrl+V and then the key you want. It should emit the code. ^[
means \E
.
shift-arrow() {
((REGION_ACTIVE)) || zle set-mark-command
zle $1
}
shift-left() shift-arrow backward-char
shift-right() shift-arrow forward-char
shift-up() shift-arrow up-line-or-history
shift-down() shift-arrow down-line-or-history
zle -N shift-left
zle -N shift-right
zle -N shift-up
zle -N shift-down
bindkey $terminfo[kLFT] shift-left
bindkey $terminfo[kRIT] shift-right
bindkey $terminfo[kri] shift-up
bindkey $terminfo[kind] shift-down
That assumes your terminal sends a different escape sequence upon Shift-Arrows from the one sent upon Arrow and that your terminfo database is properly populated with corresponding kLFT and kRIT capabilities, and that you're using emacs style key binding.
Or, to factorize the code a bit:
shift-arrow() {
((REGION_ACTIVE)) || zle set-mark-command
zle $1
}
for key kcap seq widget (
left LFT $'\e[1;2D' backward-char
right RIT $'\e[1;2C' forward-char
up ri $'\e[1;2A' up-line-or-history
down ind $'\e[1;2B' down-line-or-history
) {
functions[shift-$key]="shift-arrow $widget"
zle -N shift-$key
bindkey ${terminfo[k$kcap]-$seq} shift-$key
}
Above, hardcoded sequences for cases where the terminfo database doesn't have the information (using xterm
sequences).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With