# 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