comparison .shell.d/99.safe-paste.zsh @ 531:ec44059d05b0

zsh: update safe-paste logic
author Augie Fackler <raf@durin42.com>
date Wed, 25 Mar 2026 21:44:37 -0400
parents bef29d49d19f
children
comparison
equal deleted inserted replaced
530:dbb75edda2ff 531:ec44059d05b0
1 # taken from https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/plugins/safe-paste/safe-paste.plugin.zsh 1 # A good summary of the zsh 5.1 Bracketed Paste Mode changes is at:
2 # Code from Mikael Magnusson: http://www.zsh.org/mla/users/2011/msg00367.html 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
3 # 6 #
4 # Requires xterm, urxvt, iTerm2 or any other terminal that supports bracketed 7 # zsh 5.1 breaks url-quote-magic and other widgets replacing self-insert
5 # paste mode as documented: http://www.xfree86.org/current/ctlseqs.html 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
6 10
7 # create a new keymap to use while pasting 11 # Load bracketed-paste-magic if zsh version is >= 5.1
8 bindkey -N paste 12 autoload -Uz is-at-least
9 # make everything in this keymap call our custom widget 13 if is-at-least 5.1; then
10 bindkey -R -M paste "^@"-"\M-^?" paste-insert 14 set zle_bracketed_paste # Explicitly restore this zsh default
11 # these are the codes sent around the pasted text in bracketed 15 autoload -Uz bracketed-paste-magic
12 # paste mode. 16 zle -N bracketed-paste bracketed-paste-magic
13 # do the first one with both -M viins and -M vicmd in vi mode 17 return ### The rest of this file is NOT executed on zsh version >= 5.1 ###
14 bindkey '^[[200~' _start_paste 18 fi
15 bindkey -M paste '^[[201~' _end_paste
16 # insert newlines rather than carriage returns when pasting newlines
17 bindkey -M paste -s '^M' '^J'
18 19
19 zle -N _start_paste 20 ######################################################################
20 zle -N _end_paste 21 # The rest of this file is ONLY executed if zsh version < 5.1
21 zle -N zle-line-init _zle_line_init 22 ######################################################################
22 zle -N zle-line-finish _zle_line_finish
23 zle -N paste-insert _paste_insert
24 23
25 # switch the active keymap to paste mode 24 # Code from Mikael Magnusson: https://www.zsh.org/mla/users/2011/msg00367.html
26 function _start_paste() { 25 #
27 bindkey -A paste main 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
35 bindkey -N bracketed-paste
36 # Make everything in this new keymap enqueue characters for pasting
37 bindkey -RM bracketed-paste '\x00-\xFF' bracketed-paste-enqueue
38 # These are the codes sent around the pasted text in bracketed paste mode
39 bindkey -M main '^[[200~' _bracketed_paste_begin
40 bindkey -M bracketed-paste '^[[201~' _bracketed_paste_end
41 # Insert newlines rather than carriage returns when pasting newlines
42 bindkey -M bracketed-paste -s '^M' '^J'
43
44 zle -N _bracketed_paste_begin
45 zle -N _bracketed_paste_end
46 zle -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
50 if 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
53 else
54 zle -N zle-line-init _bracketed_paste_zle_init
55 zle -N zle-line-finish _bracketed_paste_zle_finish
56 fi
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
28 } 64 }
29 65
30 # go back to our normal keymap, and insert all the pasted text in the 66 # Go back to our normal keymap, and insert all the pasted text in the
31 # command line. this has the nice effect of making the whole paste be 67 # command line. This has the nice effect of making the whole paste be
32 # a single undo/redo event. 68 # a single undo/redo event.
33 function _end_paste() { 69 _bracketed_paste_end() {
34 #use bindkey -v here with vi mode probably. maybe you want to track 70 # Only execute the restore command if it starts with 'bindkey'
35 #if you were in ins or cmd mode and restore the right one. 71 # Allow for option KSH_ARRAYS being set (indexing starts at 0)
36 bindkey -e 72 if [ ${_bracketed_paste_restore_keymap[@]:0:1} = 'bindkey' ]; then
37 LBUFFER+=$_paste_content 73 $_bracketed_paste_restore_keymap
38 unset _paste_content 74 fi
75 LBUFFER+=$_bracketed_paste_content
76 unset _bracketed_paste_content _bracketed_paste_restore_keymap
39 } 77 }
40 78
41 function _paste_insert() { 79 # Append a pasted character to the content which is later inserted as a whole
42 _paste_content+=$KEYS 80 _bracketed_paste_enqueue() {
81 _bracketed_paste_content+=$KEYS
43 } 82 }
44 83
45 function _zle_line_init() { 84 # Run at zle-line-init
46 # Tell terminal to send escape codes around pastes. 85 _bracketed_paste_zle_init() {
47 [[ $TERM == rxvt-unicode || $TERM == xterm || $TERM = xterm-256color || $TERM = screen || $TERM = screen-256color ]] && printf '\e[?2004h' 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
48 } 91 }
49 92
50 function _zle_line_finish() { 93 # Run at zle-line-finish
51 # Tell it to stop when we leave zle, so pasting in other programs 94 _bracketed_paste_zle_finish() {
52 # doesn't get the ^[[200~ codes around the pasted text. 95 # Turn off bracketed paste when we leave ZLE, so pasting in other programs
53 [[ $TERM == rxvt-unicode || $TERM == xterm || $TERM = xterm-256color || $TERM = screen || $TERM = screen-256color ]] && printf '\e[?2004l' 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
54 } 100 }
55 101