zsh-users
 help / color / mirror / code / Atom feed
From: Peter Stephenson <pws@csr.com>
To: Zsh users list <zsh-users@sunsite.dk>
Subject: Re: [tip] mouse support
Date: Thu, 11 Nov 2004 14:40:32 +0000	[thread overview]
Message-ID: <4483.1100184032@csr.com> (raw)
In-Reply-To: <20041111122011.GB4451@sc>

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.)

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.

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.

Note no use is made of the X selection mechanism.

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.
- 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.

The version of code below is designed to be used as a (normal,
i.e. non-zle) function, called eg. setup-zle-mouse.  (Naming might need
rationalising, too.)


### code begins
[[ $TERM = *xterm* ]] || return

zmodload -i zsh/parameter

zle-xterm-mouse() {
  emulate -L zsh
  setopt extendedglob # for (#b)
  local bt mx my cx cy i match mbegin mend text
  integer rel

  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
  fi

  print -n '\e[6n' # query cursor position
  while read -k i && [[ $i != R ]]; do cx+=$i; done
  # can't use read -d R in zle

  [[ $cx = (#b)??(*)\;(*) ]] || return
  cy=$match[1]
  cx=$match[2]

  # Relative position between cursor and mouse.
  (( rel = #mx - 32 - cx + (#my - 32 - cy) * COLUMNS ))

  case $ZLE_MOUSE_BUTTON in
    (' ')
    # Button 1.  Move cursor.
    (( CURSOR += rel ))
    ;;

    ('!')
    # Button 2.  Insert selection at cursor postion.
    LBUFFER+=$CUTBUFFER
    ;;

    ('"')
    # Button 3.  Copy from cursor to mouse to cutbuffer.
    if (( rel > 0 )); then
      text=${RBUFFER[1,rel]}
    elif (( CURSOR + rel > 0 )); then
      text=${LBUFFER[rel,-1]}
    else
      text=$LBUFFER
    fi
    killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
    CUTBUFFER=$text
    ;;
  esac
  return 0
}

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

ZLE_USE_MOUSE=1
### code ends


-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


  reply	other threads:[~2004-11-11 14:40 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 [this message]
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 ` [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=4483.1100184032@csr.com \
    --to=pws@csr.com \
    --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).