One way to do it is to
- define new widgets that activate marking on shifted motion keys,
- redefine all action widgets to operate on the region (if there is one), and
- redefine all the default motion widgets to deactivate marking.
Here's a proof of concept (for xterm), working for:
Shift-Left and Shift-Right: start selecting to the left/right, respectively,
Left, Right: cancel selecting and move left/right, respectively,
Delete: delete selection if there is one, otherwise character under the cursor.
The usual disclaimers apply (there may be other and better ways, your cat may eat your toaster, etc.).
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