mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
5455798bb5
This commit reverts 40115 (commit 3594f55f
) thus restoring 38579, then
applies 40118: Relocate BUFFER/CURSOR reset to work around "fc -p" issue
222 lines
7.3 KiB
Text
222 lines
7.3 KiB
Text
# Starting with zsh-5.1, ZLE began to recognize the "bracketed paste"
|
|
# capability of terminal emulators, that is, the sequences $'\e[200~' to
|
|
# start a paste and $'\e[201~' to indicate the end of the pasted text.
|
|
# Pastes are handled by the bracketed-paste widget and insert literally
|
|
# into the editor buffer rather than being interpreted as keystrokes.
|
|
#
|
|
# This disables some common usages where the self-insert widget has been
|
|
# replaced in order to accomplish some extra processing. An example is
|
|
# the contributed url-quote-magic widget. The bracketed-paste-magic
|
|
# widget replaces bracketed-paste with a wrapper that re-enables these
|
|
# self-insert actions, and other actions as selected by the zstyles
|
|
# described below.
|
|
#
|
|
# Setup:
|
|
# autoload -Uz bracketed-paste-magic
|
|
# zle -N bracketed-paste bracketed-paste-magic
|
|
|
|
# The following zstyles may be set to control processing of pasted text.
|
|
#
|
|
# active-widgets
|
|
# Looked up in the context :bracketed-paste-magic to obtain a list of
|
|
# patterns that match widget names that should be activated during the
|
|
# paste. All other key sequences are processed as "zle .self-insert".
|
|
# The default is 'self-*' so any user-defined widgets named with that
|
|
# prefix are active along with the builtin self-insert. If this style is
|
|
# not set (note: it must be explicitly deleted after loading this
|
|
# function, otherwise it becomes set by default) or has no value, no
|
|
# widgets are active and the pasted text is inserted literally. If the
|
|
# value includes undefined-key, any unknown sequences are discarded from
|
|
# the pasted text.
|
|
#
|
|
# inactive-keys
|
|
# This is the inverse of active-widgets, it lists key sequences that
|
|
# always use "zle .self-insert" even when bound to an active-widget.
|
|
# Note that this is a list of literal key sequences, not patterns.
|
|
# This style is in context :bracketed-paste-magic and has no default.
|
|
#
|
|
# paste-init
|
|
# paste-finish
|
|
# Also looked up in the context :bracketed-paste-magic, these styles
|
|
# each are a list of function names. They are executed in widget
|
|
# context but are called as functions (NOT as widgets with "zle name").
|
|
# As with hooks, the functions are called in order until one of them
|
|
# returns a nonzero exit status. The parameter PASTED contains the
|
|
# current state of the pasted text, other ZLE parameters are as usual.
|
|
# Although a nonzero status stops each list of functions, it does NOT
|
|
# abort the entire paste operation; use "zle send-break" for that.
|
|
|
|
# IMPORTANT: During processing of the paste (after paste-init and
|
|
# before paste-finish), BUFFER starts empty and history is restricted,
|
|
# so cursor motions etc. may not pass outside of the pasted content.
|
|
# However, the paste-init functions have access to the full history and
|
|
# the original BUFFER, so they may for example move words from BUFFER
|
|
# into PASTED to make those words visible to the active-widgets.
|
|
|
|
# Establish default values for styles, but only if not already set
|
|
zstyle -m :bracketed-paste-magic active-widgets '*' ||
|
|
zstyle ':bracketed-paste-magic' active-widgets 'self-*'
|
|
|
|
# Helper/example paste-init for exposing a word prefix inside PASTED.
|
|
# Useful with url-quote-magic if you have http://... on the line and
|
|
# are pasting additional text on the end of the URL.
|
|
#
|
|
# Usage:
|
|
# zstyle :bracketed-paste-magic paste-init backward-extend-paste
|
|
#
|
|
# TODO: rewrite this using match-words-by-style
|
|
#
|
|
backward-extend-paste() {
|
|
emulate -L zsh
|
|
integer bep_mark=$MARK bep_region=$REGION_ACTIVE
|
|
if (( REGION_ACTIVE && MARK < CURSOR )); then
|
|
zle .exchange-point-and-mark
|
|
fi
|
|
if (( CURSOR )); then
|
|
local -a bep_words=( ${(z)LBUFFER} )
|
|
if [[ -n $bep_words[-1] && $LBUFFER = *$bep_words[-1] ]]; then
|
|
PASTED=$bep_words[-1]$PASTED
|
|
LBUFFER=${LBUFFER%${bep_words[-1]}}
|
|
fi
|
|
fi
|
|
if (( MARK > bep_mark )); then
|
|
zle .exchange-point-and-mark
|
|
fi
|
|
REGION_ACTIVE=$bep_region
|
|
}
|
|
|
|
# Example paste-finish for quoting the pasted text.
|
|
#
|
|
# Usage e.g.:
|
|
# zstyle :bracketed-paste-magic paste-finish quote-paste
|
|
# zstyle :bracketed-paste-magic:finish quote-style qqq
|
|
#
|
|
# Using "zstyle -e" to examine $PASTED lets you choose different quotes
|
|
# depending on context.
|
|
#
|
|
# To forcibly turn off numeric prefix quoting, use e.g.:
|
|
# zstyle :bracketed-paste-magic:finish quote-style none
|
|
#
|
|
quote-paste() {
|
|
emulate -L zsh
|
|
local qstyle
|
|
# If there's a quoting style, be sure .bracketed-paste leaves it alone
|
|
zstyle -s :bracketed-paste-magic:finish quote-style qstyle && NUMERIC=1
|
|
case $qstyle in
|
|
(b) PASTED=${(b)PASTED};;
|
|
(q-) PASTED=${(q-)PASTED};;
|
|
(\\|q) PASTED=${(q)PASTED};;
|
|
(\'|qq) PASTED=${(qq)PASTED};;
|
|
(\"|qqq) PASTED=${(qqq)PASTED};;
|
|
(\$|qqqq) PASTED=${(qqqq)PASTED};;
|
|
(Q) PASTED=${(Q)PASTED};;
|
|
esac
|
|
}
|
|
|
|
# Now the actual function
|
|
|
|
bracketed-paste-magic() {
|
|
if [[ "$LASTWIDGET" = *vi-set-buffer ]]; then
|
|
# Fast exit in the vi-mode cut-buffer context
|
|
zle .bracketed-paste
|
|
return
|
|
else
|
|
# Capture the pasted text in $PASTED
|
|
local PASTED REPLY
|
|
zle .bracketed-paste PASTED
|
|
fi
|
|
|
|
# Really necessary to go to this much effort?
|
|
local bpm_emulate="$(emulate)" bpm_opts="$-"
|
|
|
|
emulate -L zsh
|
|
local -a bpm_hooks bpm_inactive
|
|
local bpm_func bpm_active bpm_keymap=$KEYMAP
|
|
|
|
# Run the paste-init functions
|
|
if zstyle -a :bracketed-paste-magic paste-init bpm_hooks; then
|
|
for bpm_func in $bpm_hooks; do
|
|
if (( $+functions[$bpm_func] )); then
|
|
function () {
|
|
emulate -L $bpm_emulate; set -$bpm_opts
|
|
$bpm_func || break
|
|
}
|
|
fi
|
|
done
|
|
fi
|
|
|
|
zstyle -a :bracketed-paste-magic inactive-keys bpm_inactive
|
|
if zstyle -s :bracketed-paste-magic active-widgets bpm_active '|'; then
|
|
# Save context, create a clean slate for the paste
|
|
integer bpm_mark=$MARK bpm_region=$REGION_ACTIVE
|
|
integer bpm_numeric=${NUMERIC:-1}
|
|
integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO
|
|
zle .split-undo
|
|
UNDO_LIMIT_NO=$UNDO_CHANGE_NO
|
|
BUFFER=
|
|
CURSOR=1
|
|
fc -p -a /dev/null 0 0
|
|
if [[ $bmp_keymap = vicmd ]]; then
|
|
zle -K viins
|
|
fi
|
|
|
|
# There are active widgets. Reprocess $PASTED as keystrokes.
|
|
NUMERIC=1
|
|
zle -U - $PASTED
|
|
|
|
# Just in case there are active undo widgets
|
|
|
|
while [[ -n $PASTED ]] && zle .read-command; do
|
|
PASTED=${PASTED#$KEYS}
|
|
if [[ $KEYS = ${(~j:|:)${(b)bpm_inactive}} ]]; then
|
|
zle .self-insert
|
|
else
|
|
case $REPLY in
|
|
(${~bpm_active}) function () {
|
|
emulate -L $bpm_emulate; set -$bpm_opts
|
|
zle $REPLY -w
|
|
};;
|
|
(*) zle .self-insert;;
|
|
esac
|
|
fi
|
|
done
|
|
PASTED=$BUFFER
|
|
|
|
# Restore state
|
|
zle -K $bpm_keymap
|
|
fc -P
|
|
MARK=$bpm_mark
|
|
REGION_ACTIVE=$bpm_region
|
|
NUMERIC=$bpm_numeric
|
|
zle .undo $bpm_undo
|
|
UNDO_LIMIT_NO=$bpm_limit
|
|
fi
|
|
|
|
# PASTED has been updated, run the paste-finish functions
|
|
if zstyle -a :bracketed-paste-magic paste-finish bpm_hooks; then
|
|
for bpm_func in $bpm_hooks; do
|
|
if (( $+functions[$bpm_func] )); then
|
|
function () {
|
|
emulate -L $bpm_emulate; set -$bpm_opts
|
|
$bpm_func || break
|
|
}
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Reprocess $PASTED as an actual paste this time
|
|
zle -U - $PASTED$'\e[201~' # append paste-end marker
|
|
zle .bracketed-paste -- "$@"
|
|
zle .split-undo
|
|
|
|
# Arrange to display highlighting if necessary
|
|
if [[ -z $zle_highlight || -n ${(M)zle_highlight:#paste:*} ]]; then
|
|
zle -R
|
|
zle .read-command && zle -U - $KEYS
|
|
fi
|
|
}
|
|
|
|
# Handle zsh autoloading conventions
|
|
if [[ "$zsh_eval_context" = *loadautofunc && ! -o kshautoload ]]; then
|
|
bracketed-paste-magic "$@"
|
|
fi
|