# 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 : # The bracketed paste mode is extended to support VIM-like # CTRL-V 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