1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-11-01 06:20:55 +01:00

36195, 36196: wrapper of bracketed-paste for compatibilty with url-quote-magic and other self-insert wrapper widgets

This commit is contained in:
Barton E. Schaefer 2015-08-16 22:23:06 -07:00
parent 5d019f426a
commit 795e6eb9b3
2 changed files with 198 additions and 0 deletions

View file

@ -1,3 +1,9 @@
2015-08-16 Barton E. Schaefer <schaefer@brasslantern.com>
* 36195, 36196: Functions/Zle/bracketed-paste-magic: wrapper of
bracketed-paste for compatibilty with url-quote-magic and other
self-insert wrapper widgets
2015-08-15 Barton E. Schaefer <schaefer@zsh.org>
* 36180: Src/jobs.c: avoid infinite job stop/continue loop on

View file

@ -0,0 +1,192 @@
# Starting with zsh-5.0.9, 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 self-insert-unmeta.
# 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 self-insert-unmeta 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").
# They also run in zsh emulation context set by bracketed-paste-magic.
# 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 -LR zsh # Already set by bracketed-paste-magic
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 -LR zsh # Already set by bracketed-paste-magic
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() {
emulate -LR zsh
local -a bpm_hooks bpm_inactive
local PASTED bpm_func bpm_active
# Set PASTED and run the paste-init functions
zle .bracketed-paste PASTED
if zstyle -a :bracketed-paste-magic paste-init bpm_hooks; then
for bpm_func in $bpm_hooks; do
if (( $+functions[$bpm_func] )); then
$bpm_func || break
fi
done
fi
# Save context, create a clean slate for the paste
integer bpm_mark=$MARK bpm_cursor=$CURSOR bpm_region=$REGION_ACTIVE
integer bpm_numeric=${NUMERIC:-1}
local bpm_buffer=$BUFFER
fc -p -a /dev/null 0 0
BUFFER=
zstyle -a :bracketed-paste-magic inactive-keys bpm_inactive
if zstyle -s :bracketed-paste-magic active-widgets bpm_active '|'; then
# There are active widgets. Reprocess $PASTED as keystrokes.
NUMERIC=1
zle -U - $PASTED
while [[ -n $PASTED ]] && zle .read-command; do
PASTED=${PASTED#$KEYS}
if [[ $KEYS = ${(~j:|:)${(b)bpm_inactive}} ]]; then
zle .self-insert-unmeta
else
case $REPLY in
(${~bpm_active}) zle $REPLY;;
(*) zle .self-insert-unmeta;;
esac
fi
done
PASTED=$BUFFER
fi
# Restore state
BUFFER=$bpm_buffer
MARK=$bpm_mark
CURSOR=$bpm_cursor
REGION_ACTIVE=$bpm_region
NUMERIC=$bpm_numeric
fc -P
# 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
$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 [[ -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