safe-paste.plugin.zsh 4.0 KB

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