From: Stephane Chazelas <Stephane_Chazelas@yahoo.fr>
To: Zsh users list <zsh-users@sunsite.dk>
Subject: Re: [tip] mouse support
Date: Thu, 11 Nov 2004 16:22:09 +0000 [thread overview]
Message-ID: <20041111162209.GC4451@sc> (raw)
In-Reply-To: <4483.1100184032@csr.com>
On Thu, Nov 11, 2004 at 02:40:32PM +0000, Peter Stephenson wrote:
> Stephane Chazelas wrote:
> > I just posted that to comp.unix.shell, I thought it might be of
> > some interest for some of you. Basically, it's cursor
> > positionning with the mouse under xterm like terminals (works
> > with xterm, gnome-terminal and rxvt AFAICS, probably also with
> > putty, not if there are tabs or NLs (or multi-byte characters)
> > in the zle buffer).
>
> This is very useful. (Other people should note it's only useful with
> the current zsh editing buffer; there's no way of accessing other
> information on the screen.)
In that new one, I tried to address the tab/newline issue.
It tries to calculate the length of the last line of the prompt,
it may fail if PS1 contains %%s or %{ %{ ... %} %} or if two
consecutive expansions of PS1 may not generate the same thing,
it would be nice to have access at what zsh thinks is the
cursor horizontal position at begining of buffer.
> I've extended it. Other people may have suggestions, too. This
> probably requires zsh 4.2 to use the cutbuffer and killring.
>
> Button 1 is as before.
>
> Button 2 pastes the zsh cutbuffer at the mouse position. This
> is identical to yank. It also emulates normal xterm behaviour
> by pasting at the cursor, not the mouse position. This seemed
> less surprising but is easy to change or make optional.
I changed for "pasting at the mouse cursor".
> Button 3 copies the region from the cursor to the mouse position
> into the zsh cutbuffer. This is like copy-region-as-kill but
> doesn't use the zsh mark. (I could set that too, I suppose.)
> Note I'm not 100% confident the limits (i.e. indices into the editing
> buffer) used are the best ones.
Not sure of mines either ;).
> Other additions
> - It takes care to change the existing precmd and preexec rather
> than overwriting them. This won't work if there is a "return"
> earlier in either. Possibly the new lines should go at the top.
Thanks for that. I didn't know about the $functions hash.
> - There's a function/widget zle-toggle-mouse to switch between normal
> xterm mouse and zle mouse. Positive prefix forces zle mouse,
> negative or zero prefix forces normal xterm mouse.
You can use hold the <Shift> key to have the normal xterm
behavior.
Here's the code. Be careful when you bullet proof it, it may be
full of bugs...
### code begin
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
read -k mx
read -k my
if [[ $bt != "#" ]]; then
# Process on release, but record the button on press.
ZLE_MOUSE_BUTTON=$bt
return 0
fi
(( my = #my - 32 ))
(( mx = #mx - 32 ))
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
if [[ -o promptsubst ]]; then
cur_prompt=${(e)cur_prompt}
else
cur_prompt=$cur_prompt
fi
# remove visual effects:
cur_prompt=${(S)cur_prompt//("%{"*"%}"|%[BbEuUsS])/}
# restore the exit status in case $PS<n> relies on it
set-status $last_status
cur_prompt=${(%)cur_prompt}
cur_prompt=${cur_prompt##*$'\n'}
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
(' ')
# Button 1. Move cursor.
CURSOR=$mouse_CURSOR
;;
('!')
# Button 2. Insert selection at mouse cursor postion.
BUFFER=$BUFFER[1,mouse_CURSOR]$CUTBUFFER$BUFFER[mouse_CURSOR+1,-1]
(( CURSOR = $mouse_CURSOR + $#CUTBUFFER ))
;;
('"')
# 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
}
### code ends
--
Stéphane
next prev parent reply other threads:[~2004-11-11 16:22 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-11 12:20 Stephane Chazelas
2004-11-11 14:40 ` Peter Stephenson
2004-11-11 16:22 ` Stephane Chazelas [this message]
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 ` [tip] mouse and mouse-wheel support! Stephane Chazelas
2004-11-15 12:21 ` 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=20041111162209.GC4451@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).