safe-paste.plugin.zsh 3.9 KB

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