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