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

Re: bracketed paste mode in xterm and urxvt



Hi everyone,

I've kept this mail in my inbox for almost exactly four years (!), as
a cool thing to look at when I'd have time. Obvious, I haven't had
that much time since then, and I've only tested it today… What a
mistake! This is with no doubt one of the most useful additions I've
done to my config in years.

Thanks Mikael!

PS: below is the full quote of the original mail, which could be
useful for people that weren't on this list four years ago. Or for
people like me who didn't give it the attention it deserves.
PS2: I've added screen-256color to my list of supported terminals,
though technically I'm not sure it supports bracketed paste (and I'm
running tmux anyway).

---------- Forwarded message ----------
From: Mikael Magnusson <mikachu@xxxxxxxxx>
Date: 2011-05-22 21:16 GMT+02:00
Subject: bracketed paste mode in xterm and urxvt
To: Zsh Users <zsh-users@xxxxxxx>

# create a new keymap to use while pasting
bindkey -N paste
# make everything in this keymap call our custom widget
bindkey -R -M paste "^@"-"\M-^?" paste-insert
# these are the codes sent around the pasted text in bracketed
# paste mode.
# do the first one with both -M viins and -M vicmd in vi mode
bindkey '^[[200~' _start_paste
bindkey -M paste '^[[201~' _end_paste
# insert newlines rather than carriage returns when pasting newlines
bindkey -M paste -s '^M' '^J'

zle -N _start_paste
zle -N _end_paste
zle -N paste-insert _paste_insert

# switch the active keymap to paste mode
function _start_paste() {
  bindkey -A paste main
}

# go back to our normal keymap, and insert all the pasted text in the
# command line. this has the nice effect of making the whole paste be
# a single undo/redo event.
function _end_paste() {
#use bindkey -v here with vi mode probably. maybe you want to track
#if you were in ins or cmd mode and restore the right one.
  bindkey -e
  LBUFFER+=$_paste_content
  unset _paste_content
}

function _paste_insert() {
  _paste_content+=$KEYS
}

function _zle_line_init() {
  # Tell terminal to send escape codes around pastes.
  [[ $TERM == rxvt-unicode || $TERM == xterm ]] && printf '\e[?2004h'
}

function _zle_line_finish() {
  # Tell it to stop when we leave zle, so pasting in other programs
  # doesn't get the ^[[200~ codes around the pasted text.
  [[ $TERM == rxvt-unicode || $TERM == xterm ]] && printf '\e[?2004l'
}

Alternatively, you can also do stuff to the text before inserting it,
I have this additional stuff which lets me toggle a mode where all the
pasted text is automatically quoted and a space is appended, which is
useful when pasting (some) urls with ? and & and what have you.

function _end_paste() {
  bindkey -e
  if [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; then
    LBUFFER+=${(q)_paste_content}' '
  else
    LBUFFER+=$_paste_content
  fi
  unset _paste_content
}

function _spaceafterpastequote() {
  if [[ $_SPACE_AFTER_PASTE_QUOTE = 1 ]]; then
    _SPACE_AFTER_PASTE_QUOTE=0
    zle -M "Not inserting a space after pastes, not quoting"
  else
    _SPACE_AFTER_PASTE_QUOTE=1
    zle -M "Inserting a space after pastes and quoting"
  fi
}
zle -N _spaceafterpastequote
# this is a custom wrapper that uses zkbd stuff, just use regular bindkey.
zbindkey Control-Insert _spaceafterpastequote



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