Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [tip] mouse support



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@xxxxxxx>                  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
**********************************************************************



Messages sorted by: Reverse Date, Date, Thread, Author