# Code from Mikael Magnusson: http://www.zsh.org/mla/users/2011/msg00367.html
#
# Requires xterm, urxvt, iTerm2 or any other terminal that supports bracketed
# paste mode as documented: http://www.xfree86.org/current/ctlseqs.html
#
# Extended by Jan Pobrislo <ccx_at_wpr_dot_cz>:
# The bracketed paste mode is extended to support VIM-like
# CTRL-V <character-code> input method that can be used to escape the pasted
# content.
#
# Script for rxvt-unicode to escape control characters like that is here:
# http://wpr.cz/ccx/paste/2016-08-03/0/
# 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'
bindkey -M paste '^V0' paste-ctrl-v-digit
bindkey -M paste '^V1' paste-ctrl-v-digit
bindkey -M paste '^V2' paste-ctrl-v-digit
bindkey -M paste '^Vo' paste-ctrl-v-octal
bindkey -M paste '^VO' paste-ctrl-v-octal
bindkey -M paste '^Vx' paste-ctrl-v-hex
bindkey -M paste '^VX' paste-ctrl-v-hex
bindkey -M paste '^Vu' paste-ctrl-v-hex
bindkey -M paste '^VU' paste-ctrl-v-hex
zle -N _start_paste
zle -N _end_paste
zle -N paste-insert _paste_insert
zle -N paste-ctrl-v-digit _paste_escape_decimal
zle -N paste-ctrl-v-octal _paste_escape_octal
zle -N paste-ctrl-v-hex _paste_escape_hex
# 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 -v
case $_paste_content in
(http:*) _paste_content=${(qqq)_paste_content};;
(https:*) _paste_content=${(qqq)_paste_content};;
esac
LBUFFER+=$_paste_content
unset _paste_content
}
function _paste_insert() {
_paste_content+=$KEYS
}
function _paste_escape_decimal() {
IFS= read -srk 2
REPLY='10#'$KEYS[2]${REPLY//[^0-9]/}
_paste_content+=${(#)REPLY}
}
function _paste_escape_octal() {
IFS= read -srk 3
REPLY='8#'${REPLY//[^0-7]/}
_paste_content+=${(#)REPLY}
}
function _paste_escape_hex() {
case $KEYS[2] in
(u) IFS= read -srk 4;;
(U) IFS= read -srk 8;;
(*) IFS= read -srk 2;;
esac
REPLY='16#'${REPLY//[^0-9a-fA-F]/}
_paste_content+=${(#)REPLY}
}
function _zle_line_init_paste() {
# Tell terminal to send escape codes around pastes.
case ${TERM#-256color} in (rxvt-unicode|xterm) printf '\e[?2004h';; esac
}
zle_init_add _zle_line_init_paste
function _zle_line_finish_paste() {
# Tell it to stop when we leave zle, so pasting in other programs
# doesn't get the ^[[200~ codes around the pasted text.
case ${TERM#-256color} in (rxvt-unicode|xterm) printf '\e[?2004l';; esac
}
zle_finish_add _zle_line_finish_paste
# vim: ft=zsh et sw=2