zsh-users
 help / color / mirror / code / Atom feed
From: Stephane Chazelas <Stephane_Chazelas@yahoo.fr>
To: Zsh users list <zsh-users@sunsite.dk>
Subject: Re: [tip] mouse and mouse-wheel support!
Date: Mon, 15 Nov 2004 12:21:34 +0000	[thread overview]
Message-ID: <20041115122134.GA4463@sc> (raw)
In-Reply-To: <20041112120248.GC4461@sc>

On Fri, Nov 12, 2004 at 12:02:48PM +0000, Stephane Chazelas wrote:
> Ok, thanks to the help of Peter, Bart and Andy, here is a new
> version.
[...]

Yet another one, please test it:

- fix problem when a ^M like char is spanned on two lines
- works within "select" and zed and zcalc
- fixed typo bug ($'\0200' should be $'\200')
- now works within vared as long as there is no prompt (-p vared
  option) because I didn't know how to get vared prompt.

(again, either set ZLE_USE_MOUSE to 1 or add 
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)
to your resource file to have <Super-btnClick> do the stuff).

### code begins
if [[ $TERM = *xterm* || $TERM = *rxvt* || $TERM = *screen* ]]; 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

    case $CONTEXT in
      (vared)
        if [[ $0 = zcalc ]]; then
	  cur_prompt=${ZCALCPROMPT-'%1v> '}
	  setopt nopromptsubst nopromptbang promptpercent
	  # (ZCALCPROMPT is expanded with (%))
	fi;;
	# if vared is passed a prompt, we're lost
      (select)
        cur_prompt=$PS3;;
      (cont)
	cur_prompt=$PS2;;
      (start)
	cur_prompt=$PS1;;
    esac

    [[ -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 n x=0 y=1 cursor=$((${#cur_prompt}+$CURSOR+1))
    local Y

    set -x
    buf=$cur_prompt$BUFFER
    for ((i=1; i<=$#buf; i++)); do
      (( i == cursor )) && Y=$y
      n=0
      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'$'\200'-$'\237'])
	  # characters like ^M
	  n=2;;
	(*)
	  n=1;;
      esac
      while
	(( x >= mx )) && : ${pos[y]=$i}
	(( x >= COLUMNS )) && (( x=0, y++ ))
	(( n > 0 ))
      do
	(( x++, n-- ))
      done
    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 ends

-- 
Stéphane


  reply	other threads:[~2004-11-15 12:23 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 ` [tip] mouse and mouse-wheel support! Stephane Chazelas
2004-11-15 12:21   ` Stephane Chazelas [this message]
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=20041115122134.GA4463@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).