home/.zsh/plugins/fast-syntax-highlighting/fast-highlight

1464 lines
70 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
# -------------------------------------------------------------------------------------------------
# Copyright (c) 2010-2016 zsh-syntax-highlighting contributors
# Copyright (c) 2016-2019 Sebastian Gniazdowski (modifications)
# All rights reserved.
#
# The only licensing for this file follows.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this list of conditions
# and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice, this list of
# conditions and the following disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
# may be used to endorse or promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# -------------------------------------------------------------------------------------------------
typeset -gA __fast_highlight_main__command_type_cache FAST_BLIST_PATTERNS
typeset -g FAST_WORK_DIR
: ${FAST_WORK_DIR:=$FAST_BASE_DIR}
FAST_WORK_DIR=${~FAST_WORK_DIR}
() {
emulate -L zsh -o extendedglob
local -A map
map=( "XDG:" "${XDG_CONFIG_HOME:-$HOME/.config}/fsh/"
"LOCAL:" "/usr/local/share/fsh/"
"HOME:" "$HOME/.fsh/"
"OPT:" "/opt/local/share/fsh/"
)
FAST_WORK_DIR=${${FAST_WORK_DIR/(#m)(#s)(XDG|LOCAL|HOME|OPT):(#c0,1)/${map[${MATCH%:}:]}}%/}
}
# Define default styles. You can set this after loading the plugin in
# Zshrc and use 256 colors via numbers, like: fg=150
typeset -gA FAST_HIGHLIGHT_STYLES
if [[ -e $FAST_WORK_DIR/current_theme.zsh ]]; then
source $FAST_WORK_DIR/current_theme.zsh
else
# built-in theme
zstyle :plugin:fast-syntax-highlighting theme default
: ${FAST_HIGHLIGHT_STYLES[default]:=none}
: ${FAST_HIGHLIGHT_STYLES[unknown-token]:=fg=red,bold}
: ${FAST_HIGHLIGHT_STYLES[reserved-word]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[subcommand]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[alias]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[suffix-alias]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[global-alias]:=bg=blue}
: ${FAST_HIGHLIGHT_STYLES[builtin]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[function]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[command]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[precommand]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[commandseparator]:=none}
: ${FAST_HIGHLIGHT_STYLES[hashed-command]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[path]:=fg=magenta}
: ${FAST_HIGHLIGHT_STYLES[path-to-dir]:=fg=magenta,underline}
: ${FAST_HIGHLIGHT_STYLES[path_pathseparator]:=}
: ${FAST_HIGHLIGHT_STYLES[globbing]:=fg=blue,bold}
: ${FAST_HIGHLIGHT_STYLES[globbing-ext]:=fg=13}
: ${FAST_HIGHLIGHT_STYLES[history-expansion]:=fg=blue,bold}
: ${FAST_HIGHLIGHT_STYLES[single-hyphen-option]:=fg=cyan}
: ${FAST_HIGHLIGHT_STYLES[double-hyphen-option]:=fg=cyan}
: ${FAST_HIGHLIGHT_STYLES[back-quoted-argument]:=none}
: ${FAST_HIGHLIGHT_STYLES[single-quoted-argument]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[double-quoted-argument]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[dollar-quoted-argument]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[back-or-dollar-double-quoted-argument]:=fg=cyan}
: ${FAST_HIGHLIGHT_STYLES[back-dollar-quoted-argument]:=fg=cyan}
: ${FAST_HIGHLIGHT_STYLES[assign]:=none}
: ${FAST_HIGHLIGHT_STYLES[redirection]:=none}
: ${FAST_HIGHLIGHT_STYLES[comment]:=fg=black,bold}
: ${FAST_HIGHLIGHT_STYLES[variable]:=fg=113}
: ${FAST_HIGHLIGHT_STYLES[mathvar]:=fg=blue,bold}
: ${FAST_HIGHLIGHT_STYLES[mathnum]:=fg=magenta}
: ${FAST_HIGHLIGHT_STYLES[matherr]:=fg=red}
: ${FAST_HIGHLIGHT_STYLES[assign-array-bracket]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[for-loop-variable]:=none}
: ${FAST_HIGHLIGHT_STYLES[for-loop-operator]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[for-loop-number]:=fg=magenta}
: ${FAST_HIGHLIGHT_STYLES[for-loop-separator]:=fg=yellow,bold}
: ${FAST_HIGHLIGHT_STYLES[here-string-tri]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[here-string-text]:=bg=18}
: ${FAST_HIGHLIGHT_STYLES[here-string-var]:=fg=cyan,bg=18}
: ${FAST_HIGHLIGHT_STYLES[case-input]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[case-parentheses]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[case-condition]:=bg=blue}
: ${FAST_HIGHLIGHT_STYLES[paired-bracket]:=bg=blue}
: ${FAST_HIGHLIGHT_STYLES[bracket-level-1]:=fg=green,bold}
: ${FAST_HIGHLIGHT_STYLES[bracket-level-2]:=fg=yellow,bold}
: ${FAST_HIGHLIGHT_STYLES[bracket-level-3]:=fg=cyan,bold}
: ${FAST_HIGHLIGHT_STYLES[single-sq-bracket]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[double-sq-bracket]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[double-paren]:=fg=yellow}
: ${FAST_HIGHLIGHT_STYLES[correct-subtle]:=fg=12}
: ${FAST_HIGHLIGHT_STYLES[incorrect-subtle]:=fg=red}
: ${FAST_HIGHLIGHT_STYLES[subtle-separator]:=fg=green}
: ${FAST_HIGHLIGHT_STYLES[subtle-bg]:=bg=18}
: ${FAST_HIGHLIGHT_STYLES[secondary]:=free}
fi
# This can overwrite some of *_STYLES fields
[[ -r $FAST_WORK_DIR/theme_overlay.zsh ]] && source $FAST_WORK_DIR/theme_overlay.zsh
typeset -gA __FAST_HIGHLIGHT_TOKEN_TYPES
__FAST_HIGHLIGHT_TOKEN_TYPES=(
# Precommand
'builtin' 1
'command' 1
'exec' 1
'nocorrect' 1
'noglob' 1
'pkexec' 1 # immune to #121 because it's usually not passed --option flags
# Control flow
# Tokens that, at (naively-determined) "command position", are followed by
# a de jure command position. All of these are reserved words.
$'\x7b' 2 # block '{'
$'\x28' 2 # subshell '('
'()' 2 # anonymous function
'while' 2
'until' 2
'if' 2
'then' 2
'elif' 2
'else' 2
'do' 2
'time' 2
'coproc' 2
'!' 2 # reserved word; unrelated to $histchars[1]
# Command separators
'|' 3
'||' 3
';' 3
'&' 3
'&&' 3
'|&' 3
'&!' 3
'&|' 3
# ### 'case' syntax, but followed by a pattern, not by a command
# ';;' ';&' ';|'
)
# A hash instead of multiple globals
typeset -gA FAST_HIGHLIGHT
# Brackets highlighter active by default
: ${FAST_HIGHLIGHT[use_brackets]:=1}
FAST_HIGHLIGHT+=(
chroma-fast-theme →chroma/-fast-theme.ch
chroma-alias →chroma/-alias.ch
chroma-autoload →chroma/-autoload.ch
chroma-autorandr →chroma/-autorandr.ch
chroma-docker →chroma/-docker.ch
chroma-example →chroma/-example.ch
chroma-ionice →chroma/-ionice.ch
chroma-make →chroma/-make.ch
chroma-nice →chroma/-nice.ch
chroma-nmcli →chroma/-nmcli.ch
chroma-node →chroma/-node.ch
chroma-perl →chroma/-perl.ch
chroma-printf →chroma/-printf.ch
chroma-ruby →chroma/-ruby.ch
chroma-scp →chroma/-scp.ch
chroma-ssh →chroma/-ssh.ch
chroma-git →chroma/main-chroma.ch%git
chroma-hub →chroma/-hub.ch
chroma-lab →chroma/-lab.ch
chroma-svn →chroma/-subversion.ch
chroma-svnadmin →chroma/-subversion.ch
chroma-svndumpfilter →chroma/-subversion.ch
chroma-egrep →chroma/-grep.ch
chroma-fgrep →chroma/-grep.ch
chroma-grep →chroma/-grep.ch
chroma-awk →chroma/-awk.ch
chroma-gawk →chroma/-awk.ch
chroma-mawk →chroma/-awk.ch
chroma-source →chroma/-source.ch
chroma-. →chroma/-source.ch
chroma-bash →chroma/-sh.ch
chroma-fish →chroma/-sh.ch
chroma-sh →chroma/-sh.ch
chroma-zsh →chroma/-sh.ch
chroma-whatis →chroma/-whatis.ch
chroma-man →chroma/-whatis.ch
chroma-- →chroma/-precommand.ch
chroma-xargs →chroma/-precommand.ch
chroma-nohup →chroma/-precommand.ch
chroma-strace →chroma/-precommand.ch
chroma-ltrace →chroma/-precommand.ch
chroma-hg →chroma/-subcommand.ch
chroma-cvs →chroma/-subcommand.ch
chroma-pip →chroma/-subcommand.ch
chroma-pip2 →chroma/-subcommand.ch
chroma-pip3 →chroma/-subcommand.ch
chroma-gem →chroma/-subcommand.ch
chroma-bundle →chroma/-subcommand.ch
chroma-yard →chroma/-subcommand.ch
chroma-cabal →chroma/-subcommand.ch
chroma-npm →chroma/-subcommand.ch
chroma-nvm →chroma/-subcommand.ch
chroma-yarn →chroma/-subcommand.ch
chroma-brew →chroma/-subcommand.ch
chroma-port →chroma/-subcommand.ch
chroma-yum →chroma/-subcommand.ch
chroma-dnf →chroma/-subcommand.ch
chroma-tmux →chroma/-subcommand.ch
chroma-pass →chroma/-subcommand.ch
chroma-aws →chroma/-subcommand.ch
chroma-apt →chroma/-subcommand.ch
chroma-apt-get →chroma/-subcommand.ch
chroma-apt-cache →chroma/-subcommand.ch
chroma-aptitude →chroma/-subcommand.ch
chroma-keyctl →chroma/-subcommand.ch
chroma-systemctl →chroma/-subcommand.ch
chroma-asciinema →chroma/-subcommand.ch
chroma-ipfs →chroma/-subcommand.ch
chroma-zinit →chroma/main-chroma.ch%zinit
chroma-aspell →chroma/-subcommand.ch
chroma-bspc →chroma/-subcommand.ch
chroma-cryptsetup →chroma/-subcommand.ch
chroma-diskutil →chroma/-subcommand.ch
chroma-exercism →chroma/-subcommand.ch
chroma-gulp →chroma/-subcommand.ch
chroma-i3-msg →chroma/-subcommand.ch
chroma-openssl →chroma/-subcommand.ch
chroma-solargraph →chroma/-subcommand.ch
chroma-subliminal →chroma/-subcommand.ch
chroma-svnadmin →chroma/-subcommand.ch
chroma-travis →chroma/-subcommand.ch
chroma-udisksctl →chroma/-subcommand.ch
chroma-xdotool →chroma/-subcommand.ch
chroma-zmanage →chroma/-subcommand.ch
chroma-zsystem →chroma/-subcommand.ch
chroma-zypper →chroma/-subcommand.ch
chroma-fpath+=\( →chroma/-fpath_peq.ch
chroma-fpath=\( →chroma/-fpath_peq.ch
chroma-FPATH+= →chroma/-fpath_peq.ch
chroma-FPATH= →chroma/-fpath_peq.ch
#chroma-which →chroma/-which.ch
#chroma-vim →chroma/-vim.ch
)
if [[ $OSTYPE == darwin* ]] {
noglob unset FAST_HIGHLIGHT[chroma-man] FAST_HIGHLIGHT[chroma-whatis]
}
# Assignments seen, to know if math parameter exists
typeset -gA FAST_ASSIGNS_SEEN
# Exposing tokens found on command position,
# for other scripts to process
typeset -ga ZLAST_COMMANDS
# Get the type of a command.
#
# Uses the zsh/parameter module if available to avoid forks, and a
# wrapper around 'type -w' as fallback.
#
# Takes a single argument.
#
# The result will be stored in REPLY.
-fast-highlight-main-type() {
REPLY=$__fast_highlight_main__command_type_cache[(e)$1]
[[ -z $REPLY ]] && {
if zmodload -e zsh/parameter; then
if (( $+aliases[(e)$1] )); then
REPLY=alias
elif (( ${+galiases[(e)$1]} )); then
REPLY="global alias"
elif (( $+functions[(e)$1] )); then
REPLY=function
elif (( $+builtins[(e)$1] )); then
REPLY=builtin
elif (( $+commands[(e)$1] )); then
REPLY=command
elif (( $+saliases[(e)${1##*.}] )); then
REPLY='suffix alias'
elif (( $reswords[(Ie)$1] )); then
REPLY=reserved
# zsh 5.2 and older have a bug whereby running 'type -w ./sudo' implicitly
# runs 'hash ./sudo=/usr/local/bin/./sudo' (assuming /usr/local/bin/sudo
# exists and is in $PATH). Avoid triggering the bug, at the expense of
# falling through to the $() below, incurring a fork. (Issue #354.)
#
# The second disjunct mimics the isrelative() C call from the zsh bug.
elif [[ $1 != */* || ${+ZSH_ARGZERO} = "1" ]] && ! builtin type -w -- $1 >/dev/null 2>&1; then
REPLY=none
fi
fi
[[ -z $REPLY ]] && REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)##*: }"
[[ $REPLY = "none" ]] && {
[[ -n ${FAST_BLIST_PATTERNS[(k)${${(M)1:#/*}:-$PWD/$1}]} ]] || {
[[ -d $1 ]] && REPLY="dirpath" || {
for cdpath_dir in $cdpath; do
[[ -d $cdpath_dir/$1 ]] && { REPLY="dirpath"; break; }
done
}
}
}
__fast_highlight_main__command_type_cache[(e)$1]=$REPLY
}
}
# Below are variables that must be defined in outer
# scope so that they are reachable in *-process()
-fast-highlight-fill-option-variables() {
if [[ -o ignore_braces ]] || eval '[[ -o ignore_close_braces ]] 2>/dev/null'; then
FAST_HIGHLIGHT[right_brace_is_recognised_everywhere]=0
else
FAST_HIGHLIGHT[right_brace_is_recognised_everywhere]=1
fi
if [[ -o path_dirs ]]; then
FAST_HIGHLIGHT[path_dirs_was_set]=1
else
FAST_HIGHLIGHT[path_dirs_was_set]=0
fi
if [[ -o multi_func_def ]]; then
FAST_HIGHLIGHT[multi_func_def]=1
else
FAST_HIGHLIGHT[multi_func_def]=0
fi
if [[ -o interactive_comments ]]; then
FAST_HIGHLIGHT[ointeractive_comments]=1
else
FAST_HIGHLIGHT[ointeractive_comments]=0
fi
}
# Main syntax highlighting function.
-fast-highlight-process()
{
emulate -L zsh
setopt extendedglob bareglobqual nonomatch typesetsilent
[[ $CONTEXT == "select" ]] && return 0
(( FAST_HIGHLIGHT[path_dirs_was_set] )) && setopt PATH_DIRS
(( FAST_HIGHLIGHT[ointeractive_comments] )) && local interactive_comments= # _set_ to empty
# Variable declarations and initializations
# in_array_assignment true between 'a=(' and the matching ')'
# braces_stack: "R" for round, "Q" for square, "Y" for curly
# _mybuf, cdpath_dir are used in sub-functions
local _start_pos=$3 _end_pos __start __end highlight_glob=1 __arg __style in_array_assignment=0 MATCH expanded_path braces_stack __buf=$1$2 _mybuf __workbuf cdpath_dir active_command alias_target _was_double_hyphen=0 __nul=$'\0' __tmp
# __arg_type can be 0, 1, 2 or 3, i.e. precommand, control flow, command separator
# __idx and _end_idx are used in sub-functions
# for this_word and next_word look below at commented integers and at state machine description
integer __arg_type=0 MBEGIN MEND in_redirection __len=${#__buf} __PBUFLEN=${#1} already_added offset __idx _end_idx this_word=1 next_word=0 __pos __asize __delimited=0 itmp iitmp
local -a match mbegin mend __inputs __list
# This comment explains the numbers:
# BIT_for - word after reserved-word-recognized `for'
# BIT_afpcmd - word after a precommand that can take options, like `command' and `exec'
# integer BIT_start=1 BIT_regular=2 BIT_sudo_opt=4 BIT_sudo_arg=8 BIT_always=16 BIT_for=32 BIT_afpcmd=64
# integer BIT_chroma=8192
integer BIT_case_preamble=512 BIT_case_item=1024 BIT_case_nempty_item=2048 BIT_case_code=4096
# Braces stack
# T - typeset, local, etc.
# State machine
#
# The states are:
# - :__start: Command word
# - :sudo_opt: A leading-dash option to sudo (such as "-u" or "-i")
# - :sudo_arg: The argument to a sudo leading-dash option that takes one,
# when given as a separate word; i.e., "foo" in "-u foo" (two
# words) but not in "-ufoo" (one word).
# - :regular: "Not a command word", and command delimiters are permitted.
# Mainly used to detect premature termination of commands.
# - :always: The word 'always' in the «{ foo } always { bar }» syntax.
#
# When the kind of a word is not yet known, $this_word / $next_word may contain
# multiple states. For example, after "sudo -i", the next word may be either
# another --flag or a command name, hence the state would include both :__start:
# and :sudo_opt:.
#
# The tokens are always added with both leading and trailing colons to serve as
# word delimiters (an improvised array); [[ $x == *:foo:* ]] and x=${x//:foo:/}
# will DTRT regardless of how many elements or repetitions $x has..
#
# Handling of redirections: upon seeing a redirection token, we must stall
# the current state --- that is, the value of $this_word --- for two iterations
# (one for the redirection operator, one for the word following it representing
# the redirection target). Therefore, we set $in_redirection to 2 upon seeing a
# redirection operator, decrement it each iteration, and stall the current state
# when it is non-zero. Thus, upon reaching the next word (the one that follows
# the redirection operator and target), $this_word will still contain values
# appropriate for the word immediately following the word that preceded the
# redirection operator.
#
# The "the previous word was a redirection operator" state is not communicated
# to the next iteration via $next_word/$this_word as usual, but via
# $in_redirection. The value of $next_word from the iteration that processed
# the operator is discarded.
#
# Command exposure for other scripts
ZLAST_COMMANDS=()
# Restart observing of assigns
FAST_ASSIGNS_SEEN=()
# Restart function's gathering
FAST_HIGHLIGHT[chroma-autoload-elements]=""
# Restart FPATH elements gathering
FAST_HIGHLIGHT[chroma-fpath_peq-elements]=""
# Restart svn zinit's ICE gathering
FAST_HIGHLIGHT[chroma-zinit-ice-elements-svn]=0
FAST_HIGHLIGHT[chroma-zinit-ice-elements-id-as]=""
[[ -n $ZCALC_ACTIVE ]] && {
_start_pos=0; _end_pos=__len; __arg=$__buf
-fast-highlight-math-string
return 0
}
# Processing buffer
local proc_buf=$__buf needle
for __arg in ${interactive_comments-${(z)__buf}} \
${interactive_comments+${(zZ+c+)__buf}}; do
# Initialize $next_word to its default value?
(( in_redirection = in_redirection > 0 ? in_redirection - 1 : in_redirection ));
(( next_word = (in_redirection == 0) ? 2 : next_word )) # else Stall $next_word.
(( next_word = next_word | (this_word & (BIT_case_code|8192)) ))
# If we have a good delimiting construct just ending, and '{'
# occurs, then respect this and go for alternate syntax, i.e.
# treat '{' (\x7b) as if it's on command position
[[ $__arg = '{' && $__delimited = 2 ]] && { (( this_word = (this_word & ~2) | 1 )); __delimited=0; }
__asize=${#__arg}
# Reset state of working variables
already_added=0
__style=${FAST_THEME_NAME}unknown-token
(( this_word & 1 )) && { in_array_assignment=0; [[ $__arg == 'noglob' ]] && highlight_glob=0; }
# Compute the new $_start_pos and $_end_pos, skipping over whitespace in $__buf.
if [[ $__arg == ';' ]] ; then
braces_stack=${braces_stack#T}
__delimited=0
# Both ; and \n are rendered as a ";" (SEPER) by the ${(z)..} flag.
needle=$';\n'
[[ $proc_buf = (#b)[^$needle]#([$needle]##)* ]] && offset=${mbegin[1]}-1
(( _start_pos += offset ))
(( _end_pos = _start_pos + __asize ))
# Prepare next loop cycle
(( this_word & BIT_case_item )) || { (( in_array_assignment )) && (( this_word = 2 | (this_word & BIT_case_code) )) || { (( this_word = 1 | (this_word & BIT_case_code) )); highlight_glob=1; }; }
in_redirection=0
# Chance to highlight ';'
[[ ${proc_buf[offset+1]} != $'\n' ]] && {
[[ ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}commandseparator]} != "none" ]] && \
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}commandseparator]}")
}
proc_buf=${proc_buf[offset + __asize + 1,__len]}
_start_pos=$_end_pos
continue
else
offset=0
if [[ $proc_buf = (#b)(#s)(([[:space:]]|\\[[:space:]])##)* ]]; then
# The first, outer parenthesis
offset=${mend[1]}
fi
(( _start_pos += offset ))
(( _end_pos = _start_pos + __asize ))
# No-hit will result in value 0
__arg_type=${__FAST_HIGHLIGHT_TOKEN_TYPES[$__arg]}
fi
(( this_word & 1 )) && ZLAST_COMMANDS+=( $__arg );
proc_buf=${proc_buf[offset + __asize + 1,__len]}
# Handle the INTERACTIVE_COMMENTS option.
#
# We use the (Z+c+) flag so the entire comment is presented as one token in $__arg.
if [[ -n ${interactive_comments+'set'} && $__arg == ${histchars[3]}* ]]; then
if (( this_word & 3 )); then
__style=${FAST_THEME_NAME}comment
else
__style=${FAST_THEME_NAME}unknown-token # prematurely terminated
fi
# ADD
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}")
_start_pos=$_end_pos
continue
fi
# Redirection?
[[ $__arg == (<0-9>|)(\<|\>)* && $__arg != (\<|\>)$'\x28'* && $__arg != "<<<" ]] && \
in_redirection=2
# Special-case the first word after 'sudo'.
if (( ! in_redirection )); then
(( this_word & 4 )) && [[ $__arg != -* ]] && (( this_word = this_word ^ 4 ))
# Parse the sudo command line
if (( this_word & 4 )); then
case $__arg in
# Flag that requires an argument
'-'[Cgprtu])
(( this_word = this_word & ~1 ))
(( next_word = 8 | (this_word & BIT_case_code) ))
;;
# This prevents misbehavior with sudo -u -otherargument
'-'*)
(( this_word = this_word & ~1 ))
(( next_word = next_word | 1 | 4 ))
;;
esac
elif (( this_word & 8 )); then
(( next_word = next_word | 4 | 1 ))
elif (( this_word & 64 )); then
[[ $__arg = -[pvV-]## && $active_command = "command" ]] && (( this_word = (this_word & ~1) | 2, next_word = (next_word | 65) & ~2 ))
[[ $__arg = -[cla-]## && $active_command = "exec" ]] && (( this_word = (this_word & ~1) | 2, next_word = (next_word | 65) & ~2 ))
[[ $__arg = \{[a-zA-Z_][a-zA-Z0-9_]#\} && $active_command = "exec" ]] && {
# Highlight {descriptor} passed to exec
(( this_word = (this_word & ~1) | 2, next_word = (next_word | 65) & ~2 ))
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}exec-descriptor]}")
already_added=1
}
fi
fi
(( this_word & 8192 )) && {
__list=( ${(z@)${aliases[$active_command]:-${active_command##*/}}##[[:space:]]#(command|builtin|exec|noglob|nocorrect|pkexec)[[:space:]]#} )
${${FAST_HIGHLIGHT[chroma-${__list[1]}]}%\%*} ${(M)FAST_HIGHLIGHT[chroma-${__list[1]}]%\%*} 0 "$__arg" $_start_pos $_end_pos 2>/dev/null && continue
}
(( this_word & 1 )) && {
# !in_redirection needed particularly for exec {A}>b {C}>d
(( !in_redirection )) && active_command=$__arg
_mybuf=${${aliases[$active_command]:-${active_command##*/}}##[[:space:]]#(command|builtin|exec|noglob|nocorrect|pkexec)[[:space:]]#}
[[ "$_mybuf" = (#b)(FPATH+(#c0,1)=)* ]] && _mybuf="${match[1]} ${(j: :)${(s,:,)${_mybuf#FPATH+(#c0,1)=}}}"
[[ -n ${FAST_HIGHLIGHT[chroma-${_mybuf%% *}]} ]] && {
__list=( ${(z@)_mybuf} )
if (( ${#__list} > 1 )) || [[ $active_command != $_mybuf ]]; then
__style=${FAST_THEME_NAME}alias
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}")
${${FAST_HIGHLIGHT[chroma-${__list[1]}]}%\%*} ${(M)FAST_HIGHLIGHT[chroma-${__list[1]}]%\%*} 1 "${__list[1]}" "-100000" $_end_pos 2>/dev/null || \
(( this_word = next_word, next_word = 2 ))
for _mybuf in "${(@)__list[2,-1]}"; do
(( next_word = next_word | (this_word & (BIT_case_code|8192)) ))
${${FAST_HIGHLIGHT[chroma-${__list[1]}]}%\%*} ${(M)FAST_HIGHLIGHT[chroma-${__list[1]}]%\%*} 0 "$_mybuf" "-100000" $_end_pos 2>/dev/null || \
(( this_word = next_word, next_word = 2 ))
done
# This might have been done multiple times in chroma, but
# as _end_pos doesn't change, it can be done one more time
_start_pos=$_end_pos
continue
else
${${FAST_HIGHLIGHT[chroma-${__list[1]}]}%\%*} ${(M)FAST_HIGHLIGHT[chroma-${__list[1]}]%\%*} 1 "$__arg" $_start_pos $_end_pos 2>/dev/null && continue
fi
} || (( 1 ))
}
expanded_path=""
# The Great Fork: is this a command word? Is this a non-command word?
if (( this_word & 16 )) && [[ $__arg == 'always' ]]; then
# try-always construct
__style=${FAST_THEME_NAME}reserved-word # de facto a reserved word, although not de jure
(( next_word = 1 | (this_word & BIT_case_code) ))
elif (( (this_word & 1) && (in_redirection == 0) )) || [[ $braces_stack = T* ]]; then # T - typedef, etc.
if (( __arg_type == 1 )); then
__style=${FAST_THEME_NAME}precommand
[[ $__arg = "command" || $__arg = "exec" ]] && (( next_word = next_word | 64 ))
elif [[ $__arg = (sudo|doas) ]]; then
__style=${FAST_THEME_NAME}precommand
(( next_word = (next_word & ~2) | 4 | 1 ))
else
_mybuf=${${(Q)__arg}#\"}
if (( ${+parameters} )) && \
[[ $_mybuf = (#b)(*)(*)\$([a-zA-Z_][a-zA-Z0-9_]#|[0-9]##)(*) || \
$_mybuf = (#b)(*)(*)\$\{([a-zA-Z_][a-zA-Z0-9_:-]#|[0-9]##)(*) ]] && \
(( ${+parameters[${match[3]%%:-*}]} ))
then
-fast-highlight-main-type ${match[1]}${match[2]}${(P)match[3]%%:-*}${match[4]#\}}
elif [[ $braces_stack = T* ]]; then # T - typedef, etc.
REPLY=none
else
: ${expanded_path::=${~_mybuf}}
-fast-highlight-main-type $expanded_path
fi
case $REPLY in
reserved) # reserved word
[[ $__arg = "[[" ]] && __style=${FAST_THEME_NAME}double-sq-bracket || __style=${FAST_THEME_NAME}reserved-word
if [[ $__arg == $'\x7b' ]]; then # Y - '{'
braces_stack='Y'$braces_stack
elif [[ $__arg == $'\x7d' && $braces_stack = Y* ]]; then # Y - '}'
# We're at command word, so no need to check right_brace_is_recognised_everywhere
braces_stack=${braces_stack#Y}
__style=${FAST_THEME_NAME}reserved-word
(( next_word = next_word | 16 ))
elif [[ $__arg == "[[" ]]; then # A - [[
braces_stack='A'$braces_stack
# Counting complex brackets (for brackets-highlighter): 1. [[ as command
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN + 1 )) )
elif [[ $__arg == "for" ]]; then
(( next_word = next_word | 32 )) # BIT_for
elif [[ $__arg == "case" ]]; then
(( next_word = BIT_case_preamble ))
elif [[ $__arg = (typeset|declare|local|float|integer|export|readonly) ]]; then
braces_stack='T'$braces_stack
fi
;;
'suffix alias') __style=${FAST_THEME_NAME}suffix-alias;;
'global alias') __style=${FAST_THEME_NAME}global-alias;;
alias)
if [[ $__arg = ?*'='* ]]; then
# The so called (by old code) "insane_alias"
__style=${FAST_THEME_NAME}unknown-token
else
__style=${FAST_THEME_NAME}alias
(( ${+aliases} )) && alias_target=${aliases[$__arg]} || alias_target="${"$(alias -- $__arg)"#*=}"
[[ ${__FAST_HIGHLIGHT_TOKEN_TYPES[$alias_target]} = "1" && $__arg_type != "1" ]] && __FAST_HIGHLIGHT_TOKEN_TYPES[$__arg]="1"
fi
;;
builtin) [[ $__arg = "[" ]] && {
__style=${FAST_THEME_NAME}single-sq-bracket
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) )
} || __style=${FAST_THEME_NAME}builtin
# T - typeset, etc. mode
[[ $__arg = (typeset|declare|local|float|integer|export|readonly) ]] && braces_stack='T'$braces_stack
[[ $__arg = eval ]] && (( next_word = next_word | 256 ))
;;
function) __style=${FAST_THEME_NAME}function;;
command) __style=${FAST_THEME_NAME}command;;
hashed) __style=${FAST_THEME_NAME}hashed-command;;
dirpath) __style=${FAST_THEME_NAME}path-to-dir;;
none) # Assign?
if [[ $__arg == [a-zA-Z_][a-zA-Z0-9_]#(|\[[^\]]#\])(|[^\]]#\])(|[+])=* || $__arg == [0-9]##(|[+])=* || ( $braces_stack = T* && ${__arg_type} != 3 ) ]] {
__style=${FAST_THEME_NAME}assign
FAST_ASSIGNS_SEEN[${__arg%%=*}]=1
# Handle array assignment
[[ $__arg = (#b)*=(\()*(\))* || $__arg = (#b)*=(\()* ]] && {
(( __start=_start_pos-__PBUFLEN+${mbegin[1]}-1, __end=__start+1, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}assign-array-bracket]}")
# Counting complex brackets (for brackets-highlighter): 2. ( in array assign
_FAST_COMPLEX_BRACKETS+=( $__start )
(( mbegin[2] >= 1 )) && {
(( __start=_start_pos-__PBUFLEN+${mbegin[2]}-1, __end=__start+1, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}assign-array-bracket]}")
# Counting complex brackets (for brackets-highlighter): 3a. ) in array assign
_FAST_COMPLEX_BRACKETS+=( $__start )
} || in_array_assignment=1
} || { [[ ${braces_stack[1]} != 'T' ]] && (( next_word = (next_word | 1) & ~2 )); }
# Handle no-string highlight, string "/' highlight, math mode highlight
local ctmp="\"" dtmp="'"
itmp=${__arg[(i)$ctmp]}-1 iitmp=${__arg[(i)$dtmp]}-1
integer jtmp=${__arg[(b:itmp+2:i)$ctmp]} jjtmp=${__arg[(b:iitmp+2:i)$dtmp]}
(( itmp < iitmp && itmp <= __asize - 1 )) && (( jtmp > __asize && (jtmp = __asize), 1 > 0 )) && \
(( __start=_start_pos-__PBUFLEN+itmp, __end=_start_pos-__PBUFLEN+jtmp, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}") && \
{ itmp=${__arg[(i)=]}; __arg=${__arg[itmp,__asize]}; (( _start_pos += itmp - 1 ));
-fast-highlight-string; (( _start_pos = _start_pos - itmp + 1, 1 > 0 )); } || \
{
(( iitmp <= __asize - 1 )) && (( jjtmp > __asize && (jjtmp = __asize), 1 > 0 )) && \
(( __start=_start_pos-__PBUFLEN+iitmp, __end=_start_pos-__PBUFLEN+jjtmp, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}single-quoted-argument]}")
} || \
{
itmp=${__arg[(i)=]}; __arg=${__arg[itmp,__asize]}; (( _start_pos += itmp - 1 ));
[[ ${__arg[2,4]} = '$((' ]] && { -fast-highlight-math-string;
(( __start=_start_pos-__PBUFLEN+2, __end=__start+2, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}")
# Counting complex brackets (for brackets-highlighter): 4. $(( in assign argument
_FAST_COMPLEX_BRACKETS+=( $__start $(( __start + 1 )) )
(( jtmp = ${__arg[(I)\)\)]}-1, jtmp > 0 )) && {
(( __start=_start_pos-__PBUFLEN+jtmp, __end=__start+2, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}")
# Counting complex brackets (for brackets-highlighter): 5. )) in assign argument
_FAST_COMPLEX_BRACKETS+=( $__start $(( __start + 1 )) )
}
} || -fast-highlight-string;
(( _start_pos = _start_pos - itmp + 1, 1 > 0 ))
}
} elif [[ $__arg = ${histchars[1]}* && -n ${__arg[2]} ]] {
__style=${FAST_THEME_NAME}history-expansion
} elif [[ $__arg == ${histchars[2]}* ]] {
__style=${FAST_THEME_NAME}history-expansion
} elif (( __arg_type == 3 )) {
# This highlights empty commands (semicolon follows nothing) as an error.
# Zsh accepts them, though.
(( this_word & 3 )) && __style=${FAST_THEME_NAME}commandseparator
} elif [[ $__arg[1,2] == '((' ]] {
# Arithmetic evaluation.
#
# Note: prior to zsh-5.1.1-52-g4bed2cf (workers/36669), the ${(z)...}
# splitter would only output the '((' token if the matching '))' had
# been typed. Therefore, under those versions of zsh, BUFFER="(( 42"
# would be highlighted as an error until the matching "))" are typed.
#
# We highlight just the opening parentheses, as a reserved word; this
# is how [[ ... ]] is highlighted, too.
# ADD
(( __start=_start_pos-__PBUFLEN, __end=__start+2, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}")
already_added=1
# Counting complex brackets (for brackets-highlighter): 6. (( as command
_FAST_COMPLEX_BRACKETS+=( $__start $(( __start + 1 )) )
-fast-highlight-math-string
# ADD
[[ $__arg[-2,-1] == '))' ]] && {
(( __start=_end_pos-__PBUFLEN-2, __end=__start+2, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}")
(( __delimited = __delimited ? 2 : __delimited ))
# Counting complex brackets (for brackets-highlighter): 7. )) for as-command ((
_FAST_COMPLEX_BRACKETS+=( $__start $(( __start + 1 )) )
}
} elif [[ $__arg == '()' ]] {
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN + 1 )) )
# anonymous function
__style=${FAST_THEME_NAME}reserved-word
} elif [[ $__arg == $'\x28' ]] {
# subshell '(', stack: letter 'R'
__style=${FAST_THEME_NAME}reserved-word
braces_stack='R'$braces_stack
} elif [[ $__arg == $'\x29' ]] {
# ')', stack: letter 'R' for subshell
[[ $braces_stack = R* ]] && { braces_stack=${braces_stack#R}; __style=${FAST_THEME_NAME}reserved-word; }
} elif (( this_word & 14 )) {
__style=${FAST_THEME_NAME}default
} elif [[ $__arg = (';;'|';&'|';|') ]] && (( this_word & BIT_case_code )) {
(( next_word = (next_word | BIT_case_item) & ~(BIT_case_code+3) ))
__style=${FAST_THEME_NAME}default
} elif [[ $__arg = \$\([^\(]* ]] {
already_added=1
}
;;
*)
# ADD
# (( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end commandtypefromthefuture-$REPLY")
already_added=1
;;
esac
fi
# in_redirection || BIT_regular || BIT_sudo_opt || BIT_sudo_arg
elif (( in_redirection + this_word & 14 ))
then # $__arg is a non-command word
case $__arg in
']]')
# A - [[
[[ $braces_stack = A* ]] && {
__style=${FAST_THEME_NAME}double-sq-bracket
(( __delimited = __delimited ? 2 : __delimited ))
# Counting complex brackets (for brackets-highlighter): 8a. ]] for as-command [[
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN+1 )) )
} || {
[[ $braces_stack = *A* ]] && {
__style=${FAST_THEME_NAME}unknown-token
# Counting complex brackets (for brackets-highlighter): 8b. ]] for as-command [[
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN+1 )) )
} || __style=${FAST_THEME_NAME}default
}
braces_stack=${braces_stack#A}
;;
']')
__style=${FAST_THEME_NAME}single-sq-bracket
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) )
;;
$'\x28')
# '(' inside [[
__style=${FAST_THEME_NAME}reserved-word
braces_stack='R'$braces_stack
;;
$'\x29') # ')' - subshell or end of array assignment
if (( in_array_assignment )); then
in_array_assignment=0
(( next_word = next_word | 1 ))
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}assign-array-bracket]}")
already_added=1
# Counting complex brackets (for brackets-highlighter): 3b. ) in array assign
_FAST_COMPLEX_BRACKETS+=( $__start )
elif [[ $braces_stack = R* ]]; then
braces_stack=${braces_stack#R}
__style=${FAST_THEME_NAME}reserved-word
# Zsh doesn't tokenize final ) if it's just single ')',
# but logically what's below is correct, so it is kept
# in case Zsh will be changed / fixed, etc.
elif [[ $braces_stack = F* ]]; then
__style=${FAST_THEME_NAME}builtin
fi
;;
$'\x28\x29') # '()' - possibly a function definition
# || false # TODO: or if the previous word was a command word
(( FAST_HIGHLIGHT[multi_func_def] )) && (( next_word = next_word | 1 ))
__style=${FAST_THEME_NAME}reserved-word
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN + 1 )) )
# Remove possible annoying unknown-token __style, or misleading function __style
reply[-1]=()
__fast_highlight_main__command_type_cache[$active_command]="function"
;;
'--'*) [[ $__arg == "--" ]] && { _was_double_hyphen=1; __style=${FAST_THEME_NAME}double-hyphen-option; } || {
(( !_was_double_hyphen )) && {
[[ "$__arg" = (#b)(--[a-zA-Z0-9_]##)=(*) ]] && {
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-hyphen-option]}")
(( __start=_start_pos-__PBUFLEN+1+mend[1], __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}optarg-${${${(M)match[2]:#<->}:+number}:-string}]}")
already_added=1
} || __style=${FAST_THEME_NAME}double-hyphen-option
} || __style=${FAST_THEME_NAME}default
}
;;
'-'*) (( !_was_double_hyphen )) && __style=${FAST_THEME_NAME}single-hyphen-option || __style=${FAST_THEME_NAME}default;;
\$\'*)
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}dollar-quoted-argument]}")
-fast-highlight-dollar-string
already_added=1
;;
[\"\']*|[^\"\\]##([\\][\\])#\"*|[^\'\\]##([\\][\\])#\'*)
# 256 is eval-mode
if (( this_word & 256 )) && [[ $__arg = [\'\"]* ]]; then
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}recursive-base]}")
if [[ -n ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}secondary]} ]]; then
__idx=1
_mybuf=$FAST_THEME_NAME
FAST_THEME_NAME=${${${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}secondary]}:t:r}#(XDG|LOCAL|HOME|OPT):}
(( ${+FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}default]} )) || source $FAST_WORK_DIR/secondary_theme.zsh
else
__idx=0
fi
(( _start_pos-__PBUFLEN >= 0 )) && \
-fast-highlight-process "$PREBUFFER" "${${__arg%[\'\"]}#[\'\"]}" $(( _start_pos + 1 ))
(( __idx )) && FAST_THEME_NAME=$_mybuf
already_added=1
else
[[ $__arg = *([^\\][\#][\#]|"(#b)"|"(#B)"|"(#m)"|"(#c")* && $highlight_glob -ne 0 ]] && \
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}globbing-ext]}")
# Reusing existing vars, treat this code like C++ STL
# header, full of underscores and unhelpful var names
itmp=0 __workbuf=$__arg __tmp="" cdpath_dir=$__arg
while [[ $__workbuf = (#b)[^\"\'\\]#(([\"\'])|[\\](*))(*) ]]; do
[[ -n ${match[3]} ]] && {
itmp+=${mbegin[1]}
# Optionally skip 1 quoted char
[[ $__tmp = \' ]] && __workbuf=${match[3]} || { itmp+=1; __workbuf=${match[3]:1}; }
} || {
itmp+=${mbegin[1]}
__workbuf=${match[4]}
# Toggle quoting
[[ ( ${match[1]} = \" && $__tmp != \' ) || ( ${match[1]} = \' && $__tmp != \" ) ]] && {
[[ $__tmp = [\"\'] ]] && {
# End of quoting
(( __start=_start_pos-__PBUFLEN+iitmp-1, __end=_start_pos-__PBUFLEN+itmp, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}${${${__tmp#\'}:+double-quoted-argument}:-single-quoted-argument}]}")
already_added=1
[[ $__tmp = \" ]] && {
__arg=${cdpath_dir[iitmp+1,itmp-1]}
(( _start_pos += iitmp - 1 + 1 ))
-fast-highlight-string
(( _start_pos = _start_pos - iitmp + 1 - 1 ))
}
# The end-of-quoting proper algorithm action
__tmp=
} || {
# Beginning of quoting
iitmp=itmp
# The beginning-of-quoting proper algorithm action
__tmp=${match[1]}
}
}
}
done
[[ $__tmp = [\"\'] ]] && {
(( __start=_start_pos-__PBUFLEN+iitmp-1, __end=_start_pos-__PBUFLEN+__asize, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}${${${__tmp#\'}:+double-quoted-argument}:-single-quoted-argument}]}")
already_added=1
[[ $__tmp = \" ]] && {
__arg=${cdpath_dir[iitmp+1,__asize]}
(( _start_pos += iitmp - 1 + 1 ))
-fast-highlight-string
(( _start_pos = _start_pos - iitmp + 1 - 1 ))
}
}
fi
;;
\$\(\(*)
already_added=1
-fast-highlight-math-string
# ADD
(( __start=_start_pos-__PBUFLEN+1, __end=__start+2, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}")
# Counting complex brackets (for brackets-highlighter): 9. $(( as argument
_FAST_COMPLEX_BRACKETS+=( $__start $(( __start + 1 )) )
# ADD
[[ $__arg[-2,-1] == '))' ]] && (( __start=_end_pos-__PBUFLEN-2, __end=__start+2, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}")
# Counting complex brackets (for brackets-highlighter): 10. )) for as-argument $((
_FAST_COMPLEX_BRACKETS+=( $__start $(( __start + 1 )) )
;;
'`'*)
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}back-quoted-argument]}")
if [[ -n ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}secondary]} ]]; then
__idx=1
_mybuf=$FAST_THEME_NAME
FAST_THEME_NAME=${${${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}secondary]}:t:r}#(XDG|LOCAL|HOME|OPT):}
(( ${+FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}default]} )) || source $FAST_WORK_DIR/secondary_theme.zsh
else
__idx=0
fi
(( _start_pos-__PBUFLEN >= 0 )) && \
-fast-highlight-process "$PREBUFFER" "${${__arg%[\`]}#[\`]}" $(( _start_pos + 1 ))
(( __idx )) && FAST_THEME_NAME=$_mybuf
already_added=1
;;
'((') # 'F' - (( after for
(( this_word & 32 )) && {
braces_stack='F'$braces_stack
__style=${FAST_THEME_NAME}double-paren
# Counting complex brackets (for brackets-highlighter): 11. (( as for-syntax
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN+1 )) )
# This is set after __arg_type == 2, and also here,
# when another alternate-syntax capable command occurs
__delimited=1
}
;;
'))') # 'F' - (( after for
[[ $braces_stack = F* ]] && {
braces_stack=${braces_stack#F}
__style=${FAST_THEME_NAME}double-paren
# Counting complex brackets (for brackets-highlighter): 12. )) as for-syntax
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN+1 )) )
(( __delimited = __delimited ? 2 : __delimited ))
}
;;
'<<<')
(( next_word = (next_word | 128) & ~3 ))
[[ ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-tri]} != "none" ]] && (( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-tri]}")
already_added=1
;;
*) # F - (( after for
if [[ $braces_stack = F* ]]; then
-fast-highlight-string
_mybuf=$__arg
__idx=_start_pos
while [[ $_mybuf = (#b)[^a-zA-Z\{\$]#([a-zA-Z][a-zA-Z0-9]#)(*) ]]; do
(( __start=__idx-__PBUFLEN+${mbegin[1]}-1, __end=__idx-__PBUFLEN+${mend[1]}+1-1, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-variable]}")
__idx+=${mend[1]}
_mybuf=${match[2]}
done
_mybuf=$__arg
__idx=_start_pos
while [[ $_mybuf = (#b)[^+\<\>=:\*\|\&\^\~-]#([+\<\>=:\*\|\&\^\~-]##)(*) ]]; do
(( __start=__idx-__PBUFLEN+${mbegin[1]}-1, __end=__idx-__PBUFLEN+${mend[1]}+1-1, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-operator]}")
__idx+=${mend[1]}
_mybuf=${match[2]}
done
_mybuf=$__arg
__idx=_start_pos
while [[ $_mybuf = (#b)[^0-9]#([0-9]##)(*) ]]; do
(( __start=__idx-__PBUFLEN+${mbegin[1]}-1, __end=__idx-__PBUFLEN+${mend[1]}+1-1, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-number]}")
__idx+=${mend[1]}
_mybuf=${match[2]}
done
if [[ $__arg = (#b)[^\;]#(\;)[\ ]# ]]; then
(( __start=_start_pos-__PBUFLEN+${mbegin[1]}-1, __end=_start_pos-__PBUFLEN+${mend[1]}+1-1, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-separator]}")
fi
already_added=1
elif [[ $__arg = *([^\\][\#][\#]|"(#b)"|"(#B)"|"(#m)"|"(#c")* ]]; then
(( highlight_glob )) && __style=${FAST_THEME_NAME}globbing-ext || __style=${FAST_THEME_NAME}default
elif [[ $__arg = ([*?]*|*[^\\][*?]*) ]]; then
(( highlight_glob )) && __style=${FAST_THEME_NAME}globbing || __style=${FAST_THEME_NAME}default
elif [[ $__arg = \$* ]]; then
__style=${FAST_THEME_NAME}variable
elif [[ $__arg = $'\x7d' && $braces_stack = Y* && ${FAST_HIGHLIGHT[right_brace_is_recognised_everywhere]} = "1" ]]; then
# right brace, i.e. $'\x7d' == '}'
# Parsing rule: # {
#
# Additionally, `tt(})' is recognized in any position if neither the
# tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set."""
braces_stack=${braces_stack#Y}
__style=${FAST_THEME_NAME}reserved-word
(( next_word = next_word | 16 ))
elif [[ $__arg = (';;'|';&'|';|') ]] && (( this_word & BIT_case_code )); then
(( next_word = (next_word | BIT_case_item) & ~(BIT_case_code+3) ))
__style=${FAST_THEME_NAME}default
elif [[ $__arg = ${histchars[1]}* && -n ${__arg[2]} ]]; then
__style=${FAST_THEME_NAME}history-expansion
elif (( __arg_type == 3 )); then
__style=${FAST_THEME_NAME}commandseparator
elif (( in_redirection == 2 )); then
__style=${FAST_THEME_NAME}redirection
elif (( ${+galiases[(e)$__arg]} )); then
__style=${FAST_THEME_NAME}global-alias
else
if [[ ${FAST_HIGHLIGHT[no_check_paths]} != 1 ]]; then
if [[ ${FAST_HIGHLIGHT[use_async]} != 1 ]]; then
if -fast-highlight-check-path noasync; then
# ADD
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}")
already_added=1
# TODO: path separators, optimize and add to async code-path
[[ -n ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]} && ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path]} != ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]} ]] && {
for (( __pos = _start_pos; __pos <= _end_pos; __pos++ )) ; do
# ADD
[[ ${__buf[__pos]} == "/" ]] && (( __start=__pos-__PBUFLEN, __start >= 0 )) && reply+=("$(( __start - 1 )) $__start ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]}")
done
}
else
__style=${FAST_THEME_NAME}default
fi
else
if [[ -z ${FAST_HIGHLIGHT[cache-path-${(q)__arg}-${_start_pos}]} || $(( EPOCHSECONDS - FAST_HIGHLIGHT[cache-path-${(q)__arg}-${_start_pos}-born-at] )) -gt 8 ]]; then
if [[ $LASTWIDGET != *-or-beginning-search ]]; then
exec {PCFD}< <(-fast-highlight-check-path; sleep 5)
command sleep 0
FAST_HIGHLIGHT[path-queue]+=";$_start_pos $_end_pos;"
is-at-least 5.0.6 && __pos=1 || __pos=0
zle -F ${${__pos:#0}:+-w} $PCFD fast-highlight-check-path-handler
already_added=1
else
__style=${FAST_THEME_NAME}default
fi
elif [[ ${FAST_HIGHLIGHT[cache-path-${(q)__arg}-${_start_pos}]%D} -eq 1 ]]; then
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path${${(M)FAST_HIGHLIGHT[cache-path-${(q)__arg}-${_start_pos}]%D}:+-to-dir}]}")
already_added=1
else
__style=${FAST_THEME_NAME}default
fi
fi
else
__style=${FAST_THEME_NAME}default
fi
fi
;;
esac
elif (( this_word & 128 ))
then
(( next_word = (next_word | 2) & ~129 ))
[[ ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-text]} != "none" ]] && (( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-text]}")
-fast-highlight-string ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-var]:#none}
already_added=1
elif (( this_word & (BIT_case_preamble + BIT_case_item) ))
then
if (( this_word & BIT_case_preamble )); then
[[ $__arg = "in" ]] && {
__style=${FAST_THEME_NAME}reserved-word
(( next_word = BIT_case_item ))
} || {
__style=${FAST_THEME_NAME}case-input
(( next_word = BIT_case_preamble ))
}
else
if (( this_word & BIT_case_nempty_item == 0 )) && [[ $__arg = "esac" ]]; then
(( next_word = 1 ))
__style=${FAST_THEME_NAME}reserved-word
elif [[ $__arg = (\(*\)|\)|\() ]]; then
[[ $__arg = *\) ]] && (( next_word = BIT_case_code | 1 )) || (( next_word = BIT_case_item | BIT_case_nempty_item ))
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) )
(( ${#__arg} > 1 )) && {
_FAST_COMPLEX_BRACKETS+=( $(( _start_pos+${#__arg}-1-__PBUFLEN )) )
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-parentheses]}")
(( __start=_start_pos+1-__PBUFLEN, __end=_end_pos-1-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-condition]}")
already_added=1
} || {
__style=${FAST_THEME_NAME}case-parentheses
}
else
(( next_word = BIT_case_item | BIT_case_nempty_item ))
__style=${FAST_THEME_NAME}case-condition
fi
fi
fi
if [[ $__arg = (#b)*'#'(([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])|([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F]))* || $__arg = (#b)*'rgb('(([0-9a-fA-F][0-9a-fA-F](#c0,1)),([0-9a-fA-F][0-9a-fA-F](#c0,1)),([0-9a-fA-F][0-9a-fA-F](#c0,1)))* ]]; then
if [[ -n $match[2] ]]; then
if [[ $match[2] = ?? || $match[3] = ?? || $match[4] = ?? ]]; then
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end bg=#${(l:2::0:)match[2]}${(l:2::0:)match[3]}${(l:2::0:)match[4]}")
else
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end bg=#$match[2]$match[3]$match[4]")
fi
else
(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end bg=#$match[5]$match[6]$match[7]")
fi
already_added=1
fi
# ADD
(( already_added == 0 )) && [[ ${FAST_HIGHLIGHT_STYLES[$__style]} != "none" ]] && (( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}")
if (( (__arg_type == 3) && ((this_word & (BIT_case_preamble|BIT_case_item)) == 0) )); then
if [[ $__arg == ';' ]] && (( in_array_assignment )); then
# literal newline inside an array assignment
(( next_word = 2 | (next_word & BIT_case_code) ))
elif [[ -n ${braces_stack[(r)A]} ]]; then
# 'A' in stack -> inside [[ ... ]]
(( next_word = 2 | (next_word & BIT_case_code) ))
else
braces_stack=${braces_stack#T}
(( next_word = 1 | (next_word & BIT_case_code) ))
highlight_glob=1
# A new command means that we should not expect that alternate
# syntax will occur (this is also in the ';' short-path), but
# || and && mean going down just 1 step, not all the way to 0
[[ $__arg != ("||"|"&&") ]] && __delimited=0 || (( __delimited = __delimited == 2 ? 1 : __delimited ))
fi
elif (( ( (__arg_type == 1) || (__arg_type == 2) ) && (this_word & 1) )); then # (( __arg_type == 1 || __arg_type == 2 )) && (( this_word & 1 ))
__delimited=1
(( next_word = 1 | (next_word & (64 | BIT_case_code)) ))
elif [[ $__arg == "repeat" ]] && (( this_word & 1 )); then
__delimited=1
# skip the repeat-count word
in_redirection=2
# The redirection mechanism assumes $this_word describes the word
# following the redirection. Make it so.
#
# That word can be a command word with shortloops (`repeat 2 ls`)
# or a command separator (`repeat 2; ls` or `repeat 2; do ls; done`).
#
# The repeat-count word will be handled like a redirection target.
(( this_word = 3 ))
fi
_start_pos=$_end_pos
# This is the default/common codepath.
(( this_word = in_redirection == 0 ? next_word : this_word )) #else # Stall $this_word.
done
# Do we have whole buffer? I.e. start at zero
[[ $3 != 0 ]] && return 0
# The loop overwrites ")" with "x", except those from $( ) substitution
#
# __pos: current nest level, starts from 0
# __workbuf: copy of __buf, with limit on 250 characters
# __idx: index in whole command line buffer
# __list: list of coordinates of ) which shouldn't be ovewritten
_mybuf=${__buf[1,250]} __workbuf=$_mybuf __idx=0 __pos=0 __list=()
while [[ $__workbuf = (#b)[^\(\)]#([\(\)])(*) ]]; do
if [[ ${match[1]} == \( ]]; then
__arg=${_mybuf[__idx+${mbegin[1]}-1,__idx+${mbegin[1]}-1+2]}
[[ $__arg = '$('[^\(] ]] && __list+=( $__pos )
[[ $__arg = '$((' ]] && _mybuf[__idx+${mbegin[1]}-1]=x
# Increase parenthesis level
__pos+=1
else
# Decrease parenthesis level
__pos=__pos-1
[[ -z ${__list[(r)$__pos]} ]] && [[ $__pos -gt 0 ]] && _mybuf[__idx+${mbegin[1]}]=x
fi
__idx+=${mbegin[2]}-1
__workbuf=${match[2]}
done
# Run on fake buffer with replaced parentheses: ")" into "x"
if [[ "$_mybuf" = *$__nul* ]]; then
# Try to avoid conflict with the \0, however
# we have to split at *some* character - \7
# is ^G, so one cannot have null and ^G at
# the same time on the command line
__nul=$'\7'
fi
__inputs=( ${(ps:$__nul:)${(S)_mybuf//(#b)*\$\(([^\)]#)(\)|(#e))/${mbegin[1]};${mend[1]}${__nul}}%$__nul*} )
if [[ "${__inputs[1]}" != "$_mybuf" && -n "${__inputs[1]}" ]]; then
if [[ -n ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}secondary]} ]]; then
__idx=1
__tmp=$FAST_THEME_NAME
FAST_THEME_NAME=${${${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}secondary]}:t:r}#(XDG|LOCAL|HOME|OPT):}
(( ${+FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}default]} )) || source $FAST_WORK_DIR/secondary_theme.zsh
else
__idx=0
fi
for _mybuf in $__inputs; do
(( __start=${_mybuf%%;*}-__PBUFLEN-1, __end=${_mybuf##*;}-__PBUFLEN, __start >= 0 )) && \
reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${__tmp}recursive-base]}")
# Pass authentic buffer for recursive analysis
-fast-highlight-process "$PREBUFFER" "${__buf[${_mybuf%%;*},${_mybuf##*;}]}" $(( ${_mybuf%%;*} - 1 ))
done
# Restore theme
(( __idx )) && FAST_THEME_NAME=$__tmp
fi
return 0
}
-fast-highlight-check-path()
{
(( _start_pos-__PBUFLEN >= 0 )) || \
{ [[ $1 != "noasync" ]] && print -r -- "- $_start_pos $_end_pos"; return 1; }
[[ $1 != "noasync" ]] && {
print -r -- ${sysparams[pid]}
# This is to fill cache
print -r -- $__arg
}
: ${expanded_path:=${(Q)~__arg}}
[[ -n ${FAST_BLIST_PATTERNS[(k)${${(M)expanded_path:#/*}:-$PWD/$expanded_path}]} ]] && { [[ $1 != "noasync" ]] && print -r -- "- $_start_pos $_end_pos"; return 1; }
[[ -z $expanded_path ]] && { [[ $1 != "noasync" ]] && print -r -- "- $_start_pos $_end_pos"; return 1; }
[[ -d $expanded_path ]] && { [[ $1 != "noasync" ]] && print -r -- "$_start_pos ${_end_pos}D" || __style=${FAST_THEME_NAME}path-to-dir; return 0; }
[[ -e $expanded_path ]] && { [[ $1 != "noasync" ]] && print -r -- "$_start_pos $_end_pos" || __style=${FAST_THEME_NAME}path; return 0; }
# Search the path in CDPATH, only for CD command
[[ $active_command = "cd" ]] && for cdpath_dir in $cdpath; do
[[ -d $cdpath_dir/$expanded_path ]] && { [[ $1 != "noasync" ]] && print -r -- "$_start_pos ${_end_pos}D" || __style=${FAST_THEME_NAME}path-to-dir; return 0; }
[[ -e $cdpath_dir/$expanded_path ]] && { [[ $1 != "noasync" ]] && print -r -- "$_start_pos $_end_pos" || __style=${FAST_THEME_NAME}path; return 0; }
done
# It's not a path.
[[ $1 != "noasync" ]] && print -r -- "- $_start_pos $_end_pos"
return 1
}
-fast-highlight-check-path-handler() {
local IFS=$'\n' pid PCFD=$1 line stripped val
integer idx
if read -r -u $PCFD pid; then
if read -r -u $PCFD val; then
if read -r -u $PCFD line; then
stripped=${${line#- }%D}
FAST_HIGHLIGHT[cache-path-${(q)val}-${stripped%% *}-born-at]=$EPOCHSECONDS
idx=${${FAST_HIGHLIGHT[path-queue]}[(I)$stripped]}
(( idx > 0 )) && {
if [[ $line != -* ]]; then
FAST_HIGHLIGHT[cache-path-${(q)val}-${stripped%% *}]="1${(M)line%D}"
region_highlight+=("${line%% *} ${${line##* }%D} ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path${${(M)line%D}:+-to-dir}]}")
else
FAST_HIGHLIGHT[cache-path-${(q)val}-${stripped%% *}]=0
fi
val=${FAST_HIGHLIGHT[path-queue]}
val[idx-1,idx+${#stripped}]=""
FAST_HIGHLIGHT[path-queue]=$val
[[ ${FAST_HIGHLIGHT[cache-path-${(q)val}-${stripped%% *}]%D} = 1 && ${#val} -le 27 ]] && zle -R
}
fi
fi
kill -9 $pid 2>/dev/null
fi
zle -F -w ${PCFD}
exec {PCFD}<&-
}
zle -N -- fast-highlight-check-path-handler -fast-highlight-check-path-handler
# Highlight special blocks inside double-quoted strings
#
# The while [[ ... ]] pattern is logically ((A)|(B)|(C)|(D)|(E))(*), where:
# - A matches $var[abc]
# - B matches ${(...)var[abc]}
# - C matches $
# - D matches \$ or \" or \'
# - E matches \*
#
# and the first condition -n ${match[7] uses D to continue searching when
# backslash-something (not ['"$]) is occured.
#
# $1 - additional style to glue-in to added style
-fast-highlight-string()
{
(( _start_pos-__PBUFLEN >= 0 )) || return 0
_mybuf=$__arg
__idx=_start_pos
# 7 8
while [[ $_mybuf = (#b)[^\$\\]#((\$(#B)([#+^=~](#c1,2))(#c0,1)(#B)([a-zA-Z_:][a-zA-Z0-9_:]#|[0-9]##)(#b)(\[[^\]]#\])(#c0,1))|(\$[{](#B)([#+^=~](#c1,2))(#c0,1)(#b)(\([a-zA-Z0-9_:@%#]##\))(#c0,1)[a-zA-Z0-9_:#]##(\[[^\]]#\])(#c0,1)[}])|\$|[\\][\'\"\$]|[\\](*))(*) ]]; do
[[ -n ${match[7]} ]] && {
# Skip following char it is quoted. Choice is
# made to not highlight such quoting
__idx+=${mbegin[1]}+1
_mybuf=${match[7]:1}
} || {
__idx+=${mbegin[1]}-1
_end_idx=__idx+${mend[1]}-${mbegin[1]}+1
_mybuf=${match[8]}
# ADD
(( __start=__idx-__PBUFLEN, __end=_end_idx-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${${1:+$1}:-${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}back-or-dollar-double-quoted-argument]}}")
__idx=_end_idx
}
done
return 0
}
# Highlight math and non-math context variables inside $(( )) and (( ))
#
# The while [[ ... ]] pattern is logically ((A)|(B)|(C)|(D))(*), where:
# - A matches $var[abc]
# - B matches ${(...)var[abc]}
# - C matches $
# - D matches words [a-zA-Z]## (variables)
#
# Parameters used: _mybuf, __idx, _end_idx, __style
-fast-highlight-math-string()
{
(( _start_pos-__PBUFLEN >= 0 )) || return 0
_mybuf=$__arg
__idx=_start_pos
# 7
while [[ $_mybuf = (#b)[^\$_a-zA-Z0-9]#((\$(#B)(+|)(#B)([a-zA-Z_:][a-zA-Z0-9_:]#|[0-9]##)(#b)(\[[^\]]##\])(#c0,1))|(\$[{](#B)(+|)(#b)(\([a-zA-Z0-9_:@%#]##\))(#c0,1)[a-zA-Z0-9_:#]##(\[[^\]]##\])(#c0,1)[}])|\$|[a-zA-Z_][a-zA-Z0-9_]#|[0-9]##)(*) ]]; do
__idx+=${mbegin[1]}-1
_end_idx=__idx+${mend[1]}-${mbegin[1]}+1
_mybuf=${match[7]}
[[ ${match[1]} = [0-9]* ]] && __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathnum]} || {
[[ ${match[1]} = [a-zA-Z_]* ]] && {
[[ ${+parameters[${match[1]}]} = 1 || ${FAST_ASSIGNS_SEEN[${match[1]}]} = 1 ]] && \
__style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathvar]} || \
__style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}matherr]}
} || {
[[ ${match[1]} = "$"* ]] && {
match[1]=${match[1]//[\{\}+]/}
if [[ ${match[1]} = "$" || ${FAST_ASSIGNS_SEEN[${match[1]:1}]} = 1 ]] || \
{ eval "[[ -n \${(P)\${match[1]:1}} ]]" } 2>> /dev/null; then
__style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}back-or-dollar-double-quoted-argument]}
else
__style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}matherr]}
fi
}
}
}
# ADD
[[ $__style != "none" && -n $__style ]] && (( __start=__idx-__PBUFLEN, __end=_end_idx-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end $__style")
__idx=_end_idx
done
}
# Highlight special chars inside dollar-quoted strings
-fast-highlight-dollar-string()
{
(( _start_pos-__PBUFLEN >= 0 )) || return 0
local i j k __style
local AA
integer c
# Starting dollar-quote is at 1:2, so __start parsing at offset 3 in the string.
for (( i = 3 ; i < _end_pos - _start_pos ; i += 1 )) ; do
(( j = i + _start_pos - 1 ))
(( k = j + 1 ))
case ${__arg[$i]} in
"\\") __style=${FAST_THEME_NAME}back-dollar-quoted-argument
for (( c = i + 1 ; c <= _end_pos - _start_pos ; c += 1 )); do
[[ ${__arg[$c]} != ([0-9xXuUa-fA-F]) ]] && break
done
AA=$__arg[$i+1,$c-1]
# Matching for HEX and OCT values like \0xA6, \xA6 or \012
if [[ "$AA" == (#m)(#s)(x|X)[0-9a-fA-F](#c1,2)
|| "$AA" == (#m)(#s)[0-7](#c1,3)
|| "$AA" == (#m)(#s)u[0-9a-fA-F](#c1,4)
|| "$AA" == (#m)(#s)U[0-9a-fA-F](#c1,8)
]]; then
(( k += MEND ))
(( i += MEND ))
else
if (( __asize > i+1 )) && [[ $__arg[i+1] == [xXuU] ]]; then
# \x not followed by hex digits is probably an error
__style=${FAST_THEME_NAME}unknown-token
fi
(( k += 1 )) # Color following char too.
(( i += 1 )) # Skip parsing the escaped char.
fi
;;
*) continue ;;
esac
# ADD
(( __start=j-__PBUFLEN, __end=k-__PBUFLEN, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}")
done
}
-fast-highlight-init() {
_FAST_COMPLEX_BRACKETS=()
__fast_highlight_main__command_type_cache=()
}
typeset -ga FSH_LIST
-fsh_sy_h_shappend() {
FSH_LIST+=( "$(( $1 - 1 ));;$(( $2 ))" )
}
functions -M fsh_sy_h_append 2 2 -fsh_sy_h_shappend 2>/dev/null
# vim:ft=zsh:sw=2:sts=2