mirror of
https://github.com/zsh-users/zsh-syntax-highlighting.git
synced 2025-04-17 11:35:32 +08:00
Add 'files' highlighter
This new highlighter highlights names of existing files on the command line, in the style of LS_COLORS. It can pull its configuration directly from LS_COLORS, or can be configured separately.
This commit is contained in:
parent
dde84e1b25
commit
73636fae13
49
docs/highlighters/files.md
Normal file
49
docs/highlighters/files.md
Normal file
@ -0,0 +1,49 @@
|
||||
zsh-syntax-highlighting / highlighters / files
|
||||
----------------------------------------------
|
||||
|
||||
This is the `files` highlighter, that highlights existing files appearing on the
|
||||
command line.
|
||||
|
||||
|
||||
### Quickstart
|
||||
|
||||
If you are happy with your `LS_COLORS`, simply add the following line to your
|
||||
`.zshrc` after sourcing `zsh-syntax-highlighting.zsh`:
|
||||
|
||||
```zsh
|
||||
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`):
|
||||
|
||||
* `fi` - ordinary files
|
||||
* `di` - directories
|
||||
* `ln` - symbolic links
|
||||
* `pi` - pipes
|
||||
* `so` - sockets
|
||||
* `bd` - block devices
|
||||
* `cd` - character devices
|
||||
* `or` - broken symlinks
|
||||
* `ex` - executable files
|
||||
* `su` - files that have the suid bit set
|
||||
* `sg` - files that have the sgid bit set
|
||||
* `ow` - files that are world-writable
|
||||
* `tw` - files that are world-writable and sticky
|
||||
* `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
|
||||
|
||||
```zsh
|
||||
ZSH_HIGHLIGHT_FILE_PATTERNS[(#i)*.jpe#g]=red,bold
|
||||
```
|
||||
|
||||
then the files `foo.jpg` and `bar.jPeG` will be colored red and bold.
|
192
highlighters/files/files-highlighter.zsh
Normal file
192
highlighters/files/files-highlighter.zsh
Normal file
@ -0,0 +1,192 @@
|
||||
# Highlighter for zsh-syntax-highlighting that highlights filenames
|
||||
|
||||
typeset -gA ZSH_HIGHLIGHT_FILE_TYPES 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_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
|
||||
|
||||
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
|
||||
|
||||
str=$back
|
||||
done
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
# Whether the highlighter should be called or not.
|
||||
_zsh_highlight_highlighter_files_predicate() {
|
||||
_zsh_highlight_buffer_modified
|
||||
}
|
||||
|
||||
# Syntax highlighting function.
|
||||
_zsh_highlight_highlighter_files_paint() {
|
||||
emulate -L zsh
|
||||
setopt localoptions extended_glob
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
1
highlighters/files/files.md
Symbolic link
1
highlighters/files/files.md
Symbolic link
@ -0,0 +1 @@
|
||||
../../docs/highlighters/files.md
|
Loading…
Reference in New Issue
Block a user