mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 18:10:56 +01:00 
			
		
		
		
	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
 |