diff options
Diffstat (limited to '.config')
64 files changed, 9371 insertions, 1 deletions
diff --git a/.config/shell/.zshrc b/.config/shell/.zshrc index ecb00cc..d397f44 100644 --- a/.config/shell/.zshrc +++ b/.config/shell/.zshrc @@ -1,8 +1,9 @@ # source zsh extensions (order is important) source ~/.config/shell/zsh-autosuggestions/zsh-autosuggestions.zsh -source ~/.config/shell/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +source ~/.config/shell/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh source ~/.config/shell/git-prompt.zsh source ~/.config/shell/git-prompts/kj_sh604.zsh +# source ~/.config/shell/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh # configure history settings diff --git a/.config/shell/zsh-fast-syntax-highlighting/-fast-make-targets b/.config/shell/zsh-fast-syntax-highlighting/-fast-make-targets new file mode 100644 index 0000000..7f905d6 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/-fast-make-targets @@ -0,0 +1,98 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Almost all code borrowed from Zshell's _make function +# +# Copyright (c) 2018 Sebastian Gniazdowski + +local -a TARGETS + +_make-expandVars() { + local open close var val front='' rest=$1 + + while [[ $rest == (#b)[^$]#($)* ]]; do + front=$front${rest[1,$mbegin[1]-1]} + rest=${rest[$mbegin[1],-1]} + + case $rest[2] in + ($) # '$$'. may not appear in target and variable's value + front=$front\$\$ + rest=${rest[3,-1]} + continue + ;; + (\() # Variable of the form $(foobar) + open='(' + close=')' + ;; + ({) # ${foobar} + open='{' + close='}' + ;; + ([[:alpha:]]) # $foobar. This is exactly $(f)oobar. + open='' + close='' + var=$rest[2] + ;; + (*) # bad parameter name + print -- $front$rest + return 1 + ;; + esac + + if [[ -n $open ]]; then + if [[ $rest == \$$open(#b)([[:alnum:]_]##)(#B)$close* ]]; then + var=$match + else # unmatched () or {}, or bad parameter name + print -- $front$rest + return 1 + fi + fi + + val='' + if [[ -n ${VAR_ARGS[(i)$var]} ]]; then + val=${VAR_ARGS[$var]} + else + if [[ -n $opt_args[(I)(-e|--environment-overrides)] ]]; then + if [[ $parameters[$var] == scalar-export* ]]; then + val=${(P)var} + elif [[ -n ${VARIABLES[(i)$var]} ]]; then + val=${VARIABLES[$var]} + fi + else + if [[ -n ${VARIABLES[(i)$var]} ]]; then + val=${VARIABLES[$var]} + elif [[ $parameters[$var] == scalar-export* ]]; then + val=${(P)var} + fi + fi + fi + rest=${rest//\$$open$var$close/$val} + done + + print -- ${front}${rest} +} + + +_make-parseMakefile () { + local input var val target dep TAB=$'\t' tmp IFS= + + while read input + do + case "$input " in + # TARGET: dependencies + # TARGET1 TARGET2 TARGET3: dependencies + ([[*?[:alnum:]$][^$TAB:=%]#:[^=]*) + target=$(_make-expandVars ${input%%:*}) + TARGETS+=( ${(z)target} ) + ;; + esac + done +} + +if [[ -z "${FAST_HIGHLIGHT[chroma-make-cache]}" || $(( EPOCHSECONDS - FAST_HIGHLIGHT[chroma-make-cache-born-at] )) -gt 7 ]]; then + _make-parseMakefile + FAST_HIGHLIGHT[chroma-make-cache-born-at]="$EPOCHSECONDS" + FAST_HIGHLIGHT[chroma-make-cache]="${(j:;:)TARGETS}" +fi + +reply2=( "${(s:;:)FAST_HIGHLIGHT[chroma-make-cache]}" ) + +# vim:ft=zsh:et diff --git a/.config/shell/zsh-fast-syntax-highlighting/-fast-run-command b/.config/shell/zsh-fast-syntax-highlighting/-fast-run-command new file mode 100644 index 0000000..e251bcc --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/-fast-run-command @@ -0,0 +1,37 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# FAST_HIGHLIGHT hash serves as container for variables that +# prevents creating them in global scope. (P) flag is not used, +# output array is fixed (__lines_list). +# +# $1 - the command, e.g. "git remote"; 2>/dev/null redirection is +# added automatically +# $2 - FAST_HIGHLIGHT field name, e.g. "chroma-git-branches"; two +# additional fields will be used, $2-cache, $2-cache-born-at +# $3 - what to remove from beginning of the lines returned by the +# command +# $4 - cache validity time, default 5 (seconds) +# +# Output: array __lines_list, with output of the command ran + +# User should not forget to define this array, the below code +# will only ensure that it's array (can also define a global) +typeset -ga __lines_list +local -a __response + +if [[ -z "${FAST_HIGHLIGHT[$2-cache]}" || $(( EPOCHSECONDS - FAST_HIGHLIGHT[$2-cache-born-at] )) -gt ${4:-5} ]]; then + FAST_HIGHLIGHT[$2-cache-born-at]="$EPOCHSECONDS" + __response=( ${${(f)"$(command ${(Qz)1#+} 2>/dev/null)"}#${~3}} ) + [[ "$1" = "+"* ]] && __lines_list+=( "${__response[@]}" ) || __lines_list=( "${__response[@]}" ) + FAST_HIGHLIGHT[$2-cache]="${(j:;:)__response}" +else + # Quoted (s:;:) flag without @ will skip empty elements. It + # still produces array output, interesingly. All this is for + # the trailing ";" above, to skip last, empty element. + [[ "$1" = "+"* ]] && \ + __lines_list+=( "${(@s:;:)FAST_HIGHLIGHT[$2-cache]}" ) || \ + __lines_list=( "${(@s:;:)FAST_HIGHLIGHT[$2-cache]}" ) +fi + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/-fast-run-git-command b/.config/shell/zsh-fast-syntax-highlighting/-fast-run-git-command new file mode 100644 index 0000000..604cbea --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/-fast-run-git-command @@ -0,0 +1,47 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# It runs given command, which in general will be a git command, +# automatically looking at cache first (a field named *-cache, +# in FAST_HIGHLIGHT), which is valid for 5 seconds, and in case +# of outdated or not existing cache, runs the command, splitting +# on new-lines, first checking if PWD is inside git repository. +# +# FAST_HIGHLIGHT hash serves as container for variables that +# prevents creating them in global scope. (P) flag is not used, +# output array is fixed (__lines_list). +# +# $1 - the command, e.g. "git remote"; 2>/dev/null redirection is +# added automatically +# $2 - FAST_HIGHLIGHT field name, e.g. "chroma-git-branches"; two +# additional fields will be used, $2-cache, $2-cache-born-at +# $3 - what to remove from beginning of the lines returned by the +# command +# $4 - cache validity time, default 5 (seconds) +# +# Output: array __lines_list, with output of the (git) command ran + +# User should not forget to define this array, the below code +# will only ensure that it's array (can also define a global) +typeset -ga __lines_list +local -a __response + +if [[ -z "${FAST_HIGHLIGHT[$2-cache]}" || $(( EPOCHSECONDS - FAST_HIGHLIGHT[$2-cache-born-at] )) -gt ${4:-5} ]]; then + FAST_HIGHLIGHT[$2-cache-born-at]="$EPOCHSECONDS" + if [[ "$(command git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]]; then + __response=( ${${(f)"$(command ${(Qz)${1#+}} 2>/dev/null)"}#$3} ) + [[ "$1" = "+"* ]] && __lines_list+=( "${__response[@]}" ) || __lines_list=( "${__response[@]}" ) + else + __lines_list=() + fi + FAST_HIGHLIGHT[$2-cache]="${(j:;:)__response}" +else + # Quoted (s:;:) flag without @ will skip empty elements. It + # still produces array output, interesingly. All this is for + # the trailing ";" above, to skip last, empty element. + [[ "$1" = "+"* ]] && \ + __lines_list+=( "${(@s:;:)FAST_HIGHLIGHT[$2-cache]}" ) || \ + __lines_list=( "${(@s:;:)FAST_HIGHLIGHT[$2-cache]}" ) +fi + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/-fast-zts-read-all b/.config/shell/zsh-fast-syntax-highlighting/-fast-zts-read-all new file mode 100644 index 0000000..96c52ab --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/-fast-zts-read-all @@ -0,0 +1,17 @@ +# $1 - file-descriptor to be read from +# $2 - name of output variable (default: REPLY) + +local __in_fd=${1:-0} __out_var=${2:-REPLY} +local -a __tmp +integer __ret=1 __repeat=10 __tmp_size=0 + +while sysread -s 65535 -i "$__in_fd" '__tmp[__tmp_size + 1]'; do + (( ( __ret=$? ) == 0 )) && (( ++ __tmp_size )) + (( __ret == 5 )) && { __ret=0; (( --__repeat == 0 )) && break; } +done + +: ${(P)__out_var::="${(j::)__tmp}"} + +return __ret + +# vim: ft=zsh:et:sw=4:sts=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/.travis.yml b/.config/shell/zsh-fast-syntax-highlighting/.travis.yml new file mode 100644 index 0000000..351b593 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/.travis.yml @@ -0,0 +1,13 @@ +addons: + apt: + packages: + zsh +install: + - mkdir .bin + - curl -L https://github.com/zunit-zsh/zunit/releases/download/v0.8.2/zunit > .bin/zunit + - curl -L https://raw.githubusercontent.com/molovo/revolver/master/revolver > .bin/revolver + - curl -L https://raw.githubusercontent.com/molovo/color/master/color.zsh > .bin/color +before_script: + - chmod u+x .bin/{color,revolver,zunit} + - export PATH="$PWD/.bin:$PATH" +script: zunit diff --git a/.config/shell/zsh-fast-syntax-highlighting/.zunit.yml b/.config/shell/zsh-fast-syntax-highlighting/.zunit.yml new file mode 100644 index 0000000..e4fd57f --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/.zunit.yml @@ -0,0 +1,8 @@ +tap: false +directories: + tests: tests + output: tests/_output + support: tests/_support +time_limit: 0 +fail_fast: false +allow_risky: false diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-alias.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-alias.ch new file mode 100644 index 0000000..d581341 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-alias.ch @@ -0,0 +1,29 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +[[ "$__arg_type" = 3 ]] && return 2 + +local __first_call="$1" __wrd="${2%%=*}" __start_pos="$3" __end_pos="$4" + +if (( __first_call )) || [[ "$2" = -* ]]; then + return 1 +else + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + elif (( $+aliases[(e)$__wrd] )) || (( ${+galiases[(e)$__wrd]} )); then + (( __start=__start_pos-${#PREBUFFER}, __end=__start_pos+${#__wrd}-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + elif (( $+functions[(e)$__wrd] )) || (( $+builtins[(e)$__wrd] )) || (( $+commands[(e)$__wrd] )) || (( $reswords[(Ie)$__wrd] )); then + (( __start=__start_pos-${#PREBUFFER}, __end=__start_pos+${#__wrd}-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + else + return 1 + fi + if [[ "$__wrd" != "$2" ]]; then + return 1 + fi +fi + +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-autoload.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-autoload.ch new file mode 100644 index 0000000..78a8924 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-autoload.ch @@ -0,0 +1,104 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Tracks autoload command - highlights function names if they exist somewhere +# in $fpath. Also warns that the autoloaded function is already defined. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __chars +integer __idx1 __idx2 +local -a __results __deserialized __noshsplit + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-autoload-counter]=0 + FAST_HIGHLIGHT[chroma-autoload-counter-all]=1 + FAST_HIGHLIGHT[chroma-autoload-message]="" + #FAST_HIGHLIGHT[chroma-autoload-message-shown]="" + [[ -z ${FAST_HIGHLIGHT[chroma-autoload-message-shown-at]} ]] && FAST_HIGHLIGHT[chroma-autoload-message-shown-at]=0 + FAST_HIGHLIGHT[chroma-autoload-elements]="" + __style=${FAST_THEME_NAME}command + +} || { + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + (( FAST_HIGHLIGHT[chroma-autoload-counter-all] += 1, __idx2 = FAST_HIGHLIGHT[chroma-autoload-counter-all] )) + + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if [[ "$__wrd" = [-+]* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + else + # Count non-option tokens. + (( FAST_HIGHLIGHT[chroma-autoload-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-autoload-counter] )) + + if [[ $__wrd != (\$|\"\$)* && $__wrd != (/|\"/|\'/)* && $__wrd != \`* ]]; then + __results=( ${^fpath}/$__wrd(N) ) + __deserialized=( "${(Q@)${(z@)FAST_HIGHLIGHT[chroma-fpath_peq-elements]}}" ) + __results+=( ${^__deserialized}/$__wrd(N) ) + [[ "${#__results}" -gt 0 ]] && { + __style=${FAST_THEME_NAME}correct-subtle + __deserialized=( "${(Q@)${(z@)FAST_HIGHLIGHT[chroma-autoload-elements]}}" ) + [[ -z "${__deserialized[1]}" && ${#__deserialized} -eq 1 ]] && __deserialized=() + # Cannot use ${abc:+"$abc"} trick with ${~...}, so handle most + # cases of the possible shwordsplit through an additional array + __noshsplit=( ${~__wrd} ) + __deserialized+=( "${(j: :)__noshsplit}" ) + FAST_HIGHLIGHT[chroma-autoload-elements]="${(j: :)${(q@)__deserialized}}" + # Make the function defined for big-loop's *main-type mechanism + __fast_highlight_main__command_type_cache[${(j: :)__noshsplit}]="function" + } || __style=${FAST_THEME_NAME}incorrect-subtle + fi + + if (( ${+functions[${(Q)__wrd}]} )); then + FAST_HIGHLIGHT[chroma-autoload-message]+="Warning: Function ${(Q)__wrd} already defined (e.g. loaded)"$'\n' + fi + fi + + # Display only when processing last autoload argument + if (( ${#${(z)BUFFER}} == FAST_HIGHLIGHT[chroma-autoload-counter-all] )); then + # Display only if already shown message differs or when it timeouts + if [[ ${FAST_HIGHLIGHT[chroma-autoload-message]} != ${FAST_HIGHLIGHT[chroma-autoload-message-shown]} || + $(( EPOCHSECONDS - FAST_HIGHLIGHT[chroma-autoload-message-shown-at] )) -gt 7 + ]]; then + FAST_HIGHLIGHT[chroma-autoload-message-shown]=${FAST_HIGHLIGHT[chroma-autoload-message]} + FAST_HIGHLIGHT[chroma-autoload-message-shown-at]=$EPOCHSECONDS + zle -M "${FAST_HIGHLIGHT[chroma-autoload-message]}" + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above code +# can do it itself and skip setting __style to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-autorandr.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-autorandr.ch new file mode 100644 index 0000000..9687db3 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-autorandr.ch @@ -0,0 +1,22 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +[[ "$__arg_type" = 3 ]] && return 2 + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" + +if (( __first_call )) || [[ "$__wrd" = -* ]]; then + return 1 +else + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + if [[ -d "${XDG_CONFIG_HOME:-$HOME/.config}/autorandr/$__wrd" ]] then + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + fi +fi + +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-awk.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-awk.ch new file mode 100644 index 0000000..47b3ec7 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-awk.ch @@ -0,0 +1,108 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __chars __val __style2 +integer __idx1 __idx2 + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-awk-counter]=0 + FAST_HIGHLIGHT[chroma-awk-f-seen]=0 + return 1 +} || { + # Following call, i.e. not the first one. + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + [[ "$__wrd" = "-f" ]] && FAST_HIGHLIGHT[chroma-awk-f-seen]=1 + else + # Count non-option tokens. + (( FAST_HIGHLIGHT[chroma-awk-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-awk-counter] )) + + # First non-option token is the pattern (regex), we will + # highlight it. + if (( FAST_HIGHLIGHT[chroma-awk-counter] == 1 && FAST_HIGHLIGHT[chroma-awk-f-seen] == 0 )); then + if print -r -- "${(Q)__wrd}" | gawk --source 'BEGIN { exit } END { exit 0 }' -f - >/dev/null 2>&1; then + __style2="${FAST_THEME_NAME}subtle-bg" + else + __style2="${FAST_THEME_NAME}incorrect-subtle" + fi + + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style2]}") + + # Highlight keywords + FSH_LIST=() + : "${__wrd//(#m)(BEGIN|END|FIELDWIDTHS|RS|ARGC|ARGV|ENVIRON|NF|NR|IGNORECASE|FILENAME|if|then|else|while|toupper|tolower|function|print|sub)/$(( fsh_sy_h_append($MBEGIN, $MEND) ))}"; + for __val in "${FSH_LIST[@]}" ; do + [[ ${__wrd[${__val%%;;*}]} = [a-zA-Z0-9_] || ${__wrd[${__val##*;;}+1]} = [a-zA-Z0-9_] ]] && continue + __idx1=$(( __start_pos + ${__val%%;;*} )) + __idx2=__idx1+${__val##*;;}-${__val%%;;*}+1 + (( __start=__idx1-${#PREBUFFER}, __end=__idx2-${#PREBUFFER}-1, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}reserved-word]},${FAST_HIGHLIGHT_STYLES[$__style2]}") + done + + # Highlight regex characters + __chars="*+\\)(\{\}[]^" + __idx1=__start_pos + __idx2=__start_pos + while [[ "$__wrd" = (#b)[^$__chars]#([\\][\\])#((+|\*|\[|\]|\)|\(|\^|\}|\{)|[\\](+|\*|\[|\]|\)|\(|\^|\{|\}))(*) ]]; do + if [[ -n "${match[3]}" ]]; then + __idx1+=${mbegin[3]}-1 + __idx2=__idx1+${mend[3]}-${mbegin[3]}+1 + (( __start=__idx1-${#PREBUFFER}, __end=__idx2-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathnum]},${FAST_HIGHLIGHT_STYLES[$__style2]}") + __idx1=__idx2 + else + __idx1+=${mbegin[5]}-1 + fi + __wrd="${match[5]}" + done + elif (( FAST_HIGHLIGHT[chroma-awk-counter] >= 2 || FAST_HIGHLIGHT[chroma-awk-f-seen] == 1 )); then + FAST_HIGHLIGHT[chroma-awk-f-seen]=0 + # Handle paths, etc. normally - just pass-through to the big + # highlighter (the main FSH highlighter, used before chromas). + return 1 + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does) and skip setting __style +# to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-docker.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-docker.ch new file mode 100644 index 0000000..0a6a3bb --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-docker.ch @@ -0,0 +1,90 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma function for command `docker'. It verifies command line, by denoting +# wrong and good arguments by color. Currently implemented: verification of +# image IDs passed to: docker image rm <ID>. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 +local -a __lines_list + +(( __first_call )) && { + # Called for the first time - new command + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global variables + FAST_HIGHLIGHT[chroma-docker-counter]=0 + FAST_HIGHLIGHT[chroma-docker-got-subcommand]=0 + FAST_HIGHLIGHT[chroma-docker-subcommand]="" + FAST_HIGHLIGHT[chrome-docker-got-msg1]=0 + return 1 +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* && ${FAST_HIGHLIGHT[chroma-docker-got-subcommand]} -eq 0 ]]; then + __style=${FAST_THEME_NAME}${${${__wrd:#--*}:+single-hyphen-option}:-double-hyphen-option} + else + if (( FAST_HIGHLIGHT[chroma-docker-got-subcommand] == 0 )); then + FAST_HIGHLIGHT[chroma-docker-got-subcommand]=1 + FAST_HIGHLIGHT[chroma-docker-subcommand]="$__wrd" + __style=${FAST_THEME_NAME}subcommand + (( FAST_HIGHLIGHT[chroma-docker-counter] += 1 )) + else + __wrd="${__wrd//\`/x}" + __arg="${__arg//\`/x}" + __wrd="${(Q)__wrd}" + if [[ "${FAST_HIGHLIGHT[chroma-docker-subcommand]}" = "image" ]]; then + [[ "$__wrd" != -* ]] && { + (( FAST_HIGHLIGHT[chroma-docker-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-docker-counter] )) + + if (( __idx1 == 2 )); then + __style=${FAST_THEME_NAME}subcommand + elif (( __idx1 == 3 )); then + -fast-run-command "docker images -q" chroma-docker-list "" + [[ -n "${__lines_list[(r)$__wrd]}" ]] && { + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + } || { + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + } + fi + } || __style=${FAST_THEME_NAME}${${${__wrd:#--*}:+single-hyphen-option}:-double-hyphen-option} + else + return 1 + fi + fi + fi +} + +# Add region_highlight entry (via `reply' array) +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-example.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-example.ch new file mode 100644 index 0000000..8814922 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-example.ch @@ -0,0 +1,120 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Example chroma function. It colorizes first two arguments as `builtin' style, +# third and following arguments as `globbing' style. First two arguments may +# be "strings", they will be passed through to normal higlighter (by returning 1). +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# +# +# Overall functioning is: when command "example" is occured, this function +# is called with $1 == 1, it ("example") is the first token ($2), then for any +# following token, this function is called with $1 == 0, until end of command +# is occured (i.e. till enter is pressed or ";" is put into source, or the +# command line simply ends). +# +# Other tips are: +# - $CURSOR holds cursor position +# - $BUFFER holds whole command line buffer +# - $LBUFFER holds command line buffer that is left from the cursor, i.e. it's a +# BUFFER substring 1 .. $CURSOR +# - $RBUFFER is the same as LBUFFER but holds part of BUFFER right to the cursor +# +# The function receives $BUFFER but via sequence of tokens, which are shell words, +# e.g. "a b c" is a shell word, while a b c are 3 shell words. +# +# FAST_HIGHLIGHT is a friendly hash array which allows to store strings without +# creating global parameters (variables). If you need hash, just use it first +# declaring, under some distinct name like: typeset -gA CHROMA_EXPLE_DICT. +# Remember to reset the hash and others at __first_call == 1, so that you have +# a fresh state for new command. + +# Keep chroma-takever state meaning: until ;, handle highlighting via chroma. +# So the below 8192 assignment takes care that next token will be routed to chroma. +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global string variables. + FAST_HIGHLIGHT[chroma-example-counter]=0 + + # Set style for region_highlight entry. It is used below in + # '[[ -n "$__style" ]] ...' line, which adds highlight entry, + # like "10 12 fg=green", through `reply' array. + # + # Could check if command `example' exists and set `unknown-token' + # style instead of `command' + __style=${FAST_THEME_NAME}command + +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + else + # Count non-option tokens + (( FAST_HIGHLIGHT[chroma-example-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-example-counter] )) + + # Colorize 1..2 as builtin, 3.. as glob + if (( FAST_HIGHLIGHT[chroma-example-counter] <= 2 )); then + if [[ "$__wrd" = \"* ]]; then + # Pass through, fsh main code will do the highlight! + return 1 + else + __style=${FAST_THEME_NAME}builtin + fi + else + __style=${FAST_THEME_NAME}globbing + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# If 1 will be added to __start_pos, this will highlight "oken". +# If 1 will be subtracted from __end_pos, this will highlight "toke". +# $PREBUFFER is for specific situations when users does command \<ENTER> +# i.e. when multi-line command using backslash is entered. +# +# This is a common place of adding such entry, but any above code can do +# it itself (and it does in other chromas) and skip setting __style to +# this way disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves. +# _start_pos=$_end_pos advainces pointers in command line buffer. +# +# To pass through means to `return 1'. The highlighting of +# this single token is then done by fast-syntax-highlighting's +# main code and chroma doesn't have to do anything. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-fast-theme.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-fast-theme.ch new file mode 100644 index 0000000..15bc210 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-fast-theme.ch @@ -0,0 +1,40 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +[[ "$__arg_type" = 3 ]] && return 2 + +local __first_call="$1" __wrd="${(Q)2}" __start_pos="$3" __end_pos="$4" +local __style + +if (( __first_call )); then + FAST_HIGHLIGHT[chroma-fast-theme-first]=0 + return 1 +elif (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +elif (( ${FAST_HIGHLIGHT[chroma-fast-theme-first]} )) || [[ $__wrd = -* ]]; then + return 1 +else + FAST_HIGHLIGHT[chroma-fast-theme-first]=1 +fi + +if [[ "$__wrd" = */* || "$__wrd" = (XDG|LOCAL|HOME|OPT):* ]]; then + __wrd="${${__wrd/(#s)XDG:/${${XDG_CONFIG_HOME:-$HOME/.config}%/}/fsh/}%.ini}.ini" + __wrd="${${__wrd/(#s)LOCAL://usr/local/share/fsh/}%.ini}.ini" + __wrd="${${__wrd/(#s)HOME:/$HOME/.fsh/}%.ini}.ini" + __wrd="${${__wrd/(#s)OPT://opt/local/share/fsh/}%.ini}.ini" + __wrd=${~__wrd} # allow user to quote ~ +else + __wrd="$FAST_BASE_DIR/themes/$__wrd.ini" +fi + +if [[ -f $__wrd ]]; then + __style=${FAST_THEME_NAME}path +else + __style=${FAST_THEME_NAME}incorrect-subtle +fi + +(( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-fpath_peq.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-fpath_peq.ch new file mode 100644 index 0000000..072cee3 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-fpath_peq.ch @@ -0,0 +1,61 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# This chroma does a narrow, obscure but prestigious parsing of fpath+=( elem1 +# elem2 ... ) construct to provide *the* *future* contents of $fpath to +# -autoload.ch, so that it can detect functions in those provided directories +# `elem1', `elem2', etc. and highlight the functions with `correct-subtle' +# instead of `incorrect-subtle'. Basically all thit is for command-lines like: +# +# % fpath+=( `pwd` ); autoload my-fun-from-PWD + +# Keep chroma-takever state meaning: until ; or similar (see $__arg_type below) +# The 8192 sum takes care that the next token will be routed to this chroma +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local -a deserialized + +(( __first_call )) && { + case $__wrd in + (fpath=\() + FAST_HIGHLIGHT[fpath_peq_mode]=1 + ;; + (fpath+=\() + FAST_HIGHLIGHT[fpath_peq_mode]=2 + ;; + (FPATH=) + FAST_HIGHLIGHT[fpath_peq_mode]=4 + ;; + (FPATH+=) + FAST_HIGHLIGHT[fpath_peq_mode]=8 + ;; + esac + if (( FAST_HIGHLIGHT[fpath_peq_mode] & 5 )); then + FAST_HIGHLIGHT[chroma-fpath_peq-elements]="! ${FAST_HIGHLIGHT[chroma-fpath_peq-elements]}" + fi + return 1 +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + [[ "$__wrd" != ")" ]] && { + deserialized=( "${(Q@)${(z@)FAST_HIGHLIGHT[chroma-fpath_peq-elements]}}" ) + [[ -z "${deserialized[1]}" && ${#deserialized} -eq 1 ]] && deserialized=() + # Support ~ and $VAR, for [a-zA-Z_][a-ZA-Z0-9_]# characters in "VAR" + deserialized+=( "${(Q)${${(j: :)__wrd}//(#b)((\$([0-9]##|[a-zA-Z_][a-zA-Z0-9_]#))|(\$\{([0-9]##|[a-zA-Z_][a-zA-Z0-9_]#)\})|(#s)~)/${(P)${${${${match[1]##\$\{(#c0,1)}%\}}:#\~}:-HOME}}}}" ) + FAST_HIGHLIGHT[chroma-fpath_peq-elements]="${(j: :)${(q@)deserialized}}" + } + + return 1 +} + +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-git.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-git.ch new file mode 100644 index 0000000..bf5fbe5 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-git.ch @@ -0,0 +1,945 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma function for command `git'. It colorizes the part of command +# line that holds `git' invocation. + +(( FAST_HIGHLIGHT[-git.ch-chroma-def] )) && return 1 + +FAST_HIGHLIGHT[-git.ch-chroma-def]=1 + +typeset -gA fsh__git__chroma__def +fsh__git__chroma__def=( + ## + ## No subcommand + ## + ## {{{ + + subcmd:NULL "NULL_0_opt" + NULL_0_opt "(-C|--exec-path=|--git-dir=|--work-tree=|--namespace=|--super-prefix=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || -c + <<>> __style=\${FAST_THEME_NAME}single-hyphen-option // NO-OP + <<>> __style=\${FAST_THEME_NAME}optarg-string // NO-OP + || (--version|--help|--html-path|--man-path|--info-path|-p|--paginate| + -P|--no-pager|--no-replace-objects|--bare) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + + "subcommands" ":::chroma/-git-get-subcommands" # run a function (the :: causes this) and use `reply' + #"subcommands" "(fetch|pull)" # run a function (the :: causes this) and use `reply' + + "subcmd-hook" ":chroma/-git-check-if-alias" + + ## }}} + + ## + ## `FETCH' + ## + ## {{{ + + subcmd:fetch "FETCH_MULTIPLE_0_opt^ // FETCH_ALL_0_opt^ // FETCH_0_opt // + REMOTE_GR_1_arg // REF_#_arg // NO_MATCH_#_opt" + + # Special options (^ - has directives, currently - an :add and :del directive) + "FETCH_MULTIPLE_0_opt^" " + --multiple + <<>> __style=\${FAST_THEME_NAME}double-hyphen-option // NO-OP + || --multiple:add + <<>> REMOTE_GR_#_arg + || --multiple:del + <<>> REMOTE_GR_1_arg // REF_#_arg" # when --multiple is passed, then + # there is no refspec argument, only remotes-ids + # follow unlimited # of them, hence the # in the + # REMOTE_GR_#_arg + + # Special options (^ - has directives - an :del-directive) + "FETCH_ALL_0_opt^" " + --all + <<>> __style=\${FAST_THEME_NAME}double-hyphen-option // NO-OP + || --all:del + <<>> REMOTE_GR_1_arg // REF_#_arg" # --all can be only followed by options + + # FETCH_0_opt. FETCH-options (FETCH is an identifier) at position 0 -> + # -> before any argument + FETCH_0_opt " + (--depth=|--deepen=|--shallow-exclude=|--shallow-since=|--receive-pack=| + --refmap=|--recurse-submodules=|-j|--jobs=|--submodule-prefix=| + --recurse-submodules-default=|-o|--server-option=|--upload-pack| + --negotiation-tip=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (--help|--all|-a|--append|--unshallow|--update-shallow|--dry-run|-f|--force| + -k|--keep|--multiple|-p|--prune|-n|--no-tags|-t|--tags|--no-recurse-submodules| + -u|--update-head-ok|-q|--quiet|-v|--verbose|--progress| + -4|--ipv4|-6|--ipv6) + <<>> __style=\${FAST_THEME_NAME}single-hyphen-option // NO-OP" + # Above: note the two <<>>-separated blocks for options that have + # some arguments – the second pair of action/handler is being + # run when an option argument is occurred (first one: the option + # itself). If there is only one <<>>-separated block, then the option + # is set to be argument-less. The argument is a) -o/--option argument + # and b) -o/--option=argument. + + REMOTE_GR_1_arg "NO-OP // :::chroma/-git-verify-remote-or-group" # This definition is generic, reused later + "REF_#_arg" "NO-OP // :::chroma/-git-verify-ref" # This too + "REMOTE_GR_#_arg" "NO-OP // :::chroma/-git-verify-remote-or-group" # and this too + # The hash `#' above denotes: an argument at any position + # It will nicely match any following (above the first explicitly + # numbered ones) arguments passed when using --multiple + + # A generic action + NO_MATCH_\#_opt "* <<>> __style=\${FAST_THEME_NAME}incorrect-subtle // NO-OP" + NO_MATCH_\#_arg "__style=\${FAST_THEME_NAME}incorrect-subtle // NO-OP" + + ## }}} + + ## + ## PUSH + ## + ## {{{ + + subcmd:push "PUSH_0_opt // REMOTE_1_arg // REF_#_arg // NO_MATCH_#_opt" + + PUSH_0_opt " + (--receive-pack=|--exec=|--repo=|--push-option=|--signed=| + --force-with-lease=|--signed=|--recurse-submodules=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (--help|--all|--mirror|--tags|--follow-tags|--atomic|-n|--dry-run| + --porcelain|--delete|--tags|--follow-tags|--signed|--no-signed| + --atomic|--no-atomic|-o|--push-option|--force-with-lease| + --no-force-with-lease|-f|--force|-u|--set-upstream|--thin| + --no-thin|-q|--quiet|-v|--verbose|--progress|--no-recurse-submodules| + --verify|--no-verify|-4|--ipv4|-6|--ipv6) + <<>> __style=\${FAST_THEME_NAME}single-hyphen-option // NO-OP" + + REMOTE_1_arg "NO-OP // :::chroma/-git-verify-remote" # This definition is generic, reused later + + ### }}} + + ## + ## PULL + ## + ## {{{ + + subcmd:pull "PULL_0_opt // REMOTE_1_arg // REF_#_arg // NO_MATCH_#_opt" + + PULL_0_opt " + (--recurse-submodules=|-S|--gpg-sign=|--log=|-s|--strategy=|-X| + --strategy-option=|--rebase=|--depth=|--deepen=|--shallow-exclude=| + --shallow-since=|--negotiation-tip|--upload-pack|-o|--server-option=| + --no-recurse-submodules=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (--help|-q|--quiet|-v|--verbose|--progress|--no-recurse-submodules| + --commit|--no-commit|--edit|--no-edit|--ff|--no-ff|--ff-only| + --log|--no-log|--signoff|--no-signoff|--stat|-n|--no-stat|--squash| + --no-squash|--verify-signatures|--no-verify-signatures|--summary| + --no-summary|--allow-unrelated-histories|-r|--rebase|--no-rebase| + --autostash|--no-autostash|--all|-a|--append|--unshallow| + --update-shallow|-f|--force|-k|--keep|--no-tags|-u|--update-head-ok| + --progress|-4|--ipv4|-6|--ipv6|--recurse-submodules) + <<>> __style=\${FAST_THEME_NAME}single-hyphen-option // NO-OP" + + ## }}} + + ## + ## COMMIT + ## + ## {{{ + + subcmd:commit "COMMIT_#_opt // FILE_#_arg // NO_MATCH_#_opt" + + "COMMIT_#_opt" " + (-m|--message=|-am) + <<>> NO-OP // :::chroma/-git-commit-msg-opt-action + <<>> NO-OP // :::chroma/-git-commit-msg-opt-ARG-action + || (--help|-a|--all|-p|--patch|--reset-author|--short|--branch| + --porcelain|--long|-z|--null|-s|--signoff|-n|--no-verify| + --allow-empty|--allow-empty-message|-e|--edit|--no-edit| + --amend|--no-post-rewrite|-i|--include|-o|--only|--untracked-files| + -v|--verbose|-q|--quiet|--dry-run|--status|--no-status|--no-gpg-sign) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || (-C|--reuse-message=|-c|--reedit-message=|--fixup=|--squash=| + -F|--file=|--author=|--date=|-t|--template=|--cleanup=| + -u|--untracked-files=|-S|--gpg-sign=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action" + + # A generic action + "FILE_#_arg" "NO-OP // :::chroma/-git-verify-file" + + ## }}} + + ## + ## MERGE + ## + ## {{{ + + subcmd:merge "MERGE_0_opt // COMMIT_#_arg" + MERGE_0_opt + "(-m) + <<>> NO-OP // :::chroma/-git-commit-msg-opt-action + <<>> NO-OP // :::chroma/-git-commit-msg-opt-ARG-action + (-S|--gpg-sign=|--log=|-e|--strategy=|-X|--strategy-option=|-F| + --file) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (--help|--commit|--no-commit|-e|--edit|--no-edit|--ff|--no-ff|--ff-only| + --log|--no-log|--signoff|--no-signoff|-n|--stat|--no-stat|--squash| + --no-squash|--verify-signatures|--no-verify-signatures|--summary| + --no-summary|-q|--quiet|-v|--verbose|--progress|--no-progress| + --allow-unrelated-histories|--rerere-autoupdate|--no-rerere-autoupdate| + --abort|--continue) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + COMMIT_\#_arg "NO-OP // :::chroma/-git-verify-commit" + + ## }}} + + ## + ## RESET + ## + ## {{{ + + subcmd:reset "RESET_0_opt^ // RESET_0_opt // RESET_#_arg // NO_MATCH_#_opt" + "RESET_0_opt^" " + (--soft|--mixed|--hard|--merge|--keep) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || (--soft|--mixed|--hard|--merge|--keep):del + <<>> RESET_0_opt // RESET_#_arg + || (--soft|--mixed|--hard|--merge|--keep):add + <<>> RESET_1_arg // NO_MATCH_#_arg + " + + RESET_0_opt " + (-q|-p|--patch) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + RESET_1_arg "NO-OP // :::chroma/-git-verify-commit" + + "RESET_#_arg" "NO-OP // :::chroma/-git-RESET-verify-commit-or-file" + + + ## }}} + + ## + ## REVERT + ## + ## {{{ + + subcmd:revert "REVERT_SEQUENCER_0_opt^ // REVERT_0_opt // REVERT_#_arg // NO_MATCH_#_opt" + REVERT_0_opt " + (-m|--mainline|-S|--gpg-sign=|--strategy=|-X|--strategy-option=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (-e|--edit|--no-edit|-n|--no-commit|-s|--signoff) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + "REVERT_SEQUENCER_0_opt^" " + (--continue|--quit|--abort) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || (--continue|--quit|--abort):del + <<>> REVERT_0_opt // REVERT_#_arg + || (--continue|--quit|--abort):add + <<>> NO_MATCH_#_arg" + + "REVERT_#_arg" "NO-OP // :::chroma/-git-verify-commit" + + ## }}} + + ## + ## DIFF + ## + ## TODO: When a second argument is also a path and it points to a directory, then + ## git appends the previous file name to it – good to implement this too + ## {{{ + + subcmd:diff "DIFF_NO_INDEX_0_opt^ // DIFF_0_opt // COMMIT_FILE_DIR_#_arg // NO_MATCH_#_opt" + + "DIFF_NO_INDEX_0_opt^" " + --no-index + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || --no-index:del + <<>> COMMIT_FILE_DIR_#_arg + || --no-index:add + <<>> FILE_1_arg // FILE_2_arg // NO_MATCH_#_arg" + DIFF_0_opt " + (-U|--unified=|--anchored=|--diff-algorithm=|--stat=|--dirstat| + --submodule=|--color=|--color-moved=|--color-moved-ws=|--word-diff=| + --word-diff-regex=|--color-words=|--ws-error-highlight=|--abbrev=| + -B|--break-rewrites=|-M|--find-renames=|-C|--find-copies=|-l| + --diff-filter=|-S|-G|--find-object=|--relative=|-O|--relative=| + --inter-hunk-context=|--ignore-submodules=|--src-prefix=|--dst-prefix=| + --line-prefix=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (-p|--patch|-u|-s|--no-patch|--raw|--patch-with-raw|--indent-heuristic| + --no-indent-heuristic|--minimal|--patience|--histogram|--stat| + --compact-summary|--numstat|--shortstat|--dirstat|--summary| + --patch-with-stat|-z|--name-only|--name-status|--submodule|--no-color| + --color-moved|--word-diff|--color-words|--no-renames|--check| + --full-index|--binary|--abbrev|--break-rewrites|--find-renames| + --find-copies|--find-copies-harder|-D|--pickaxe-all|--pickaxe-regex| + --irreversible-delete|-R|--relative|-a|--text|--ignore-cr-at-eol| + --ignore-space-at-eol|-b|--ignore-space-change|-w|--ignore-all-space| + --ignore-blank-lines|-W|--function-context|--exit-code|--quiet| + --ext-diff|--no-ext-diff|--textconv|--no-textconv|--ignore-submodules| + --no-prefix|--ita-invisible-in-index|-1|--base|-2|--ours|-3|--theirs| + -0|--cached) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + # A generic action + "COMMIT_FILE_DIR_#_arg" "NO-OP // :::chroma/-git-verify-commit-or-file-or-dir" + + # A generic action + "FILE_1_arg" "NO-OP // :::chroma/-git-verify-file" + + # A generic action + "FILE_2_arg" "NO-OP // :::chroma/-git-verify-file" + + ## }}} + + ## + ## ADD + ## + ## {{{ + + subcmd:add "ADD_0_opt // FILE_OR_DIR_#_arg // NO_MATCH_#_opt" + + ADD_0_opt " + --chmod= + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (-v|--verbose|-f|--force|-i|--interactive|-n|--dry-run| + -p|--patch|-e|--edit|--all|--no-all|-A|--all|--no-all| + --ignore-removal|--no-ignore-removal|-u|--update|-N| + --intent-to-add|--refresh|--ignore-errors|--ignore-missing| + --renormalize|--no-warn-embedded-repo) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + FILE_OR_DIR_#_arg "NO-OP // :::chroma/-git-verify-file-or-dir" + + ## }}} + + ## + ## CHECKOUT + ## + ## {{{ + + subcmd:checkout "CHECKOUT_BRANCH_0_opt^ // + CHECKOUT_0_opt // FILE_OR_DIR_OR_BRANCH_OR_COMMIT_1_arg // FILE_#_arg // + FILE_#_arg // NO_MATCH_#_opt" + + "CHECKOUT_BRANCH_0_opt^" " + (-b|-B|--orphan) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || (-b|-B|--orphan):del + <<>> FILE_OR_DIR_OR_BRANCH_OR_COMMIT_1_arg // FILE_#_arg // FILE_#_arg + || (-b|-B|--orphan):add + <<>> NEW_BRANCH_1_arg // COMMIT_2_arg // NO_MATCH_#_arg" + + NEW_BRANCH_1_arg "NO-OP // :::chroma/-git-verify-correct-branch-name" + + COMMIT_2_arg "NO-OP // :::chroma/-git-verify-commit" + + CHECKOUT_0_opt " + --conflict= + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (-q|--quiet|--progress|--no-progress|-f|--force|--ours|--theirs| + -b|-B|-t|--track|--no-track|-l|--detach|--orphan| + --ignore-skip-worktree-bits|-m|--merge|-p|--patch| + --ignore-other-worktrees|--no-ignore-other-worktrees) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + # A generic action + COMMIT_1_arg "NO-OP // :::chroma/-git-verify-commit" + + # Unused + FILE_OR_BRANCH_OR_COMMIT_1_arg "NO-OP // :::chroma/-git-file-or-ubranch-or-commit-verify" + FILE_OR_DIR_OR_BRANCH_OR_COMMIT_1_arg "NO-OP // :::chroma/-git-file-or-dir-or-ubranch-or-commit-verify" + + ## }}} + + ## + ## REMOTE + ## + ## {{{ + + subcmd:remote "REMOTE_0_opt // REMOTE_ADD_1_arg // REMOTE_RENAME_1_arg // REMOTE_REMOVE_1_arg // + REMOTE_SET_HEAD_1_arg // REMOTE_SET_BRANCHES_1_arg // + REMOTE_GET_URL_1_arg // REMOTE_SET_URL_1_arg // REMOTE_SHOW_1_arg // + REMOTE_PRUNE_1_arg // REMOTE_UPDATE_1_arg" + + REMOTE_0_opt "(-v|--verbose) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_ADD_1_arg "add ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_ADD_OPTS_1_opt // REMOTE_A_NAME_2_arg // + REMOTE_A_URL_3_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + REMOTE_RENAME_1_arg "rename ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_2_arg // REMOTE_A_NAME_3_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + REMOTE_REMOVE_1_arg "remove ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_2_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + REMOTE_SET_HEAD_1_arg "set-head ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_2_arg // BRANCH_3_arg // + REMOTE_SET_HEAD_OPTS_1_opt // REMOTE_SET_HEAD_OPTS_2_opt // + NO_MATCH_#_opt // NO_MATCH_#_arg" + + REMOTE_SET_BRANCHES_1_arg "set-branches ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_SET_BRANCHES_OPTS_1_opt // REMOTE_2_arg // + BRANCH_#_arg // NO_MATCH_#_opt" + + REMOTE_GET_URL_1_arg "get-url ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_GET_URL_OPTS_1_opt // REMOTE_2_arg // + NO_MATCH_#_opt // NO_MATCH_#_arg" + + REMOTE_SET_URL_1_arg "set-url ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_SET_URL_OPTS_1_opt^ // + REMOTE_2_arg // REMOTE_A_URL_3_arg // REMOTE_A_URL_4_arg // + NO_MATCH_#_opt // NO_MATCH_#_arg" + + REMOTE_SHOW_1_arg "show ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_SHOW_OPTS_1_opt // REMOTE_#_arg // NO_MATCH_#_opt" + + REMOTE_PRUNE_1_arg "prune ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_PRUNE_OPTS_1_opt // REMOTE_#_arg // NO_MATCH_#_opt" + + REMOTE_UPDATE_1_arg "update ::::: __style=${FAST_THEME_NAME}subcommand // NO-OP <<>> + add:REMOTE_UPDATE_OPTS_1_opt // REMOTE_GR_#_arg // NO_MATCH_#_opt" + + REMOTE_ADD_OPTS_1_opt " + (-t|-m|--mirror=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (-f|--tags|--no-tags) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_SET_HEAD_OPTS_1_opt " + (-a|--auto|-d|--delete) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_SET_HEAD_OPTS_2_opt " + (-a|--auto|-d|--delete) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_SET_BRANCHES_OPTS_1_opt " + --add + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_GET_URL_OPTS_1_opt " + (--push|--all) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + "REMOTE_SET_URL_OPTS_1_opt^" " + --push|--add|--delete + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || (--add|--delete):del + <<>> REMOTE_A_URL_4_arg" + + REMOTE_SHOW_OPTS_1_opt " + -n + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_PRUNE_OPTS_1_opt " + (-n|--dry-run) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_UPDATE_OPTS_1_opt " + (-p|--prune) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + REMOTE_A_NAME_2_arg "NO-OP // :::chroma/-git-verify-correct-branch-name" + REMOTE_A_NAME_3_arg "NO-OP // :::chroma/-git-verify-correct-branch-name" + REMOTE_A_URL_3_arg "NO-OP // :::chroma/main-chroma-std-verify-url" + REMOTE_A_URL_4_arg "NO-OP // :::chroma/main-chroma-std-verify-url" + BRANCH_3_arg "NO-OP // :::chroma/-git-verify-branch" + BRANCH_\#_arg "NO-OP // :::chroma/-git-verify-branch" + REMOTE_2_arg "NO-OP // :::chroma/-git-verify-remote" + REMOTE_\#_arg "NO-OP // :::chroma/-git-verify-remote" + + ## }}} + + ## + ## LOG + ## + + subcmd:log "LOG_0_opt // LOG_1_arg // FILE_#_arg // NO_MATCH_#_opt" + + LOG_0_opt " + (--decorate=|--decorate-refs=|--decorate-refs-exclude=|-L|-n|--max-count=| + --skip=|--since=|--after=|--until=|--before=|--author=|--committer=| + --grep-reflog=|--grep=|--min-parents=|--max-parents=|--branches=|--tags=| + --remotes=|--glob=|--exclude=|--no-walk=|--pretty=|--format=|--encoding=| + --expand-tabs=|--notes=|--show-notes=|--date=|--show-linear-break=|-U| + --unified=|--anchored=|--diff-algorithm=|--stat=|--dirstat=|--submodule=| + --color=|--color-moved=|--color-moved-ws=|--word-diff=|--word-diff-regex=| + --color-words=|--ws-error-highlight=|--abbrev=|-B|--break-rewrites=|-M| + --find-renames=|-C|--find-copies=|-l|--diff-filter=|-S|-G|--find-object=| + --relative=|-O|--relative=|--inter-hunk-context=|--ignore-submodules=| + --src-prefix=|--dst-prefix=|--line-prefix=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + + || (--follow|--decorate|--no-decorate|--source|--use-mailmap|--full-diff| + --log-size|--all-match|--invert-grep|-i|--regexp-ignore-case|--basic-regexp| + -E|--extended-regexp|-F|--fixed-strings|-P|--perl-regexp|--remove-empty| + --merges|--no-merges|--no-min-parents|--no-max-parents|--first-parent| + --not|--all|--branches|--tags|--remotes|--reflog|--single-worktree| + --ignore-missing|--bisect|--stdin|--cherry-mark|--cherry-pick|--left-only| + --right-only|--cherry|-g|--walk-reflogs|--merge|--boundary|--simplify-by-decoration| + --full-history|--dense|--sparse|--simplify-merges|--ancestry-path|--date-order| + --author-date-order|--topo-order|--reverse|--no-walk|--do-walk|--pretty| + --abbrev-commit|--no-abbrev-commit|--oneline|--expand-tabs|--no-expand-tabs| + --notes|--no-notes|--show-notes|--no-standard-notes|--show-signature| + --relative-date|--parents|--children|--left-right|--graph|--show-linear-break| + -c|--cc|-m|-r|-t|-p|-u|--patch|-s|--no-patch|--raw|--patch-with-raw| + --indent-heuristic|--no-indent-heuristic|--minimal|--patience|--histogram| + --stat|--compact-summary|--numstat|--shortstat|--dirstat|--summary| + --patch-with-stat|-z|--name-only|--name-status|--submodule|--color|--no-color| + --color-moved|--word-diff|--color-words|--no-renames|--check|--full-index| + --binary|--abbrev|--break-rewrites|--find-renames| + --find-copies|--find-copies-harder|-D|--irreversible-delete| + --pickaxe-all|--pickaxe-regex|-R|--relative|-a|--text|--ignore-cr-at-eol| + --ignore-space-at-eol|-b|--ignore-space-change|-w|--ignore-all-space| + --ignore-blank-lines|-W|--function-context|--ext-diff|--no-ext-diff| + --textconv|--no-textconv|--ignore-submodules|--no-prefix| + --ita-invisible-in-index) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + LOG_1_arg "NO-OP // :::chroma/-git-verify-rev-range-or-file" + + ## + ## TAG + ## + + subcmd:tag "TAG_D_0_opt^ // TAG_L_0_opt^ // TAG_V_0_opt^ // TAG_0_opt^" + + "TAG_0_opt^" " + (-u|--local-user=|--cleanup=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || -m + <<>> NO-OP // :::chroma/-git-commit-msg-opt-action + <<>> NO-OP // :::chroma/-git-commit-msg-opt-ARG-action + || (-F|--file) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/-git-verify-file + || (-a|--annotate|-s|--sign|-f|-e|--edit) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || (-u|--local-user=|--cleanup=|-m|-F|--file|-a|--annotate|-s|--sign| + -f|-e|--edit):add + <<>> TAG_NEW_1_arg // COMMIT_2_arg // NO_MATCH_#_arg // + NO_MATCH_#_opt" + + TAG_NEW_1_arg "NO-OP // :::chroma/-git-verify-correct-branch-name" + + TAG_1_arg "NO-OP // :::chroma/-git-verify-tag-name" + + "TAG_D_0_opt^" " + (-d) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || -d:add + <<>> TAG_#_arg // NO_MATCH_#_opt + || -d:del + <<>> TAG_0_opt // TAG_NEW_1_arg // COMMIT_2_arg" + + "TAG_#_arg" "NO-OP // :::chroma/-git-verify-tag-name" + + "TAG_L_0_opt^" " + (-l) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || -l:add + <<>> TAG_L_0_opt // TAG_PAT_#_arg // NO_MATCH_#_opt + || -l:del + <<>> TAG_0_opt // TAG_NEW_1_arg // COMMIT_2_arg" + + "TAG_L_0_opt" " + (-n|--contains|--no-contains|--points-at|--column=|--sort=|--format=| + --color=) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action + || (--column|--no-column|--create-reflog|--merged|--no-merged|--color|-i) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + "TAG_PAT_#_arg" "NO-OP // :::chroma/main-chroma-std-verify-pattern" + + "TAG_V_0_opt^" " + (-v) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + || -v:add + <<>> TAG_V_0_opt // TAG_#_arg // NO_MATCH_#_opt + || -v:del + <<>> TAG_0_opt // TAG_NEW_1_arg // COMMIT_2_arg" + + "TAG_V_0_opt" " + --format= + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action + <<>> NO-OP // :::chroma/main-chroma-std-aopt-ARG-action" + + ## + ## All remaining subcommands + ## + ## {{{ + + "subcmd:*" "CATCH_ALL_#_opt" + "CATCH_ALL_#_opt" "* <<>> NO-OP // :::chroma/main-chroma-std-aopt-SEMI-action" + + ## }}} +) + +# Called after entering just "git" on the command line +:chroma/-git-first-call() { + # Called for the first time - new command + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global variables + FAST_HIGHLIGHT[chroma-git-counter]=0 + FAST_HIGHLIGHT[chroma-git-got-subcommand]=0 + FAST_HIGHLIGHT[chroma-git-subcommand]="" + FAST_HIGHLIGHT[chrome-git-got-msg1]=0 + FAST_HIGHLIGHT[chrome-git-got-anymsg]=0 + FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]=0 + FAST_HIGHLIGHT[chroma-git-checkout-new]=0 + FAST_HIGHLIGHT[chroma-git-fetch-multiple]=0 + FAST_HIGHLIGHT[chroma-git-branch-change]=0 + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=0 + FAST_HIGHLIGHT[chroma-git-reset-etc-saw-commit]=0 + FAST_HIGHLIGHT[chroma-git-reset-etc-saw-file]=0 + return 1 +} + +:chroma/-git-check-if-alias() { + local _wrd="$1" + local -a _result + + typeset -ga fsh__chroma__git__aliases + _result=( ${(M)fsh__chroma__git__aliases[@]:#${_wrd}[[:space:]]##*} ) + :chroma/main-chroma-print "Got is-alias-_result: $_result" + [[ -n "$_result" ]] && \ + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]="${${${_result#* }## ##}%% *}" +} + +# A hook that returns the list of git's +# available subcommands in $reply +:chroma/-git-get-subcommands() { + local __svalue + integer __ivalue + LANG=C -fast-run-command "git help -a" chroma-${FAST_HIGHLIGHT[chroma-current]}-subcmd-list "" $(( 15 * 60 )) + if [[ "${__lines_list[1]}" = See* ]]; then + # (**) + # git >= v2.20, the aliases in the `git help -a' command + __lines_list=( ${${${${(M)__lines_list[@]:#([[:space:]](#c3,3)[a-zA-Z0-9_]*|Command aliases)}##[[:space:]]##}//(#s)Command\ aliases(#e)/Command_aliases}} ) + __svalue="+${__lines_list[(I)Command_aliases]}" + __lines_list[1,__svalue-1]=( ${(@)__lines_list[1,__svalue-1]%%[[:space:]]##*} ) + else + # (**) + # git < v2.20, add aliases through extra code + __lines_list=( ${(s: :)${(M)__lines_list[@]:# [a-z]*}} ) + + __svalue=${#__lines_list} + # This allows to check if the command is an alias - we want to + # highlight the aliased command just like the target command of + # the alias + -fast-run-command "+git config --get-regexp 'alias.*'" chroma-${FAST_HIGHLIGHT[chroma-current]}-alias-list "[[:space:]]#alias." $(( 15 * 60 )) + fi + + __tmp=${#__lines_list} + typeset -ga fsh__chroma__git__aliases + fsh__chroma__git__aliases=( ${__lines_list[__svalue+1,__tmp]} ) + [[ ${__lines_list[__svalue]} != "Command_aliases" ]] && (( ++ __svalue, __ivalue=0, 1 )) || (( __ivalue=1 )) + __lines_list[__svalue,__tmp]=( ${(@)__lines_list[__svalue+__ivalue,__tmp]%%[[:space:]]##*} ) + reply=( "${__lines_list[@]}" ) +} + +# A generic handler +:chroma/-git-verify-remote() { + local _wrd="$4" + -fast-run-git-command "git remote" "chroma-git-remotes-$PWD" "" $(( 2 * 60 )) + [[ -n ${__lines_list[(r)$_wrd]} ]] && { + __style=${FAST_THEME_NAME}correct-subtle; return 0 + } || { + [[ $_wrd != *:* ]] && { __style=${FAST_THEME_NAME}incorrect-subtle; return 1; } + } +} + +# A generic handler - checks if given ref is correct +:chroma/-git-verify-ref() { + local _wrd="$4" + _wrd="${_wrd%%:*}" + -fast-run-git-command "git for-each-ref --format='%(refname:short)' refs/heads" "chroma-git-refs-$PWD" "refs/heads" $(( 2 * 60 )) + [[ -n ${__lines_list[(r)$_wrd]} ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 1; } +} + +# A generic handler - checks if given remote or group is correct +:chroma/-git-verify-remote-or-group() { + :chroma/-git-verify-remote "$@" && return 0 + # The check for a group is to follow below + integer _start="$2" _end="$3" + local _scmd="$1" _wrd="$4" +} + +# A generic handler - checks whether the file exists +:chroma/-git-verify-file() { + integer _start="$2" _end="$3" __pos __start __end + local _wrd="$4" bg + + [[ -f $_wrd ]] && { + (( __start=_start, __end=_end, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + bg=${(M)FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]%bg=*} + ((1)) + } || { + (( __start=_start, __end=_end, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + bg=${(M)FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]%bg=*} + } + + [[ -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 = 1; __pos <= (_end-_start); __pos++ )) { + [[ ${_wrd[__pos]} == "/" ]] && { + [[ ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]} = *bg=* ]] && { + (( __start=_start+__pos-__PBUFLEN, __start >= 0 )) && \ + reply+=("$(( __start - 1 )) $__start ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]}") + ((1)) + } || { + (( __start=_start+__pos-__PBUFLEN, __start >= 0 )) && \ + reply+=("$(( __start - 1 )) $__start ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]}${bg:+,$bg}") + } + } + } +} + +# A generic handler - checks whether the file exists +:chroma/-git-verify-file-or-dir() { + integer _start="$2" _end="$3" __pos __start __end retval + local _wrd="$4" bg + + __style= + [[ -f $_wrd || -d $_wrd ]] && { + (( __start=_start, __end=_end, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + bg=${(M)FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]%bg=*} + ((1)) + } || { + (( __start=_start, __end=_end, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + bg=${(M)FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]%bg=*} + retval=1 + } + + [[ -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 = 1; __pos <= (_end-_start); __pos++ )) { + [[ ${_wrd[__pos]} == "/" ]] && { + [[ ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]} = *bg=* ]] && { + (( __start=_start+__pos-__PBUFLEN, __start >= 0 )) && \ + reply+=("$(( __start - 1 )) $__start ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]}") + ((1)) + } || { + (( __start=_start+__pos-__PBUFLEN, __start >= 0 )) && \ + reply+=("$(( __start - 1 )) $__start ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path_pathseparator]}${bg:+,$bg}") + } + } + } + return $retval +} + +:chroma/-git-verify-branch() { + local _wrd="$4" + -fast-run-git-command "git for-each-ref --format='%(refname:short)' refs/heads" "chroma-git-branches-$PWD" "refs/heads" $(( 2 * 60 )) + [[ -n ${__lines_list[(r)$_wrd]} ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 1; } +} + +:chroma/-git-verify-also-unfetched-ref() { + local _wrd="$4" + -fast-run-git-command "git config --get checkout.defaultRemote" \ + "chroma-git-defaultRemote-$PWD" "" $(( 2 * 60 )) + local remote="${__lines_list[1]:-origin}" + -fast-run-git-command "git rev-list --count --no-walk + --glob=\"refs/remotes/$remote/$_wrd\"" \ + "chroma-git-unfetched-ref-$PWD" "" $(( 2 * 60 )) + + (( __lines_list[1] )) && { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 1; } +} + +# A generic handler +:chroma/-git-file-or-ubranch-or-commit-verify() { + :chroma/-git-verify-commit "$@" && return + :chroma/-git-verify-file "$@" && return + :chroma/-git-verify-also-unfetched-ref "$@" +} + +# A generic handler +:chroma/-git-file-or-dir-or-ubranch-or-commit-verify() { + :chroma/-git-verify-commit "$@" && return + :chroma/-git-verify-file-or-dir "$@" && return + :chroma/-git-verify-also-unfetched-ref "$@" +} + +# A generic handler +:chroma/-git-verify-correct-branch-name() { + local _wrd="$4" + :chroma/-git-verify-commit "$@" && \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 0; } + + :chroma/-git-verify-remote "$@" && \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 0; } + + [[ "$_wrd" != ./* && "$_wrd" != *..* && "$_wrd" != *[~\^\ $'\t']* && + "$_wrd" != */ && "$_wrd" != *.lock && "$_wrd" != *\\* ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 1; } +} + +# A generic handler that checks if given commit reference is correct +:chroma/-git-verify-commit() { + local _wrd="$4" + __lines_list=() + -fast-run-git-command "git rev-parse --verify --quiet \"$_wrd\"" "chroma-git-commits-$PWD-$_wrd" "" $(( 1.5 * 60 )) + if (( ${#__lines_list} )); then + __style=${FAST_THEME_NAME}correct-subtle + return 0 + fi + __style=${FAST_THEME_NAME}incorrect-subtle + return 1 +} + +# A generic handler that checks if given commit reference +# is correct or if it's a file that exists +:chroma/-git-verify-commit-or-file() { + :chroma/-git-verify-commit "$@" && return + :chroma/-git-verify-file "$@" +} + +# A generic handler that checks if given commit reference +# is correct or if it's a file or directives that exists +:chroma/-git-verify-commit-or-file-or-dir() { + :chroma/-git-verify-commit "$@" && return + :chroma/-git-verify-file-or-dir "$@" +} + +# A generic handler that checks if given revision range +# is correct or if a file of that name exists +:chroma/-git-verify-rev-range-or-file() { + local _wrd="$4" + + :chroma/-git-verify-commit "$@" && return 0 + + if [[ "$_wrd" = *..* ]]; then + (( FAST_HIGHLIGHT[chroma-git-reset-etc-saw-file] )) && { + :chroma/-git-verify-file "$@" && return 0 + __style=${FAST_THEME_NAME}unknown-token + return 1 + } + + __style="" + return 0 + fi + + :chroma/-git-verify-file "$@" && \ + { FAST_HIGHLIGHT[chroma-git-reset-etc-saw-file]=1; return 0; } + + __style="" + return 1 +} + +:chroma/-git-verify-tag-name() { + local _wrd="$4" + -fast-run-git-command "git tag" "chroma-git-tags-$PWD" "" $(( 2*60 )) + [[ -n ${__lines_list[(r)$_wrd]} ]] && \ + __style=${FAST_THEME_NAME}correct-subtle || \ + __style=${FAST_THEME_NAME}incorrect-subtle +} + +# A handler for the commit's -m/--message options.Currently +# does the same what :chroma/main-chroma-std-aopt-action does +:chroma/-git-commit-msg-opt-action() { + :chroma/main-chroma-std-aopt-action "$@" +} + +# A handler for the commit's -m/--message options' argument +:chroma/-git-commit-msg-opt-ARG-action() { + integer _start="$2" _end="$3" + local _scmd="$1" _wrd="$4" + + (( __start >= 0 )) || return + + # Match the message body in case of an --message= option + if [[ "$_wrd" = (#b)(--message=)(*) && -n "${match[2]}" ]]; then + _wrd="${(Q)${match[2]//\`/x}}" + # highlight --message=>>something<< + reply+=("$(( __start+10 )) $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}") + elif [[ "$_wrd" != --message ]]; then + # highlight the message's body + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}") + fi + + integer length=${FAST_HIGHLIGHT[git-cmsg-len]:-50} + + if (( ${#_wrd} > length )); then + for (( __idx1 = 1, __idx2 = 1; __idx1 <= length; ++ __idx1, ++ __idx2 )); do + # Use __arg from the fast-highlight-process's scope + while [[ "${__arg[__idx2]}" != "${_wrd[__idx1]}" ]]; do + (( ++ __idx2 )) + (( __idx2 > __asize )) && { __idx2=-1; break; } + done + (( __idx2 == -1 )) && break + done + if (( __idx2 != -1 )); then + if [[ -n "${match[1]}" ]]; then + reply+=("$(( __start+__idx2 )) $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + else + reply+=("$(( __start+__idx2-1 )) $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + fi + fi + fi +} + +# A RESET handler +# TODO: differentiate tree-ish from commit +:chroma/-git-RESET-verify-commit-or-file() { + :chroma/-git-verify-commit "$@" && { + :chroma/-git-verify-file "$@" && { + # TODO: with -p/--patch, the <paths> are optional, + # and this argument will be taken as a commit in a + # specific circumstances + FAST_HIGHLIGHT[chroma-git-reset-etc-saw-file]=1 + return 0 + } + + (( FAST_HIGHLIGHT[chroma-git-reset-etc-saw-file] || + FAST_HIGHLIGHT[chroma-git-reset-etc-saw-commit] )) && \ + { __style=${FAST_THEME_NAME}unknown-token; return 1; } + + FAST_HIGHLIGHT[chroma-git-reset-etc-saw-commit]=1 + + __style=${FAST_THEME_NAME}correct-subtle + + return 0 + } + + :chroma/-git-verify-file "$@" && \ + { FAST_HIGHLIGHT[chroma-git-reset-etc-saw-file]=1; return 0; } + + return 1 +} + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-grep.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-grep.ch new file mode 100644 index 0000000..54309bf --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-grep.ch @@ -0,0 +1,89 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __chars +integer __idx1 __idx2 + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-grep-counter]=0 + return 1 +} || { + # Following call, i.e. not the first one. + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + else + # Count non-option tokens. + (( FAST_HIGHLIGHT[chroma-grep-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-grep-counter] )) + + # First non-option token is the pattern (regex), we will + # highlight it. + if (( FAST_HIGHLIGHT[chroma-grep-counter] == 1 )); then + [[ "$__wrd" = \"* ]] && __style=${FAST_THEME_NAME}double-quoted-argument + [[ "$__wrd" = \'* ]] && __style=${FAST_THEME_NAME}single-quoted-argument + [[ "$__wrd" = \$\'* ]] && __style=${FAST_THEME_NAME}dollar-quoted-argument + [[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + __style="" + + __chars="*+\\)([]^\$" + __idx1=__start_pos + __idx2=__start_pos + while [[ "$__wrd" = (#b)[^$__chars]#([\\][\\])#((+|\*|\[|\]|\)|\(|\^|\$)|[\\](+|\*|\[|\]|\)|\(|\^|\$))(*) ]]; do + if [[ -n "${match[3]}" ]]; then + __idx1+=${mbegin[3]}-1 + __idx2=__idx1+${mend[3]}-${mbegin[3]}+1 + (( __start=__idx1-${#PREBUFFER}, __end=__idx2-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-operator]}") + __idx1=__idx2 + else + __idx1+=${mbegin[5]}-1 + fi + __wrd="${match[5]}" + done + elif (( FAST_HIGHLIGHT[chroma-grep-counter] == 2 )); then + # Handle paths, etc. normally - just pass-through to the big + # highlighter (the main FSH highlighter, used before chromas). + return 1 + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does) and skip setting __style +# to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-hub.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-hub.ch new file mode 100644 index 0000000..466d2e5 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-hub.ch @@ -0,0 +1,51 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" + +if (( __first_call )); then + chroma/-git.ch $* + return 1 +fi +[[ "$__arg_type" = 3 ]] && return 2 + +if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +fi + +if [[ "$__wrd" != -* ]] && (( FAST_HIGHLIGHT[chroma-git-got-subcommand] == 0 )); then + -fast-run-command "git config --get-regexp 'alias.*'" chroma-git-alias-list "" $(( 5 * 60 )) + # Grep for line: alias.{user-entered-subcmd}[[:space:]], and remove alias. prefix + __lines_list=( ${${(M)__lines_list[@]:#alias.${__wrd}[[:space:]]##*}#alias.} ) + + if (( ${#__lines_list} > 0 )); then + # (*) + # First remove alias name (#*[[:space:]]) and the space after it, then + # remove any leading spaces from what's left (##[[:space:]]##), then + # remove everything except the first word that's in the left line + # (%%[[:space:]]##*, i.e.: "everything from right side up to any space") + FAST_HIGHLIGHT[chroma-git-subcommand]="${${${__lines_list[1]#*[[:space:]]}##[[:space:]]##}%%[[:space:]]##*}" + else + FAST_HIGHLIGHT[chroma-git-subcommand]="$__wrd" + fi + if [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "browse" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "ci-status" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "compare" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "create" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "delete" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "fork" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "issue" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "pr" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "pull-request" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "release" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "sync" ]]; then + FAST_HIGHLIGHT[chroma-git-got-subcommand]=1 + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}subcommand]}") + (( FAST_HIGHLIGHT[chroma-git-counter] += 1 )) + (( this_word = next_word )) + _start_pos=$4 + return 0 + fi +fi + +chroma/-git.ch $* diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ionice.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ionice.ch new file mode 100644 index 0000000..f328f83 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ionice.ch @@ -0,0 +1,117 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2018 Sebastian Gniazdowski +# Copyright (C) 2019 by Philippe Troin (F-i-f on GitHub) +# 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. +# ------------------------------------------------------------------------------------------------- + +setopt local_options extendedglob warn_create_global typeset_silent + +# Keep chroma-takever state meaning: until ;, handle highlighting via chroma. +# So the below 8192 assignment takes care that next token will be routed to chroma. +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style option_start=0 option_end=0 number_start=0 number_end=0 +local -a match mbegin mend + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global string variables. + FAST_HIGHLIGHT[ionice-option-argument]=0 + + # Set style for region_highlight entry. It is used below in + # '[[ -n "$__style" ]] ...' line, which adds highlight entry, + # like "10 12 fg=green", through `reply' array. + # + # Could check if command `example' exists and set `unknown-token' + # style instead of `command' + __style=${FAST_THEME_NAME}precommand + +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if (( FAST_HIGHLIGHT[ionice-option-argument] )); then + (( FAST_HIGHLIGHT[ionice-option-argument] = 0 )) + [[ $__wrd == [0-9]# ]] && __style=${FAST_THEME_NAME}mathnum || __style=${FAST_THEME_NAME}incorrect-subtle + else + case $__wrd in + --(class(data|)|(u|p(g|))id)) + __style=${FAST_THEME_NAME}double-hyphen-option + FAST_HIGHLIGHT[ionice-option-argument]=1 + ;; + -[cnpPu]) + __style=${FAST_THEME_NAME}single-hyphen-option + FAST_HIGHLIGHT[ionice-option-argument]=1 + ;; + --*) + __style=${FAST_THEME_NAME}double-hyphen-option + ;; + -*) + __style=${FAST_THEME_NAME}single-hyphen-option + ;; + *) + this_word=1 + next_word=2 + return 1 + ;; + esac + fi +} + +# Add region_highlight entry (via `reply' array). +# If 1 will be added to __start_pos, this will highlight "oken". +# If 1 will be subtracted from __end_pos, this will highlight "toke". +# $PREBUFFER is for specific situations when users does command \<ENTER> +# i.e. when multi-line command using backslash is entered. +# +# This is a common place of adding such entry, but any above code can do +# it itself (and it does in other chromas) and skip setting __style to +# this way disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves. +# _start_pos=$_end_pos advainces pointers in command line buffer. +# +# To pass through means to `return 1'. The highlighting of +# this single token is then done by fast-syntax-highlighting's +# main code and chroma doesn't have to do anything. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-lab.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-lab.ch new file mode 100644 index 0000000..cf3fc95 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-lab.ch @@ -0,0 +1,59 @@ +# vim:ft=zsh:et:sw=4 +# +# The `lab' tool after which this chroma is modeled after: +# https://github.com/zaquestion/lab +# +(( next_word = 2 | 8192 )) +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" + +if (( __first_call )); then + chroma/-git.ch $* + return 1 +fi +[[ "$__arg_type" = 3 ]] && return 2 + +if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +fi + +if [[ "$__wrd" != -* ]] && (( FAST_HIGHLIGHT[chroma-git-got-subcommand] == 0 )); then + -fast-run-command "git config --get-regexp 'alias.*'" chroma-git-alias-list "" $(( 5 * 60 )) + # Grep for line: alias.{user-entered-subcmd}[[:space:]], and remove alias. prefix + __lines_list=( ${${(M)__lines_list[@]:#alias.${__wrd}[[:space:]]##*}#alias.} ) + + if (( ${#__lines_list} > 0 )); then + # (*) + # First remove alias name (#*[[:space:]]) and the space after it, then + # remove any leading spaces from what's left (##[[:space:]]##), then + # remove everything except the first word that's in the left line + # (%%[[:space:]]##*, i.e.: "everything from right side up to any space") + FAST_HIGHLIGHT[chroma-git-subcommand]="${${${__lines_list[1]#*[[:space:]]}##[[:space:]]##}%%[[:space:]]##*}" + else + FAST_HIGHLIGHT[chroma-git-subcommand]="$__wrd" + fi + if [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "browse" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "ci" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "mr" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "project" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "snippet" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "ci-status" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "compare" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "create" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "delete" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "fork" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "issue" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "pr" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "pull-request" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "release" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "sync" ]]; then + FAST_HIGHLIGHT[chroma-git-got-subcommand]=1 + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}subcommand]}") + (( FAST_HIGHLIGHT[chroma-git-counter] += 1 )) + (( this_word = next_word )) + _start_pos=$4 + return 0 + fi +fi + +chroma/-git.ch $* diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-make.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-make.ch new file mode 100644 index 0000000..91f7324 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-make.ch @@ -0,0 +1,105 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma function for command `make'. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 +local -a __lines_list reply2 + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global variables. + FAST_HIGHLIGHT[chroma-make-counter]=0 + FAST_HIGHLIGHT[chroma-make-skip-two]=0 + FAST_HIGHLIGHT[chroma-make-custom-dir]="./" + FAST_HIGHLIGHT[chroma-make-custom-file]="Makefile" + FAST_HIGHLIGHT[chroma-make-got-custom-dir-opt]=0 + FAST_HIGHLIGHT[chroma-make-got-custom-file-opt]=0 + return 1 +} || { + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* || "$__wrd" = *=* ]]; then + [[ "$__wrd" = *=* ]] && { + __style=${FAST_THEME_NAME}variable + } || { + __style=${FAST_THEME_NAME}${${${__wrd:#--*}:+single-hyphen-option}:-double-hyphen-option} + } + + if [[ "$__wrd" = (-I|-o|-W) ]]; then + FAST_HIGHLIGHT[chroma-make-skip-two]=1 + elif [[ "$__wrd" = "-C" ]]; then + FAST_HIGHLIGHT[chroma-make-got-custom-dir-opt]=1 + elif [[ "$__wrd" = "-f" ]]; then + FAST_HIGHLIGHT[chroma-make-got-custom-file-opt]=1 + fi + else + if (( FAST_HIGHLIGHT[chroma-make-skip-two] )); then + FAST_HIGHLIGHT[chroma-make-skip-two]=0 + elif (( FAST_HIGHLIGHT[chroma-make-got-custom-dir-opt] )); then + FAST_HIGHLIGHT[chroma-make-got-custom-dir-opt]=0 + FAST_HIGHLIGHT[chroma-make-custom-dir]="$__wrd" + elif (( FAST_HIGHLIGHT[chroma-make-got-custom-file-opt] )); then + FAST_HIGHLIGHT[chroma-make-got-custom-file-opt]=0 + FAST_HIGHLIGHT[chroma-make-custom-file]="$__wrd" + else + # Count non-option tokens. + (( FAST_HIGHLIGHT[chroma-make-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-make-counter] )) + if (( FAST_HIGHLIGHT[chroma-make-counter] == 1 )); then + __wrd="${__wrd//\`/x}" + __wrd="${(Q)__wrd}" + + if [[ -f "${FAST_HIGHLIGHT[chroma-make-custom-dir]%/}/${FAST_HIGHLIGHT[chroma-make-custom-file]}" ]] && \ + -fast-make-targets < "${FAST_HIGHLIGHT[chroma-make-custom-dir]%/}/${FAST_HIGHLIGHT[chroma-make-custom-file]}" + then + if [[ "${reply2[(r)$__wrd]}" ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + else + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + fi + fi + else + # Pass-through to the big-loop outside + return 1 + fi + fi + fi +} + +# Add region_highlight entry (via `reply' array) +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does) and skip setting __style +# to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-nice.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-nice.ch new file mode 100644 index 0000000..7fa8a94 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-nice.ch @@ -0,0 +1,138 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2018 Sebastian Gniazdowski +# Copyright (C) 2019 by Philippe Troin (F-i-f on GitHub) +# 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. +# ------------------------------------------------------------------------------------------------- + +setopt local_options extendedglob warn_create_global typeset_silent + +# Keep chroma-takever state meaning: until ;, handle highlighting via chroma. +# So the below 8192 assignment takes care that next token will be routed to chroma. +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style option_start=0 option_end=0 number_start=0 number_end=0 +local -a match mbegin mend + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global string variables. + FAST_HIGHLIGHT[nice-arg-count]=0 + FAST_HIGHLIGHT[nice-increment-argument]=0 + + # Set style for region_highlight entry. It is used below in + # '[[ -n "$__style" ]] ...' line, which adds highlight entry, + # like "10 12 fg=green", through `reply' array. + # + # Could check if command `example' exists and set `unknown-token' + # style instead of `command' + __style=${FAST_THEME_NAME}precommand + +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if (( FAST_HIGHLIGHT[nice-increment-argument] )); then + (( FAST_HIGHLIGHT[nice-increment-argument] = 0 )) + [[ $__wrd = (-|+|)[0-9]## ]] \ + && __style=${FAST_THEME_NAME}mathnum \ + || __style=${FAST_THEME_NAME}incorrect-subtle + else + case $__wrd in + -(-|+|)[0-9]##) + (( option_start = __start_pos-${#PREBUFFER} , + option_end = option_start+1 , + number_start = option_end , + number_end = __end_pos-${#PREBUFFER} )) + option_style=${FAST_THEME_NAME}single-hyphen-option + ;; + (#b)(--adjustment)(=(-|+|)[0-9]#|)) + (( option_start = __start_pos-${#PREBUFFER} , + option_end = option_start+mend[1] )) + option_style=${FAST_THEME_NAME}double-hyphen-option + [[ -z $match[2] ]] \ + && (( FAST_HIGHLIGHT[nice-increment-argument] = 1 )) \ + || (( option_end += 1 , + number_start = option_start+mbegin[2]-mbegin[1]+1 , + number_end = __end_pos-${#PREBUFFER} )) + ;; + -n) + __style=${FAST_THEME_NAME}double-hyphen-option + FAST_HIGHLIGHT[nice-increment-argument]=1 + ;; + --*) + __style=${FAST_THEME_NAME}double-hyphen-option + ;; + -*) + __style=${FAST_THEME_NAME}single-hyphen-option + ;; + *) + this_word=1 + next_word=2 + return 1 + ;; + esac + + (( option_start > 0 && option_end )) \ + && reply+=("$option_start $option_end ${FAST_HIGHLIGHT_STYLES[$option_style]}") + (( number_start > 0 && number_end )) \ + && reply+=("$number_start $number_end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathnum]}") + fi +} + +# Add region_highlight entry (via `reply' array). +# If 1 will be added to __start_pos, this will highlight "oken". +# If 1 will be subtracted from __end_pos, this will highlight "toke". +# $PREBUFFER is for specific situations when users does command \<ENTER> +# i.e. when multi-line command using backslash is entered. +# +# This is a common place of adding such entry, but any above code can do +# it itself (and it does in other chromas) and skip setting __style to +# this way disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves. +# _start_pos=$_end_pos advainces pointers in command line buffer. +# +# To pass through means to `return 1'. The highlighting of +# this single token is then done by fast-syntax-highlighting's +# main code and chroma doesn't have to do anything. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-nmcli.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-nmcli.ch new file mode 100644 index 0000000..be444e5 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-nmcli.ch @@ -0,0 +1,58 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +[[ "$__arg_type" = 3 ]] && return 2 + +typeset -A subcommands +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" subcommand +subcommands=( + help "_" + general "help status hostname permissions logging _" + networking "help on off connectivity _" + radio "help all wifi wwan _" + connection "help show up down add modify clone edit delete monitor reload load import export _" + device "help status show set connect reapply modify disconnect delete monitor wifi lldp _" + agent "help secret polkit all _" + monitor "help _" + _ "_" +) + +if (( __first_call )); then + FAST_HIGHLIGHT[chroma-nmcli-subcommand-a]="" + FAST_HIGHLIGHT[chroma-nmcli-subcommand-b]="" + return 1 +elif (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +elif [[ "$2" = -* ]]; then + return 1 +elif [[ -z ${FAST_HIGHLIGHT[chroma-nmcli-subcommand-a]} ]]; then + for subcommand in ${(@k)subcommands}; do + [[ $subcommand = $__wrd* ]] && break || subcommand="_" + done + if [[ $subcommand = _ ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + else + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}subcommand]}") + fi + FAST_HIGHLIGHT[chroma-nmcli-subcommand-a]="$subcommand" +elif [[ -z ${FAST_HIGHLIGHT[chroma-nmcli-subcommand-b]} ]]; then + for subcommand in ${(s. .)subcommands[${FAST_HIGHLIGHT[chroma-nmcli-subcommand-a]}]}; do + [[ "$subcommand" = $__wrd* ]] && break || subcommand="_" + done + if [[ $subcommand = _ ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + else + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}subcommand]}") + fi + FAST_HIGHLIGHT[chroma-nmcli-subcommand-b]="$subcommand" +else + return 1 +fi + +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-node.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-node.ch new file mode 100644 index 0000000..65f214c --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-node.ch @@ -0,0 +1,37 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +[[ "$__arg_type" = 3 ]] && return 2 + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style + +if (( __first_call )); then + FAST_HIGHLIGHT[chroma-node-file]=1 +elif (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +elif [[ "$__wrd" = -- ]]; then + FAST_HIGHLIGHT[chroma-node-file]=2 +elif (( FAST_HIGHLIGHT[chroma-node-file] != 2 )) && [[ "$__wrd" = -* ]]; then + if [[ "$__wrd" = -*e* || "$__wrd" = --eval ]]; then + FAST_HIGHLIGHT[chroma-node-file]=0 + fi +elif (( FAST_HIGHLIGHT[chroma-node-file] )); then + if [[ "$__wrd" = debug || "$__wrd" = inspect ]]; then + __style=${FAST_THEME_NAME}subcommand + else + FAST_HIGHLIGHT[chroma-node-file]=0 + if [[ -f ${~__wrd} || -f ${~__wrd}.js || -f ${~__wrd}/index.js ]]; then + __style=${FAST_THEME_NAME}path + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + fi + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + (( this_word = next_word )) + _start_pos=$_end_pos + + return 0 +fi + +return 1 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ogit.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ogit.ch new file mode 100644 index 0000000..06f0d75 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ogit.ch @@ -0,0 +1,383 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# Copyright (c) 2018 plexigras +# +# The old chroma function for command `git'. It colorizes the part of command +# line that holds `git' invocation. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 +local -a __lines_list chroma_git_remote_subcommands +chroma_git_remote_subcommands=(add rename remove set-head set-branches get-url set-url set-url set-url show prune update) + +if (( __first_call )); then + # Called for the first time - new command + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global variables + FAST_HIGHLIGHT[chroma-git-counter]=0 + FAST_HIGHLIGHT[chroma-git-got-subcommand]=0 + FAST_HIGHLIGHT[chroma-git-subcommand]="" + FAST_HIGHLIGHT[chrome-git-got-msg1]=0 + FAST_HIGHLIGHT[chrome-git-got-anymsg]=0 + FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]=0 + FAST_HIGHLIGHT[chroma-git-checkout-new]=0 + FAST_HIGHLIGHT[chroma-git-fetch-multiple]=0 + FAST_HIGHLIGHT[chroma-git-branch-change]=0 + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=0 + return 1 +else + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if [[ "$__wrd" = "--" ]]; then + FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]=1 + __style=${FAST_THEME_NAME}double-hyphen-option + elif [[ "$__wrd" = -* && ${FAST_HIGHLIGHT[chroma-git-got-subcommand]} -eq 0 ]]; then + # Options occuring before a subcommand + if (( FAST_HIGHLIGHT[chroma-git-option-with-argument-active] == 0 )); then + if [[ "$__wrd" = -[^[:space:]-]#C ]]; then + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=2 + elif [[ "$__wrd" = -[^[:space:]-]#c ]]; then + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=1 + fi + fi + return 1 + else + # If at e.g. '>' or destination/source spec (of the redirection) + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + # If at main git option taking argument in a separate word (-C and -c) + elif (( FAST_HIGHLIGHT[chroma-git-option-with-argument-active] > 0 && \ + 0 == FAST_HIGHLIGHT[chroma-git-got-subcommand] )) + then + # Remember the value + __idx2=${FAST_HIGHLIGHT[chroma-git-option-with-argument-active]} + # Reset the is-argument mark-field + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=0 + + (( __idx2 == 2 )) && return 1 + # Other options' args (i.e. arg of -c) aren't routed to the big-loop + # as they aren't paths and aren't handled in any special way there + elif (( FAST_HIGHLIGHT[chroma-git-got-subcommand] == 0 )); then + FAST_HIGHLIGHT[chroma-git-got-subcommand]=1 + + # Check if the command is an alias - we want to highlight the + # aliased command just like the target command of the alias + -fast-run-command "git config --get-regexp 'alias.*'" chroma-git-alias-list "" $(( 10 * 60 )) + # Grep for line: alias.{user-entered-subcmd}[[:space:]], and remove alias. prefix + __lines_list=( ${${(M)__lines_list[@]:#alias.${__wrd}[[:space:]]##*}#alias.} ) + + if (( ${#__lines_list} > 0 )); then + # (*) + # First remove alias name (#*[[:space:]]) and the space after it, then + # remove any leading spaces from what's left (##[[:space:]]##), then + # remove everything except the first word that's in the left line + # (%%[[:space:]]##*, i.e.: "everything from right side up to any space") + FAST_HIGHLIGHT[chroma-git-subcommand]="${${${__lines_list[1]#*[[:space:]]}##[[:space:]]##}%%[[:space:]]##*}" + else + FAST_HIGHLIGHT[chroma-git-subcommand]="$__wrd" + fi + if (( __start_pos >= 0 )); then + # if subcommand exists + LANG=C -fast-run-command "git help -a" chroma-git-subcmd-list "" $(( 10 * 60 )) + # (s: :) will split on every space, but because the expression + # isn't double-quoted, the empty elements will be eradicated + # Some further knowledge-base: s-flag is special, it skips + # empty elements and creates an array (not a concatenated + # string) even when double-quoted. The normally needed @-flag + # that logically breaks the concaetnated string back into array + # in case of double-quoting has additional effect for s-flag: + # it finally blocks empty-elements eradication. + if [[ "${__lines_list[1]}" = See* ]]; then + # (**) + # git >= v2.20 + __lines_list=( ${(M)${${${(M)__lines_list[@]:# [[:blank:]]#[a-z]*}##[[:blank:]]##}%%[[:blank:]]##*}:#${FAST_HIGHLIGHT[chroma-git-subcommand]}} ) + else + # (**) + # git < v2.20 + __lines_list=( ${(M)${(s: :)${(M)__lines_list[@]:# [a-z]*}}:#${FAST_HIGHLIGHT[chroma-git-subcommand]}} ) + fi + + # Above we've checked: + # 1) If given subcommand is an alias (*) + # 2) If the command, or command pointed by the alias, exists (**) + # 3) There's little problem, git v2.20 outputs aliases in git help -a, + # which means that alias will be recognized as correct if it will + # point at another alias or on itself. That's a minor problem, a + # TODO for future planned optimization for v2.20 Git + # 4) Notice that the above situation is better than the previous - the + # alias is being verified to point to a valid git subcommand + # That's all that's needed to decide on the correctnes: + if (( ${#__lines_list} > 0 )); then + __style=${FAST_THEME_NAME}subcommand + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + fi + # The counter includes the subcommand itself + (( FAST_HIGHLIGHT[chroma-git-counter] += 1 )) + else + __wrd="${__wrd//\`/x}" + __arg="${__arg//\`/x}" + __wrd="${(Q)__wrd}" + if [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "push" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "pull" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "fetch" ]] \ + && (( ${FAST_HIGHLIGHT[chroma-git-fetch-multiple]} == 0 )); then + # if not option + if [[ "$__wrd" != -* || "${FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]}" -eq 1 ]]; then + (( FAST_HIGHLIGHT[chroma-git-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-git-counter] )) + if (( __idx1 == 2 )); then + -fast-run-git-command "git remote" "chroma-git-remotes" "" + else + __wrd="${__wrd%%:*}" + -fast-run-git-command "git for-each-ref --format='%(refname:short)' refs/heads" "chroma-git-branches" "refs/heads" + fi + # if remote/ref exists + if [[ -n ${__lines_list[(r)$__wrd]} ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__start_pos+${#__wrd}-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + # if ref (__idx1 == 3) does not exist and subcommand is push + elif (( __idx1 != 2 )) && [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "push" ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__start_pos+${#__wrd}-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + # if not existing remote name, because not an URL (i.e. no colon) + elif [[ $__idx1 -eq 2 && $__wrd != *:* ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__start_pos+${#__wrd}-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + fi + # if option + else + if [[ "$__wrd" = "--multiple" && "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "fetch" ]]; then + FAST_HIGHLIGHT[chroma-git-fetch-multiple]=1 + __style=${FAST_THEME_NAME}double-hyphen-option + else + return 1 + fi + fi + elif (( ${FAST_HIGHLIGHT[chroma-git-fetch-multiple]} )) \ + && [[ "$__wrd" != -* || "${FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]}" -eq 1 ]]; then + -fast-run-git-command "git remote" "chroma-git-remotes" "" + if [[ -n ${__lines_list[(r)$__wrd]} ]]; then + __style=${FAST_THEME_NAME}correct-subtle + fi + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "commit" ]]; then + match[1]="" + match[2]="" + # if previous argument is -m or current argument is --message=something + if (( FAST_HIGHLIGHT[chrome-git-got-msg1] == 1 && ! FAST_HIGHLIGHT[chrome-git-got-anymsg] )) \ + || [[ "$__wrd" = (#b)(--message=)(*) && "${FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]}" = 0 ]]; then + FAST_HIGHLIGHT[chrome-git-got-msg1]=0 + FAST_HIGHLIGHT[chrome-git-got-anymsg]=1 + if [[ -n "${match[1]}" ]]; then + __wrd="${(Q)${match[2]//\`/x}}" + # highlight (--message=)something + (( __start=__start_pos-${#PREBUFFER}, __end=__start_pos-${#PREBUFFER}+10, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-hyphen-option]}") + # highlight --message=(something) + (( __start=__start_pos-${#PREBUFFER}+10, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}") + else + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}") + fi + local __firstline=${__wrd%%$'\n'*} + if (( ${#__firstline} > 50 )); then + for (( __idx1 = 1, __idx2 = 1; __idx1 <= 50; ++ __idx1, ++ __idx2 )); do + while [[ "${__arg[__idx2]}" != "${__firstline[__idx1]}" ]]; do + (( ++ __idx2 )) + (( __idx2 > __asize )) && { __idx2=-1; break; } + done + (( __idx2 == -1 )) && break + done + if (( __idx2 != -1 )); then + if [[ -n "${match[1]}" ]]; then + (( __start=__start_pos-${#PREBUFFER}+__idx2, __end=__end_pos-${#PREBUFFER}-$#__wrd+$#__firstline-1, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + else + (( __start=__start_pos-${#PREBUFFER}+__idx2-1, __end=__end_pos-${#PREBUFFER}-$#__wrd+$#__firstline-1, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + fi + fi + fi + # if before -- + elif [[ "${FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]}" = 0 ]]; then + if [[ "$__wrd" = -[^[:space:]-]#m ]]; then + FAST_HIGHLIGHT[chrome-git-got-msg1]=1 + __style=${FAST_THEME_NAME}single-hyphen-option + else + return 1 + fi + # if after -- is file + elif [[ -e "$__wrd" ]]; then + __style=${FAST_THEME_NAME}path + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "checkout" ]] \ + || [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "revert" ]] \ + || [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "merge" ]] \ + || [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "diff" ]] \ + || [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "reset" ]] \ + || [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "rebase" ]]; then + + # if doing `git checkout -b ...' + if [[ "$__wrd" = -[^[:space:]-]#b && "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "checkout" ]]; then + FAST_HIGHLIGHT[chroma-git-checkout-new]=1 + __style=${FAST_THEME_NAME}single-hyphen-option + # if command is not checkout -b something + elif [[ "${FAST_HIGHLIGHT[chroma-git-checkout-new]}" = 0 ]]; then + # if not option + if [[ "$__wrd" != -* || "${FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]}" = 1 ]]; then + (( FAST_HIGHLIGHT[chroma-git-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-git-counter] )) + if (( __idx1 == 2 )) || \ + [[ "$__idx1" = 3 && "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "diff" ]]; then + # if is ref + if command git rev-parse --verify --quiet "$__wrd" >/dev/null 2>&1; then + __style=${FAST_THEME_NAME}correct-subtle + # if is file and subcommand is checkout or diff + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "checkout" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "reset" \ + || "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "diff" ]] && [[ -e ${~__wrd} ]]; then + __style=${FAST_THEME_NAME}path + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "checkout" && \ + "1" = "$(command git rev-list --count --no-walk --glob="refs/remotes/${$(git \ + config --get checkout.defaultRemote):-*}/$__wrd")" ]] + then + __style=${FAST_THEME_NAME}correct-subtle + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + fi + # if option + else + return 1 + fi + # if option + elif [[ "${FAST_HIGHLIGHT[chrome-git-occurred-double-hyphen]}" = 0 && "$__wrd" = -* ]]; then + return 1 + fi + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "remote" && "$__wrd" != -* ]]; then + (( FAST_HIGHLIGHT[chroma-git-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-git-counter] )) + if [[ "$__idx1" = 2 ]]; then + if (( ${chroma_git_remote_subcommands[(I)$__wrd]} )); then + FAST_HIGHLIGHT[chroma-git-remote-subcommand]="$__wrd" + __style=${FAST_THEME_NAME}subcommand + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + elif [[ "$__idx1" = 3 && "$FAST_HIGHLIGHT[chroma-git-remote-subcommand]" = "add" ]]; then + -fast-run-git-command "git remote" "chroma-git-remotes" "" + if [[ -n ${__lines_list[(r)$__wrd]} ]]; then + __style=${FAST_THEME_NAME}incorrect-subtle + fi + elif [[ "$__idx1" = 3 && -n "$FAST_HIGHLIGHT[chroma-git-remote-subcommand]" ]]; then + -fast-run-git-command "git remote" "chroma-git-remotes" "" + if [[ -n ${__lines_list[(r)$__wrd]} ]]; then + __style=${FAST_THEME_NAME}correct-subtle + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + fi + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "branch" ]]; then + if [[ "$__wrd" = --delete \ + || "$__wrd" = --edit-description \ + || "$__wrd" = --set-upstream-to=* \ + || "$__wrd" = --unset-upstream \ + || "$__wrd" = -[^[:space:]-]#d \ + || "$__wrd" = -[^[:space:]-]#D ]]; then + FAST_HIGHLIGHT[chroma-git-branch-change]=1 + return 1 + elif [[ "$__wrd" != -* ]]; then + -fast-run-git-command "git for-each-ref --format='%(refname:short)' refs/heads" "chroma-git-branches" "refs/heads" + if [[ -n ${__lines_list[(r)$__wrd]} ]]; then + __style=${FAST_THEME_NAME}correct-subtle + elif (( FAST_HIGHLIGHT[chroma-git-branch-change] )); then + __style=${FAST_THEME_NAME}incorrect-subtle + fi + else + return 1 + fi + elif [[ "${FAST_HIGHLIGHT[chroma-git-subcommand]}" = "tag" ]]; then + if [[ "${FAST_HIGHLIGHT[chroma-git-option-with-argument-active]}" -le 0 ]]; then + if [[ "$__wrd" = -[^[:space:]-]#(u|m) ]]; then + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=1 + elif [[ "$__wrd" = -[^[:space:]-]#F ]]; then + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=2 + elif [[ "$__wrd" = -[^[:space:]-]#d ]]; then + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=3 + elif [[ "$__wrd" = (--contains|--no-contains|--points-at|--merged|--no-merged) ]]; then + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=4 + fi + if [[ "$__wrd" != -* ]]; then + (( FAST_HIGHLIGHT[chroma-git-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-git-counter] )) + if [[ ${FAST_HIGHLIGHT[chroma-git-counter]} -eq 2 ]]; then + -fast-run-git-command "git for-each-ref --format='%(refname:short)' refs/heads" "chroma-git-branches" "refs/heads" + -fast-run-git-command "+git tag" "chroma-git-tags" "" + [[ -n ${__lines_list[(r)$__wrd]} ]] && __style=${FAST_THEME_NAME}incorrect-subtle + elif [[ ${FAST_HIGHLIGHT[chroma-git-counter]} -eq 3 ]]; then + fi + else + return 1 + fi + else + case "${FAST_HIGHLIGHT[chroma-git-option-with-argument-active]}" in + (1) + __style=${FAST_THEME_NAME}optarg-string + ;; + (2) + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=0 + return 1; + ;; + (3) + -fast-run-git-command "git tag" "chroma-git-tags" "" + [[ -n ${__lines_list[(r)$__wrd]} ]] && \ + __style=${FAST_THEME_NAME}correct-subtle || \ + __style=${FAST_THEME_NAME}incorrect-subtle + ;; + (4) + if git rev-parse --verify --quiet "$__wrd" >/dev/null 2>&1; then + __style=${FAST_THEME_NAME}correct-subtle + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + ;; + esac + FAST_HIGHLIGHT[chroma-git-option-with-argument-active]=0 + fi + else + return 1 + fi + fi + fi +fi + +# Add region_highlight entry (via `reply' array) +if [[ -n "$__style" ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") +fi + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-perl.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-perl.ch new file mode 100644 index 0000000..49f0ad3 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-perl.ch @@ -0,0 +1,80 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma function for command `perl'. It highlights code passed to perl +# with -e option - does syntax check by calling `perl -ce', then highlights +# as correct or incorrect code. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global variables. + FAST_HIGHLIGHT[chrome-perl-got-eswitch]=0 + return 1 +} || { + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* && ${FAST_HIGHLIGHT[chroma-perl-got-subcommand]} -eq 0 ]]; then + __style=${FAST_THEME_NAME}${${${__wrd:#--*}:+single-hyphen-option}:-double-hyphen-option} + + if [[ "$__wrd" = "-e" || ("$__wrd" = -*e* && "$__wrd" != --*) ]]; then + FAST_HIGHLIGHT[chrome-perl-got-eswitch]=1 + fi + else + __wrd="${__wrd//\`/x}" + __arg="${__arg//\`/x}" + __wrd="${(Q)__wrd}" + if (( FAST_HIGHLIGHT[chrome-perl-got-eswitch] == 1 )); then + FAST_HIGHLIGHT[chrome-perl-got-eswitch]=0 + if perl -ce "$__wrd" >/dev/null 2>&1; then + # Add correct-subtle style + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + else + # Add incorrect-subtle style + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + fi + else + # Pass-through to the big-loop outside + return 1 + fi + fi +} + +# Add region_highlight entry (via `reply' array) +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does) and skip setting __style +# to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-precommand.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-precommand.ch new file mode 100644 index 0000000..7e85a06 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-precommand.ch @@ -0,0 +1,17 @@ +# vim:ft=zsh:et:sw=4 + +local __first_call="$1" __start_pos="$3" __end_pos="$4" + +[[ "$__arg_type" = 3 ]] && return 2 + +(( __first_call )) && { + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}precommand]}") + (( next_word = (next_word & ~2) | 4 | 1 )) +} || { + return 1 +} + +(( this_word = next_word )) +_start_pos=$_end_pos +return 0 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-printf.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-printf.ch new file mode 100644 index 0000000..89d2789 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-printf.ch @@ -0,0 +1,86 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Highlights the special sequences like "%s" in string passed to `printf'. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __val +integer __idx1 __idx2 + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-printf-counter]=0 + FAST_HIGHLIGHT[chroma-printf-counter-all]=1 + FAST_HIGHLIGHT[chroma-printf-message]="" + FAST_HIGHLIGHT[chroma-printf-skip-two]=0 + return 1 +# Following call (not first one). +} || { + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + (( FAST_HIGHLIGHT[chroma-printf-counter-all] += 1, __idx2 = FAST_HIGHLIGHT[chroma-printf-counter-all] )) + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if [[ "$__wrd" = -* ]]; then + if [[ "$__wrd" = "-v" ]]; then + FAST_HIGHLIGHT[chroma-printf-skip-two]=1 + fi + return 1 + else + # Count non-option tokens. + if (( FAST_HIGHLIGHT[chroma-printf-skip-two] )); then + FAST_HIGHLIGHT[chroma-printf-skip-two]=0 + return 1 + else + (( FAST_HIGHLIGHT[chroma-printf-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-printf-counter] )) + if [[ "$__idx1" -eq 1 ]]; then + [[ "$__wrd" = \"* ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}") + [[ "$__wrd" = \'* ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}single-quoted-argument]}") + FSH_LIST=() # use fsh_sy_h_append function to write to FSH_LIST + : "${__wrd//(#m)\%[\#\+\ 0-]#[0-9]#([.][0-9]#)(#c0,1)[diouxXfFeEgGaAcsb]/$(( fsh_sy_h_append($MBEGIN, $MEND) ))}"; + for __val in "${FSH_LIST[@]}" ; do + __idx1=$(( __start_pos + ${__val%%;;*} )) + __idx2=__idx1+${__val##*;;}-${__val%%;;*}+1 + (( __start=__idx1-${#PREBUFFER}, __end=__idx2-${#PREBUFFER}-1, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathnum]}") + done + else + return 1 + fi + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above code +# can do it itself and skip setting __style to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ruby.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ruby.ch new file mode 100644 index 0000000..3495cc8 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ruby.ch @@ -0,0 +1,81 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma function for command `ruby'. It highlights code passed to ruby +# with -e option - does syntax check by calling `ruby -ce', then highlights +# as correct or incorrect code. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global variables. + FAST_HIGHLIGHT[chrome-ruby-got-eswitch]=0 + return 1 +} || { + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* && ${FAST_HIGHLIGHT[chroma-ruby-got-subcommand]} -eq 0 ]]; then + __style=${FAST_THEME_NAME}${${${__wrd:#--*}:+single-hyphen-option}:-double-hyphen-option} + + if [[ "$__wrd" = "-e" || ("$__wrd" = -*e* && "$__wrd" != --*) ]]; then + FAST_HIGHLIGHT[chrome-ruby-got-eswitch]=1 + fi + else + __wrd="${__wrd//\`/x}" + __arg="${__arg//\`/x}" + __wrd="${(Q)__wrd}" + if (( FAST_HIGHLIGHT[chrome-ruby-got-eswitch] == 1 )); then + FAST_HIGHLIGHT[chrome-ruby-got-eswitch]=0 + if ruby -ce "$__wrd" >/dev/null 2>&1; then + # Add correct-subtle style + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]}") + else + # Add incorrect-subtle style + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") + fi + else + # Pass-through to the big-loop outside + return 1 + fi + FAST_HIGHLIGHT[chrome-ruby-got-eswitch]=0 + fi +} + +# Add region_highlight entry (via `reply' array) +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does) and skip setting __style +# to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-scp.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-scp.ch new file mode 100644 index 0000000..d162284 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-scp.ch @@ -0,0 +1,87 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Tracks scp command and emits message when one tries to pass port to hostspec. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __chars +integer __idx1 __idx2 +local -a __results + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-scp-counter]=0 + FAST_HIGHLIGHT[chroma-scp-counter-all]=1 + FAST_HIGHLIGHT[chroma-scp-message]="" + FAST_HIGHLIGHT[chroma-scp-skip-two]=0 + return 1 +} || { + (( FAST_HIGHLIGHT[chroma-scp-counter-all] += 1, __idx2 = FAST_HIGHLIGHT[chroma-scp-counter-all] )) + + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + if [[ "$__wrd" = (-c|-F|-i|-l|-o|-P|-S) ]]; then + FAST_HIGHLIGHT[chroma-scp-skip-two]=1 + fi + else + # Count non-option tokens. + if (( FAST_HIGHLIGHT[chroma-scp-skip-two] )); then + FAST_HIGHLIGHT[chroma-scp-skip-two]=0 + else + (( FAST_HIGHLIGHT[chroma-scp-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-scp-counter] )) + if [[ "${FAST_HIGHLIGHT[chroma-scp-counter]}" -eq 1 ]]; then + if [[ "$__arg" = [^:]##:[0-9]## ]]; then + FAST_HIGHLIGHT[chroma-scp-message]+="Format of hostname incorrect, use -P to pass port number" + else + return 1 + fi + else + return 1 + fi + fi + fi + + if (( ${#${(z)BUFFER}} <= FAST_HIGHLIGHT[chroma-scp-counter-all] )); then + [[ -n "${FAST_HIGHLIGHT[chroma-scp-message]}" ]] && zle -M "${FAST_HIGHLIGHT[chroma-scp-message]}" + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above code +# can do it itself and skip setting __style to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-sh.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-sh.ch new file mode 100644 index 0000000..13c8ded --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-sh.ch @@ -0,0 +1,72 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma function for `sh' shell. It colorizes string passed with -c option. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 +local -a __lines_list + +(( __first_call )) && { + # Called for the first time - new command + FAST_HIGHLIGHT[chrome-git-got-c]=0 + return 1 +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + __wrd="${${${(Q)__wrd}#[\"\']}%[\"\']}" + if [[ "$__wrd" = -* && "$__wrd" != -*c* ]]; then + __style=${FAST_THEME_NAME}${${${__wrd:#--*}:+single-hyphen-option}:-double-hyphen-option} + else + if (( FAST_HIGHLIGHT[chrome-git-got-c] == 1 )); then + for (( __idx1 = 1, __idx2 = 1; __idx2 <= __asize; ++ __idx1 )); do + [[ "${__arg[__idx2]}" = "${__wrd[__idx1]}" ]] && break + while [[ "${__arg[__idx2]}" != "${__wrd[__idx1]}" ]]; do + (( ++ __idx2 )) + (( __idx2 > __asize )) && { __idx2=0; break; } + done + (( __idx2 == 0 )) && break + [[ "${__arg[__idx2]}" = "${__wrd[__idx1]}" ]] && break + done + + FAST_HIGHLIGHT[chrome-git-got-c]=0 + (( _start_pos-__PBUFLEN >= 0 )) && \ + -fast-highlight-process "$PREBUFFER" "${__wrd}" "$(( __start_pos + __idx2 - 1 ))" + elif [[ "$__wrd" = -*c* ]]; then + FAST_HIGHLIGHT[chrome-git-got-c]=1 + else + return 1 + fi + fi +} + +# Add region_highlight entry (via `reply' array) +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-source.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-source.ch new file mode 100644 index 0000000..dc27e76 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-source.ch @@ -0,0 +1,75 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma for `source' builtin - verifies if file to be sourced compiles +# correctly. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __chars __home=${XDG_CACHE_HOME:-$HOME/.cache}/fsh +integer __idx1 __idx2 + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-src-counter]=0 + __style=${FAST_THEME_NAME}builtin + +} || { + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + else + # Count non-option tokens. + (( FAST_HIGHLIGHT[chroma-src-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-src-counter] )) + + if (( FAST_HIGHLIGHT[chroma-src-counter] == 1 )); then + command mkdir -p "$__home" + command cp -f "${__wrd}" "$__home" 2>/dev/null && { + zcompile "$__home"/"${__wrd:t}" 2>/dev/null 1>&2 && __style=${FAST_THEME_NAME}correct-subtle || __style=${FAST_THEME_NAME}incorrect-subtle + } + elif (( FAST_HIGHLIGHT[chroma-src-counter] == 2 )); then + # Handle paths, etc. normally - just pass-through to the big + # highlighter (the main FSH highlighter, used before chromas). + return 1 + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does) and skip setting __style +# to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ssh.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ssh.ch new file mode 100644 index 0000000..879158f --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-ssh.ch @@ -0,0 +1,156 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# Copyright (C) 2019 by Philippe Troin (F-i-f on GitHub) +# +# Tracks ssh command and emits message when one tries to pass port to hostspec. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +emulate -LR zsh +setopt extended_glob warn_create_global typeset_silent + +# This chroma guards that port number isn't passed in hostname (no :{port} occurs). + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style check_port=0 host_start_offset host_style user_style possible_host +local -a match mbegin mend completions_user completions_host + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-ssh-counter]=0 + FAST_HIGHLIGHT[chroma-ssh-counter-all]=1 + FAST_HIGHLIGHT[chroma-ssh-message]="" + FAST_HIGHLIGHT[chroma-ssh-skip-two]=0 + return 1 +} || { + # Following call, i.e. not the first one. + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + (( FAST_HIGHLIGHT[chroma-ssh-counter-all] += 1 )) + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + if [[ "$__wrd" = (-b|-c|-D|-E|-e|-F|-I|-i|-J|-L|-l|-m|-O|-o|-p|Q|R|-S|-W|-w) ]]; then + FAST_HIGHLIGHT[chroma-ssh-skip-two]=1 + fi + else + if (( FAST_HIGHLIGHT[chroma-ssh-skip-two] )); then + FAST_HIGHLIGHT[chroma-ssh-skip-two]=0 + else + # Count non-option tokens. + (( FAST_HIGHLIGHT[chroma-ssh-counter] += 1 )) + if [[ "${FAST_HIGHLIGHT[chroma-ssh-counter]}" -eq 1 ]]; then + if [[ $__arg = (#b)(([^@]#)(@)|)(*) ]] + then + [[ -n $match[2] ]] \ + && { + user_style= + () { + # Zstyle clobbers reply for sure + zstyle -a ":completion:*:users" users completions_users + } + (( ! $#completions_users )) && completions_users=(${(k)userdirs}) + if (( $#completions_users )); then + [[ $match[2] = ${~${:-(${(j:|:)completions_users})}} ]] \ + && user_style=${FAST_THEME_NAME}correct-subtle \ + || user_style=${FAST_THEME_NAME}incorrect-subtle + fi + [[ -n $user_style ]] \ + && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}-(mend[5]-mend[2]), __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$user_style]}") + } + [[ -n $match[3] ]] \ + && (( __start=__start_pos-${#PREBUFFER}+(mbegin[3]-mbegin[1]), __end=__end_pos-${#PREBUFFER}-(mend[5]-mend[3]), __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}subtle-separator]}") + + host_style= + case $match[4] in + (<->|<0-255>.<0-255>.<0-255>.<0-255>) + host_style=${FAST_THEME_NAME}mathnum + check_port=1 + ;; + (([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]) + host_style=${FAST_THEME_NAME}mathnum + ;; + (*) + check_port=1 + ;; + esac + possible_host=$match[4] + (( host_start_offset = mbegin[4] - mbegin[1], host_end_offset = 0 )) + + if (( check_port )) && [[ $possible_host = (#b)(*)(:[0-9]##) ]]; then + (( __start=__start_pos-${#PREBUFFER}+(host_start_offset+mbegin[2]-mbegin[1]), __end=__end_pos-host_end_offset-${#PREBUFFER}, __start >= 0, + host_end_offset+=mend[2]-mend[1] )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]}") \ + && possible_host=$match[1] \ + && FAST_HIGHLIGHT[chroma-ssh-message]+="Format of hostname incorrect, use -p to pass port number" + + fi + + if [[ -z $host_style ]]; then + () { + # Zstyle clobbers reply for sure + local mbegin mend match reply + zstyle -a ":completion:*:hosts" hosts completions_host + } + (( ! $#completions_host && $+_cache_hosts )) && completions_host=($_cache_hosts[*]) + if (( $#completions_host )); then + [[ $possible_host = ${~${:-(${(j:|:)completions_host})}} ]] \ + && host_style=${FAST_THEME_NAME}correct-subtle \ + || host_style=${FAST_THEME_NAME}incorrect-subtle + fi + fi + + [[ -n $host_style ]] \ + && (( __start=__start_pos-${#PREBUFFER}+host_start_offset, __end=__end_pos-${#PREBUFFER}-host_end_offset, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$host_style]}") + else + __style=${FAST_THEME_NAME}incorrect-subtle + fi + + (( next_word = 1 )) + + fi + fi + fi + + if (( ${#${(z)BUFFER}} <= FAST_HIGHLIGHT[chroma-ssh-counter-all] )); then + [[ -n "${FAST_HIGHLIGHT[chroma-ssh-message]}" ]] && zle -M "${FAST_HIGHLIGHT[chroma-ssh-message]}" + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above code +# can do it itself and skip setting __style to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-subcommand.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-subcommand.ch new file mode 100644 index 0000000..0665548 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-subcommand.ch @@ -0,0 +1,25 @@ +# vim:ft=zsh:et:sw=4 +(( next_word = 2 | 8192 )) +[[ "$__arg_type" = 3 ]] && return 2 + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" + +if (( __first_call )); then + FAST_HIGHLIGHT[chroma-subcommand]="" + return 1 +elif (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +elif [[ "$2" = -* ]]; then + return 1 +elif [[ -z "${FAST_HIGHLIGHT[chroma-subcommand]}" ]]; then + FAST_HIGHLIGHT[chroma-subcommand]="$__wrd" + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}subcommand]}") +else + return 1 +fi + +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-subversion.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-subversion.ch new file mode 100644 index 0000000..57b5674 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-subversion.ch @@ -0,0 +1,252 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2018 Sebastian Gniazdowski +# Copyright (C) 2019 by Philippe Troin (F-i-f on GitHub) +# 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. +# ------------------------------------------------------------------------------------------------- + +chroma/-subversion.ch/parse-revision() { + setopt local_options extendedglob warn_create_global typeset_silent + local __wrd="$1" __start_pos="$2" __end_pos="$3" __style __start __end + case $__wrd in + (r|)[0-9]##) __style=${FAST_THEME_NAME}mathnum ;; + (HEAD|BASE|COMITTED|PREV)) __style=${FAST_THEME_NAME}correct-subtle ;; + '{'[^}]##'}') __style=${FAST_THEME_NAME}subtle-bg ;; + *) __style=${FAST_THEME_NAME}incorrect-subtle ;; + esac + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") +} + +chroma/-subversion.ch/parse-target() { + setopt local_options extendedglob warn_create_global typeset_silent + local __wrd="$1" __start_pos="$2" __end_pos="$3" __style __start __end + if [[ $__wrd == *@[^/]# ]] + then + local place=${__wrd%@[^/]#} + local rev=$__wrd[$(($#place+2)),$#__wrd] + if [[ -e $place ]]; then + local __style + [[ -d $place ]] && __style="${FAST_THEME_NAME}path-to-dir" || __style="${FAST_THEME_NAME}path" + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}-$#rev-1, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + fi + (( __start=__start_pos-${#PREBUFFER}+$#place, __end=__end_pos-${#PREBUFFER}-$#rev, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-separator]}") + chroma/-subversion.ch/parse-revision $rev $((__start_pos+$#place+1)) $__end_pos + else + return 1 + fi +} + +chroma/-subversion.ch() { + setopt local_options extendedglob warn_create_global + + # Keep chroma-takever state meaning: until ;, handle highlighting via chroma. + # So the below 8192 assignment takes care that next token will be routed to chroma. + (( next_word = 2 | 8192 )) + + local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" + local __style + integer __idx1 __idx2 + + (( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global string variables. + FAST_HIGHLIGHT[subversion-command]=$__wrd + FAST_HIGHLIGHT[subversion-option-argument]= + FAST_HIGHLIGHT[subversion-subcommand]= + FAST_HIGHLIGHT[subversion-subcommand-arguments]=0 + + # Set style for region_highlight entry. It is used below in + # '[[ -n "$__style" ]] ...' line, which adds highlight entry, + # like "10 12 fg=green", through `reply' array. + # + # Could check if command `example' exists and set `unknown-token' + # style instead of `command' + __style=${FAST_THEME_NAME}command + + } || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + case $FAST_HIGHLIGHT[subversion-command]/$FAST_HIGHLIGHT[subversion-subcommand] in + svn/) + case $__wrd in + --username|-u) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --password|-p) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --config-(dir|option)) FAST_HIGHLIGHT[subversion-option-argument]=any;; + esac + ;; + svn/?*) + case $__wrd in + --accept) FAST_HIGHLIGHT[subversion-option-argument]=accept;; + --change|-c) FAST_HIGHLIGHT[subversion-option-argument]=revision;; + --changelist|--cl) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --(set-|)depth) FAST_HIGHLIGHT[subversion-option-argument]=depth;; + --diff(3|)-cmd) FAST_HIGHLIGHT[subversion-option-argument]=cmd;; + --editor-cmd) FAST_HIGHLIGHT[subversion-option-argument]=cmd;; + --encoding) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --file) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --limit|-l) FAST_HIGHLIGHT[subversion-option-argument]=number;; + --message|-m) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --native-eol) FAST_HIGHLIGHT[subversion-option-argument]=eol;; + --new|--old) FAST_HIGHLIGHT[subversion-option-argument]=target;; + --revision|-r) FAST_HIGHLIGHT[subversion-option-argument]=revision-pair;; + --show-revs) FAST_HIGHLIGHT[subversion-option-argument]=show-revs;; + --strip) FAST_HIGHLIGHT[subversion-option-argument]=number;; + --with-revprop) FAST_HIGHLIGHT[subversion-option-argument]=revprop;; + esac + ;; + svnadmin/*) + case $__wrd in + --config-dir) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --fs-type) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --memory-cache-size|-M) FAST_HIGHLIGHT[subversion-option-argument]=number;; + --parent-dir) FAST_HIGHLIGHT[subversion-option-argument]=any;; + --revision|-r) FAST_HIGHLIGHT[subversion-option-argument]=revision-pair;; + esac + ;; + svndumpfilter/*) + case $__wrd in + --targets) FAST_HIGHLIGHT[subversion-option-argument]=any;; + esac + ;; + esac + elif [[ -n $FAST_HIGHLIGHT[subversion-option-argument] ]]; then + case $FAST_HIGHLIGHT[subversion-option-argument] in + any) + FAST_HIGHLIGHT[subversion-option-argument]= + return 1 + ;; + accept) + [[ $__wrd = (p(|ostpone)|e(|dit)|l(|aunch)|base|working|recommended|[mt][cf]|(mine|theirs)-(conflict|full)) ]] \ + && __style=${FAST_THEME_NAME}correct-subtle \ + || __style=${FAST_THEME_NAME}incorrect-subtle + ;; + depth) + [[ $__wrd = (empty|files|immediates|infinity) ]] \ + && __style=${FAST_THEME_NAME}correct-subtle \ + || __style=${FAST_THEME_NAME}incorrect-subtle + ;; + number) + [[ $__wrd = [0-9]## ]] \ + && __style=${FAST_THEME_NAME}mathnum \ + || __style=${FAST_THEME_NAME}incorrect-subtle + ;; + eol) + [[ $__wrd = (CR(|LF)|LF) ]] \ + && __style=${FAST_THEME_NAME}correct-subtle \ + || __style=${FAST_THEME_NAME}incorrect-subtle + ;; + show-revs) + [[ $__wrd = (merged|eligible) ]] \ + && __style=${FAST_THEME_NAME}correct-subtle \ + || __style=${FAST_THEME_NAME}incorrect-subtle + ;; + revision) + chroma/-subversion.ch/parse-revision $__wrd $__start_pos $__end_pos + ;; + revision-pair) + local -a match mbegin mend + if [[ $__wrd = (#b)(\{[^}]##\}|[^:]##)(:)(*) ]]; then + chroma/-subversion.ch/parse-revision $match[1] $__start_pos $(( __end_pos - ( mend[3]-mend[2] ) - 1 )) + chroma/-subversion.ch/parse-revision $match[3] $(( __start_pos + ( mbegin[3]-mbegin[1] ) )) $__end_pos + (( __start=__start_pos-${#PREBUFFER}+(mbegin[2]-mbegin[1]), __end=__end_pos-${#PREBUFFER}-(mend[3]-mend[2]), __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}for-loop-separator]}") + else + chroma/-subversion.ch/parse-revision $__wrd $__start_pos $__end_pos + fi + ;; + target) + chroma/-subversion.ch/parse-target $__wrd $__start_pos $__end_pos || return $? + ;; + cmd) + this_word=1 + return 1 + ;; + esac + FAST_HIGHLIGHT[subversion-option-argument]= + elif [[ -z $FAST_HIGHLIGHT[subversion-subcommand] ]] + then + FAST_HIGHLIGHT[subversion-subcommand]=$__wrd + local subcmds + case $FAST_HIGHLIGHT[subversion-command] in + svn) subcmds='(add|auth|blame|praise|annotate|ann|cat|changelist|cl|checkout|co|cleanup|commit|ci|copy|cp|delete|del|remove|rm|diff|di|export|help|\?|h|import|info|list|ls|lock|log|merge|mergeinfo|mkdir|move|mv|rename|ren|patch|propdel|pdel|pd|propedit|pedit|pe|propget|pget|pg|proplist|plist|pl|propset|pset|ps|relocate|resolve|resolved|revert|status|stat|st|switch|sw|unlock|update|up|upgrade|x-shelf-diff|x-shelf-drop|x-shelf-list|x-shelves|x-shelf-list-by-paths|x-shelf-log|x-shelf-save|x-shelve|x-unshelve)' ;; + svnadmin) subcmds="(crashtest|create|delrevprop|deltify|dump|dump-revprops|freeze|help|\?|h|hotcopy|info|list-dblogs|list-unused-dblogs|load|load-revprops|lock|lslocks|lstxns|pack|recover|rmlocks|rmtxns|setlog|setrevprop|setuuid|unlock|upgrade|verify)";; + svndumpfilter) subcmds='(include|exclude|help|\?)';; + esac + [[ $FAST_HIGHLIGHT[subversion-subcommand] = $~subcmds ]] \ + && __style=${FAST_THEME_NAME}subcommand \ + || __style=${FAST_THEME_NAME}incorrect-subtle + FAST_HIGHLIGHT[subversion-subcommand-arguments]=0 + else + (( FAST_HIGHLIGHT[subversion-subcommand-arguments]+=1 )) + if [[ ( $FAST_HIGHLIGHT[subversion-subcommand] == (checkout|co|export|log|merge|switch|sw) && $FAST_HIGHLIGHT[subversion-subcommand-arguments] -eq 1 ) \ + || $FAST_HIGHLIGHT[subversion-subcommand] == (blame|praise|annotate|ann|cat|copy|cp|diff|info|list|ls|mergeinfo) ]]; then + chroma/-subversion.ch/parse-target $__wrd $__start_pos $__end_pos || return $? + else + return 1 + fi + fi + } + + # Add region_highlight entry (via `reply' array). + # If 1 will be added to __start_pos, this will highlight "oken". + # If 1 will be subtracted from __end_pos, this will highlight "toke". + # $PREBUFFER is for specific situations when users does command \<ENTER> + # i.e. when multi-line command using backslash is entered. + # + # This is a common place of adding such entry, but any above code can do + # it itself (and it does in other chromas) and skip setting __style to + # this way disable this code. + [[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + + # We aren't passing-through, do obligatory things ourselves. + # _start_pos=$_end_pos advainces pointers in command line buffer. + # + # To pass through means to `return 1'. The highlighting of + # this single token is then done by fast-syntax-highlighting's + # main code and chroma doesn't have to do anything. + (( this_word = next_word )) + _start_pos=$_end_pos + + return 0 + + # vim:ft=zsh:et:sw=4 +} diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-vim.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-vim.ch new file mode 100644 index 0000000..b3fecd1 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-vim.ch @@ -0,0 +1,51 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Chroma for vim, shows last opened files under prompt. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __chars +integer __idx1 __idx2 +local -a __viminfo + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + (( ${+commands[vim]} )) && __style=${FAST_THEME_NAME}command || __style=${FAST_THEME_NAME}unknown-token + + { __viminfo=( ${(f)"$(<$HOME/.viminfo)"} ); } >> /dev/null + __viminfo=( "${${(M)__viminfo[@]:#>*}[@]:t}" ) + __viminfo=( "${__viminfo[@]:#COMMIT_EDITMSG}" ) + zle -M "Last opened:"$'\n'"${(F)__viminfo[1,5]}" +} || { + # Pass almost everything to big loop + return 1 +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above +# code can do it itself (and it does, see other chromas) and +# skip setting __style to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-whatis.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-whatis.ch new file mode 100644 index 0000000..ce59e8f --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-whatis.ch @@ -0,0 +1,134 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018-2019 Sebastian Gniazdowski + +(( next_word = 2 | 8192 )) +local THEFD check __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" + +(( ! ${+FAST_HIGHLIGHT[whatis_chroma_callback_was_ran]} )) && \ + FAST_HIGHLIGHT[whatis_chroma_callback_was_ran]=0 + +(( ! ${+FAST_HIGHLIGHT[whatis_chroma_zle_-F_have_-w_opt]} )) && { + is-at-least 5.0.6 && local __res=1 || local __res=0 + FAST_HIGHLIGHT[whatis_chroma_zle_-F_have_-w_opt]="$__res" +} + +-fast-whatis-chroma-callback() { + emulate -L zsh + setopt extendedglob warncreateglobal typesetsilent + + local THEFD="$1" input check=2 nl=$'\n' __wrd __style + + -fast-zts-read-all "$THEFD" input + + zle -F "$THEFD" + exec {THEFD}<&- + + __wrd="${${input#[^$nl]#$nl}%%$nl*}" + if [[ "$input" = test* ]]; then + if [[ "${input%$nl}" = *[^0-9]'0' ]]; then + if [[ "${input#test$nl}" = *nothing\ appropriate* ]]; then + FAST_HIGHLIGHT[whatis_chroma_type]=2 + else + FAST_HIGHLIGHT[whatis_chroma_type]=0 + fi + else + FAST_HIGHLIGHT[whatis_chroma_type]=1 + fi + elif [[ "$input" = type2* ]]; then + [[ "$input" != *nothing\ appropriate* ]] && check=1 || check=0 + elif [[ "$input" = type1* ]]; then + [[ "${input%$nl}" = *0 ]] && check=1 || check=0 + fi + + if (( check != 2 )); then + FAST_HIGHLIGHT[whatis-cache-$__wrd]=$check + if (( check )) then + __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]} + elif [[ ${~__wrd} = */* && -e ${~__wrd} ]] then + __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path]} + else + __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]} + fi + local -a start_end + start_end=( ${(s:/:)${${(M)${${input#type?${nl}[^$nl]#$nl}}#*$nl}%$nl}} ) + (( start_end[1] >= 0 )) && region_highlight+=("$start_end[1] $start_end[2] $__style") + zle -R + fi + + FAST_HIGHLIGHT[whatis_chroma_callback_was_ran]=1 + return 0 +} + +zle -N -- -fast-whatis-chroma-callback + +if (( __first_call )) && [[ -z "${FAST_HIGHLIGHT[whatis_chroma_type]}" ]] ;then + if ! command -v whatis > /dev/null; then + FAST_HIGHLIGHT[whatis_chroma_type]=0 + return 1 + fi + + exec {THEFD}< <( + print "test" + LANG=C whatis "osx whatis fallback check" + print "$?" + ) + command true # a workaround of Zsh bug + zle -F ${${FAST_HIGHLIGHT[whatis_chroma_zle_-F_have_-w_opt]:#0}:+-w} "$THEFD" -fast-whatis-chroma-callback +fi + +[[ "$__arg_type" = 3 ]] && return 2 + +if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 +fi + +if (( __first_call )) || [[ "$__wrd" = -* ]]; then + return 1 +elif (( ! FAST_HIGHLIGHT[whatis_chroma_type] )); then + # Return 1 (i.e. treat the argument as a path) only if the callback have + # had a chance to establish the whatis_chroma_type field + (( FAST_HIGHLIGHT[whatis_chroma_callback_was_ran] )) && return 1 +else + if [[ -z "${FAST_HIGHLIGHT[whatis-cache-$__wrd]}" ]]; then + if (( FAST_HIGHLIGHT[whatis_chroma_type] == 2 )); then + exec {THEFD}< <( + print "type2" + print "$__wrd" + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER} )) + print "$__start/$__end" + LANG=C whatis "$__wrd" 2>/dev/null + ) + command true # see above + zle -F ${${FAST_HIGHLIGHT[whatis_chroma_zle_-F_have_-w_opt]:#0}:+-w} "$THEFD" -fast-whatis-chroma-callback + else + exec {THEFD}< <( + print "type1" + print "$__wrd" + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER} )) + print "$__start/$__end" + LANG=C whatis "$__wrd" &> /dev/null + print "$?" + ) + command true + zle -F ${${FAST_HIGHLIGHT[whatis_chroma_zle_-F_have_-w_opt]:#0}:+-w} "$THEFD" -fast-whatis-chroma-callback + fi + else + check=${FAST_HIGHLIGHT[whatis-cache-$__wrd]} + if (( check )) then + __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}correct-subtle]} + elif [[ ${~__wrd} = */* && -e ${~__wrd} ]] then + __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path]} + elif (( FAST_HIGHLIGHT[whatis_chroma_type] )); then + __style=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}incorrect-subtle]} + fi + [[ -n "$__style" ]] && \ + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end $__style") + fi +fi +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4:sts=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-which.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-which.ch new file mode 100644 index 0000000..5a5d7b3 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-which.ch @@ -0,0 +1,96 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Outputs (under prompt) result of query done with `which', `type -w', +# `whence -v', `whereis', `whatis'. +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg; the token can be eg.: "grep" +# +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style __output __chars +integer __idx1 __idx2 +local -a __results + +# First call, i.e. command starts, i.e. "grep" token etc. +(( __first_call )) && { + FAST_HIGHLIGHT[chroma-which-counter]=0 + FAST_HIGHLIGHT[chroma-which-counter-all]=1 + FAST_HIGHLIGHT[chroma-which-message]="" + FAST_HIGHLIGHT[chroma-which-skip-two]=0 + __style=${FAST_THEME_NAME}command + __output="" + +# Following call (not first one). +} || { + (( FAST_HIGHLIGHT[chroma-which-counter-all] += 1, __idx2 = FAST_HIGHLIGHT[chroma-which-counter-all] )) + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + fi + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + if [[ "$__wrd" = "-x" ]]; then + FAST_HIGHLIGHT[chroma-which-skip-two]=1 + fi + else + # Count non-option tokens. + if (( FAST_HIGHLIGHT[chroma-which-skip-two] )); then + FAST_HIGHLIGHT[chroma-which-skip-two]=0 + else + (( FAST_HIGHLIGHT[chroma-which-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-which-counter] )) + if [[ "$__idx1" -eq 1 ]]; then + __chars="{" + __output="$(command which "$__wrd" 2>/dev/null)" + FAST_HIGHLIGHT[chroma-which-message]+=$'\n'"command which: $__output" + __output="$(builtin which "$__wrd" 2>/dev/null)" + FAST_HIGHLIGHT[chroma-which-message]+=$'\n'"builtin which: ${${${${__output[1,100]}//$'\n'/;}//$'\t'/ }//$__chars;/$__chars}${__output[101,101]:+...}" + __output="$(builtin type -w "$__wrd" 2>/dev/null)" + FAST_HIGHLIGHT[chroma-which-message]+=$'\n'"type -w: $__output" + __output="$(builtin whence -v "$__wrd" 2>/dev/null)" + FAST_HIGHLIGHT[chroma-which-message]+=$'\n'"whence -v: $__output" + __output="$(command whereis "$__wrd" 2>/dev/null)" + FAST_HIGHLIGHT[chroma-which-message]+=$'\n'"whereis: $__output" + __output="$(command whatis "$__wrd" 2>/dev/null)" + __output="${${__output%%$'\n'*}//[[:blank:]]##/ }" + FAST_HIGHLIGHT[chroma-which-message]+=$'\n'"whatis: $__output" + fi + fi + fi + + if (( ${#${(z)BUFFER}} <= FAST_HIGHLIGHT[chroma-which-counter-all] )); then + [[ -n "${FAST_HIGHLIGHT[chroma-which-message]}" ]] && zle -M "${FAST_HIGHLIGHT[chroma-which-message]#$'\n'}" + fi +} + +# Add region_highlight entry (via `reply' array). +# +# This is a common place of adding such entry, but any above code +# can do it itself and skip setting __style to disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through (no return 1 occured), do obligatory things ourselves. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/-zplugin.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-zplugin.ch new file mode 100644 index 0000000..2302da5 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/-zplugin.ch @@ -0,0 +1,348 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018-2019 Sebastian Gniazdowski +# +# Chroma function for command `git'. It colorizes the part of command +# line that holds `git' invocation. + +(( FAST_HIGHLIGHT[-zplugin.ch-chroma-def] )) && return 1 + +FAST_HIGHLIGHT[-zplugin.ch-chroma-def]=1 + +typeset -gA fsh__zplugin__chroma__def +fsh__zplugin__chroma__def=( + ## + ## No subcommand + ## + ## {{{ + + subcmd:NULL "NULL_0_opt" + NULL_0_opt "(-help|--help|-h) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + "subcommands" "(help|man|self-update|cd|times|zstatus|load|light|unload|snippet|ls|ice|<ice|specification>|update|status|report|delete|loaded|list|cd|create|edit|glance|stress|changes|recently|clist|completions|cdisable|cname|cenable|cname|creinstall|cuninstall|csearch|compinit|dtrace|dstart|dstop|dunload|dreport|dclear|compile|uncompile|compiled|cdlist|cdreplay|cdclear|srv|recall|env-whitelist|bindkeys|module)" + + ## }}} + + # Generic actions + NO_MATCH_\#_opt "* <<>> __style=\${FAST_THEME_NAME}incorrect-subtle // NO-OP" + NO_MATCH_\#_arg "__style=\${FAST_THEME_NAME}incorrect-subtle // NO-OP" + + + ## + ## `ice' + ## + ## {{{ + + subcmd:ice "ICE_#_arg // NO_MATCH_#_opt" + + "ICE_#_arg" "NO-OP // :::chroma/-zplugin-check-ice-mod" + + ## }}} + + ## + ## `snippet' + ## + ## {{{ + + subcmd:snippet "SNIPPET_0_opt // SNIPPET_1_arg // NO_MATCH_#_opt // + NO_MATCH_#_arg" + + SNIPPET_0_opt "(-f|--command) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + SNIPPET_1_arg "NO-OP // :::chroma/-zplugin-verify-snippet" + + ## }}} + + ## + ## `load' + ## + ## {{{ + + "subcmd:(load|light|compile|stress|edit|glance|recall|status|cd|changes)" + "LOAD_1_arg // LOAD_2_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + LOAD_1_arg "NO-OP // :::chroma/-zplugin-verify-plugin" + + LOAD_2_arg "NO-OP // :::chroma/-zplugin-verify-plugin" + + ## }}} + + ## + ## `update' + ## + ## {{{ + + subcmd:update "UPDATE_0_opt // LOAD_1_arg // LOAD_2_arg // + NO_MATCH_#_opt // NO_MATCH_#_arg" + + UPDATE_0_opt " + (--all|-r|--reset|-q|--quiet) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + LOAD_1_arg "NO-OP // :::chroma/-zplugin-verify-plugin" + + LOAD_2_arg "NO-OP // :::chroma/-zplugin-verify-plugin" + + ## }}} + + ## + ## `light' + ## + ## {{{ + + subcmd:light "LIGHT_0_opt // LOAD_1_arg // LOAD_2_arg // NO_MATCH_#_opt // + NO_MATCH_#_arg" + + LIGHT_0_opt "-b + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + ## }}} + + ## + ## `unload|report' + ## + ## {{{ + + subcmd:"(unload|report)" "UNLOAD_1_arg // UNLOAD_2_arg // NO_MATCH_#_opt // + NO_MATCH_#_arg" + + UNLOAD_1_arg "NO-OP // :::chroma/-zplugin-verify-loaded-plugin" + + UNLOAD_2_arg "NO-OP // :::chroma/-zplugin-verify-loaded-plugin" + + ## }}} + + ## + ## `delete' + ## + ## {{{ + + "subcmd:delete" + "DELETE_0_opt // LOAD_1_arg // LOAD_2_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + DELETE_0_opt " + (--all|--clean|-y|--yes|-q|--quiet) + <<>> NO-OP // :::chroma/main-chroma-std-aopt-action" + + LOAD_1_arg "NO-OP // :::chroma/-zplugin-verify-plugin" + + LOAD_2_arg "NO-OP // :::chroma/-zplugin-verify-plugin" + + ## }}} + + ## + ## `cenable' + ## + ## {{{ + + subcmd:cenable "COMPLETION_1_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + COMPLETION_1_arg "NO-OP // :::chroma/-zplugin-verify-disabled-completion" + + ## }}} + + ## + ## `cdisable' + ## + ## {{{ + + subcmd:cdisable "DISCOMPLETION_1_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + DISCOMPLETION_1_arg "NO-OP // :::chroma/-zplugin-verify-completion" + + ## }}} + + + ## + ## `light' + ## + ## {{{ + + subcmd:uncompile "UNCOMPILE_1_arg // NO_MATCH_#_opt // NO_MATCH_#_arg" + + UNCOMPILE_1_arg "NO-OP // :::chroma/-zplugin-verify-compiled-plugin" + + ## }}} + + ## + ## `*' + ## + ## {{{ + + "subcmd:*" "CATCH_ALL_#_opt" + "CATCH_ALL_#_opt" "* <<>> NO-OP // :::chroma/main-chroma-std-aopt-SEMI-action" + + ## }}} +) + +#:chroma/-zplugin-first-call() { + # This is being done in the proper place - in -fast-highlight-process + #FAST_HIGHLIGHT[chroma-zplugin-ice-elements-svn]=0 +#} + +:chroma/-zplugin-verify-plugin() { + local _scmd="$1" _wrd="$4" + + [[ -d "$_wrd" ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } + + typeset -a plugins + plugins=( "${ZPLGM[PLUGINS_DIR]}"/*(N:t) ) + plugins=( "${plugins[@]//---//}" ) + plugins=( "${plugins[@]:#_local/zplugin}" ) + plugins=( "${plugins[@]:#custom}" ) + + [[ -n "${plugins[(r)$_wrd]}" ]] && \ + __style=${FAST_THEME_NAME}correct-subtle || \ + return 1 + #__style=${FAST_THEME_NAME}incorrect-subtle + return 0 +} + +:chroma/-zplugin-verify-loaded-plugin() { + local _scmd="$1" _wrd="$4" + typeset -a plugins absolute1 absolute2 absolute3 normal + plugins=( "${ZPLG_REGISTERED_PLUGINS[@]:#_local/zplugin}" ) + normal=( "${plugins[@]:#%*}" ) + absolute1=( "${(M)plugins[@]:#%*}" ) + absolute1=( "${absolute1[@]/\%\/\//%/}" ) + local hm="${HOME%/}" + absolute2=( "${absolute1[@]/$hm/HOME}" ) + absolute3=( "${absolute1[@]/\%/}" ) + plugins=( $absolute1 $absolute2 $absolute3 $normal ) + + [[ -n "${plugins[(r)$_wrd]}" ]] && \ + __style=${FAST_THEME_NAME}correct-subtle || \ + return 1 + #__style=${FAST_THEME_NAME}incorrect-subtle + + return 0 +} + +:chroma/-zplugin-verify-completion() { + local _scmd="$1" _wrd="$4" + # Find enabled completions + typeset -a completions + completions=( "${ZPLGM[COMPLETIONS_DIR]}"/_*(N:t) ) + completions=( "${completions[@]#_}" ) + + [[ -n "${completions[(r)${_wrd#_}]}" ]] && \ + __style=${FAST_THEME_NAME}correct-subtle || \ + return 1 + + return 0 +} + +:chroma/-zplugin-verify-disabled-completion() { + local _scmd="$1" _wrd="$4" + # Find enabled completions + typeset -a completions + completions=( "${ZPLGM[COMPLETIONS_DIR]}"/[^_]*(N:t) ) + + [[ -n "${completions[(r)${_wrd#_}]}" ]] && \ + __style=${FAST_THEME_NAME}correct-subtle || \ + return 1 + + return 0 +} + +:chroma/-zplugin-verify-compiled-plugin() { + local _scmd="$1" _wrd="$4" + + typeset -a plugins + plugins=( "${ZPLGM[PLUGINS_DIR]}"/*(N) ) + + typeset -a show_plugins p matches + for p in "${plugins[@]}"; do + matches=( $p/*.zwc(N) ) + if [ "$#matches" -ne "0" ]; then + p="${p:t}" + [[ "$p" = (_local---zplugin|custom) ]] && continue + p="${p//---//}" + show_plugins+=( "$p" ) + fi + done + + [[ -n "${show_plugins[(r)$_wrd]}" ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + return 1 +} + +:chroma/-zplugin-verify-snippet() { + local _scmd="$1" url="$4" dirname local_dir + url="${${url#"${url%%[! $'\t']*}"}%/}" + id_as="${FAST_HIGHLIGHT[chroma-zplugin-ice-elements-id-as]:-${ZPLG_ICE[id-as]:-$url}}" + + filename="${${id_as%%\?*}:t}" + dirname="${${id_as%%\?*}:t}" + local_dir="${${${id_as%%\?*}:h}/:\/\//--}" + [[ "$local_dir" = "." ]] && local_dir="" || local_dir="${${${${${local_dir#/}//\//--}//=/--EQ--}//\?/--QM--}//\&/--AMP--}" + local_dir="${ZPLGM[SNIPPETS_DIR]}${local_dir:+/$local_dir}" + + (( ${+ZPLG_ICE[svn]} || ${FAST_HIGHLIGHT[chroma-zplugin-ice-elements-svn]} )) && { + # TODO: handle the SVN path's specifics + [[ -d "$local_dir/$dirname" ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + return 1 + } || { + # TODO: handle the non-SVN path's specifics + [[ -d "$local_dir/$dirname" ]] && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + return 1 + } +} + +:chroma/-zplugin-check-ice-mod() { + local _scmd="$1" _wrd="$4" + [[ "$_wrd" = (svn(\'|\")*|svn) ]] && \ + FAST_HIGHLIGHT[chroma-zplugin-ice-elements-svn]=1 + [[ "$_wrd" = (#b)(id-as(:|)(\'|\")(*)(\'|\")|id-as:(*)|id-as(*)) ]] && \ + FAST_HIGHLIGHT[chroma-zplugin-ice-elements-id-as]="${match[4]}${match[6]}${match[7]}" + + # Copy from zplugin-autoload.zsh / -zplg-recall + local -a ice_order nval_ices ext_val_ices + ext_val_ices=( ${(@)${(@Ms.|.)ZPLG_EXTS[ice-mods]:#*\'\'*}//\'\'/} ) + + ice_order=( + svn proto from teleid bindmap cloneopts id-as depth if wait load + unload blockf pick bpick src as ver silent lucid notify mv cp + atinit atclone atload atpull nocd run-atpull has cloneonly make + service trackbinds multisrc compile nocompile nocompletions + reset-prompt wrap-track reset sh \!sh bash \!bash ksh \!ksh csh + \!csh aliases countdown + # Include all additional ices – after + # stripping them from the possible: '' + ${(@s.|.)${ZPLG_EXTS[ice-mods]//\'\'/}} + ) + nval_ices=( + blockf silent lucid trackbinds cloneonly nocd run-atpull + nocompletions sh \!sh bash \!bash ksh \!ksh csh \!csh + aliases countdown + + # Include only those additional ices, + # don't have the '' in their name, i.e. + # aren't designed to hold value + ${(@)${(@s.|.)ZPLG_EXTS[ice-mods]}:#*\'\'*} + + # Must be last + svn + ) + + if [[ "$_wrd" = (#b)(${(~j:|:)${ice_order[@]:#(${(~j:|:)nval_ices[@]:#(${(~j:|:)ext_val_ices[@]})})}})(*) ]]; then + reply+=("$(( __start )) $(( __start+${mend[1]} )) ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-hyphen-option]}") + reply+=("$(( __start+${mbegin[2]} )) $(( __end )) ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}optarg-string]}") + -fast-highlight-string + return 0 + elif [[ "$_wrd" = (#b)(${(~j:|:)nval_ices[@]}) ]]; then + __style=${FAST_THEME_NAME}single-hyphen-option + return 0 + else + __style=${FAST_THEME_NAME}incorrect-subtle + return 1 + fi +} + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/:chroma/main-chroma.ch b/.config/shell/zsh-fast-syntax-highlighting/:chroma/main-chroma.ch new file mode 100644 index 0000000..842bf8b --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/:chroma/main-chroma.ch @@ -0,0 +1,453 @@ +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Main chroma function. It allows to create the command-dedicated chromas +# (like -git.ch) through a definition provided by `chroma_def' array (read +# from the upper scope). +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# $2 - the current token, also accessible by $__arg from the above scope - +# basically a private copy of $__arg +# $3 - a private copy of $_start_pos, i.e. the position of the token in the +# command line buffer, used to add region_highlight entry (see man), +# because Zsh colorizes by *ranges* in command line buffer +# $4 - a private copy of $_end_pos from the above scope +# + +(( next_word = 2 | 8192 )) + +:chroma/main-chroma-print() { + (( FAST_HIGHLIGHT[DEBUG] )) && print "$@" >> /tmp/fsh-dbg +} + +local __chroma_name="${1#\%}" __first_call="$2" __wrd="$3" __start_pos="$4" __end_pos="$5" + +# Not a well formed chroma name +[[ -z "$__chroma_name" ]] && return 1 + +# Load the fsh_{name-of-the-chroma}_chroma_def array +(( !FAST_HIGHLIGHT[-${__chroma_name}.ch-chroma-def] )) && :chroma/-${__chroma_name}.ch + +:chroma/main-chroma-print -r -- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +:chroma/main-chroma-print -r -- @@@@@@@ local __chroma_name="${1#\%}" __first_call="$2" __wrd="$3" __start_pos="$4" __end_pos="$5" @@@@@@@ +local __style __entry __value __action __handler __tmp __svalue __hspaces=$'\t ' __nl=$'\n' __ch_def_name +integer __idx1 __idx2 __start __end __ivalue __have_value=0 +local -a __lines_list __avalue +local -A map +map=( "#" "_H" "^" "_D" "*" "_S" ) + +(( __start=_start_pos-__PBUFLEN, __end=_end_pos-__PBUFLEN )) + +# Handler that highlights the options +:chroma/main-chroma-std-aopt-action() { + integer _start="$2" _end="$3" + local _scmd="$1" _wrd="$4" + + [[ "$_wrd" = (#b)(--[a-zA-Z0-9_-]##)=(*) ]] && { + reply+=("$_start $(( _end - mend[2] + mbegin[2] - 1 )) ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-hyphen-option]}") + } || { + [[ "$_wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + } +} + +# Handler that highlights the options' arguments +:chroma/main-chroma-std-aopt-ARG-action() { + integer _start="$2" _end="$3" + local _scmd="$1" _wrd="$4" + + [[ "$_wrd" = (#b)(--[a-zA-Z0-9_-]##)=(*) ]] && { + reply+=("$(( _start + 1 + mend[1] )) $_end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}optarg-${${${(M)match[2]:#<->}:+number}:-string}]}") + } || __style=${FAST_THEME_NAME}optarg-${${${(M)_wrd:#(-|)<->}:+number}:-string} +} + +# This handler also highlights explicit arguments, i.e. --opt=the-explicit-arg +:chroma/main-chroma-std-aopt-SEMI-action() { + integer _start="$2" _end="$3" + local _scmd="$1" _wrd="$4" + + [[ "$_wrd" = (#b)(--[a-zA-Z0-9_-]##)=(*) ]] && { + reply+=("$_start $(( _end - mend[2] + mbegin[2] - 1 )) ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-hyphen-option]}") + reply+=("$(( _start + 1 + mend[1] )) $_end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}optarg-${${${(M)match[2]:#<->}:+number}:-string}]}") + } || { + [[ "$_wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + } +} + +# A handler which verifies the token as an GIT url +:chroma/main-chroma-std-verify-url() { + setopt localoptions extendedglob + local _wrd="$4" + integer url_correct=0 + # Correct matches + # Correct matches + if [[ "$_wrd" = (#b)(git|http|https|ftp|ftps|file)://([a-zA-Z0-9._~-]##)(:[0-9]##)(#c0,1)(/([a-zA-Z0-9./_~:-]##))(#c0,1) ]]; then + url_correct=1 + elif [[ "$_wrd" = (#b)rsync://([a-zA-Z0-9._~-]##)(/([a-zA-Z0-9./_~:-]##))(#c0,1) ]]; then + url_correct=1 + elif [[ "$_wrd" = (#b)ssh://([a-zA-Z0-9._~-]##@)(#c0,1)([a-zA-Z0-9._~-]##)(:[0-9]##)(#c0,1)(/([a-zA-Z0-9./_~:-]##))(#c0,1) ]]; then + url_correct=1 + elif [[ "$_wrd" = (#b)([a-zA-Z0-9._~-]##@)(#c0,1)([a-zA-Z0-9._~-]##):([a-zA-Z0-9./_~:-](#c0,1)[a-zA-Z0-9._~:-][a-zA-Z0-9./_~:-]#)(#c0,1) ]]; then + url_correct=1 + elif [[ "$_wrd" = (#b)[[:alnum:]/_~:.-]## ]]; then + url_correct=1 + fi + + (( url_correct )) && \ + { __style=${FAST_THEME_NAME}correct-subtle; return 0; } || \ + { __style=${FAST_THEME_NAME}incorrect-subtle; return 1; } +} + +# A handler which verifies the token as a shell wildcard +:chroma/main-chroma-std-verify-pattern() { + setopt localoptions extendedglob + local _wrd="$4" + __style=${FAST_THEME_NAME}globbing-ext +} + +# Creates a hash table for given option set (an *_opt field in the chroma def.) +:chroma/main-create-OPTION-hash.ch() { + local __subcmd="$1" __option_set_id="$2" __the_hash_name="$3" __ __e __el __the_hash_name __var_name + local -a __split __sp __s + + :chroma/main-chroma-print -rl "======================" " **## STARTING ##** :chroma/main-##CREATE##-option-HASH.ch // subcmd:$__subcmd // option_set_id:$__option_set_id // h-nam:$__the_hash_name" + :chroma/main-chroma-print "[D] Got option-set: ${(j:,:)__option_set_id}" + typeset -gA "$__the_hash_name" + :chroma/main-chroma-print "[E] __the_hash_name ${__the_hash_name}:[$__option_set_id]" + + # Split on || + __ch_def_name="fsh__${__chroma_name}__chroma__def[${__option_set_id}]" + __split=( "${(P@s:||:)__ch_def_name}" ) + [[ ${#__split} -eq 1 && -z "${__split[1]}" ]] && __split=() + # Remove only leading and trailing whitespace + __split=( "${__split[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + + :chroma/main-chroma-print -rl "[F] Got ||-__split: _________" ${${(@)${${__split[@]##[[:space:]]##}[@]//[${__hspaces}]##/ }[@]//[${__nl}]##/$__nl}[@]//(#s)/:::} "_________" + for __el in $__split; do + __sp=( "${(@s:<<>>:)__el}" ) + [[ ${#__sp} -eq 1 && -z "${__sp[1]}" ]] && __sp=() + __sp=( "${__sp[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + + :chroma/main-chroma-print -l -- "Processing an ||-part - got <<>>-split: _________" "${${__sp[@]}[@]/(#s)/-\\t}" "_________" + __e="${__sp[1]}" + local __e1=${${__e#\(}%\)(:add|:del|)} + local __e2=${(M)__e##\(*\)(:add|:del)} + # Split on | with the ( and ) and :add/:del stripped and then append + # the :add or :del depending on what's on the input line + __s=() + for __ in ${(@s:|:)__e1}; do + __s+=( $__${__e2:+${(M)__e%(:add|:del)}} ) + done + [[ ${#__s} -eq 1 && -z "${__s[1]}" ]] && __s=() + __s=( "${__s[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + shift __sp + + for __ in $__s; do + __=${__%\^} + [[ "$__" = -*:(add|del) ]] && __var_name="${__the_hash_name}[${__}-directive]" || __var_name="${__the_hash_name}[${__}-opt-action]" + :chroma/main-chroma-print "${(r:70:: :):-${__var_name}} := >>${__sp[1]}${${${#__sp}:#(0|1)}:+ +}<<" + : ${(P)__var_name::=${__sp[1]}${${${#__sp}:#(0|1)}:+ +}} + + if (( ${#__sp} >= 2 )); then + __var_name="${__the_hash_name}[${__}-opt-arg-action]" + :chroma/main-chroma-print "${(r:70:: :):-${__var_name}} := >>${__sp[2]}<<}" + : ${(P)__var_name::=$__sp[2]} + fi + done + done +} + +# Processes given token +:chroma/main-process-token.ch() { + local __subcmd="$1" __wrd="$2" __val __var_name __main_hash_name __the_hash_name __i __size + local -a __splitted __split __added + + :chroma/main-chroma-print "\n******************* Starting :chroma/main-process-token <<$__wrd>>// subcmd:${(qq)__subcmd}" + __main_hash_name="fsh__chroma__main__${${FAST_HIGHLIGHT[chroma-current]//[^a-zA-Z0-9_]/_}//(#b)([\#\^\*])/${map[${match[1]}]}}" + __var_name="${__main_hash_name}[subcmd:$__subcmd]" + __splitted=( "${(@s://:P)__var_name}" ) + [[ ${#__splitted} -eq 1 && -z "${__splitted[1]}" ]] && __splitted=() + __splitted=( "${__splitted[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + + :chroma/main-chroma-print -rl -- "[B] MAIN-PROCESS-TOKEN: got [OPTION/ARG-**S-E-T-S**] //-splitted from subcmd:$__subcmd: ${${(j:, :)__splitted}:-EMPTY-SET!}" "----- __splitted\\Deleted: -----" ${${(j:, :)${__splitted[@]:#(${(~j:|:)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}})}}:-EMPTY-SET (deleted)!} "----- Added\\Deleted: -----" ${${(j:, :)${${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]}:#(${(~j:|:)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}})}}:-EMPTY-SET (added)!} -----\ Deleted:\ ----- ${(j:, :)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}} >> /tmp/reply + + (( ! ${#__splitted} )) && { + __var_name="${__main_hash_name}[subcmd:*]" + __splitted=( "${(@s://:P)__var_name}" ) + [[ ${#__splitted} -eq 1 && -z "${__splitted[1]}" ]] && __splitted=() + __splitted=( "${__splitted[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + (( ! ${#__splitted} )) && return 1 + } + + :chroma/main-chroma-print -rl -- "---NO-HASH-CREATE-FROM-NOW-ON---" + + if [[ -z "${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]}" ]]; then + :chroma/main-chroma-print -rl -- "-z OPT-WITH-ARG-ACTIVE == true" + if [[ "$__wrd" = -* ]]; then + :chroma/main-chroma-print "1st-PATH (-z opt-with-arg-active, non-opt-arg branch, i.e. OPTION BRANCH) [#${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}]" + for __val in ${__splitted[@]:#(${(~j:|:)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}})} ${${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]}:#(${(~j:|:)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}})}; do + [[ "${__val}" != "${__val%%_([0-9]##|\#)##*}"_${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}_opt(\*|\^|) && "${__val}" != "${__val%%_([0-9]##|\#)*}"_"#"_opt(\*|\^|) ]] && { :chroma/main-chroma-print "DIDN'T MATCH $__val / arg counter:${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}" ; continue; } || :chroma/main-chroma-print "Got candidate: $__val" + # Create the hash cache-parameter if needed + __the_hash_name="fsh__chroma__${FAST_HIGHLIGHT[chroma-current]//[^a-zA-Z0-9_]/_}__${__subcmd//[^a-zA-Z0-9_]/_}__${${__val//(#b)([\#\^\*])/${map[${match[1]}]}}//[^a-zA-Z0-9_]/_}" + [[ "$__val" = *_opt(\*|\^|) && "${(P)+__the_hash_name}" -eq 0 ]] && :chroma/main-create-OPTION-hash.ch "$__subcmd" "$__val" "$__the_hash_name" || :chroma/main-chroma-print "Not creating, the hash already exists..." + # Try dedicated-entry for the option + __var_name="${__the_hash_name}[${${${${(M)__wrd#?*=}:+${__wrd%=*}=}:-$__wrd}}-opt-action]" + __split=( "${(@s://:P)__var_name}" ) + [[ ${#__split} -eq 1 && -z "${__split[1]}" ]] && __split=() + # If no result, then try with catch-all entry + (( ! ${#__split} )) && { + :chroma/main-chroma-print "% no ${(q-)${${${(M)__wrd#?*=}:+${__wrd%=*}=}:-$__wrd}}-opt-action, retrying with *-opt-action" "|__var_name|:$__var_name" + __var_name="${__the_hash_name}[*-opt-action]" + __split=( "${(@s://:P)__var_name}" ) + [[ ${#__split} -eq 1 && -z "${__split[1]}" ]] && __split=() + } + __svalue="$__var_name" + # Remove whitespace + __split=( "${__split[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + :chroma/main-chroma-print -l -- "\`$__val' // ${#__split} // $__wrd: (ch.run #${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-call-nr]}), deref. of \`$__var_name'" + if (( ${#__split} )); then + :chroma/main-chroma-print -l -- "Got split of {\$#__split:$#__split} ${__wrd}-opt-action or *-opt-action" "${${(q-)__split[@]}[@]/(#s)/->\\t}" + if [[ "${__split[2]}" = *[[:blank:]]+ ]]; then + :chroma/main-chroma-print "YES handling the value (the OPT.ARGUMENT)! [${__split[2]}]" + if [[ "$__wrd" = *=* ]]; then + :chroma/main-chroma-print "The-immediate Arg-Acquiring, of option" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]="${__svalue%-opt-action\]}-opt-arg-action]" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-arg]="${__wrd#*=}" + __have_value=2 + else + :chroma/main-chroma-print "Enable Arg-Awaiting, of option" + :chroma/main-chroma-print "FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]=\"${__svalue%-opt-action\]}-opt-arg-action]\"" + __have_value=0 + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]="${__svalue%-opt-action\]}-opt-arg-action]" + fi + fi + + __action="${__split[1]}" + __handler="${__split[2]%[[:blank:]]+}" + + # Check for directives (like :add) + if [[ "$__val" = *_opt\^ ]]; then + __var_name="${__the_hash_name}[${${${${(M)__wrd#?*=}:+${__wrd%=*}=}:-$__wrd}}:add-directive]" + (( ${(P)+__var_name} )) && __split=( "${(@s://:P)__var_name}" ) || __split=() + [[ ${#__split} -eq 1 && -z "${__split[1]}" ]] && __split[1]=() + __ivalue=${#__split} + __var_name="${__var_name%:add-*}:del-directive]" + (( ${(P)+__var_name} )) && __split+=( "${(@s://:P)__var_name}" ) + [[ ${#__split} -eq $(( __ivalue + 1 )) && -z "${__split[__ivalue+1]}" ]] && __split[__ivalue+1]=() + __split=( "${__split[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + __tmp=${#__split} + + # First: del-directive + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]+="${(j: :)__split[__ivalue+1,__tmp]} " + + :chroma/main-chroma-print -rl ":add / :del directives: __ivalue:$__ivalue, THE __SPLIT[#$__tmp]: " "${__split[@]}" "//" "The FAST_HIGHLIGHT[chroma-*deleted-nodes]: " ${=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]} >> /tmp/reply + + # Second: add-directive + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]+="${(j: :)__split[1,__ivalue]} " + fi + [[ "$__handler" = ::[^[:space:]]* ]] && __handler="${__handler#::}" || __handler="" + [[ -n "$__handler" && "$__handler" != "NO-OP" ]] && { :chroma/main-chroma-print -rl -- "Running handler(1): $__handler" ; "$__handler" "${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]:-NULL}" "$__start" "$__end" "$__wrd"; } + [[ "$__have_value" -ne 2 && -n "$__action" && "$__action" != "NO-OP" ]] && { :chroma/main-chroma-print -rl "Running action (1): $__action" ; eval "() { $__action; }"; } + [[ "$__val" != *\* ]] && break + else + :chroma/main-chroma-print -rl -- "NO-MATCH ROUTE TAKEN" + fi + done + else + :chroma/main-chroma-print "1st-PATH-B (-z opt-with-arg-active, non-opt-arg branch, ARGUMENT BRANCH [#${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}]) //// added-nodes: ${=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]}" + for __val in ${__splitted[@]:#(${(~j:|:)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}})} ${${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]}:#(${(~j:|:)${(@)=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}})}; do + [[ "${__val}" != "${__val%%_([0-9]##|\#)*}"_"${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}"_arg(\*|\^|) && "${__val}" != "${__val%%_([0-9]##|\#)*}"_"#"_arg(\*|\^|) ]] && { :chroma/main-chroma-print "Continuing for $__val / arg counter ${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}" ; continue } + # Create the hash cache-parameter if needed + __the_hash_name="fsh__chroma__${FAST_HIGHLIGHT[chroma-current]//[^a-zA-Z0-9_]/_}__${__subcmd//[^a-zA-Z0-9_]/_}__${${__val//\#/H}//[^a-zA-Z0-9_]/_}" + __action="" __handler="" + :chroma/main-chroma-print "A hit, chosen __val:$__val!" + __ch_def_name="fsh__${__chroma_name}__chroma__def[$__val]" + __split=( "${(P@s:<<>>:)__ch_def_name}" ) + __split=( "${__split[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + + __sp=( "${(@s://:)__split[1]}" ) + __sp=( "${__sp[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + __action="${__sp[1]#*::::: ##}" + + # Verify if it's the expected argument + [[ "${__sp[1]}" = *:::::* && "$__wrd" != ${~${__sp[1]%% ##:::::*}} ]] && \ + { :chroma/main-chroma-print -r "mismatch ${__sp[1]%% ##:::::*} != $__wrd, continuing" ; continue; } + + :chroma/main-chroma-print -l -- "Got action record for $__val, i.e. the split:" "${__sp[@]//(#s)/-\t}" "_________" + + [[ "${__sp[2]}" = ::[^[:space:]]* ]] && __handler="${__sp[2]#::}" || { [[ -n "$__handler" && "$__handler" != "NO-OP" ]] && :chroma/main-chroma-print "=== Error === In chroma definition: a handler entry ${(q)__sp[2]} without leading \`::'" ; } + [[ -n "$__handler" && "$__handler" != "NO-OP" ]] && { :chroma/main-chroma-print -rl -- "Running handler(3): $__handler" ; "$__handler" "${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]:-NULL}" "$__start" "$__end" "$__wrd"; } + [[ -n "$__action" && "$__action" != "NO-OP" ]] && { :chroma/main-chroma-print -rl -- "Running action(3): $__action" ; eval "() { $__action; } \"${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]:-NULL}\" \"$__start\" \"$__end\" \"$__wrd\""; } + + # Check for argument directives (like :add) + if (( ${#__split} >= 2 )); then + for __ in "${(@)__split[2,-1]}"; do + __splitted=( "${(@s://:)__}" ) + if [[ "${__splitted[1]}" = add:* ]]; then + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]+="${__splitted[1]#add:} ${(j: :)__splitted[2,-1]} " + elif [[ "${__splitted[1]}" = del:* ]]; then + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]+="${__splitted[1]#del:} ${(j: :)__splitted[2,-1]} " + fi + done + :chroma/main-chroma-print -l "ARGUMENT :add / :del directives: THE __SPLIT[#${#__split}]: " "${__split[@]//(#s)/-\\t}" "//" "The FAST_HIGHLIGHT[chroma-*deleted-nodes]: " ${(@)${=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]}//(#s)/-\\t} "The FAST_HIGHLIGHT[chroma-*added-nodes]: " ${(@)${=FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]}//(#s)/-\\t} + fi + + [[ "$__val" != *\* ]] && break + done + fi + else + :chroma/main-chroma-print -- "2nd-PATH (-n opt-with-arg-active) NON-EMPTY arg-active:\nThe actual opt-val <<< \$__wrd:$__wrd >>> store (after the \`Arg-Awaiting' in the chroma-run: #$(( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-call-nr]-1 )) [current: #$(( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-call-nr] ))])" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-arg]="$__wrd" + __have_value=1 + fi + + # Execute the action if not during simulated opt-argument (--opt=...) + :chroma/main-chroma-print "** BEFORE: \`if (( __have_value ))'" + if (( __have_value )); then + :chroma/main-chroma-print "In the \`if (( __have_value ))' [have_value: $__have_value]" + # Split + __var_name="${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]}" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]="" + __split=( "${(@s://:P)__var_name}" ) + [[ ${#__split} -eq 1 && -z "${__split[1]}" ]] && { :chroma/main-chroma-print -rl "NULL at __var_name:$__var_name" ; __split=(); } + __split=( "${__split[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + + # Remember 1st level action + (( __have_value == 2 )) && __value="$__action" || __value="" + + if (( ${#__split} )); then + :chroma/main-chroma-print -l -- "Got //-split (3, for opt-ARG-action, from [$__var_name]):" "${${(q-)__split[@]}[@]/(#s)/+\\t}" + __action="${__split[1]}" + __handler="${__split[2]}" + [[ "$__handler" = ::[^[:space:]]* ]] && __handler="${__handler#::}" + + [[ -n "$__handler" && "$__handler" != "NO-OP" ]] && { :chroma/main-chroma-print -rl -- "Running handler(2): $__handler" ; "$__handler" "${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]:-NULL}" "$__start" "$__end" "$__wrd"; } + [[ -n "$__action" && "$__action" != "NO-OP" ]] && { :chroma/main-chroma-print -rl -- "Running action(2): $__action" ; eval "$__action"; } + :chroma/main-chroma-print -rl -- "The __action value: [$__value]" + [[ "$__have_value" -eq 2 && -n "$__value" && "$__value" != "NO-OP" ]] && { :chroma/main-chroma-print -rl "Running action (of 1, at 2): $__value" ; eval "$__value"; } + fi + fi + :chroma/main-chroma-print -- "_________ Exiting :chroma/main-process-token.ch $__subcmd / $__wrd _________" +} + +# Iterates over the chroma def. fields and creates initial +# fields in the fsh__${__chroma_name}__chroma__def hash +:chroma/-pre_process_chroma_def.ch() { + local __key __value __ke _val __the_hash_name="$1" __var_name + local -a __split + + :chroma/main-chroma-print -rl -- "Starting PRE_PROCESS for __the_hash_name:$__the_hash_name" + + __ch_def_name="fsh__${__chroma_name}__chroma__def[subcommands]" + local __subcmds="${(P)__ch_def_name}" + if [[ "$__subcmds" = "::"* ]]; then + ${__subcmds#::} + __var_name="${__the_hash_name}[subcommands]" + : ${(P)__var_name::=(${(j:|:)reply})} + else + __var_name="${__the_hash_name}[subcommands]" + : ${(P)__var_name::=$__subcmds} + fi + :chroma/main-chroma-print "Got SUBCOMMANDS: ${(P)__var_name}" + + __ch_def_name="fsh__${__chroma_name}__chroma__def[subcmd-hook]" + local __subcmd_hook="${(P)__ch_def_name}" + if [[ -n "$__subcmd_hook" ]]; then + __var_name="${__the_hash_name}[subcmd-hook]" + : ${(P)__var_name::=$__subcmd_hook} + fi + + __ch_def_name="fsh__${__chroma_name}__chroma__def[(I)subcmd:*]" + for __key in "${(P@)__ch_def_name}"; do + __split=( "${(@s:|:)${${__key##subcmd:\((#c0,1)}%\)}}" ) + [[ ${#__split} -eq 1 && -z "${__split[1]}" ]] && __split=() + __split=( "${__split[@]//((#s)[[:space:]]##|[[:space:]]##(#e))/}" ) + for __ke in "${__split[@]}"; do + __var_name="${__the_hash_name}[subcmd:$__ke]" + __ch_def_name="fsh__${__chroma_name}__chroma__def[$__key]" + : ${(P)__var_name::=${(P)__ch_def_name}} + :chroma/main-chroma-print -rl -- "Storred ${__var_name}=chroma_def[$__key], i.e. = ${(P)__ch_def_name}" + done + done +} + +if (( __first_call )); then + :chroma/-${__chroma_name}-first-call + FAST_HIGHLIGHT[chroma-current]="$__wrd" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]=0 + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-got-subcommand]=0 + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]="" + FAST_HIGHLIGHT[chrome-${FAST_HIGHLIGHT[chroma-current]}-occurred-double-hyphen]=0 + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]="" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-arg]="" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-call-nr]=1 + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-added-nodes]="" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-deleted-nodes]="" + __the_hash_name="fsh__chroma__main__${${FAST_HIGHLIGHT[chroma-current]//[^a-zA-Z0-9_]/_}//(#b)([\#\^])/${map[${match[1]}]}}" + (( 0 == ${(P)+__the_hash_name} )) && { + typeset -gA "$__the_hash_name" + :chroma/-pre_process_chroma_def.ch "$__the_hash_name" + } || :chroma/main-chroma-print "...No... [\${+$__the_hash_name} ${(P)+__the_hash_name}]" + return 1 +else + (( ++ FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-call-nr] )) + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + :chroma/main-chroma-print "== @@ Starting @@ #${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-call-nr]} Main-Chroma-call == // << __WORD:$__wrd >> ## Subcommand: ${${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]}:-NULL} //@@// -n option-with-arg-active:${(q-)FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]}" + if [[ "$__wrd" = -* || -n "${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-option-with-arg-active]}" + ]]; then + :chroma/main-chroma-print "## The \`if -*' i.e. \`IF OPTION' MAIN branch" + :chroma/main-process-token.ch "${${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]}:-NULL}" "$__wrd" + else + # If at e.g. '>' or destination/source spec (of the redirection) + if (( in_redirection > 0 || this_word & 128 )) || [[ $__wrd == "<<<" ]]; then + return 1 + elif (( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-got-subcommand] == 0 )); then + __the_hash_name="fsh__chroma__main__${${FAST_HIGHLIGHT[chroma-current]//[^a-zA-Z0-9_]/_}//(#b)([\#\^])/${map[${match[1]}]}}" + __var_name="${__the_hash_name}[subcommands]" + if [[ "$__wrd" = ${(P)~__var_name} ]]; then + :chroma/main-chroma-print "GOT-SUBCOMMAND := $__wrd, subcmd verification / OK" + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-got-subcommand]=1 + FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]="$__wrd" + __var_name="${__the_hash_name}[subcmd-hook]" + (( ${(P)+__var_name} )) && { :chroma/main-chroma-print -r -- "Running subcmd-hook: ${(P)__var_name}" ; "${(P)__var_name}" "$__wrd"; } + __style="${FAST_THEME_NAME}subcommand" + else + :chroma/main-chroma-print "subcmd verif / NOT OK; Incrementing the COUNTER-ARG ${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]} -> $(( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg] + 1 ))" >> /tmp/fsh-dbg + (( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg] += 1 )) + :chroma/main-chroma-print "UNRECOGNIZED ARGUMENT ${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}" + :chroma/main-process-token.ch "${${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]}:-NULL}" "$__wrd" + fi + else + __wrd="${__wrd//\`/x}" + __arg="${__arg//\`/x}" + __wrd="${(Q)__wrd}" + + :chroma/main-chroma-print "Incrementing the COUNTER-ARG ${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]} -> $(( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg] + 1 ))" + (( FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg] += 1 )) + :chroma/main-chroma-print "ARGUMENT ${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-counter-arg]}" + + :chroma/main-chroma-print "ELSE *-got-subcommand == 1 is TRUE" + :chroma/main-process-token.ch "${FAST_HIGHLIGHT[chroma-${FAST_HIGHLIGHT[chroma-current]}-subcommand]}" "$__wrd" + fi + fi +fi + + +# Add region_highlight entry (via `reply' array) +if [[ -n "$__style" ]]; then + (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) \ + && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") +fi + +# We aren't passing-through, do obligatory things ourselves +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 + +# vim:ft=zsh:et:sw=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/CHROMA_GUIDE.adoc b/.config/shell/zsh-fast-syntax-highlighting/CHROMA_GUIDE.adoc new file mode 100644 index 0000000..579f192 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/CHROMA_GUIDE.adoc @@ -0,0 +1,166 @@ +# Chroma Guide for F-Sy-H + +## Motivation + +Someone might want to create a detailed highlighting for a **specific program** +and this document helps achieving this. It explains how chroma functions – the +code behind such detailed highlighting – are constructed and used. + +## Keywords + +- `chroma` - a shorthand for `chroma function` – the thing that literally colorizes selected commands, like `git`, `grep`, etc. invocations, see `chroma function` below, +- `big loop` - main highlighting code, a loop over tokens and at least 2 large structular constructs (big `if` and `case`); + it is advanced, e.g. parses `case` statements, here-string, it basically constitutes 90% of the F-Sy-H project, +- `chroma function` - a plugin-function that is called when a specific command occurs (e.g. when user enters `git` at + command line) suppressing activity of `big loop` (i.e. no standard highlighting unless requested), +- `token` - result of splitting whole command line (i.e. `$BUFFER`, the Zle variable) into bits called tokens, which are + words in general, separated by spaces on the command line. + +## Overview Of Functioning + +1. Big loop is working – token by token processes command line, changes states (e.g. enters state "inside case + statement") and in the end decides on color of the token currently processed. + +2. Big loop occurs a command that has a chroma, e.g. `git`. + +3. Big loop enters "chroma" state, calls associated chroma function. + +4. Chroma takes care of "chroma" state, ensures it will be set also for next token. + +5. "chroma" state is active, so all following tokens are routed to the chroma (in general skipping big-loop, see next items), + +6. When processing of a single token is complete, the associated chroma returns 0 + (shell-truth) to request no further processing by the big loop. + +7. It can also return 1 so that single, current token will be passed into big-loop + for processing (to do a standard highlighting). + +## Chroma-Function Arguments + +- `$1` - 0 or 1, denoting if it's the first call to the chroma, or a following one, + +- `$2` - the current token, also accessible by `$\__arg` from the upper scope - + basically a private copy of `$__arg`; the token can be eg.: "grep", + +- `$3` - a private copy of `$_start_pos`, i.e. the position of the token in the + command line buffer, used to add region_highlight entry (see man), + because Zsh colorizes by *ranges* applied onto command line buffer (e.g. + `from-10 to-13 fg=red`), + +- `$4` - a private copy of `$_end_pos` from the upper scope; denotes where current token + ends (at which index in the string being the command line). + +So example invocation could look like this: + +---- +chroma/-example.ch 1 "grep" "$_start_pos" "$_end_pos" +---- + +Big-loop will be doing such calls for the user, after occurring a specific chroma-enabled command (like e.g. `awk`), and then until chroma will detect end of this chroma-enabled command (end of whole invocation, with arguments, etc.; in other words, when e.g. new line or `;`-character occurs, etc.). + +## Example Chroma-Function + +[source,zsh] +---- +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Example chroma function. It colorizes first two arguments as `builtin' style, +# third and following arguments as `globbing' style. First two arguments may +# be "strings", they will be passed through to normal higlighter (by returning 1). +# +# $1 - 0 or 1, denoting if it's first call to the chroma, or following one +# +# $2 - like above document says +# +# $3 - ... +# +# $4 - ... +# +# Other tips are: +# - $CURSOR holds cursor position +# - $BUFFER holds whole command line buffer +# - $LBUFFER holds command line buffer that is left from the cursor, i.e. it's a +# BUFFER substring 1 .. $CURSOR +# - $RBUFFER is the same as LBUFFER but holds part of BUFFER right to the cursor +# +# The function receives $BUFFER but via sequence of tokens, which are shell words, +# e.g. "a b c" is a shell word, while a b c are 3 shell words. +# +# FAST_HIGHLIGHT is a friendly hash array which allows to store strings without +# creating global parameters (variables). If you need hash, go ahead and use it, +# declaring first, under some distinct name like: typeset -gA CHROMA_EXPLE_DICT. +# Remember to reset the hash and others at __first_call == 1, so that you have +# a fresh state for new command. + +# Keep chroma-takever state meaning: until ;, handle highlighting via chroma. +# So the below 8192 assignment takes care that next token will be routed to chroma. +(( next_word = 2 | 8192 )) + +local __first_call="$1" __wrd="$2" __start_pos="$3" __end_pos="$4" +local __style +integer __idx1 __idx2 + +(( __first_call )) && { + # Called for the first time - new command. + # FAST_HIGHLIGHT is used because it survives between calls, and + # allows to use a single global hash only, instead of multiple + # global string variables. + FAST_HIGHLIGHT[chroma-example-counter]=0 + + # Set style for region_highlight entry. It is used below in + # '[[ -n "$__style" ]] ...' line, which adds highlight entry, + # like "10 12 fg=green", through `reply' array. + # + # Could check if command `example' exists and set `unknown-token' + # style instead of `command' + __style=${FAST_THEME_NAME}command + +} || { + # Following call, i.e. not the first one + + # Check if chroma should end – test if token is of type + # "starts new command", if so pass-through – chroma ends + [[ "$__arg_type" = 3 ]] && return 2 + + if [[ "$__wrd" = -* ]]; then + # Detected option, add style for it. + [[ "$__wrd" = --* ]] && __style=${FAST_THEME_NAME}double-hyphen-option || \ + __style=${FAST_THEME_NAME}single-hyphen-option + else + # Count non-option tokens + (( FAST_HIGHLIGHT[chroma-example-counter] += 1, __idx1 = FAST_HIGHLIGHT[chroma-example-counter] )) + + # Colorize 1..2 as builtin, 3.. as glob + if (( FAST_HIGHLIGHT[chroma-example-counter] <= 2 )); then + if [[ "$__wrd" = \"* ]]; then + # Pass through, fsh main code will do the highlight! + return 1 + else + __style=${FAST_THEME_NAME}builtin + fi + else + __style=${FAST_THEME_NAME}globbing + fi + fi +} + +# Add region_highlight entry (via `reply' array). +# If 1 will be added to __start_pos, this will highlight "oken". +# If 1 will be subtracted from __end_pos, this will highlight "toke". +# $PREBUFFER is for specific situations when users does command \<ENTER> +# i.e. when multi-line command using backslash is entered. +# +# This is a common place of adding such entry, but any above code can do +# it itself (and it does in other chromas) and skip setting __style to +# this way disable this code. +[[ -n "$__style" ]] && (( __start=__start_pos-${#PREBUFFER}, __end=__end_pos-${#PREBUFFER}, __start >= 0 )) && reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + +# We aren't passing-through, do obligatory things ourselves. +# _start_pos=$_end_pos advainces pointers in command line buffer. +(( this_word = next_word )) +_start_pos=$_end_pos + +return 0 +---- + diff --git a/.config/shell/zsh-fast-syntax-highlighting/_fast-theme b/.config/shell/zsh-fast-syntax-highlighting/_fast-theme new file mode 100644 index 0000000..4c88062 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/_fast-theme @@ -0,0 +1,33 @@ +#compdef fast-theme + +# +# Copyright (c) 2018 Sebastian Gniazdowski +# +# Completion for theme-switching function, fast-theme, +# part of zdharma/fast-syntax-highlighting. +# + +integer ret=1 +local -a arguments + +arguments=( + {-h,--help}'[display help text]' + {-l,--list}'[list available themes]' + {-r,--reset}'[unset any theme (revert to default highlighting)]' + {-R,--ov-reset}'[unset overlay, use styles only from main-theme (requires restart)]' + {-q,--quiet}'[no default messages]' + {-s,--show}'[get and display the theme currently being set]' + {-v,--verbose}'[more messages during operation]' + {-t,--test}'[test theme after setting it (show example code)]' + {-p,--palette}'[just print all 256 colors and exit (useful when creating a theme)]' + {-w,--workdir}'[cd into $FAST_WORK_DIR (if not set, then into the plugin directory)]' +) + +typeset -a themes +themes=( "$FAST_WORK_DIR"/themes/*.ini(:t:r) ) + +_wanted themes expl "Themes" \ + compadd "$@" -a - themes && ret=0 +_arguments -s $arguments && ret=0 + +return $ret diff --git a/.config/shell/zsh-fast-syntax-highlighting/fast-highlight b/.config/shell/zsh-fast-syntax-highlighting/fast-highlight new file mode 100644 index 0000000..c410c23 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/fast-highlight @@ -0,0 +1,1423 @@ +# -*- 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} +() { + setopt localoptions 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]:=} +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-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-zplugin :chroma/main-chroma.ch%zplugin + 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 +) + +# 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 noksharrays 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 zplugin's ICE gathering + FAST_HIGHLIGHT[chroma-zplugin-ice-elements-svn]=0 + FAST_HIGHLIGHT[chroma-zplugin-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 ) ]]; then + __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]} ]]; then + __style=${FAST_THEME_NAME}history-expansion + elif [[ $__arg == ${histchars[2]}* ]]; then + __style=${FAST_THEME_NAME}history-expansion + elif (( __arg_type == 3 )); then + # 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] == '((' ]]; then + # 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 == '()' ]]; then + _FAST_COMPLEX_BRACKETS+=( $(( _start_pos-__PBUFLEN )) $(( _start_pos-__PBUFLEN + 1 )) ) + # anonymous function + __style=${FAST_THEME_NAME}reserved-word + elif [[ $__arg == $'\x28' ]]; then + # subshell '(', stack: letter 'R' + __style=${FAST_THEME_NAME}reserved-word + braces_stack='R'$braces_stack + elif [[ $__arg == $'\x29' ]]; then + # ')', stack: letter 'R' for subshell + [[ $braces_stack = R* ]] && { braces_stack=${braces_stack#R}; __style=${FAST_THEME_NAME}reserved-word; } + elif (( this_word & 14 )); then + __style=${FAST_THEME_NAME}default + 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 = \$\([^\(]* ]]; then + already_added=1 + fi + ;; + *) + # 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 + + # 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" =~ "^(x|X)[0-9a-fA-F]{1,2}" + || "$AA" =~ "^[0-7]{1,3}" + || "$AA" =~ "^u[0-9a-fA-F]{1,4}" + || "$AA" =~ "^U[0-9a-fA-F]{1,8}" + ]]; then + (( k += $#MATCH )) + (( i += $#MATCH )) + 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 diff --git a/.config/shell/zsh-fast-syntax-highlighting/fast-read-ini-file b/.config/shell/zsh-fast-syntax-highlighting/fast-read-ini-file new file mode 100644 index 0000000..2e57d10 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/fast-read-ini-file @@ -0,0 +1,30 @@ +# Copyright (c) 2018 Sebastian Gniazdowski +# +# $1 - path to the ini file to parse +# $2 - name of output hash (INI by default) +# $3 - prefix for keys in the hash (can be empty) +# +# Writes to given hash under keys built in following way: ${3}<section>_field. +# Values are values from ini file. + +local __ini_file="$1" __out_hash="${2:-INI}" __key_prefix="$3" +local IFS='' __line __cur_section="void" __access_string +local -a match mbegin mend + +[[ ! -r "$__ini_file" ]] && { builtin print -r "fast-syntax-highlighting: an ini file is unreadable ($__ini_file)"; return 1; } + +while read -r -t 1 __line; do + if [[ "$__line" = [[:blank:]]#\;* ]]; then + continue + elif [[ "$__line" = (#b)[[:blank:]]#\[([^\]]##)\][[:blank:]]# ]]; then + __cur_section="${match[1]}" + elif [[ "$__line" = (#b)[[:blank:]]#([^[:blank:]=]##)[[:blank:]]#[=][[:blank:]]#(*) ]]; then + match[2]="${match[2]%"${match[2]##*[! $'\t']}"}" # remove trailing whitespace + __access_string="${__out_hash}[${__key_prefix}<$__cur_section>_${match[1]}]" + : "${(P)__access_string::=${match[2]}}" + fi +done < "$__ini_file" + +return 0 + +# vim:ft=zsh:sw=4:sts=4:et diff --git a/.config/shell/zsh-fast-syntax-highlighting/fast-string-highlight b/.config/shell/zsh-fast-syntax-highlighting/fast-string-highlight new file mode 100644 index 0000000..dd8eb4f --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/fast-string-highlight @@ -0,0 +1,66 @@ +# vim:ft=zsh:sw=4:sts=4 + +# +# $1 - PREBUFFER +# $2 - BUFFER +# +function -fast-highlight-string-process { + emulate -LR zsh + setopt extendedglob warncreateglobal typesetsilent + + local -A pos_to_level level_to_pos pair_map final_pairs + local input=$1$2 _mybuf=$1$2 __style __quoting + integer __idx=0 __pair_idx __level=0 __start __end + local -a match mbegin mend + + pair_map=( "(" ")" "{" "}" "[" "]" ) + + while [[ $_mybuf = (#b)[^"{}()[]\\\"'"]#((["({[]})\"'"])|[\\](*))(*) ]]; do + [[ -n ${match[3]} ]] && { + __idx+=${mbegin[1]} + + [[ $__quoting = \' ]] && _mybuf=${match[3]} || { _mybuf=${match[3]:1}; (( ++ __idx )); } + } || { + __idx+=${mbegin[1]} + [[ -z $__quoting && -z ${_FAST_COMPLEX_BRACKETS[(r)$((__idx-${#PREBUFFER}-1))]} ]] && { + if [[ ${match[1]} = ["({["] ]]; then + pos_to_level[$__idx]=$(( ++__level )) + level_to_pos[$__level]=$__idx + elif [[ ${match[1]} = ["]})"] ]]; then + if (( __level > 0 )); then + __pair_idx=${level_to_pos[$__level]} + pos_to_level[$__idx]=$(( __level -- )) + [[ ${pair_map[${input[__pair_idx]}]} = ${input[__idx]} ]] && { + final_pairs[$__idx]=$__pair_idx + final_pairs[$__pair_idx]=$__idx + } + else + pos_to_level[$__idx]=-1 + fi + fi + } + + [[ ${match[1]} = \" && $__quoting != \' ]] && { [[ $__quoting = '"' ]] && __quoting="" || __quoting='"'; } + [[ ${match[1]} = \' && $__quoting != \" ]] && { [[ $__quoting = "'" ]] && __quoting="" || __quoting="'"; } + + _mybuf=${match[4]} + } + done + + for __idx in ${(k)pos_to_level}; do + (( ${+final_pairs[$__idx]} )) && __style=${FAST_THEME_NAME}bracket-level-$(( ( (pos_to_level[$__idx]-1) % 3 ) + 1 )) || __style=${FAST_THEME_NAME}unknown-token + (( __start=__idx-${#PREBUFFER}-1, __end=__idx-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[$__style]}") + done + + # If cursor is on a bracket, then highlight corresponding bracket, if any. + if [[ $WIDGET != zle-line-finish ]]; then + __idx=$(( CURSOR + 1 )) + if (( ${+pos_to_level[$__idx]} )) && (( ${+final_pairs[$__idx]} )); then + (( __start=final_pairs[$__idx]-${#PREBUFFER}-1, __end=final_pairs[$__idx]-${#PREBUFFER}, __start >= 0 )) && \ + reply+=("$__start $__end ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}paired-bracket]}") && \ + reply+=("$CURSOR $__idx ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}paired-bracket]}") + fi + fi + return 0 +} diff --git a/.config/shell/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh b/.config/shell/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh new file mode 100644 index 0000000..c5357e1 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh @@ -0,0 +1,357 @@ +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2010-2016 zsh-syntax-highlighting contributors +# Copyright (c) 2017-2019 Sebastian Gniazdowski (modifications) +# All rights reserved. +# +# 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. +# ------------------------------------------------------------------------------------------------- +# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- +# vim: ft=zsh sw=2 ts=2 et +# ------------------------------------------------------------------------------------------------- + + +# Standarized way of handling finding plugin dir, +# regardless of functionargzero and posixargzero, +# and with an option for a plugin manager to alter +# the plugin directory (i.e. set ZERO parameter) +# http://zdharma.org/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html +0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" +0="${${(M)0:#/*}:-$PWD/$0}" + +typeset -g FAST_BASE_DIR="${0:h}" +typeset -ga _FAST_MAIN_CACHE +# Holds list of indices pointing at brackets that +# are complex, i.e. e.g. part of "[[" in [[ ... ]] +typeset -ga _FAST_COMPLEX_BRACKETS + +typeset -g FAST_WORK_DIR +: ${FAST_WORK_DIR:=$FAST_BASE_DIR} +FAST_WORK_DIR=${~FAST_WORK_DIR} + +if [[ -z "$ZPLG_CUR_PLUGIN" && "${fpath[(r)$FAST_BASE_DIR]}" != $FAST_BASE_DIR ]]; then + fpath+=( "$FAST_BASE_DIR" ) +fi + +if [[ "$FAST_WORK_DIR" = /usr/* || ( "$FAST_WORK_DIR" = /opt/* && ! -w "$FAST_WORK_DIR" ) ]]; then + FAST_WORK_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/fsh" + command mkdir -p "$FAST_WORK_DIR" +fi + +# Invokes each highlighter that needs updating. +# This function is supposed to be called whenever the ZLE state changes. +_zsh_highlight() +{ + # Store the previous command return code to restore it whatever happens. + local ret=$? + + # Remove all highlighting in isearch, so that only the underlining done by zsh itself remains. + # For details see FAQ entry 'Why does syntax highlighting not work while searching history?'. + if [[ $WIDGET == zle-isearch-update ]] && ! (( $+ISEARCHMATCH_ACTIVE )); then + region_highlight=() + return $ret + fi + + setopt localoptions warncreateglobal noksharrays noshwordsplit extendedglob typesetsilent nokshglob + local REPLY # don't leak $REPLY into global scope + local -a reply + + # Do not highlight if there are more than 300 chars in the buffer. It's most + # likely a pasted command or a huge list of files in that case.. + [[ -n ${ZSH_HIGHLIGHT_MAXLENGTH:-} ]] && [[ $#BUFFER -gt $ZSH_HIGHLIGHT_MAXLENGTH ]] && return $ret + + # Do not highlight if there are pending inputs (copy/paste). + [[ $PENDING -gt 0 ]] && return $ret + + # Reset region highlight to build it from scratch + # may need to remove path_prefix highlighting when the line ends + if [[ $WIDGET == zle-line-finish ]] || _zsh_highlight_buffer_modified; then + -fast-highlight-init + -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 + (( FAST_HIGHLIGHT[use_brackets] )) && { + _FAST_MAIN_CACHE=( $reply ) + -fast-highlight-string-process "$PREBUFFER" "$BUFFER" + } + region_highlight=( $reply ) + else + local char="${BUFFER[CURSOR+1]}" + if [[ "$char" = ["{([])}"] || "${FAST_HIGHLIGHT[prev_char]}" = ["{([])}"] ]]; then + FAST_HIGHLIGHT[prev_char]="$char" + (( FAST_HIGHLIGHT[use_brackets] )) && { + reply=( $_FAST_MAIN_CACHE ) + -fast-highlight-string-process "$PREBUFFER" "$BUFFER" + region_highlight=( $reply ) + } + fi + fi + + { + local cache_place + local -a region_highlight_copy + + # Re-apply zle_highlight settings + + # region + if (( REGION_ACTIVE == 1 )); then + _zsh_highlight_apply_zle_highlight region standout "$MARK" "$CURSOR" + elif (( REGION_ACTIVE == 2 )); then + () { + local needle=$'\n' + integer min max + if (( MARK > CURSOR )) ; then + min=$CURSOR max=$(( MARK + 1 )) + else + min=$MARK max=$CURSOR + fi + (( min = ${${BUFFER[1,$min]}[(I)$needle]} )) + (( max += ${${BUFFER:($max-1)}[(i)$needle]} - 1 )) + _zsh_highlight_apply_zle_highlight region standout "$min" "$max" + } + fi + + # yank / paste (zsh-5.1.1 and newer) + (( $+YANK_ACTIVE )) && (( YANK_ACTIVE )) && _zsh_highlight_apply_zle_highlight paste standout "$YANK_START" "$YANK_END" + + # isearch + (( $+ISEARCHMATCH_ACTIVE )) && (( ISEARCHMATCH_ACTIVE )) && _zsh_highlight_apply_zle_highlight isearch underline "$ISEARCHMATCH_START" "$ISEARCHMATCH_END" + + # suffix + (( $+SUFFIX_ACTIVE )) && (( SUFFIX_ACTIVE )) && _zsh_highlight_apply_zle_highlight suffix bold "$SUFFIX_START" "$SUFFIX_END" + + return $ret + + } always { + typeset -g _ZSH_HIGHLIGHT_PRIOR_BUFFER="$BUFFER" + typeset -g _ZSH_HIGHLIGHT_PRIOR_RACTIVE="$REGION_ACTIVE" + typeset -gi _ZSH_HIGHLIGHT_PRIOR_CURSOR=$CURSOR + } +} + +# Apply highlighting based on entries in the zle_highlight array. +# This function takes four arguments: +# 1. The exact entry (no patterns) in the zle_highlight array: +# region, paste, isearch, or suffix +# 2. The default highlighting that should be applied if the entry is unset +# 3. and 4. Two integer values describing the beginning and end of the +# range. The order does not matter. +_zsh_highlight_apply_zle_highlight() { + local entry="$1" default="$2" + integer first="$3" second="$4" + + # read the relevant entry from zle_highlight + local region="${zle_highlight[(r)${entry}:*]}" + + if [[ -z "$region" ]]; then + # entry not specified at all, use default value + region=$default + else + # strip prefix + region="${region#${entry}:}" + + # no highlighting when set to the empty string or to 'none' + if [[ -z "$region" ]] || [[ "$region" == none ]]; then + return + fi + fi + + integer start end + if (( first < second )); then + start=$first end=$second + else + start=$second end=$first + fi + region_highlight+=("$start $end $region") +} + + +# ------------------------------------------------------------------------------------------------- +# API/utility functions for highlighters +# ------------------------------------------------------------------------------------------------- + +# Whether the command line buffer has been modified or not. +# +# Returns 0 if the buffer has changed since _zsh_highlight was last called. +_zsh_highlight_buffer_modified() +{ + [[ "${_ZSH_HIGHLIGHT_PRIOR_BUFFER:-}" != "$BUFFER" ]] || [[ "$REGION_ACTIVE" != "$_ZSH_HIGHLIGHT_PRIOR_RACTIVE" ]] || { _zsh_highlight_cursor_moved && [[ "$REGION_ACTIVE" = 1 || "$REGION_ACTIVE" = 2 ]] } +} + +# Whether the cursor has moved or not. +# +# Returns 0 if the cursor has moved since _zsh_highlight was last called. +_zsh_highlight_cursor_moved() +{ + [[ -n $CURSOR ]] && [[ -n ${_ZSH_HIGHLIGHT_PRIOR_CURSOR-} ]] && (($_ZSH_HIGHLIGHT_PRIOR_CURSOR != $CURSOR)) +} + +# ------------------------------------------------------------------------------------------------- +# Setup functions +# ------------------------------------------------------------------------------------------------- + +# Helper for _zsh_highlight_bind_widgets +# $1 is name of widget to call +_zsh_highlight_call_widget() +{ + integer ret + builtin zle "$@" + ret=$? + _zsh_highlight + return $ret +} + +# Rebind all ZLE widgets to make them invoke _zsh_highlights. +_zsh_highlight_bind_widgets() +{ + setopt localoptions noksharrays + local -F2 SECONDS + local prefix=orig-s${SECONDS/./}-r$(( RANDOM % 1000 )) # unique each time, in case we're sourced more than once + + # Load ZSH module zsh/zleparameter, needed to override user defined widgets. + zmodload zsh/zleparameter 2>/dev/null || { + print -r -- >&2 'zsh-syntax-highlighting: failed loading zsh/zleparameter.' + return 1 + } + + # Override ZLE widgets to make them invoke _zsh_highlight. + local -U widgets_to_bind + widgets_to_bind=(${${(k)widgets}:#(.*|run-help|which-command|beep|set-local-history|yank)}) + + # Always wrap special zle-line-finish widget. This is needed to decide if the + # current line ends and special highlighting logic needs to be applied. + # E.g. remove cursor imprint, don't highlight partial paths, ... + widgets_to_bind+=(zle-line-finish) + + # Always wrap special zle-isearch-update widget to be notified of updates in isearch. + # This is needed because we need to disable highlighting in that case. + widgets_to_bind+=(zle-isearch-update) + + local cur_widget + for cur_widget in $widgets_to_bind; do + case $widgets[$cur_widget] in + + # Already rebound event: do nothing. + user:_zsh_highlight_widget_*);; + + # The "eval"'s are required to make $cur_widget a closure: the value of the parameter at function + # definition time is used. + # + # We can't use ${0/_zsh_highlight_widget_} because these widgets are always invoked with + # NO_function_argzero, regardless of the option's setting here. + + # User defined widget: override and rebind old one with prefix "orig-". + user:*) zle -N -- $prefix-$cur_widget ${widgets[$cur_widget]#*:} + eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget ${(q)prefix}-${(q)cur_widget} -- \"\$@\" }" + zle -N -- $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;; + + # Completion widget: override and rebind old one with prefix "orig-". + completion:*) zle -C $prefix-$cur_widget ${${(s.:.)widgets[$cur_widget]}[2,3]} + eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget ${(q)prefix}-${(q)cur_widget} -- \"\$@\" }" + zle -N -- $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;; + + # Builtin widget: override and make it call the builtin ".widget". + builtin) eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget .${(q)cur_widget} -- \"\$@\" }" + zle -N -- $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;; + + # Incomplete or nonexistent widget: Bind to z-sy-h directly. + *) + if [[ $cur_widget == zle-* ]] && [[ -z $widgets[$cur_widget] ]]; then + _zsh_highlight_widget_${cur_widget}() { :; _zsh_highlight } + zle -N -- $cur_widget _zsh_highlight_widget_$cur_widget + else + # Default: unhandled case. + print -r -- >&2 "zsh-syntax-highlighting: unhandled ZLE widget ${(qq)cur_widget}" + fi + esac + done +} + +# ------------------------------------------------------------------------------------------------- +# Setup +# ------------------------------------------------------------------------------------------------- + +# Try binding widgets. +_zsh_highlight_bind_widgets || { + print -r -- >&2 'zsh-syntax-highlighting: failed binding ZLE widgets, exiting.' + return 1 +} + +# Reset scratch variables when commandline is done. +_zsh_highlight_preexec_hook() +{ + typeset -g _ZSH_HIGHLIGHT_PRIOR_BUFFER= + typeset -gi _ZSH_HIGHLIGHT_PRIOR_CURSOR=0 + typeset -ga _FAST_MAIN_CACHE + _FAST_MAIN_CACHE=() +} + +autoload -Uz add-zsh-hook +add-zsh-hook preexec _zsh_highlight_preexec_hook 2>/dev/null || { + print -r -- >&2 'zsh-syntax-highlighting: failed loading add-zsh-hook.' +} + +/fshdbg() { + print -r -- "$@" >>! /tmp/reply +} + +ZSH_HIGHLIGHT_MAXLENGTH=10000 + +# Load zsh/parameter module if available +zmodload zsh/parameter 2>/dev/null +zmodload zsh/system 2>/dev/null + +autoload -Uz -- is-at-least fast-theme fast-read-ini-file -fast-run-git-command -fast-make-targets \ + -fast-run-command -fast-zts-read-all +autoload -Uz -- :chroma/-git.ch :chroma/-hub.ch :chroma/-lab.ch :chroma/-example.ch \ + :chroma/-grep.ch :chroma/-perl.ch :chroma/-make.ch :chroma/-awk.ch \ + :chroma/-vim.ch :chroma/-source.ch :chroma/-sh.ch :chroma/-docker.ch \ + :chroma/-autoload.ch :chroma/-ssh.ch :chroma/-scp.ch :chroma/-which.ch \ + :chroma/-printf.ch :chroma/-ruby.ch :chroma/-whatis.ch :chroma/-alias.ch \ + :chroma/-subcommand.ch :chroma/-autorandr.ch :chroma/-nmcli.ch \ + :chroma/-fast-theme.ch :chroma/-node.ch :chroma/-fpath_peq.ch \ + :chroma/-precommand.ch :chroma/-subversion.ch :chroma/-ionice.ch \ + :chroma/-nice.ch :chroma/main-chroma.ch :chroma/-ogit.ch :chroma/-zplugin.ch + +source "${0:h}/fast-highlight" +source "${0:h}/fast-string-highlight" + +local __fsyh_theme +zstyle -s :plugin:fast-syntax-highlighting theme __fsyh_theme + +[[ ( "${+termcap}" != 1 || "${termcap[Co]}" != <-> || "${termcap[Co]}" -lt "256" ) && "$__fsyh_theme" = (default|) ]] && { + FAST_HIGHLIGHT_STYLES[defaultvariable]="none" + FAST_HIGHLIGHT_STYLES[defaultglobbing-ext]="fg=blue,bold" + FAST_HIGHLIGHT_STYLES[defaulthere-string-text]="bg=blue" + FAST_HIGHLIGHT_STYLES[defaulthere-string-var]="fg=cyan,bg=blue" + FAST_HIGHLIGHT_STYLES[defaultcorrect-subtle]="bg=blue" + FAST_HIGHLIGHT_STYLES[defaultsubtle-bg]="bg=blue" + [[ "${FAST_HIGHLIGHT_STYLES[variable]}" = "fg=113" ]] && FAST_HIGHLIGHT_STYLES[variable]="none" + [[ "${FAST_HIGHLIGHT_STYLES[globbing-ext]}" = "fg=13" ]] && FAST_HIGHLIGHT_STYLES[globbing-ext]="fg=blue,bold" + [[ "${FAST_HIGHLIGHT_STYLES[here-string-text]}" = "bg=18" ]] && FAST_HIGHLIGHT_STYLES[here-string-text]="bg=blue" + [[ "${FAST_HIGHLIGHT_STYLES[here-string-var]}" = "fg=cyan,bg=18" ]] && FAST_HIGHLIGHT_STYLES[here-string-var]="fg=cyan,bg=blue" + [[ "${FAST_HIGHLIGHT_STYLES[correct-subtle]}" = "fg=12" ]] && FAST_HIGHLIGHT_STYLES[correct-subtle]="bg=blue" + [[ "${FAST_HIGHLIGHT_STYLES[subtle-bg]}" = "bg=18" ]] && FAST_HIGHLIGHT_STYLES[subtle-bg]="bg=blue" +} + +unset __fsyh_theme + +alias fsh-alias=fast-theme + +-fast-highlight-fill-option-variables diff --git a/.config/shell/zsh-fast-syntax-highlighting/fast-theme b/.config/shell/zsh-fast-syntax-highlighting/fast-theme new file mode 100644 index 0000000..0bc1188 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/fast-theme @@ -0,0 +1,385 @@ +# -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# Copyright (c) 2018 Sebastian Gniazdowski +# Copyright (c) 2018, 2019 Philippe Troin (F-i-f on GitHub) +# +# Theme support using ini-files. +# + +zmodload zsh/zutil 2>/dev/null + +emulate -LR zsh +setopt extendedglob typesetsilent warncreateglobal +autoload colors; colors + +typeset -g FAST_WORK_DIR +: ${FAST_WORK_DIR:=$FAST_BASE_DIR} +FAST_WORK_DIR=${~FAST_WORK_DIR} + +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%:}:]}}%/} + +local OPT_HELP OPT_VERBOSE OPT_QUIET OPT_RESET OPT_LIST OPT_TEST OPT_SECONDARY OPT_SHOW OPT_COPY OPT_OV_RESET +local OPT_PALETTE OPT_CDWD OPT_XCHG OPT_OV_XCHG +local -A opthash +zparseopts -E -D -A opthash h -help v -verbose q -quiet r -reset l -list t -test -secondary \ + s -show -copy-shipped-theme: R -ov-reset p -palette w -workdir \ + x -xchg y -ov-xchg || \ + { echo "Improper options given, see help (-h/--help)"; return 1; } + +(( ${+opthash[-h]} + ${+opthash[--help]} )) && OPT_HELP="-h" +(( ${+opthash[-v]} + ${+opthash[--verbose]} )) && OPT_VERBOSE="-v" +(( ${+opthash[-q]} + ${+opthash[--quiet]} )) && OPT_QUIET="-q" +(( ${+opthash[-r]} + ${+opthash[--reset]} )) && OPT_RESET="-r" +(( ${+opthash[-l]} + ${+opthash[--list]} )) && OPT_LIST="-l" +(( ${+opthash[-t]} + ${+opthash[--test]} )) && OPT_TEST="-t" +(( ${+opthash[--secondary]} )) && OPT_SECONDARY="--secondary" +(( ${+opthash[-s]} + ${+opthash[--show]} )) && OPT_SHOW="-s" +(( ${+opthash[--copy-shipped-theme]} )) && OPT_COPY="${opthash[--copy-shipped-theme]}" +(( ${+opthash[-R]} + ${+opthash[--ov-reset]} )) && OPT_OV_RESET="-R" +(( ${+opthash[-p]} + ${+opthash[--palette]} )) && OPT_PALETTE="-p" +(( ${+opthash[-w]} + ${+opthash[--workdir]} )) && OPT_CDWD="-w" +(( ${+opthash[-x]} + ${+opthash[--xchg]} )) && OPT_XCHG="-x" +(( ${+opthash[-y]} + ${+opthash[--ov-xchg]} )) && OPT_OV_XCHG="-y" + +local -a match mbegin mend +local MATCH; integer MBEGIN MEND + +[[ -n "$OPT_CDWD" ]] && { + builtin cd $FAST_WORK_DIR + return 0 +} + +[[ -n "$OPT_PALETTE" ]] && { + local n + local -a __colors + for n in {000..255} + do + __colors+=("%F{$n}$n%f") + done + print -cP $__colors + return +} + +[[ -n "$OPT_SHOW" ]] && { + print -r -- "Currently active theme: ${fg_bold[yellow]}$FAST_THEME_NAME$reset_color" + ( source "$FAST_WORK_DIR"/current_theme.zsh 2>/dev/null && print "Main theme (loaded at startup of a session): ${fg_bold[yellow]}$FAST_THEME_NAME$reset_color" || print "No main theme is set"; ) + return 0 +} + +[[ -n "$OPT_COPY" ]] && { + [[ ! -f "$FAST_BASE_DIR"/themes/"${OPT_COPY%.ini}.ini" ]] && { print "Theme \`$OPT_COPY' doesn't exist in FSH plugin dir ($FAST_BASE_DIR/themes)"; return 1; } + [[ ! -r "$FAST_BASE_DIR"/themes/"${OPT_COPY%.ini}.ini" ]] && { print "Theme \`$OPT_COPY' isn't readable in FSH plugin dir ($FAST_BASE_DIR/themes)"; return 1; } + [[ -n "$1" ]] && { + [[ ! -e "$1" && ! -e ${1:h} ]] && { print "Destination path doesn't exist, aborting"; return 1; } + } + command cp -vf "$FAST_BASE_DIR"/themes/"${OPT_COPY%.ini}.ini" "${${1:-.}%.ini}.ini" || return 1 + return 0 +} + +[[ -n "$OPT_RESET" ]] && { command rm -f "$FAST_WORK_DIR"/{current_theme.zsh,secondary_theme.zsh}; [[ -z "$OPT_QUIET" ]] && print "Reset done (no theme is now set, restart is required)"; return 0; } + +[[ -n "$OPT_OV_RESET" ]] && { command rm -f "$FAST_WORK_DIR"/theme_overlay.zsh; [[ -z "$OPT_QUIET" ]] && print "Overlay-reset done, it is inactive (restart is required)"; return 0; } + +[[ -n "$OPT_LIST" ]] && { + [[ -z "$OPT_QUIET" ]] && print -r -- "Available themes:" + print -rl -- "$FAST_BASE_DIR"/themes/*.ini(:t:r) + return 0 +} + +[[ -n "$OPT_HELP" ]] && { + print -r -- "Usage: fast-theme [-h/--help] [-v/--verbose] [-q/--quiet] [-t/--test] <theme-name|theme-path>" + print -r -- " fast-theme [-r/--reset] [-l/--list] [-s/--show] [-p/--palette] [-w/--workdir]" + print -r -- " fast-theme --copy-shipped-theme {theme-name} [destination-path]" + print -r -- "" + print -r -- "Default action (after providing <theme-name> or <theme-path>) is to switch" + print -r -- "current session and any future sessions to the new theme. Using <theme-path>," + print -r -- "i.e.: a path to an ini file means using custom, own theme. The path can use an" + print -r -- "\"XDG:\" shorthand (e.g.: \"XDG:mytheme\") that will point to ~/.config/fsh/<theme>.ini" + print -r -- "(or \$XDG_CONFIG_HOME/fsh/<theme>.ini in general if the variable is set in the" + print -r -- "environment). If the INI file pointed in the path is \"*overlay*\", then it is" + print -r -- "not a full theme, but an additional theme-snippet that overwrites only selected" + print -r -- "styles of the main theme." + print -r -- "" + print -r -- "Other path-shorthands:" + print -r -- "LOCAL: = /usr/local/share/fsh/" + print -r -- "HOME: = $HOME/.fsh/" + print -r -- "OPT: = /opt/local/share/fsh/" + print -r -- "" + print -r -- "-r/--reset - unset any theme, use default highlighting (requires restart)" + print -r -- "-R/--ov-reset - unset overlay, use styles only from main-theme (requires restart)" + print -r -- "-l/--list - list names of available themes" + print -r -- "-t/--test - show test block of code after switching theme" + print -r -- "-s/--show - get and display the theme currently being set" + print -r -- "-p/--palette - just print all 256 colors and exit (useful when creating a theme)" + print -r -- "-w/--workdir - cd into \$FAST_WORK_DIR (if not set, then into the plugin directory)" + print -r -- "-v/--verbose - more messages during operation" + print -r -- "-q/--quiet - no default messages" + print -r -- "" + print -r -- "The option --copy-shipped-theme allows easy copying of one of the 6 shipped" + print -r -- "themes into given destination path. Normal use means changing directory to" + print -r -- "e.g.: ~/.config/fsh, and then issuing e.g.: \`fast-theme --copy-shipped-theme" + print -r -- "clean mytheme', to obtain a template for own new theme." + return 0 +} + +[[ -z "$1" ]] && { print -u2 "Provide a theme (its name or path to its file) to switch to, aborting (see -h/--help)"; return 1; } + +# FAST_HIGHLIGHT_STYLES key onto ini-file key +map=( + default "-" + unknown-token "-" + reserved-word "-" + subcommand "- reserved-word" + alias "- command builtin" + suffix-alias "- alias command builtin" + builtin "-" + function "- builtin command" + command "-" + precommand "- command" + commandseparator "-" + hashed-command "- command" + path "-" + path_pathseparator "pathseparator" + globbing "- back-or-dollar-double-quoted-argument" # fallback: variable in string "text $var text" + globbing-ext "- double-quoted-argument" # fallback: the string "abc..." + history-expansion "-" + single-hyphen-option "- single-quoted-argument" + double-hyphen-option "- double-quoted-argument" + back-quoted-argument "-" + single-quoted-argument "-" + double-quoted-argument "-" + dollar-quoted-argument "-" + back-or-dollar-double-quoted-argument "- back-dollar-quoted-argument" + back-dollar-quoted-argument "- back-or-dollar-double-quoted-argument" + assign "- reserved-word" + redirection "- reserved-word" + comment "-" + variable "-" + mathvar "- forvar variable" + mathnum "- fornum" + matherr "- incorrect-subtle" + assign-array-bracket "-" + for-loop-variable "forvar mathvar variable" + for-loop-number "fornum mathnum" + for-loop-operator "foroper reserved-word" + for-loop-separator "forsep commandseparator" + exec-descriptor "- reserved-word" + here-string-tri "-" + here-string-text "- subtle-bg" + here-string-var "- back-or-dollar-double-quoted-argument" + secondary "-" + recursive-base "- default" + case-input "- variable" + case-parentheses "- reserved-word" + case-condition "- correct-subtle" + correct-subtle "-" + incorrect-subtle "-" + subtle-separator "- commandseparator" + subtle-bg "- correct-subtle" + path-to-dir "- path" + paired-bracket "- subtle-bg correct-subtle" + bracket-level-1 "-" + bracket-level-2 "-" + bracket-level-3 "-" + global-alias "- alias suffix-alias" + single-sq-bracket "-" + double-sq-bracket "-" + double-paren "-" + optarg-string "- double-quoted-argument" + optarg-number "- mathnum" +) + +# In which order to generate entries +local -a order +order=( + default unknown-token reserved-word alias suffix-alias builtin function command precommand + commandseparator hashed-command path path_pathseparator globbing globbing-ext history-expansion + single-hyphen-option double-hyphen-option back-quoted-argument single-quoted-argument + double-quoted-argument dollar-quoted-argument back-or-dollar-double-quoted-argument + back-dollar-quoted-argument assign redirection comment variable mathvar + mathnum matherr assign-array-bracket for-loop-variable for-loop-number for-loop-operator + for-loop-separator exec-descriptor here-string-tri here-string-text here-string-var secondary + case-input case-parentheses case-condition correct-subtle incorrect-subtle subtle-separator subtle-bg + path-to-dir paired-bracket bracket-level-1 bracket-level-2 bracket-level-3 + global-alias subcommand single-sq-bracket double-sq-bracket double-paren + optarg-string optarg-number recursive-base +) + +[[ -n "$OPT_VERBOSE" ]] && print "Number of styles available for customization: ${#order}" + +# Named colors +local -a color +color=( red green blue yellow cyan magenta black white default ) + +# +# Execution starts here +# + +local -A out +local THEME_NAME THEME_PATH="$1" +if [[ "$1" = */* || "$1" = (XDG|LOCAL|HOME|OPT):* ]]; then + 1="${${1/(#s)XDG:/${${XDG_CONFIG_HOME:-$HOME/.config}%/}/fsh/}%.ini}.ini" + 1="${${1/(#s)LOCAL://usr/local/share/fsh/}%.ini}.ini" + 1="${${1/(#s)HOME:/$HOME/.fsh/}%.ini}.ini" + 1="${${1/(#s)OPT://opt/local/share/fsh/}%.ini}.ini" + 1=${~1} # allow user to quote ~ + + [[ ! -f "$1" ]] && { print -u2 "No such theme \`$1', aborting"; return 1; } + [[ ! -r "$1" ]] && { print -u2 "Theme \`$1' unreadable, aborting"; return 1; } + + THEME_NAME="${1:t:r}" + fast-read-ini-file "$1" out "" +else + [[ ! -f "$FAST_BASE_DIR/themes/$1.ini" ]] && { print -u2 "No such theme \`$1', aborting"; return 1; } + [[ ! -r "$FAST_BASE_DIR/themes/$1.ini" ]] && { print -u2 "Theme \`$1' unreadable, aborting"; return 1; } + + THEME_NAME="$1" + fast-read-ini-file "$FAST_BASE_DIR/themes/$1.ini" out "" +fi + +[[ -z "$OPT_SECONDARY" ]] && { [[ "$THEME_NAME" = *"overlay"* ]] && local outfile="theme_overlay.zsh" || local outfile="current_theme.zsh"; } || local outfile="secondary_theme.zsh" +[[ -z "$OPT_XCHG" && -z "$OPT_OV_XCHG" ]] && command rm -f "$FAST_WORK_DIR"/"$outfile" + +# Set a zstyle and a parameter to carry theme name +if [[ -z "$OPT_SECONDARY" && -z "$OPT_XCHG" && -z "$OPT_OV_XCHG" ]]; then + [[ "$THEME_NAME" != *"overlay"* ]] && { + print -r -- 'zstyle :plugin:fast-syntax-highlighting theme "'"$THEME_NAME"'"' >>! "$FAST_WORK_DIR"/"$outfile" + print -r -- 'typeset -g FAST_THEME_NAME="'"$THEME_NAME"'"' >>! "$FAST_WORK_DIR"/"$outfile" + zstyle :plugin:fast-syntax-highlighting theme "$THEME_NAME" + typeset -g FAST_THEME_NAME="$THEME_NAME" + } +elif [[ -z "$OPT_XCHG" && -z "$OPT_OV_XCHG" ]]; then + local FAST_THEME_NAME="$THEME_NAME" +fi + +# Store from which file the theme or overlay is being loaded +[[ "$THEME_NAME" != *"overlay" && -z "$OPT_OV_XCHG" ]] && FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}-path]="$THEME_PATH" || FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}-ov-path]="$THEME_PATH" + +# Generate current_theme.zsh or secondary_theme.zsh, traversing ini-file associative array +local k kk +local inikey inival result result2 first_val isbg +integer ov_counter=0 first +for k in "${order[@]}"; do + first=1 + for kk in ${(s. .)map[$k]} default; do + [[ "$kk" = "-" ]] && kk="$k" + (( first )) && first_val="$kk" + inikey="${out[(i)<*>_${kk}]}" + [[ -n "$inikey" ]] && { + (( !first )) && [[ -z "$OPT_QUIET" ]] && { + [[ $kk = default ]] && { + [[ "$THEME_NAME" != *"overlay"* ]] && print "Missing style: $first_val" + } || print "For style $first_val, went for fallback style $kk" + } + break + } + first=0 + [[ "$THEME_NAME" = *"overlay"* ]] && break + done + + # ORIG: Clear orig-style when loading a new theme, not overlay + [[ -z "$OPT_OV_XCHG" ]] && unset "FAST_HIGHLIGHT_STYLES[orig-style-$k]" + # ORIG: Restore orig-style when loading a new overlay + [[ -n "$OPT_OV_XCHG" && -n "${FAST_HIGHLIGHT_STYLES[orig-style-$k]}" ]] && { FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}$k]="${FAST_HIGHLIGHT_STYLES[orig-style-$k]}"; unset "FAST_HIGHLIGHT_STYLES[orig-style-$k]"; } + # Set only the keys provided in theme + [[ -z "$inikey" ]] && { [[ -z "$OPT_QUIET" && "$THEME_NAME" != *"overlay"* ]] && print "Missing style $first_val"; continue; } + + inival="${out[$inikey]}" + if [[ "$k" = "secondary" && -z "$OPT_SECONDARY" && -n "$inival" ]]; then + fast-theme -q --secondary "$inival" + fi + + result="" + if [[ $k = secondary ]]; then + result="$inival" + else + for kk in ${(s:,:)inival} + do + if [[ $kk = (none|(no-|)(bold|blink|conceal|reverse|standout|underline)) ]]; then + result+="${result:+,}$kk" + else + isbg=0 + if [[ $kk = bg:* ]]; then + isbg=1 + kk=${kk#bg:} + fi + if [[ $kk = (${(~j:|:)color}) || $kk = [0-9]## || $kk = \#[0-9a-fA-F](#c6,6) ]]; then + result+="${result:+,}" + (( isbg )) && result+="bg=" || result+="fg=" + result+="$kk" + else + print "cannot parse style $k: unknown color or style element $kk" + fi + fi + done + fi + + if [[ "$THEME_NAME" = *"overlay"* || -n "$OPT_OV_XCHG" ]]; then + (( ++ ov_counter )) + [[ -z "$OPT_XCHG$OPT_OV_XCHG" ]] && print -r -- ': ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}'"$k"']::='"$result"'}' >>! "$FAST_WORK_DIR"/"$outfile" + # ORIG: Save original value of the overwritten style + FAST_HIGHLIGHT_STYLES[orig-style-$k]=${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}$k]} + # Overwrite theme's style + FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}$k]="$result" + else + [[ -z "$OPT_XCHG$OPT_OV_XCHG" ]] && print -r -- ': ${FAST_HIGHLIGHT_STYLES['"${FAST_THEME_NAME}$k"']:='"$result"'}' >>! "$FAST_WORK_DIR"/"$outfile" + FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}$k]="$result" + fi +done + +# This can overwrite some of *_STYLES fields +# Re-apply overlay on top of the theme we switched to +[[ "$THEME_NAME" != *"overlay"* ]] && [[ -r "$FAST_WORK_DIR"/theme_overlay.zsh ]] && source "$FAST_WORK_DIR"/theme_overlay.zsh + +zcompile $FAST_WORK_DIR/$outfile 2>/dev/null + +[[ -z "$OPT_QUIET" ]] && { + if [[ "$THEME_NAME" != *"overlay"* ]]; then + print "Switched to theme \`$THEME_NAME' (current session, and future sessions)" || \ + else + print "Processed the overlay ($ov_counter keys found), it is now active (for current session, and future sessions)" + fi +} + +[[ -n "$OPT_TEST" ]] && { + print -zr ' +# Subshell, assignments, math-mode +echo $(cat /etc/hosts |& grep -i "hello337") +local param1="text ${+variable[test]} text ${var} text"; typeset param2='"'"'other $variable'"'"' +math=$(( 10 + HISTSIZ + HISTSIZE + $SAVEHIST )) size=$(( 0 )) + +# Programming-like usage, bracket matching - through distinct colors; note the backslash quoting +for (( ii = 1; ii <= size; ++ ii )); do + if [[ "${cmds[ii]} string" = "| string" ]] + then + sidx=${buffer[(in:ii:)\$\(?#[^\\\\]\)]} # find opening cmd-subst + (( sidx <= len + 100 )) && { + eidx=${buffer[(b:sidx:ii)[^\\\\]\)]} # find closing cmd-subst + } + fi +done + +# Regular command-line usage +repeat 0 { + zsh -i -c "cat /etc/shells* | grep -x --line-buffered -i '"'/bin/zsh'"'" + builtin exit $return_value + fast-theme -tq default + fsh-alias -tq default-X # alias '"'"'fsh-alias=fast-theme'"'"' works just like the previous line + command -v git | grep ".+git" && echo $'"'"'Git is installed'"'"' + git checkout -m --ours /etc/shells && git status-X + gem install asciidoctor + cat <<<$PATH | tr : \\n > /dev/null 2>/usr/local + man -a fopen fopen-X + CFLAGS="-g -Wall -O0" ./configure +} +' +} + +return 0 +# vim:ft=zsh:et:sw=4:sts=4 diff --git a/.config/shell/zsh-fast-syntax-highlighting/test/parse.zsh b/.config/shell/zsh-fast-syntax-highlighting/test/parse.zsh new file mode 100755 index 0000000..53dec62 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/test/parse.zsh @@ -0,0 +1,220 @@ +#!/bin/sh + +# +# This file runs the highlighter on a specified file +# i.e. parses the file with the highlighter. Outputs +# running time (stderr) and resulting region_highlight +# (file parse.out, or $2 if given). +# +# Can be also run in line-wise mode on own input (-o +# option in $1), no region_highlight file then. +# + +[[ -z "$ZSH_VERSION" ]] && exec /usr/bin/env /usr/local/bin/zsh-5.5.1 -f -c "source \"$0\" \"$1\" \"$2\" \"$3\"" + +ZERO="${(%):-%N}" + +if [[ -e "${ZERO}/../fast-highlight" ]]; then + source "${ZERO}/../fast-highlight" + source "${ZERO}/../fast-string-highlight" + fpath+=( "${ZERO}/.." ) +elif [[ -e "../fast-highlight" ]]; then + source "../fast-highlight" + source "../fast-string-highlight" + fpath+=( "$PWD/.." ) +elif [[ -e "${ZERO}/fast-highlight" ]]; then + source "${ZERO}/fast-highlight" + source "${ZERO}/fast-string-highlight" + fpath+=( "${ZERO}" ) +elif [[ -e "./fast-highlight" ]]; then + source "./fast-highlight" + source "./fast-string-highlight" + fpath+=( "./" ) +else + print -u2 "Could not find fast-highlight, aborting" + exit 1 +fi + +zmodload zsh/zprof +autoload is-at-least chroma/-git.ch + +setopt interactive_comments extendedglob + +# Own input? +if [[ "$1" = "-o" || "$1" = "-oo" || "$1" = "-ooo" || "$1" = "-git" || "$1" = "-hue" || "$1" = "-hol" ]]; then + typeset -a input + input=() + if [[ "$1" = "-o" ]]; then + input+=( "./parse.zsh ../fast-highlight parse2.out" ) + input+=( "rm -f parse*.out" ) + input+=( "./mh-parse.zsh ../fast-highlight > out" ) + input+=( "if [[ -o multibyte ]]; then echo multibyte is set; fi" ) + input+=( "[[ \"a\" = *[[:alpha:]_-][[:alpha:]]# ]] && echo yes" ) + input+=( 'git tag -a v0.98 -m "Syntax highlighting of the history entries"' ) + input+=( 'func() { echo "a" >! phist2.db; echo "b" >>! phist2.db; fc -Rap "phist2.db"; list=( ${history[@]} ); echo "${history[1]}"; }' ) + (( ${+ZSH_EXECUTION_STRING} == 0 )) && { print -zr "${(F)input}"; return 0; } + elif [[ "$1" = "-oo" ]]; then + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + input+=( 'typeset -a list\n() {\necho "a" >! phist2.db\necho "b" >>! phist2.db\nfc -Rap "phist2.db"\nlist=( ${history[@]} )\necho "${history[2]}"\necho "${history[1]}"\necho "${#history}";\ninteger size="${#history}"\nsize+=1\necho "$size" / "${history[$size]}"\nlist=( "${history[$size]}" ${history[@]} )\n}' ) + (( ${+ZSH_EXECUTION_STRING} == 0 )) && { print -zr "${(F)input}"; return 0; } + elif [[ "$1" = "-ooo" ]]; then + local in=' +# This is an example code that is diverse and allows to test a theme +text="An example quite long string $with variable in it" +local param1="text $variable" param2='"'"'other $variable'"'"' +math=$(( 10 + HISTSIZ + HISTSIZE + $SAVEHIST )) size=$(( 0 )) + +for (( ii = 1; ii <= size; ++ ii )); do + if [[ "${cmds[ii]} string" = "| string" ]] + then + sidx=${buffer[(in:ii:)\$\(?#[^\\\\]\)]} # find opening $( + (( sidx <= len )) && { + eidx=${buffer[(b:sidx:ii)[^\\\\]\)]} # find closing ) + } + fi +done' + (( ${+ZSH_EXECUTION_STRING} == 0 )) && { print -zr "$in"; return 0; } + input+=( "$in" ) + input+=( "$in" ) + elif [[ "$1" = "-git" ]]; then + local in="git lp +git push origin master + git commit +git add safari.ini zdharma.ini +git st . +git diff --cached +git commit --allow-empty +git checkout themes/zdharma.ini +git commit --amend +git commit -m \"Example commit message\" +git tag -a 'v1.18' -m 'Here-string is highlighted, descriptor-variables passed to exec are correctly highlighted' +git tag -l -n9 +git checkout cb66b11 +" + (( ${+ZSH_EXECUTION_STRING} == 0 )) && { print -zr "$in"; return 0; } + input+=( "$in" ) + input+=( "$in" ) + elif [[ "$1" = "-hue" ]]; then + local in="var=\$other; local var=\$other + () { eval \"\$var\"; } + case \$other in + \$var) + ( echo OK; ) + ;; + esac + sudo -i -s ls -1 /var/log + () { ( eval \"command ls -1\" ); } argument" + + (( ${+ZSH_EXECUTION_STRING} == 0 )) && { print -zr "$in"; return 0; } + + input+=( "$in" "$in" ) + elif [[ "$1" = "-hol" ]]; then + local in="var=\$( other ) +local var2=\$(( other + 1 )) +() { eval \"\$var\"; } +sudo -i -s ls -1 >/tmp/ls-log.txt /var/log +IFS=\$'\\n' print -rl -- \$(command ls -1 | tee -a /tmp/ls-1.txt) +var3=\$(( HISTSIZE + 10 + \$var )) +local var4=\$( other command ) +touch \$(( HISTSIZE + \$SAVEHIST + 10 )) +case \$other in + \$var) + ( echo OK; ) + ;; + \$var3) + ( if { true } { noglob echo yes } ) +esac +( builtin cd /var/log; ls -1; noglob cd \"/var/log\" 'log' ) +noglob cat <<<\"\$PATH\" | tr : \"\\n\" +if [[ \"\$var\" -gt 10 ]]; then + (( var = HISTSIZE + \$SAVEHIST )) +fi +/var/log +sidx=\${buffer[(in:ii:)\\\$\\(?#[^\\\\\\\\]\\)]} # find opening cmd-subst +{ + exec {MYFD}<&0 {MYFD2}>&1 + ( read <&\$MYFD line; echo \$line >&\$MYFD2 && { builtin print \${match[1]}Written. } ) +} always { + (( MYFD > 0 )) && { print -rl -- -myfd:\$MYFD >&\$MYFD2 && print \"Sent.\" '(to filedescriptor)'; } +} +command sleep \"\$(( \$a + b + \${cde} + \${(s::)fgh[ijk]} + \\\$l + \\m + \\\" ))\" +for (( i = 0; i <= 2; ++ i )) { print \$i; } +" + + (( ${+ZSH_EXECUTION_STRING} == 0 )) && { print -zr "$in"; return 0; } + + input+=( "$in" ) + fi + + typeset -a long_input + integer i + for (( i=1; i<= 50; i ++ )); do + long_input+=( "${input[@]}" ) + done + + typeset -F SECONDS + SECONDS=0 + + local right_brace_is_recognised_everywhere + integer path_dirs_was_set multi_func_def ointeractive_comments + -fast-highlight-fill-option-variables + + local BUFFER + for BUFFER in "${long_input[@]}"; do + reply=( ) + () { + -fast-highlight-init + -fast-highlight-process "" "$BUFFER" "0" + -fast-highlight-string-process "" "$BUFFER" + } + done + + print "Running time: $SECONDS" + zprof | head +# File input? +elif [[ -r "$1" ]]; then + # Load from given file + local BUFFER="$(<$1)" + + typeset -F SECONDS + SECONDS=0 + + reply=( ) + -fast-highlight-init + + local right_brace_is_recognised_everywhere + integer path_dirs_was_set multi_func_def ointeractive_comments + -fast-highlight-fill-option-variables + + () { + -fast-highlight-process "" "$BUFFER" "0" + -fast-highlight-string-process "" "$BUFFER" + } + + print "Running time: $SECONDS" + zprof | head + + # This output can be diffed to detect changes in operation + if [[ -z "$2" ]]; then + print -rl -- "${reply[@]}" >! out.parse + else + print -rl -- "${reply[@]}" >! "$2" + fi +else + if [[ -z "$1" ]]; then + print -u2 "Usage: ./parse.zsh {to-parse file} [region_highlight output file]" + exit 2 + else + print -u2 "Unreadable to-parse file \`$1', aborting" + exit 3 + fi +fi + +exit 0 + +# vim:ft=zsh diff --git a/.config/shell/zsh-fast-syntax-highlighting/test/to-parse.zsh b/.config/shell/zsh-fast-syntax-highlighting/test/to-parse.zsh new file mode 100644 index 0000000..855d7a4 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/test/to-parse.zsh @@ -0,0 +1,823 @@ +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2010-2016 zsh-syntax-highlighting contributors +# All rights reserved. +# +# 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. +# ------------------------------------------------------------------------------------------------- +# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- +# vim: ft=zsh sw=2 ts=2 et +# ------------------------------------------------------------------------------------------------- + +typeset -gA __hsmw_highlight_main__command_type_cache + +# Define default styles. +typeset -gA HSMW_HIGHLIGHT_STYLES +: ${HSMW_HIGHLIGHT_STYLES[default]:=none} +: ${HSMW_HIGHLIGHT_STYLES[unknown-token]:=fg=red,bold} +: ${HSMW_HIGHLIGHT_STYLES[reserved-word]:=fg=yellow} +: ${HSMW_HIGHLIGHT_STYLES[alias]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[suffix-alias]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[builtin]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[function]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[command]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[precommand]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[commandseparator]:=none} +: ${HSMW_HIGHLIGHT_STYLES[hashed-command]:=fg=green} +: ${HSMW_HIGHLIGHT_STYLES[path]:=fg=magenta} +: ${HSMW_HIGHLIGHT_STYLES[path_pathseparator]:=} +: ${HSMW_HIGHLIGHT_STYLES[path_prefix]:=fg=magenta} +: ${HSMW_HIGHLIGHT_STYLES[path_prefix_pathseparator]:=} +: ${HSMW_HIGHLIGHT_STYLES[globbing]:=fg=blue,bold} +: ${HSMW_HIGHLIGHT_STYLES[history-expansion]:=fg=blue,bold} +: ${HSMW_HIGHLIGHT_STYLES[single-hyphen-option]:=none} +: ${HSMW_HIGHLIGHT_STYLES[double-hyphen-option]:=none} +: ${HSMW_HIGHLIGHT_STYLES[back-quoted-argument]:=none} +: ${HSMW_HIGHLIGHT_STYLES[single-quoted-argument]:=fg=yellow} +: ${HSMW_HIGHLIGHT_STYLES[double-quoted-argument]:=fg=yellow} +: ${HSMW_HIGHLIGHT_STYLES[dollar-quoted-argument]:=fg=yellow} +: ${HSMW_HIGHLIGHT_STYLES[dollar-double-quoted-argument]:=fg=cyan} +: ${HSMW_HIGHLIGHT_STYLES[back-double-quoted-argument]:=fg=cyan} +: ${HSMW_HIGHLIGHT_STYLES[back-dollar-quoted-argument]:=fg=cyan} +: ${HSMW_HIGHLIGHT_STYLES[assign]:=none} +: ${HSMW_HIGHLIGHT_STYLES[redirection]:=none} +: ${HSMW_HIGHLIGHT_STYLES[comment]:=fg=black,bold} + +# 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. +-hsmw-highlight-main-type() { + if (( $+__hsmw_highlight_main__command_type_cache )); then + REPLY=$__hsmw_highlight_main__command_type_cache[(e)$1] + if [[ -n "$REPLY" ]]; then + return + fi + fi + if (( $#options_to_set )); then + setopt localoptions $options_to_set; + fi + unset REPLY + if zmodload -e zsh/parameter; then + if (( $+aliases[(e)$1] )); then + REPLY=alias + elif (( $+saliases[(e)${1##*.}] )); then + REPLY='suffix alias' + elif (( $reswords[(Ie)$1] )); then + REPLY=reserved + elif (( $+functions[(e)$1] )); then + REPLY=function + elif (( $+builtins[(e)$1] )); then + REPLY=builtin + elif (( $+commands[(e)$1] )); then + REPLY=command + # 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 $(x) below, incurring a fork. (Issue #354.) + # + # The second disjunct mimics the isrelative() C call from the zsh bug. + elif { [[ $1 != */* ]] || is-at-least 5.3 } && + ! builtin type -w -- $1 >/dev/null 2>&1; then + REPLY=none + fi + fi + if ! (( $+REPLY )); then + REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)#*: }" + fi + if (( $+__hsmw_highlight_main__command_type_cache )); then + __hsmw_highlight_main__command_type_cache[(e)$1]=$REPLY + fi +} + +# Check whether the first argument is a redirection operator token. +# Report result via the exit code. +-hsmw-highlight-is-redirection() { + # A redirection operator token: + # - starts with an optional single-digit number; + # - then, has a '<' or '>' character; + # - is not a process substitution [<(...) or >(...)]. + [[ $1 == (<0-9>|)(\<|\>)* ]] && [[ $1 != (\<|\>)$'\x28'* ]] +} + +# Resolve alias. +# +# Takes a single argument. +# +# The result will be stored in REPLY. +-hsmw-highlight-resolve-alias() { + if zmodload -e zsh/parameter; then + REPLY=${aliases[$arg]} + else + REPLY="${"$(alias -- $arg)"#*=}" + fi +} + +# Check that the top of $braces_stack has the expected value. If it does, set +# the style according to $2; otherwise, set style=unknown-token. +# +# $1: character expected to be at the top of $braces_stack +# $2: assignment to execute it if matches +-hsmw-highlight-stack-pop() { + if [[ $braces_stack[1] == $1 ]]; then + braces_stack=${braces_stack:1} + eval "$2" + else + style=unknown-token + fi +} + +# Main syntax highlighting function. +-hsmw-highlight-process() +{ + ## Before we even 'emulate -L', we must test a few options that would reset. + if [[ -o interactive_comments ]]; then + local interactive_comments= # set to empty + fi + if [[ -o ignore_braces ]] || eval '[[ -o ignore_close_braces ]] 2>/dev/null'; then + local right_brace_is_recognised_everywhere=false + else + local right_brace_is_recognised_everywhere=true + fi + if [[ -o path_dirs ]]; then + integer path_dirs_was_set=1 + else + integer path_dirs_was_set=0 + fi + if [[ -o multi_func_def ]]; then + integer multi_func_def=1 + else + integer multi_func_def=0 + fi + emulate -L zsh + setopt localoptions extendedglob bareglobqual + + ## Variable declarations and initializations + local start_pos=0 end_pos highlight_glob=true arg style + local in_array_assignment=false # true between 'a=(' and the matching ')' + typeset -a __HSMW_HIGHLIGHT_TOKENS_COMMANDSEPARATOR + typeset -a __HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS + typeset -a __HSMW_HIGHLIGHT_TOKENS_CONTROL_FLOW + local -a options_to_set # used in callees + local buf="$1" + integer len="${#buf}" + integer pure_buf_len=len # historical, was $#BUFFER, i.e. len without $PREBUFFER; used e.g. in *_check_path + + local braces_stack # "R" for round, "Q" for square, "Y" for curly + + if (( path_dirs_was_set )); then + options_to_set+=( PATH_DIRS ) + fi + unset path_dirs_was_set + + __HSMW_HIGHLIGHT_TOKENS_COMMANDSEPARATOR=( + '|' '||' ';' '&' '&&' + '|&' + '&!' '&|' + # ### 'case' syntax, but followed by a pattern, not by a command + # ';;' ';&' ';|' + ) + __HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS=( + 'builtin' 'command' 'exec' 'nocorrect' 'noglob' + 'pkexec' # immune to #121 because it's usually not passed --option flags + ) + + # Tokens that, at (naively-determined) "command position", are followed by + # a de jure command position. All of these are reserved words. + __HSMW_HIGHLIGHT_TOKENS_CONTROL_FLOW=( + $'\x7b' # block + $'\x28' # subshell + '()' # anonymous function + 'while' + 'until' + 'if' + 'then' + 'elif' + 'else' + 'do' + 'time' + 'coproc' + '!' # reserved word; unrelated to $histchars[1] + ) + + local -a match mbegin mend + + # 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. + # + local this_word=':start:' next_word + integer in_redirection + # Processing buffer + local proc_buf="$buf" + for arg in ${interactive_comments-${(z)buf}} \ + ${interactive_comments+${(zZ+c+)buf}}; do + # Initialize $next_word. + if (( in_redirection )); then + (( --in_redirection )) + fi + if (( in_redirection == 0 )); then + # Initialize $next_word to its default value. + next_word=':regular:' + else + # Stall $next_word. + fi + + # Initialize per-"simple command" [zshmisc(1)] variables: + # + # $already_added (see next paragraph) + # $style how to highlight $arg + # $in_array_assignment boolean flag for "between '(' and ')' of array assignment" + # $highlight_glob boolean flag for "'noglob' is in effect" + # + # $already_added is set to 1 to disable adding an entry to region_highlight + # for this iteration. Currently, that is done for "" and $'' strings, + # which add the entry early so escape sequences within the string override + # the string's color. + integer already_added=0 + style=unknown-token + if [[ $this_word == *':start:'* ]]; then + in_array_assignment=false + if [[ $arg == 'noglob' ]]; then + highlight_glob=false + fi + fi + + # Compute the new $start_pos and $end_pos, skipping over whitespace in $buf. + if [[ $arg == ';' ]] ; then + # We're looking for either a semicolon or a newline, whichever comes + # first. Both of these are rendered as a ";" (SEPER) by the ${(z)..} + # flag. + # + # We can't use the (Z+n+) flag because that elides the end-of-command + # token altogether, so 'echo foo\necho bar' (two commands) becomes + # indistinguishable from 'echo foo echo bar' (one command with three + # words for arguments). + local needle=$'[;\n]' + integer offset=$(( ${proc_buf[(i)$needle]} - 1 )) + (( start_pos += offset )) + (( end_pos = start_pos + $#arg )) + else + # The line was: + # + # integer offset=$(((len-start_pos)-${#${proc_buf##([[:space:]]|\\[[:space:]])#}})) + # + # - len-start_pos is length of current proc_buf; basically: initial length minus where + # we are, and proc_buf is chopped to the "where we are" (compare the "previous value + # of start_pos" below, and the len-(start_pos-offset) = len-start_pos+offset) + # - what's after main minus sign is: length of proc_buf without spaces at the beginning + # - so what the line actually did, was computing length of the spaces! + # - this can be done via (#b) flag, like below + if [[ "$proc_buf" = (#b)(#s)(([[:space:]]|\\[[:space:]])##)* ]]; then + # The first, outer parenthesis + integer offset="${#match[1]}" + else + integer offset=0 + fi + ((start_pos+=offset)) + ((end_pos=$start_pos+${#arg})) + fi + + # Compute the new $proc_buf. We advance it + # (chop off characters from the beginning) + # beyond what end_pos points to, by skipping + # as many characters as end_pos was advanced. + # + # end_pos was advanced by $offset (via start_pos) + # and by $#arg. Note the `start_pos=$end_pos` + # below. + # + # As for the [,len]. We could use [,len-start_pos+offset] + # here, but to make it easier on eyes, we use len and + # rely on the fact that Zsh simply handles that. The + # length of proc_buf is len-start_pos+offset because + # we're chopping it to match current start_pos, so its + # length matches the previous value of start_pos. + # + # Why [,-1] is slower than [,length] isn't clear. + proc_buf="${proc_buf[offset + $#arg + 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[1] == $histchars[3] ]]; then + if [[ $this_word == *(':regular:'|':start:')* ]]; then + style=comment + else + style=unknown-token # prematurely terminated + fi + -hsmw-add-highlight $start_pos $end_pos $style + already_added=1 + continue + fi + + # Analyse the current word. + if -hsmw-highlight-is-redirection $arg ; then + # A '<' or '>', possibly followed by a digit + in_redirection=2 + fi + + # Special-case the first word after 'sudo'. + if (( ! in_redirection )); then + if [[ $this_word == *':sudo_opt:'* ]] && [[ $arg != -* ]]; then + this_word=${this_word//:sudo_opt:/} + fi + fi + + # Parse the sudo command line + if (( ! in_redirection )); then + if [[ $this_word == *':sudo_opt:'* ]]; then + case "$arg" in + # Flag that requires an argument + '-'[Cgprtu]) this_word=${this_word//:start:/}; + next_word=':sudo_arg:';; + # This prevents misbehavior with sudo -u -otherargument + '-'*) this_word=${this_word//:start:/}; + next_word+=':start:'; + next_word+=':sudo_opt:';; + *) ;; + esac + elif [[ $this_word == *':sudo_arg:'* ]]; then + next_word+=':sudo_opt:' + next_word+=':start:' + fi + fi + + # The Great Fork: is this a command word? Is this a non-command word? + if [[ $this_word == *':always:'* && $arg == 'always' ]]; then + # try-always construct + style=reserved-word # de facto a reserved word, although not de jure + next_word=':start:' + elif [[ $this_word == *':start:'* ]] && (( in_redirection == 0 )); then # $arg is the command word + if [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} ]]; then + style=precommand + elif [[ "$arg" = "sudo" ]]; then + style=precommand + next_word=${next_word//:regular:/} + next_word+=':sudo_opt:' + next_word+=':start:' + else + -hsmw-highlight-expand-path $arg + local expanded_arg="$REPLY" + -hsmw-highlight-main-type ${expanded_arg} + local res="$REPLY" + () { + # Special-case: command word is '$foo', like that, without braces or anything. + # + # That's not entirely correct --- if the parameter's value happens to be a reserved + # word, the parameter expansion will be highlighted as a reserved word --- but that + # incorrectness is outweighed by the usability improvement of permitting the use of + # parameters that refer to commands, functions, and builtins. + local -a match mbegin mend + local MATCH; integer MBEGIN MEND + if [[ $res == none ]] && (( ${+parameters} )) && + [[ ${arg[1]} == \$ ]] && [[ ${arg:1} = ([[:alpha:]_][[:alnum:]_]#|[[:digit:]]##) ]] && + (( ${+parameters[${MATCH}]} )) + then + -hsmw-highlight-main-type ${(P)MATCH} + res=$REPLY + fi + } + case $res in + reserved) # reserved word + style=reserved-word + if [[ $arg == $'\x7b' ]]; then + braces_stack='Y'"$braces_stack" + elif [[ $arg == $'\x7d' ]]; then + # We're at command word, so no need to check $right_brace_is_recognised_everywhere + -hsmw-highlight-stack-pop 'Y' style=reserved-word + if [[ $style == reserved-word ]]; then + next_word+=':always:' + fi + fi + ;; + 'suffix alias') style=suffix-alias;; + alias) () { + integer insane_alias + case $arg in + # Issue #263: aliases with '=' on their LHS. + # + # There are three cases: + # + # - Unsupported, breaks 'alias -L' output, but invokable: + ('='*) :;; + # - Unsupported, not invokable: + (*'='*) insane_alias=1;; + # - The common case: + (*) :;; + esac + if (( insane_alias )); then + style=unknown-token + else + style=alias + -hsmw-highlight-resolve-alias $arg + local alias_target="$REPLY" + [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$alias_target"} && -z ${(M)__HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} ]] && __HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS+=($arg) + fi + } + ;; + builtin) style=builtin;; + function) style=function;; + command) style=command;; + hashed) style=hashed-command;; + none) if -hsmw-highlight-check-assign; then + style=assign + if [[ $arg[-1] == '(' ]]; then + in_array_assignment=true + else + # assignment to a scalar parameter. + # (For array assignments, the command doesn't start until the ")" token.) + next_word+=':start:' + fi + elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then + style=history-expansion + elif [[ $arg[0,1] == $histchars[2,2] ]]; then + style=history-expansion + elif [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then + if [[ $this_word == *':regular:'* ]]; then + # This highlights empty commands (semicolon follows nothing) as an error. + # Zsh accepts them, though. + style=commandseparator + else + style=unknown-token + fi + elif (( in_redirection == 2 )); then + style=redirection + elif [[ $arg[1,2] == '((' ]]; then + # 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. + style=reserved-word + -hsmw-add-highlight $start_pos $((start_pos + 2)) $style + already_added=1 + if [[ $arg[-2,-1] == '))' ]]; then + -hsmw-add-highlight $((end_pos - 2)) $end_pos $style + already_added=1 + fi + elif [[ $arg == '()' ]]; then + # anonymous function + style=reserved-word + elif [[ $arg == $'\x28' ]]; then + # subshell + style=reserved-word + braces_stack='R'"$braces_stack" + else + if -hsmw-highlight-check-path; then + style=$REPLY + else + style=unknown-token + fi + fi + ;; + *) -hsmw-add-highlight $start_pos $end_pos commandtypefromthefuture-$res + already_added=1 + ;; + esac + fi + fi + if (( ! already_added )) && [[ $style == unknown-token ]] && # not handled by the 'command word' codepath + { (( in_redirection )) || [[ $this_word == *':regular:'* ]] || [[ $this_word == *':sudo_opt:'* ]] || [[ $this_word == *':sudo_arg:'* ]] } + then # $arg is a non-command word + case $arg in + $'\x29') # subshell or end of array assignment + if $in_array_assignment; then + style=assign + in_array_assignment=false + next_word+=':start:' + else + -hsmw-highlight-stack-pop 'R' style=reserved-word + fi;; + $'\x28\x29') # possibly a function definition + if (( multi_func_def )) || false # TODO: or if the previous word was a command word + then + next_word+=':start:' + fi + style=reserved-word + ;; + $'\x7d') # right brace + # + # 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.""" + if $right_brace_is_recognised_everywhere; then + -hsmw-highlight-stack-pop 'Y' style=reserved-word + if [[ $style == reserved-word ]]; then + next_word+=':always:' + fi + else + # Fall through to the catchall case at the end. + fi + ;| + '--'*) style=double-hyphen-option;; + '-'*) style=single-hyphen-option;; + "'"*) style=single-quoted-argument;; + '"'*) style=double-quoted-argument + -hsmw-add-highlight $start_pos $end_pos $style + -hsmw-highlight-string + already_added=1 + ;; + \$\'*) style=dollar-quoted-argument + -hsmw-add-highlight $start_pos $end_pos $style + -hsmw-highlight-dollar-string + already_added=1 + ;; + '`'*) style=back-quoted-argument;; + [*?]*|*[^\\][*?]*) + $highlight_glob && style=globbing || style=default;; + *) if false; then + elif [[ $arg = $'\x7d' ]] && $right_brace_is_recognised_everywhere; then + # was handled by the $'\x7d' case above + elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then + style=history-expansion + elif [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then + if [[ $this_word == *':regular:'* ]]; then + style=commandseparator + else + style=unknown-token + fi + elif (( in_redirection == 2 )); then + style=redirection + else + if -hsmw-highlight-check-path; then + style=$REPLY + else + style=default + fi + fi + ;; + esac + fi + if ! (( already_added )); then + -hsmw-add-highlight $start_pos $end_pos $style + [[ $style == path || $style == path_prefix ]] && -hsmw-highlight-path-separators + fi + if [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then + if [[ $arg == ';' ]] && $in_array_assignment; then + # literal newline inside an array assignment + next_word=':regular:' + else + next_word=':start:' + highlight_glob=true + fi + elif + [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_CONTROL_FLOW:#"$arg"} && $this_word == *':start:'* ]] || + [[ -n ${(M)__HSMW_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} && $this_word == *':start:'* ]]; then + next_word=':start:' + elif [[ $arg == "repeat" && $this_word == *':start:'* ]]; then + # 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=':start::regular:' + fi + start_pos=$end_pos + if (( in_redirection == 0 )); then + # This is the default/common codepath. + this_word=$next_word + else + # Stall $this_word. + fi + done +} + +# Check if $arg is variable assignment +-hsmw-highlight-check-assign() +{ + setopt localoptions extended_glob + [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[*\])(|[+])=* ]] || + [[ $arg == [0-9]##(|[+])=* ]] +} + +-hsmw-highlight-path-separators() +{ + local pos style_pathsep + style_pathsep=${style}_pathseparator + [[ -z "$HSMW_HIGHLIGHT_STYLES[$style_pathsep]" || "$HSMW_HIGHLIGHT_STYLES[$style]" == "$HSMW_HIGHLIGHT_STYLES[$style_pathsep]" ]] && return 0 + for (( pos = start_pos; $pos <= end_pos; pos++ )) ; do + if [[ ${buf[pos]} == "/" ]]; then + -hsmw-add-highlight $((pos - 1)) $pos $style_pathsep + fi + done +} + +# Check if $arg is a path. +# If yes, return 0 and in $REPLY the style to use. +# Else, return non-zero (and the contents of $REPLY is undefined). +-hsmw-highlight-check-path() +{ + -hsmw-highlight-expand-path $arg; + local expanded_path="$REPLY" + + REPLY=path + + [[ -z $expanded_path ]] && return 1 + [[ -L $expanded_path ]] && return 0 + [[ -e $expanded_path ]] && return 0 + + # Search the path in CDPATH + local cdpath_dir + for cdpath_dir in $cdpath ; do + [[ -e "$cdpath_dir/$expanded_path" ]] && return 0 + done + + # If dirname($arg) doesn't exist, neither does $arg. + [[ ! -d ${expanded_path:h} ]] && return 1 + + # If this word ends the buffer, check if it's the prefix of a valid path. + if [[ ${buf[1]} != "-" && $pure_buf_len == $end_pos ]]; then + local -a tmp + tmp=( ${expanded_path}*(N) ) + (( $#tmp > 0 )) && REPLY=path_prefix && return 0 + fi + + # It's not a path. + return 1 +} + +# Highlight special chars inside double-quoted strings +-hsmw-highlight-string() +{ + setopt localoptions noksharrays + local -a match mbegin mend + local MATCH; integer MBEGIN MEND + local i j k style + # Starting quote is at 1, so start parsing at offset 2 in the string. + for (( i = 2 ; i < end_pos - start_pos ; i += 1 )) ; do + (( j = i + start_pos - 1 )) + (( k = j + 1 )) + case "$arg[$i]" in + '$' ) style=dollar-double-quoted-argument + # Look for an alphanumeric parameter name. + if [[ ${arg:$i} = ([[:alpha:]_][[:alnum:]_]#|[[:digit:]]##) ]] ; then + (( k += $#MATCH )) # highlight the parameter name + (( i += $#MATCH )) # skip past it + elif [[ ${arg:$i} = [{]([[:alpha:]_][[:alnum:]_]#|[[:digit:]]##)[}]* ]] ; then + (( k += $#MATCH )) # highlight the parameter name and braces + (( i += $#MATCH )) # skip past it + else + continue + fi + ;; + "\\") style=back-double-quoted-argument + if [[ \\\`\"\$ == *$arg[$i+1]* ]]; then + (( k += 1 )) # Color following char too. + (( i += 1 )) # Skip parsing the escaped char. + else + continue + fi + ;; + *) continue ;; + + esac + -hsmw-add-highlight $j $k $style + done +} + +# Highlight special chars inside dollar-quoted strings +-hsmw-highlight-dollar-string() +{ + setopt localoptions noksharrays + local -a match mbegin mend + local MATCH; integer MBEGIN MEND + 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=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" =~ "^(x|X)[0-9a-fA-F]{1,2}" + || "$AA" =~ "^[0-7]{1,3}" + || "$AA" =~ "^u[0-9a-fA-F]{1,4}" + || "$AA" =~ "^U[0-9a-fA-F]{1,8}" + ]]; then + (( k += $#MATCH )) + (( i += $#MATCH )) + else + if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then + # \x not followed by hex digits is probably an error + style=unknown-token + fi + (( k += 1 )) # Color following char too. + (( i += 1 )) # Skip parsing the escaped char. + fi + ;; + *) continue ;; + + esac + -hsmw-add-highlight $j $k $style + done +} + +# Called with a single positional argument. +# Perform filename expansion (tilde expansion) on the argument and set $REPLY to the expanded value. +# Does not perform filename generation (globbing). +-hsmw-highlight-expand-path() +{ + (( $# == 1 )) || print -r -- >&2 "hsmw-highlight: BUG: -hsmw-highlight-expand-path: called without argument" + + # The $~1 syntax normally performs filename generation, but not when it's on the right-hand side of ${x:=y}. + setopt localoptions nonomatch + unset REPLY + : ${REPLY:=${(Q)~1}} +} + +# ------------------------------------------------------------------------------------------------- +# Main highlighter initialization +# ------------------------------------------------------------------------------------------------- + +-hsmw-highlight-init() { + __hsmw_highlight_main__command_type_cache=() +} + +-hsmw-add-highlight() +{ + local -i start end + local highlight + start=$1 + end=$2 + shift 2 + for highlight; do + if (( $+HSMW_HIGHLIGHT_STYLES[$highlight] )); then + reply+=("$start $end $HSMW_HIGHLIGHT_STYLES[$highlight]") + break + fi + done +} + +__HSMW_MH_SOURCED=1 + +# vim:ft=zsh diff --git a/.config/shell/zsh-fast-syntax-highlighting/tests/_output/.gitkeep b/.config/shell/zsh-fast-syntax-highlighting/tests/_output/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/tests/_output/.gitkeep diff --git a/.config/shell/zsh-fast-syntax-highlighting/tests/_support/.gitkeep b/.config/shell/zsh-fast-syntax-highlighting/tests/_support/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/tests/_support/.gitkeep diff --git a/.config/shell/zsh-fast-syntax-highlighting/tests/_support/bootstrap b/.config/shell/zsh-fast-syntax-highlighting/tests/_support/bootstrap new file mode 100644 index 0000000..0107661 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/tests/_support/bootstrap @@ -0,0 +1,2 @@ +#!/usr/bin/env zsh +# Write your bootstrap code here diff --git a/.config/shell/zsh-fast-syntax-highlighting/tests/example.zunit b/.config/shell/zsh-fast-syntax-highlighting/tests/example.zunit new file mode 100644 index 0000000..910f840 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/tests/example.zunit @@ -0,0 +1,15 @@ +#!/usr/bin/env zunit +@setup { + load "../fast-highlight" +} + +@test 'ls /usr/bin' { + PREBUFFER="" + BUFFER="ls /usr/bin" + run -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 \; print -rl -- \$reply + + assert "$lines[1]" same_as "0 2 fg=green" + assert "$lines[2]" same_as "3 11 fg=magenta,underline" +} + +# vim:ft=zsh:sw=4:sts=4:et diff --git a/.config/shell/zsh-fast-syntax-highlighting/tests/main.zunit b/.config/shell/zsh-fast-syntax-highlighting/tests/main.zunit new file mode 100644 index 0000000..110f34c --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/tests/main.zunit @@ -0,0 +1,124 @@ +#!/usr/bin/env zunit +@setup { + load "../fast-highlight" + setopt interactive_comments + -fast-highlight-fill-option-variables +} + +@test 'ls /usr/bin' { +reply=() + PREBUFFER="" + BUFFER="ls /usr/bin" + evl -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 + + assert "$reply[1]" same_as "0 2 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}command]}" + assert "$reply[2]" same_as "3 11 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path-to-dir]}" + assert "$reply[3]" same_as "" +} + +@test 'ls /bin/df' { + reply=() + PREBUFFER="" + BUFFER="ls /bin/df" + evl -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 + + assert "$reply[1]" same_as "0 2 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}command]}" + assert "$reply[2]" same_as "3 10 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path]}" + assert "$reply[3]" same_as "" +} + + +@test 'ls /bin/ls\\n # a comment\\nls /usr/bin' { + reply=() + PREBUFFER="" + BUFFER=$'ls /bin/df\n # a comment\nls /usr/bin' + evl -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 + + assert "$reply[1]" same_as "0 2 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}command]}" + assert "$reply[2]" same_as "3 10 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path]}" + assert "$reply[3]" same_as "12 23 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}comment]}" + assert "$reply[4]" same_as "24 26 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}command]}" + assert "$reply[5]" same_as "27 35 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}path-to-dir]}" + assert "$reply[6]" same_as "" +} + + +@test 'exec {FD}< <( ls /bin )' { + reply=() + PREBUFFER="" + BUFFER=$'exec {FD}< <( ls /bin )' + evl -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 + + assert "$reply[1]" same_as "0 4 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}precommand]}" + assert "$reply[2]" same_as "5 9 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}exec-descriptor]}" + assert "$reply[3]" same_as "" +} + + +@test 'case x in x) a;; (y) ;; esac' { + reply=() + PREBUFFER="" + BUFFER=$'case x in\nx) a;;\n(y)\n;;\nesac' + evl -fast-highlight-process "$PREBUFFER" "$BUFFER" 0 + + assert "$reply[1]" same_as "0 4 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}reserved-word]}" + assert "$reply[2]" same_as "5 6 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-input]}" + assert "$reply[3]" same_as "7 9 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-parentheses]}" + assert "$reply[4]" same_as "10 11 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-condition]}" + assert "$reply[5]" same_as "11 12 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-parentheses]}" + assert "$reply[6]" same_as "13 14 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}unknown-token]}" + assert "$reply[7]" same_as "17 18 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-parentheses]}" + assert "$reply[8]" same_as "18 19 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-condition]}" + assert "$reply[9]" same_as "19 20 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}case-parentheses]}" + assert "$reply[10]" same_as "24 28 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}reserved-word]}" + assert "$reply[11]" same_as "" +} + +@test '-fast-highlight-process "$PREBUFFER" "$BUFFER" 0' { + reply=() + PREBUFFER="" + BUFFER='-fast-highlight-process "$PREBUFFER" "$BUFFER" 0' + evl -fast-highlight-process "\$PREBUFFER" "\$BUFFER" 0 + + assert "$reply[1]" same_as "0 23 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}function]}" + assert "$reply[2]" same_as "24 36 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}" + assert "$reply[3]" same_as "25 35 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}back-or-dollar-double-quoted-argument]}" + assert "$reply[4]" same_as "37 46 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-quoted-argument]}" + assert "$reply[5]" same_as "38 45 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}back-or-dollar-double-quoted-argument]}" + assert "$reply[6]" same_as "" +} + +@test 'tr : \\\\n <<<$PATH' { + reply=() + PREBUFFER="" + BUFFER='command tr : \\n <<<test$PATH' + evl -fast-highlight-process "\$PREBUFFER" "\$BUFFER" 0 + + assert "$reply[1]" same_as "0 7 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}precommand]}" + assert "$reply[2]" same_as "8 10 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}command]}" + assert "$reply[3]" same_as "16 19 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-tri]}" + # BUG?: the text spans over non-text (i.e. var) part + assert "$reply[4]" same_as "19 28 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-text]}" + assert "$reply[5]" same_as "23 28 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}here-string-var]}" + assert "$reply[6]" same_as "" +} + +@test 'local var1; (( var + var1 + $var + $var1 + 123 ))' { + reply=() + PREBUFFER="" + BUFFER='local var1; (( var + var1 + $var + $var1 + 123 ))' + evl -fast-highlight-process "\$PREBUFFER" "\$BUFFER" 0 + + # Should actually be `reserved-word', but the type -w call returns `builtin'… + assert "$reply[1]" same_as "0 5 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}builtin]}" + assert "$reply[2]" same_as "12 14 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}" + assert "$reply[3]" same_as "15 18 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}matherr]}" + assert "$reply[4]" same_as "21 25 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathvar]}" + assert "$reply[5]" same_as "28 32 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}matherr]}" + assert "$reply[6]" same_as "35 40 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}back-or-dollar-double-quoted-argument]}" + assert "$reply[7]" same_as "43 46 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}mathnum]}" + assert "$reply[8]" same_as "47 49 ${FAST_HIGHLIGHT_STYLES[${FAST_THEME_NAME}double-paren]}" + assert "$reply[9]" same_as "" +} + +# vim:ft=zsh:sw=4:sts=4:et diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/clean.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/clean.ini new file mode 100644 index 0000000..f89b536 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/clean.ini @@ -0,0 +1,81 @@ +[base] +default = none +unknown-token = 124,bold +commandseparator = none +redirection = none +here-string-tri = yellow +here-string-text = bg:19 +here-string-var = 185,bg:19 +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:17 +secondary = zdharma +recursive-base = 183 + +[command-point] +reserved-word = 146 +subcommand = 146 +alias = 109 +suffix-alias = 109 +global-alias = bg:19 +builtin = 109 +function = 109 +command = 109 +precommand = 109 +hashed-command = 109 +single-sq-bracket = 109 +double-sq-bracket = 109 +double-paren = 146 + +[paths] +path = 208 +pathseparator = +path-to-dir = 208,underline +globbing = 220 +globbing-ext = 225 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 115 +bracket-level-2 = 177 +bracket-level-3 = 220 + +[arguments] +single-hyphen-option = 185 +double-hyphen-option = 185 +back-quoted-argument = none +single-quoted-argument = 147 +double-quoted-argument = 147 +dollar-quoted-argument = 147 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 185 +; backslash or $... in "..." (i.e. variable in string) +back-or-dollar-double-quoted-argument = 185 + +[other] +variable = none +assign = none +assign-array-bracket = 109 +history-expansion = blue,bold + +[math] +mathvar = blue,bold +mathnum = 208 +matherr = 124 + +[for-loop] +forvar = none +fornum = 208 +; operator +foroper = 147 +; separator +forsep = 109 + +[case] +case-input = 109 +case-parentheses = 116 +case-condition = bg:19 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/default.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/default.ini new file mode 100644 index 0000000..a5abeab --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/default.ini @@ -0,0 +1,84 @@ +; default theme, also embedded in the source of fast-syntax-highlighting + +[base] +default = none +unknown-token = red,bold +commandseparator = none +redirection = none +here-string-tri = yellow +here-string-text = 18 +here-string-var = cyan,bg:18 +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = 12 +incorrect-subtle = red +subtle-separator = green +subtle-bg = bg:18 +secondary = +; recursive-base = + +[command-point] +reserved-word = yellow +subcommand = yellow +alias = green +suffix-alias = green +global-alias = bg:blue +builtin = green +function = green +command = green +precommand = green +hashed-command = green +single-sq-bracket = green +double-sq-bracket = green +double-paren = yellow + +[paths] +path = magenta +pathseparator = +path-to-dir = magenta,underline +globbing = blue,bold +globbing-ext = 13 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = green,bold +bracket-level-2 = yellow,bold +bracket-level-3 = cyan,bold + +[arguments] +single-hyphen-option = cyan +double-hyphen-option = cyan +back-quoted-argument = none +single-quoted-argument = yellow +double-quoted-argument = yellow +dollar-quoted-argument = yellow + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = cyan +; backslash or $... in "..." +back-or-dollar-double-quoted-argument = cyan + +[other] +variable = 113 +assign = none +assign-array-bracket = green +history-expansion = blue,bold + +[math] +mathvar = blue,bold +mathnum = magenta +matherr = red + +[for-loop] +forvar = none +fornum = magenta +; operator +foroper = yellow +; separator +forsep = yellow,bold + +[case] +case-input = green +case-parentheses = yellow +case-condition = bg:blue diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/forest.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/forest.ini new file mode 100644 index 0000000..d4b145e --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/forest.ini @@ -0,0 +1,81 @@ +[base] +default = none +unknown-token = 124,bold +commandseparator = none +redirection = none +here-string-tri = yellow +here-string-text = underline +here-string-var = 65,underline +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:18 +secondary = zdharma +recursive-base = 183 + +[command-point] +reserved-word = 186 +subcommand = 186 +alias = 101 +suffix-alias = 101 +global-alias = bg:55 +builtin = 101 +function = 101 +command = 101 +precommand = 101 +hashed-command = 101 +single-sq-bracket = 101 +double-sq-bracket = 101 +double-paren = 186 + +[paths] +path = 107 +pathseparator = +path-to-dir = 107,underline +globbing = 114 +globbing-ext = 118 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = green,bold +bracket-level-2 = yellow,bold +bracket-level-3 = cyan,bold + +[arguments] +single-hyphen-option = 65 +double-hyphen-option = 65 +back-quoted-argument = none +single-quoted-argument = 186 +double-quoted-argument = 186 +dollar-quoted-argument = 186 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 65 +; backslash or $... in "..." +back-or-dollar-double-quoted-argument = 65 + +[other] +variable = none +assign = none +assign-array-bracket = 101 +history-expansion = 114 + +[math] +mathvar = 114 +mathnum = 107 +matherr = 124 + +[for-loop] +forvar = none +fornum = 107 +; operator +foroper = 186 +; separator +forsep = 109 + +[case] +case-input = 101 +case-parentheses = 65 +case-condition = underline diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/free.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/free.ini new file mode 100644 index 0000000..108f7da --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/free.ini @@ -0,0 +1,81 @@ +[base] +default = none +unknown-token = red,bold +commandseparator = none +redirection = none +here-string-tri = yellow +here-string-text = bg:19 +here-string-var = 110,bg:19 +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:18 +secondary = zdharma +recursive-base = 183 + +[command-point] +reserved-word = 150 +subcommand = 150 +alias = 180 +suffix-alias = 180 +global-alias = bg:19 +builtin = 180 +function = 180 +command = 180 +precommand = 180 +hashed-command = 180 +single-sq-bracket = 180 +double-sq-bracket = 180 +double-paren = 150 + +[paths] +path = 166 +pathseparator = +path-to-dir = 166,underline +globbing = 112 +globbing-ext = 118 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 130 +bracket-level-2 = 70 +bracket-level-3 = 69 + +[arguments] +single-hyphen-option = 110 +double-hyphen-option = 110 +back-quoted-argument = none +single-quoted-argument = 150 +double-quoted-argument = 150 +dollar-quoted-argument = 150 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 110 +; backslash or $... in "..." (i.e. variable inside a string) +back-or-dollar-double-quoted-argument = 110 + +[other] +variable = none +assign = none +assign-array-bracket = 180 +history-expansion = blue,bold + +[math] +mathvar = blue,bold +mathnum = 166 +matherr = red + +[for-loop] +forvar = none +fornum = 150 +; operator +foroper = 150 +; separator +forsep = 109 + +[case] +case-input = 180 +case-parentheses = 116 +case-condition = bg:19 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/q-jmnemonic.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/q-jmnemonic.ini new file mode 100644 index 0000000..cfefd7a --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/q-jmnemonic.ini @@ -0,0 +1,163 @@ +; X-JMnemonic theme for Fast-Syntax-Highlighting: +; https://github.com/zdharma/fast-syntax-highlighting +; Version: 1.1 +; +; Copyright (c) 2018 Sebastian Gniazdowski +; +; Based on: https://www.syntaxenvy.com/0753499 +; +; When I first saw the above theme upon syntaxenvy.com generated it randomly, +; I've had a quick, bold association with the Johnny Mnemonic movie. I don't +; know why, but I've decided to name the theme like this and who knows, maybe +; someone will decipher the connection one day. The theme looks suprisingly +; well IMO and maybe it's the effect of having this movie property/connection. +; +; This theme is a descent of the 40 work hours (or more) non-public theme X-Paragon, +; which was created to say `thanks' to the patrons at Patreon.com/psprint. It should +; carry the same quality. +; +; The palette - naive and CIE L*a*b conversion: +; +; main: +; #5e6466 -> 59 -> CIELab: 241 +; comment: +; #434749 -> 16 -> CIELab: 238 +; keyword: +; #b77c4b -> 137 -> CIELab: 173 +; number, string: +; #5794a2 -> 67 -> CIELab: 66 +; title, section, name, selector-id: +; #778ce0 -> 104 -> CIELab: 104 +; attribute, variable, type: +; #d55383 -> 168 -> CIELab: 168 +; symbol, link: +; #e66493 -> 168 -> CIELab: 168 +; builtin, deletion: +; #bd5ac0 -> 133 -> CIELab: 170 +; formula-bg: +; #363a3b -> 16 -> CIELab: 237 +; +; Token.Literal: "#dc5be0" -> CIELab: 170 (Orchid; naive: 170) +; Token.Operator: "#677dcf" -> CIELab: 68 (SteelBlue3; naive: 68) +; + +[base] +default = none +unknown-token = 196 +secondary = sv-orple +recursive-base = 183 + +[background] +correct-subtle = bg:18 +incorrect-subtle = bg:238 +subtle-bg = bg:17 +global-alias = bg:20 + +;; +;; COLOR-GROUPS +;; + +[gray] +comment = 243 + + + +[pastel] +here-string-tri = 217 + + + +[no-color] +assign = none +back-quoted-argument = none +redirection = none +variable = none + + + + +[magenta-3] +dollar-quoted-argument = 173 +double-quoted-argument = 173 +history-expansion = 173 +globbing-ext = 173 +precommand = 173 + +[light-salmon-3] +builtin = 137 +subcommand = 137 +single-quoted-argument = 137 + +[steel-blue-3] +command = 68 +double-sq-bracket = 68 +double-paren = 68 +single-sq-bracket = 68 + +[steel-blue] +reserved-word = 67 + + + +[medium-purple] +; backslash in $'...' +back-dollar-quoted-argument = 104 +commandseparator = 104 +single-hyphen-option = 104 + +[dark-khaki] +double-hyphen-option = 143 + + + +[hot-pink-3] +alias = 168 +exec-descriptor = 168 +function = 168 +hashed-command = 168 +here-string-var = 168 +suffix-alias = 168 + +[pale-green-3] +assign-array-bracket = 114 +; variable $... or backslash in "..." (i.e. variable in string) +back-or-dollar-double-quoted-argument = 114 +globbing = 114 +here-string-text = 114 + + + +[orchid] +path = 170 +path-to-dir = 170,underline +pathseparator = + + + +;; +;; FUNCTIONALITY-GROUPS +;; + +[brackets] +paired-bracket = black,bg:216 +bracket-level-1 = 117 +bracket-level-2 = 217 +bracket-level-3 = 220 + +[math] +mathvar = 68 +mathnum = 173 +matherr = 124 + +[for-loop] +forvar = 68 +fornum = 173 +; operator +foroper = 133 +; separator +forsep = 104 + +[case] +case-input = 168 +case-parentheses = 217 +case-condition = bg:25 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/safari.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/safari.ini new file mode 100644 index 0000000..e103c4d --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/safari.ini @@ -0,0 +1,83 @@ +; Light theme with colors of a Sahara oasis + +[base] +default = none +unknown-token = red,bold +commandseparator = none +redirection = none +here-string-tri = yellow +here-string-text = bg:19 +here-string-var = 153,bg:19 +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:18 +secondary = zdharma +recursive-base = 183 + +[command-point] +reserved-word = 150 +subcommand = 150 +alias = 185 +suffix-alias = 185 +global-alias = bg:19 +builtin = 185 +function = 185 +command = 185 +precommand = 185 +hashed-command = 185 +single-sq-bracket = 185 +double-sq-bracket = 185 +double-paren = 150 + +[paths] +path = 187 +pathseparator = +path-to-dir = 187,underline +globbing = 180 +globbing-ext = 184 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 178 +bracket-level-2 = 148 +bracket-level-3 = 141 + +[arguments] +single-hyphen-option = 152 +double-hyphen-option = 152 +back-quoted-argument = none +single-quoted-argument = 151 +double-quoted-argument = 151 +dollar-quoted-argument = 151 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 153 +; backslash or $... in "..." (i.e. variable inside a string) +back-or-dollar-double-quoted-argument = 153 + +[other] +variable = none +assign = none +assign-array-bracket = 185 +history-expansion = blue,bold + +[math] +mathvar = blue,bold +mathnum = 187 +matherr = red + +[for-loop] +forvar = none +fornum = 187 +; operator +foroper = 151 +; separator +forsep = 109 + +[case] +case-input = 185 +case-parentheses = 116 +case-condition = bg:19 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/spa.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/spa.ini new file mode 100644 index 0000000..651acdb --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/spa.ini @@ -0,0 +1,82 @@ +; 144, 187, 110, 203 +[base] +default = none +unknown-token = 196 +commandseparator = 150 +redirection = none +here-string-tri = yellow +here-string-text = bg:19 +here-string-var = 186,bg:19 +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:17 +secondary = zdharma +recursive-base = 183 + +[command-point] +reserved-word = 144 +subcommand = 144 +alias = 187 +suffix-alias = 187 +global-alias = bg:19 +builtin = 150 +function = 187 +command = 187 +precommand = 187 +hashed-command = 187 +single-sq-bracket = 150 +double-sq-bracket = 150 +double-paren = 144 + +[paths] +path = 110 +pathseparator = +path-to-dir = 110,underline +globbing = 220 +globbing-ext = 225 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 115 +bracket-level-2 = 177 +bracket-level-3 = 220 + +[arguments] +single-hyphen-option = 185 +double-hyphen-option = 185 +back-quoted-argument = none +single-quoted-argument = 110 +double-quoted-argument = 110 +dollar-quoted-argument = 110 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 186 +; backslash or $... in "..." (i.e. variable in string) +back-or-dollar-double-quoted-argument = 186 + +[other] +variable = none +assign = none +assign-array-bracket = 187 +history-expansion = blue,bold + +[math] +mathvar = 150 +mathnum = 110 +matherr = 196 + +[for-loop] +forvar = 71 +fornum = 110 +; operator +foroper = 203 +; separator +forsep = 147 + +[case] +case-input = 187 +case-parentheses = 116 +case-condition = bg:19 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/sv-orple.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/sv-orple.ini new file mode 100644 index 0000000..f7e8fc5 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/sv-orple.ini @@ -0,0 +1,100 @@ +; https://www.syntaxenvy.com/0073437 +; +; comment: +; #363355 -> 61 +; keyword: +; #dda69f -> 181 (138) +; number, string: +; #ca887e -> 174 (173) +; title, section, name, selector-id: +; #b3afd9 -> 146 (146) +; attribute, variable, type: +; #be85c0 -> 139 (140) +; symbol, link: +; #d6a2d8 -> 182 (182) +; builtin, deletion: +; #969c77 -> 108 (108) +; formula-bg: +; #211f37 -> 16 (17) + +[base] +default = none +unknown-token = 124 +commandseparator = 146 +redirection = none +here-string-tri = 138 +here-string-text = bg:25 +here-string-var = 140,bg:25 +exec-descriptor = 140 +comment = 61 +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:17 +secondary = clean +recursive-base = 186 + +[command-point] +reserved-word = 138 +subcommand = 182 +alias = 140 +suffix-alias = 140 +global-alias = bg:17 +builtin = 173 +function = 140 +command = 108 +precommand = 138 +hashed-command = 140 +single-sq-bracket = 173 +double-sq-bracket = 173 +double-paren = 138 + +[paths] +path = 182 +pathseparator = +path-to-dir = 182,underline +globbing = 138 +globbing-ext = 141 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 173 +bracket-level-2 = 177 +bracket-level-3 = 220 + +[arguments] +single-hyphen-option = 140 +double-hyphen-option = 140 +back-quoted-argument = none +single-quoted-argument = 173 +double-quoted-argument = 173 +dollar-quoted-argument = 173 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 146 +; backslash or $... in "..." (i.e. variable in string) +back-or-dollar-double-quoted-argument = 140 + +[other] +variable = none +assign = none +assign-array-bracket = 182 +history-expansion = blue,bold + +[math] +mathvar = 140 +mathnum = 173 +matherr = 124 + +[for-loop] +forvar = 140 +fornum = 173 +; operator +foroper = 147 +; separator +forsep = 182 + +[case] +case-input = 140 +case-parentheses = 17 +case-condition = bg:25 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/sv-plant.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/sv-plant.ini new file mode 100644 index 0000000..2191b21 --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/sv-plant.ini @@ -0,0 +1,100 @@ +; https://www.syntaxenvy.com/0854668 +; +; comment: +; #5b4e3f -> 58 +; keyword: +; #a1f2b2 -> 157 +; number, string: +; #91cf9e -> 115 (114) +; title, section, name, selector-id: +; #dadff0 -> 189 +; attribute, variable, type: +; #debb91 -> 180 +; symbol, link: +; #f1dcc6 -> 224 +; builtin, deletion: +; #95cbc1 -> 115 +; formula: +; #3f352a -> 16 + +[base] +default = none +unknown-token = 124 +commandseparator = 189 +redirection = none +here-string-tri = 157 +here-string-text = bg:25 +here-string-var = 180,bg:25 +exec-descriptor = 180 +comment = 58 +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:17 +secondary = zdharma +recursive-base = 183 + +[command-point] +reserved-word = 157 +subcommand = 224 +alias = 180 +suffix-alias = 180 +global-alias = bg:58 +builtin = 115 +function = 180 +command = 180 +precommand = 157 +hashed-command = 180 +single-sq-bracket = 115 +double-sq-bracket = 115 +double-paren = 157 + +[paths] +path = 224 +pathseparator = +path-to-dir = 224,underline +globbing = 157 +globbing-ext = 159 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 115 +bracket-level-2 = 177 +bracket-level-3 = 220 + +[arguments] +single-hyphen-option = 180 +double-hyphen-option = 180 +back-quoted-argument = none +single-quoted-argument = 114 +double-quoted-argument = 114 +dollar-quoted-argument = 114 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 189 +; backslash or $... in "..." (i.e. variable in string) +back-or-dollar-double-quoted-argument = 180 + +[other] +variable = none +assign = none +assign-array-bracket = 224 +history-expansion = blue,bold + +[math] +mathvar = 180 +mathnum = 114 +matherr = 124 + +[for-loop] +forvar = 180 +fornum = 114 +; operator +foroper = 147 +; separator +forsep = 224 + +[case] +case-input = 180 +case-parentheses = 58 +case-condition = bg:25 diff --git a/.config/shell/zsh-fast-syntax-highlighting/themes/zdharma.ini b/.config/shell/zsh-fast-syntax-highlighting/themes/zdharma.ini new file mode 100644 index 0000000..95e3e7e --- /dev/null +++ b/.config/shell/zsh-fast-syntax-highlighting/themes/zdharma.ini @@ -0,0 +1,81 @@ +[base] +default = none +unknown-token = red,bold +commandseparator = none +redirection = none +here-string-tri = 141 +here-string-text = bg:19 +here-string-var = 177,bg:19 +exec-descriptor = yellow,bold +comment = black,bold +correct-subtle = bg:55 +incorrect-subtle = bg:52 +subtle-bg = bg:17 +secondary = safari +recursive-base = 186 + +[command-point] +reserved-word = 146 +reserved-word = 146 +alias = 63 +suffix-alias = 63 +global-alias = bg:19 +builtin = 63 +function = 63 +command = 63 +precommand = 63 +hashed-command = 63 +single-sq-bracket = 63 +double-sq-bracket = 63 +double-paren = 146 + +[paths] +path = 154 +pathseparator = +path-to-dir = 154,underline +globbing = 114 +globbing-ext = 153 + +[brackets] +paired-bracket = bg:blue +bracket-level-1 = 117 +bracket-level-2 = 141 +bracket-level-3 = 90 + +[arguments] +single-hyphen-option = 177 +double-hyphen-option = 177 +back-quoted-argument = none +single-quoted-argument = 146 +double-quoted-argument = 146 +dollar-quoted-argument = 146 + +[in-string] +; backslash in $'...' +back-dollar-quoted-argument = 177 +; backslash or $... in "..." +back-or-dollar-double-quoted-argument = 177 + +[other] +variable = none +assign = none +assign-array-bracket = 63 +history-expansion = blue,bold + +[math] +mathvar = blue,bold +mathnum = 154 +matherr = red + +[for-loop] +forvar = none +fornum = 154 +; operator +foroper = 146 +; separator +forsep = 109 + +[case] +case-input = 63 +case-parentheses = 141 +case-condition = bg:19 |
