From: Stephane Chazelas <Stephane_Chazelas@yahoo.fr>
To: Zsh users list <zsh-users@sunsite.dk>
Subject: [tip] mouse and mouse-wheel support!
Date: Fri, 12 Nov 2004 12:02:48 +0000 [thread overview]
Message-ID: <20041112120248.GC4461@sc> (raw)
In-Reply-To: <20041111122011.GB4451@sc>
Ok, thanks to the help of Peter, Bart and Andy, here is a new
version.
Improvements:
- it handles the multi-line buffers correctly (except in minor
corner cases I didn't bother to fix)
- the prompt handling has been improved
- now there are two mouse modes:
o the first one, when ZLE_USE_MOUSE is set to 1, that uses
xterm mouse tracking (works with rxvt, gnome-terminal,
xterm but doesn't support mouse wheel)
o a new one that will probably work only with xterm (note
that (XFree86) xterm has 256 color, UTF8 support, a better
mouse support, a better font display... than rxvt or
gnome-terminal so why bother with other terminals).
You need to modify your resource file (~/.Xdefaults-host or
~/.Xdefaults or $XENVIRONMENT or $XAPP_RESDIR or
$XUSERFILESEARCHPATH..., see your man page for X) as
described below.
Note that the mouse wheel behavior is not connected to those
functions, it's just that the translation table tells Xterm to
send ^N and ^P characters on mouse wheel events (with modifier
Mod4).
So, it should work with every application that recognizes those
keys as <Down> and <Up>, not only zsh (readline (bash, gdb,
rc...), emacs, vim...).
### code begin
# Add that to your X resource file to have wheel-mouse support
# and <Mod4-Button> when ZLE_USE_MOUSE is off under xterm
# (remove the #)
#!!!BEGIN
#XTerm.VT100.translations: #override\
# Mod4 <Btn1Down>,<Btn1Up>: string(0x1b) string("[M ") dired-button()\n\
# Mod4 <Btn2Down>,<Btn2Up>: string(0x1b) string("[M!") dired-button()\n\
# Mod4 <Btn3Down>,<Btn3Up>: string(0x1b) string("[M") string(0x22) dired-button()\n\
# Mod4 <Btn5Down>,<Btn5Up>: string(0xe)\n\
# Mod4 <Btn4Down>,<Btn4Up>: string(0x10)
#!!!END
# note that you need to hold whatever key puts you in the "Mod4"
# (for me, it's the MS Windows keys aka "Super", see xmodmap -pm
# for details)
if [[ $TERM = *xterm* || $TERM = *rxvt* ]]; then
zmodload -i zsh/parameter
set-status() { return $1; }
zle-xterm-mouse() {
local last_status=$?
emulate -L zsh
setopt extendedglob # for (#b)
local bt mx my cy i buf
read -k bt # mouse button, x, y reported after \e[M
bt=$((#bt & 7))
read -k mx
read -k my
if [[ $mx = $'\030' ]]; then
# assume btns were mapped to \E[M<btn>dired-button()(^X\EG<x><y>)
read -k mx
read -k mx
read -k my
(( my = #my - 31 ))
(( mx = #mx - 31 ))
ZLE_MOUSE_BUTTON=$bt
else
(( my = #my - 32 ))
(( mx = #mx - 32 ))
if [[ $bt != 3 ]]; then
# Process on release, but record the button on press.
ZLE_MOUSE_BUTTON=$bt
return 0
fi
fi
print -n '\e[6n' # query cursor position
while read -k i && [[ $i != R ]]; do buf+=$i; done
local match mbegin mend
[[ $buf = (#b)??(*)\;* ]] || return
cy=$match[1]
# we don't need cx
local cur_prompt
if [[ -n $PREBUFFER ]]; then
cur_prompt=$PS2
# decide wether we're at the PS2 or PS1 prompt
else
cur_prompt=$PS1
fi
[[ -o promptsubst ]] && cur_prompt=${${(e)cur_prompt}//(#b)([\\\$\`])/\\$match}
# restore the exit status in case $PS<n> relies on it
set-status $last_status
cur_prompt=${(S%%)cur_prompt//(#b)(%([BSUbsu]|{*%})|(%[^BSUbsu{}]))/$match[3]}
local -a pos # array holding the possible positions of
# the mouse pointer
local -i x=0 y=1 cursor=$((${#cur_prompt}+$CURSOR+1))
local Y
buf=$cur_prompt$BUFFER
for ((i=1; i<=$#buf; i++)); do
(( i == cursor )) && Y=$y
case $buf[i] in
($'\n') # newline
: ${pos[y]=$i}
(( y++, x=0 ));;
($'\t') # tab advance til next tab stop
(( x = x/8*8+8 ));;
([$'\0'-$'\037'$'\0200'-$'\0237'])
# characters like ^M
(( x += 2 ));;
# may cause trouble if spanned on two lines but well...
(*)
(( x++ ));;
esac
(( x >= mx )) && : ${pos[y]=$i}
(( x >= COLUMNS )) && (( x=0, y++ ))
done
: ${pos[y]=$i} ${Y:=$y}
local mouse_CURSOR
if ((my + Y - cy > y)); then
mouse_CURSOR=$#BUFFER
elif ((my + Y - cy < 1)); then
mouse_CURSOR=0
else
mouse_CURSOR=$(($pos[my + Y - cy] - ${#cur_prompt} - 1))
fi
case $ZLE_MOUSE_BUTTON in
(0)
# Button 1. Move cursor.
CURSOR=$mouse_CURSOR
;;
(1)
# Button 2. Insert selection at mouse cursor postion.
BUFFER=$BUFFER[1,mouse_CURSOR]$CUTBUFFER$BUFFER[mouse_CURSOR+1,-1]
(( CURSOR = $mouse_CURSOR + $#CUTBUFFER ))
;;
(2)
# Button 3. Copy from cursor to mouse to cutbuffer.
killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
if (( mouse_CURSOR < CURSOR )); then
CUTBUFFER=$BUFFER[mouse_CURSOR+1,CURSOR+1]
else
CUTBUFFER=$BUFFER[CURSOR+1,mouse_CURSOR+1]
fi
;;
esac
}
zle-toggle-mouse() {
# If no prefix, toggle state.
# If positive prefix, turn on.
# If zero or negative prefix, turn off.
# Allow this to be used as a normal function, too.
if [[ -n $1 ]]; then
local PREFIX=$1
fi
if (( $+PREFIX )); then
if (( PREFIX > 0 )); then
ZLE_USE_MOUSE=1
else
ZLE_USE_MOUSE=
fi
else
if [[ -n $ZLE_USE_MOUSE ]]; then
ZLE_USE_MOUSE=
else
ZLE_USE_MOUSE=1
fi
fi
if [[ -n $WIDGET ]]; then
# Zle is currently active.
# Make sure it's turned on or off straight away if required.
if [[ -n $ZLE_USE_MOUSE ]]; then
print -n '\e[?1000h'
else
print -n '\e[?1000l'
fi
fi
}
if [[ $functions[precmd] != *ZLE_USE_MOUSE* ]]; then
functions[precmd]+='
[[ -n $ZLE_USE_MOUSE ]] && print -n '\''\e[?1000h'\'
fi
if [[ $functions[preexec] != *ZLE_USE_MOUSE* ]]; then
functions[preexec]+='
[[ -n $ZLE_USE_MOUSE ]] && print -n '\''\e[?1000l'\'
fi
zle -N zle-xterm-mouse
bindkey '\e[M' zle-xterm-mouse
zle -N zle-toggle-mouse
fi
### code end
--
Stéphane
next prev parent reply other threads:[~2004-11-12 12:07 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-11 12:20 [tip] mouse support Stephane Chazelas
2004-11-11 14:40 ` Peter Stephenson
2004-11-11 16:22 ` Stephane Chazelas
2004-11-11 17:47 ` Bart Schaefer
2004-11-11 18:05 ` Stephane Chazelas
2004-11-11 18:22 ` Stephane Chazelas
2004-11-12 1:02 ` Bart Schaefer
2004-11-12 9:22 ` Stephane Chazelas
2004-11-11 16:07 ` Andy Spiegl
2004-11-11 17:26 ` Stephane Chazelas
2004-11-12 12:02 ` Stephane Chazelas [this message]
2004-11-15 12:21 ` [tip] mouse and mouse-wheel support! Stephane Chazelas
2004-11-15 13:14 ` Stephane Chazelas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20041112120248.GC4461@sc \
--to=stephane_chazelas@yahoo.fr \
--cc=zsh-users@sunsite.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).