Parent directory

safe-paste.plugin.zsh

4052 bytes
  1# A good summary of the zsh 5.1 Bracketed Paste Mode changes is at:
  2# https://archive.zhimingwang.org/blog/2015-09-21-zsh-51-and-bracketed-paste.html
  3
  4# zsh 5.1 (September 2015) introduced built-in support for Bracketed Paste Mode
  5# https://github.com/zsh-users/zsh/blob/68405f31a043bdd5bf338eb06688ed3e1f740937/README#L38-L45
  6#
  7# zsh 5.1 breaks url-quote-magic and other widgets replacing self-insert
  8# zsh-users' bracketed-paste-magic resolves these issues:
  9# https://github.com/zsh-users/zsh/blob/f702e17b14d75aa21bff014168fa9048124db286/Functions/Zle/bracketed-paste-magic#L9-L12
 10
 11# Load bracketed-paste-magic if zsh version is >= 5.1
 12autoload -Uz is-at-least
 13if is-at-least 5.1; then
 14  set zle_bracketed_paste  # Explicitly restore this zsh default
 15  autoload -Uz bracketed-paste-magic
 16  zle -N bracketed-paste bracketed-paste-magic
 17  return  ### The rest of this file is NOT executed on zsh version >= 5.1 ###
 18fi
 19
 20######################################################################
 21#    The rest of this file is ONLY executed if zsh version < 5.1
 22######################################################################
 23
 24# Code from Mikael Magnusson: https://www.zsh.org/mla/users/2011/msg00367.html
 25#
 26# Requires xterm, urxvt, iTerm2 or any other terminal that supports
 27# Bracketed Paste Mode as documented:
 28# https://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode
 29#
 30# For tmux, use:   bind ] paste-buffer -p
 31#
 32# Additional technical details: https://cirw.in/blog/bracketed-paste
 33
 34# Create a new keymap to use while pasting
 35bindkey -N bracketed-paste
 36# Make everything in this new keymap enqueue characters for pasting
 37bindkey -RM bracketed-paste '\x00-\xFF' bracketed-paste-enqueue
 38# These are the codes sent around the pasted text in bracketed paste mode
 39bindkey -M main            '^[[200~' _bracketed_paste_begin
 40bindkey -M bracketed-paste '^[[201~' _bracketed_paste_end
 41# Insert newlines rather than carriage returns when pasting newlines
 42bindkey -M bracketed-paste -s '^M' '^J'
 43
 44zle -N _bracketed_paste_begin
 45zle -N _bracketed_paste_end
 46zle -N bracketed-paste-enqueue _bracketed_paste_enqueue
 47
 48# Attempt to not clobber zle_line_{init,finish}
 49# Use https://github.com/willghatch/zsh-hooks if available
 50if typeset -f hooks-add-hook > /dev/null; then
 51  hooks-add-hook zle_line_init_hook   _bracketed_paste_zle_init
 52  hooks-add-hook zle_line_finish_hook _bracketed_paste_zle_finish
 53else
 54  zle -N zle-line-init   _bracketed_paste_zle_init
 55  zle -N zle-line-finish _bracketed_paste_zle_finish
 56fi
 57
 58# Switch the active keymap to paste mode
 59_bracketed_paste_begin() {
 60  # Save the bindkey command to restore the active ("main") keymap
 61  # Tokenise the restorative bindkey command into an array
 62  _bracketed_paste_restore_keymap=( ${(z)"$(bindkey -lL main)"} )
 63  bindkey -A bracketed-paste main
 64}
 65
 66# Go back to our normal keymap, and insert all the pasted text in the
 67# command line. This has the nice effect of making the whole paste be
 68# a single undo/redo event.
 69_bracketed_paste_end() {
 70  # Only execute the restore command if it starts with 'bindkey'
 71  # Allow for option KSH_ARRAYS being set (indexing starts at 0)
 72  if [ ${_bracketed_paste_restore_keymap[@]:0:1} = 'bindkey' ]; then
 73    $_bracketed_paste_restore_keymap
 74  fi
 75  LBUFFER+=$_bracketed_paste_content
 76  unset _bracketed_paste_content _bracketed_paste_restore_keymap
 77}
 78
 79# Append a pasted character to the content which is later inserted as a whole
 80_bracketed_paste_enqueue() {
 81  _bracketed_paste_content+=$KEYS
 82}
 83
 84# Run at zle-line-init
 85_bracketed_paste_zle_init() {
 86  _bracketed_paste_content=''
 87  # Tell terminal to send escape codes around pastes
 88  if [[ $TERM =~ '^(rxvt-unicode|xterm(-256color)?|screen(-256color)?)$' ]]; then
 89    printf '\e[?2004h'
 90  fi
 91}
 92
 93# Run at zle-line-finish
 94_bracketed_paste_zle_finish() {
 95  # Turn off bracketed paste when we leave ZLE, so pasting in other programs
 96  # doesn't get the ^[[200~ codes around the pasted text
 97  if [[ $TERM =~ '^(rxvt-unicode|xterm(-256color)?|screen(-256color)?)$' ]]; then
 98    printf '\e[?2004l'
 99  fi
100}
101