From c432451c20ff7de300eaade49e99927bb59de327 Mon Sep 17 00:00:00 2001 From: Joe Rabinoff Date: Tue, 4 Feb 2020 10:25:34 -0500 Subject: [PATCH] Added copyright boilerplate and fixed indentation --- docs/highlighters/files.md | 28 +- highlighters/files/files-highlighter.zsh | 348 +++++++++++++---------- 2 files changed, 212 insertions(+), 164 deletions(-) diff --git a/docs/highlighters/files.md b/docs/highlighters/files.md index 9ca5687..8cde125 100644 --- a/docs/highlighters/files.md +++ b/docs/highlighters/files.md @@ -17,10 +17,11 @@ zsh_highlight_files_extract_ls_colors ### Configuration -Files are colored according to the associative arrays `ZSH_HIGHLIGHT_FILE_TYPES` -and `ZSH_HIGHLIGHT_FILE_PATTERNS`. The values of `ZSH_HIGHLIGHT_FILE_TYPES` are -color specifications as in `ZSH_HIGHLIGHT_STYLES`, and the keys define which -file types are highlighted according to that style (following `LS_COLORS`): +Files are colored according to the associative array `ZSH_HIGHLIGHT_FILE_TYPES` +and the array `ZSH_HIGHLIGHT_FILE_PATTERNS`. The values of +`ZSH_HIGHLIGHT_FILE_TYPES` are color specifications as in +`ZSH_HIGHLIGHT_STYLES`, and the keys define which file types are highlighted +according to that style (following `LS_COLORS`): * `fi` - ordinary files * `di` - directories @@ -38,12 +39,23 @@ file types are highlighted according to that style (following `LS_COLORS`): * `lp` - if set, the path-component of a filename is highlighted using this style If a file would be highlighted `fi`, then it can be highlighted according to the -filename using `ZSH_HIGHLIGHT_FILE_PATTERNS` instead. The keys of this -associative array are arbitrary glob patterns; the values are color -specifications. For instance, if have `setopt extended_glob` and you write +filename using `ZSH_HIGHLIGHT_FILE_PATTERNS` instead. This array has the form +`(glob1 style1 glob2 style2 glob3 style3 ...)`, where the globs are arbitrary +glob patterns, and the styles are color specifications. For instance, if have +`setopt extended_glob` and you write ```zsh -ZSH_HIGHLIGHT_FILE_PATTERNS[(#i)*.jpe#g]=red,bold +ZSH_HIGHLIGHT_FILE_PATTERNS+=('(#i)*.jpe#g' red,bold) ``` then the files `foo.jpg` and `bar.jPeG` will be colored red and bold. + + +### Limitations + +This highlighter makes no attempt to determine if a word is in command position. +Hence if you run the command `cat foo` and you happen to have a directory named +`cat` in the current directory, then the highlighter will highlight `cat` +according to `ZSH_HIGHLIGHT_FILE_TYPES[di]` and not +`ZSH_HIGHLIGHT_STYLES[command]` (assuming you load the `files` highlighter after +the `main` one). Likewise with aliases, reserved words, etc. diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh index eebcfab..bb2460e 100644 --- a/highlighters/files/files-highlighter.zsh +++ b/highlighters/files/files-highlighter.zsh @@ -1,192 +1,228 @@ +# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2020 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. +# ------------------------------------------------------------------------------------------------- +# vim: ft=zsh sw=2 ts=2 et +# ------------------------------------------------------------------------------------------------- + # Highlighter for zsh-syntax-highlighting that highlights filenames -typeset -gA ZSH_HIGHLIGHT_FILE_TYPES ZSH_HIGHLIGHT_FILE_PATTERNS +typeset -gA ZSH_HIGHLIGHT_FILE_TYPES +typeset -ga ZSH_HIGHLIGHT_FILE_PATTERNS # Convert an ANSI escape sequence color into zle_highlight format (man 1 zshzle) -_zsh_highlight_highlighter_files_ansi_to_zle() { - local match mbegin mend seq - local var=$1; shift - for seq in "${(@s.:.)1}"; do - seq=${seq#(#b)(*)=} - (( $#match )) || continue - _zsh_highlight_highlighter_files_ansi_to_zle1 $seq $var\[$match[1]\] - done +_zsh_highlight_highlighter_files_ansi_to_zle() +{ + local match mbegin mend seq + local var=$1; shift + for seq in "${(@s.:.)1}"; do + seq=${seq#(#b)(*)=} + (( $#match )) || continue + _zsh_highlight_highlighter_files_ansi_to_zle1 $seq $var\[$match[1]\] + done } -_zsh_highlight_highlighter_files_ansi_to_zle1() { - emulate -L zsh - setopt local_options extended_glob +_zsh_highlight_highlighter_files_ansi_to_zle1() +{ + emulate -L zsh + setopt local_options extended_glob - local -a sgrs match - local back mbegin mend fgbg hex - integer sgr arg arg2 col r g b - local str=$1 + local -a sgrs match + local back mbegin mend fgbg hex + integer sgr arg arg2 col r g b + local str=$1 - while [ -n "$str" ]; do - back=${str##(#b)([[:digit:]]##)} + while [ -n "$str" ]; do + back=${str##(#b)([[:digit:]]##)} + back=${back#;} + (( $#match )) || return 1 + + sgr=$match; unset match + case $sgr in + 0) ;; + 1) sgrs+=(bold) ;; + 4) sgrs+=(underline) ;; + 7) sgrs+=(standout) ;; + <30-37>) sgrs+=(fg=$(( $sgr - 30 ))) ;; + <40-47>) sgrs+=(bg=$(( $sgr - 40 ))) ;; + 38|48) + (( sgr == 38 )) && fgbg=fg || fgbg=bg + # 38;5;n means paletted color + # 38;2;r;g;b means truecolor + back=${back##(#b)([[:digit:]]##)} back=${back#;} (( $#match )) || return 1 + arg=$match; unset match + case $arg in + 5) back=${back##(#b)([[:digit:]]##)} + back=${back#;} + (( $#match )) || return 1 + arg2=$match; unset match + sgrs+=($fgbg=$arg2) ;; + 2) back=${back##(#b)([[:digit:]]##);([[:digit:]]##);([[:digit:]]##)} + back=${back#;} + (( $#match == 3 )) || return 1 + printf -v hex \#%02X%02X%02X $match + unset match + sgrs+=($fgbg=$hex) ;; + *) return 1 ;; + esac ;; + *) return 1 ;; + esac - sgr=$match; unset match - case $sgr in - 0) ;; - 1) sgrs+=(bold) ;; - 4) sgrs+=(underline) ;; - 7) sgrs+=(standout) ;; - <30-37>) sgrs+=(fg=$(( $sgr - 30 ))) ;; - <40-47>) sgrs+=(bg=$(( $sgr - 40 ))) ;; - 38|48) - (( sgr == 38 )) && fgbg=fg || fgbg=bg - # 38;5;n means paletted color - # 38;2;r;g;b means truecolor - back=${back##(#b)([[:digit:]]##)} - back=${back#;} - (( $#match )) || return 1 - arg=$match; unset match - case $arg in - 5) back=${back##(#b)([[:digit:]]##)} - back=${back#;} - (( $#match )) || return 1 - arg2=$match; unset match - sgrs+=($fgbg=$arg2) ;; - 2) back=${back##(#b)([[:digit:]]##);([[:digit:]]##);([[:digit:]]##)} - back=${back#;} - (( $#match == 3 )) || return 1 - printf -v hex \#%02X%02X%02X $match - unset match - sgrs+=($fgbg=$hex) ;; - *) return 1 ;; - esac ;; - *) return 1 ;; - esac + str=$back + done - str=$back - done - - if [[ -n "$2" ]]; then - eval $2='${(j.,.)sgrs}' - else - print -- ${(j.,.)sgrs} - fi + if [[ -n "$2" ]]; then + eval $2='${(j.,.)sgrs}' + else + print -- ${(j.,.)sgrs} + fi } # Extract ZSH_HIGHLIGHT_FILE_TYPES and ZSH_HIGHLIGHT_FILE_PATTERNS from LS_COLORS -zsh_highlight_files_extract_ls_colors() { - local -A ls_colors - _zsh_highlight_highlighter_files_ansi_to_zle ls_colors $LS_COLORS - for key val in ${(kv)ls_colors}; do - case $key in - di|fi|ln|pi|so|bd|cd|or|ex|su|sg|ow|tw) - ZSH_HIGHLIGHT_FILE_TYPES[$key]=$val ;; - *) ZSH_HIGHLIGHT_FILE_PATTERNS[$key]=$val ;; - esac - done +zsh_highlight_files_extract_ls_colors() +{ + local -A ls_colors + _zsh_highlight_highlighter_files_ansi_to_zle ls_colors $LS_COLORS + for key val in ${(kv)ls_colors}; do + case $key in + di|fi|ln|pi|so|bd|cd|or|ex|su|sg|ow|tw) + ZSH_HIGHLIGHT_FILE_TYPES[$key]=$val ;; + *) ZSH_HIGHLIGHT_FILE_PATTERNS+=($key $val) ;; + esac + done } # Perform simple filename expansion without globbing and without generating # errors -_zsh_highlight_highlighter_files_fn_expand() { - local fn=$1 - local match expandable tail - local -a mbegin mend - if [[ $fn = (#b)(\~[^/]#)(*) ]]; then - expandable=$match[1] - tail=$match[2] - # Try expanding expandable - (: $~expandable) >&/dev/null && expandable=$~expandable - print -- $expandable$tail - else - print -- $fn - fi +_zsh_highlight_highlighter_files_fn_expand() +{ + local fn=$1 + local match expandable tail + local -a mbegin mend + if [[ $fn = (#b)(\~[^/]#)(*) ]]; then + expandable=$match[1] + tail=$match[2] + # Try expanding expandable + (: $~expandable) >&/dev/null && expandable=$~expandable + print -- $expandable$tail + else + print -- $fn + fi } # Whether the highlighter should be called or not. -_zsh_highlight_highlighter_files_predicate() { - _zsh_highlight_buffer_modified +_zsh_highlight_highlighter_files_predicate() +{ + _zsh_highlight_buffer_modified } # Syntax highlighting function. -_zsh_highlight_highlighter_files_paint() { - emulate -L zsh - setopt localoptions extended_glob +_zsh_highlight_highlighter_files_paint() +{ + emulate -L zsh + setopt localoptions extended_glob - zmodload -F zsh/stat b:zstat + zmodload -F zsh/stat b:zstat - local buf=$BUFFER word basename word_subst col type mode - local -a words=(${(z)buf}) - local -A statdata - integer start=0 curword=0 numwords=$#words len end + local buf=$BUFFER word basename word_subst col type mode + local -a words=(${(z)buf}) + local -A statdata + integer start=0 curword=0 numwords=$#words len end - while (( curword++ < numwords )); do - col="" - word=$words[1] - words=("${(@)words:1}") - len=$#buf - buf="${buf/#[^$word[1]]#}" # strip whitespace - start+=$(( len - $#buf )) - end=$(( start + $#word )) + while (( curword++ < numwords )); do + col="" + word=$words[1] + words=("${(@)words:1}") + len=$#buf + buf="${buf/#[^$word[1]]#}" # strip whitespace + start+=$(( len - $#buf )) + end=$(( start + $#word )) - word_subst=$(_zsh_highlight_highlighter_files_fn_expand $word) + word_subst=$(_zsh_highlight_highlighter_files_fn_expand $word) - if ! zstat -H statdata -Ls -- "$word_subst" 2>/dev/null; then - start=$end - buf=${buf[$#word+1,-1]} - continue + if ! zstat -H statdata -Ls -- "$word_subst" 2>/dev/null; then + start=$end + buf=${buf[$#word+1,-1]} + continue + fi + mode=$statdata[mode] + type=$mode[1] + basename=$word:t + [[ $word[-1] = '/' ]] && basename=$basename/ + + # Color by file type + case $type in + d) [[ ${mode[9,10]} = wt ]] \ + && col=$ZSH_HIGHLIGHT_FILE_TYPES[tw] \ + || col=$ZSH_HIGHLIGHT_FILE_TYPES[di];; + l) [[ -e "$word_subst" ]] \ + && col=$ZSH_HIGHLIGHT_FILE_TYPES[ln] \ + || col=$ZSH_HIGHLIGHT_FILE_TYPES[or];; + p) col=$ZSH_HIGHLIGHT_FILE_TYPES[pi];; + b) col=$ZSH_HIGHLIGHT_FILE_TYPES[bd];; + c) col=$ZSH_HIGHLIGHT_FILE_TYPES[cd];; + s) col=$ZSH_HIGHLIGHT_FILE_TYPES[so];; + esac + + # Regular file: more special cases + if [[ -z "$col" ]]; then + if [[ $mode[4] = s ]]; then + col=$ZSH_HIGHLIGHT_FILE_TYPES[su] # setuid root + elif [[ $mode[7] = s ]]; then + col=$ZSH_HIGHLIGHT_FILE_TYPES[sg] # setgid root + elif [[ $mode[4] = x ]]; then + col=$ZSH_HIGHLIGHT_FILE_TYPES[ex] # Executable + fi + fi + + # Regular file: check file patterns + if [[ -z "$col" ]]; then + for key val in ${(kv)ZSH_HIGHLIGHT_FILE_PATTERNS}; do + if [[ $basename = $~key ]]; then + col=$val + break fi - mode=$statdata[mode] - type=$mode[1] - basename=$word:t - [[ $word[-1] = '/' ]] && basename=$basename/ + done + fi - # Color by file type - case $type in - d) [[ ${mode[9,10]} = wt ]] \ - && col=$ZSH_HIGHLIGHT_FILE_TYPES[tw] \ - || col=$ZSH_HIGHLIGHT_FILE_TYPES[di];; - l) [[ -e "$word_subst" ]] \ - && col=$ZSH_HIGHLIGHT_FILE_TYPES[ln] \ - || col=$ZSH_HIGHLIGHT_FILE_TYPES[or];; - p) col=$ZSH_HIGHLIGHT_FILE_TYPES[pi];; - b) col=$ZSH_HIGHLIGHT_FILE_TYPES[bd];; - c) col=$ZSH_HIGHLIGHT_FILE_TYPES[cd];; - s) col=$ZSH_HIGHLIGHT_FILE_TYPES[so];; - esac + # Just a regular file + if [[ -z "$col" ]]; then + col=$ZSH_HIGHLIGHT_FILE_TYPES[fi] + fi - # Regular file: more special cases - if [[ -z "$col" ]]; then - if [[ $mode[4] = s ]]; then - col=$ZSH_HIGHLIGHT_FILE_TYPES[su] # setuid root - elif [[ $mode[7] = s ]]; then - col=$ZSH_HIGHLIGHT_FILE_TYPES[sg] # setgid root - elif [[ $mode[4] = x ]]; then - col=$ZSH_HIGHLIGHT_FILE_TYPES[ex] # Executable - fi - fi + if [[ -n "$col" ]]; then + if (( end > start + $#basename && ${+ZSH_HIGHLIGHT_FILE_TYPES[lp]} )); then + region_highlight+=("$start $(( end - $#basename )) $ZSH_HIGHLIGHT_FILE_TYPES[lp]") + fi + region_highlight+=("$(( end - $#basename )) $end $col") + fi - # Regular file: check file patterns - if [[ -z "$col" ]]; then - for key val in ${(kv)ZSH_HIGHLIGHT_FILE_PATTERNS}; do - if [[ $basename = $~key ]]; then - col=$val - break - fi - done - fi - - # Just a regular file - if [[ -z "$col" ]]; then - col=$ZSH_HIGHLIGHT_FILE_TYPES[fi] - fi - - if [[ -n "$col" ]]; then - if (( end > start + $#basename && ${+ZSH_HIGHLIGHT_FILE_TYPES[lp]} )); then - region_highlight+=("$start $(( end - $#basename )) $ZSH_HIGHLIGHT_FILE_TYPES[lp]") - fi - region_highlight+=("$(( end - $#basename )) $end $col") - fi - - start=$end - buf=${buf[$#word+1,-1]} - done + start=$end + buf=${buf[$#word+1,-1]} + done }