From 73636fae13a15402f00fbe25622db1fae505fbcf Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Mon, 3 Feb 2020 16:30:40 -0500
Subject: [PATCH 01/11] 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.
---
 docs/highlighters/files.md               |  49 ++++++
 highlighters/files/files-highlighter.zsh | 192 +++++++++++++++++++++++
 highlighters/files/files.md              |   1 +
 3 files changed, 242 insertions(+)
 create mode 100644 docs/highlighters/files.md
 create mode 100644 highlighters/files/files-highlighter.zsh
 create mode 120000 highlighters/files/files.md

diff --git a/docs/highlighters/files.md b/docs/highlighters/files.md
new file mode 100644
index 000000000..9ca5687bf
--- /dev/null
+++ b/docs/highlighters/files.md
@@ -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.
diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
new file mode 100644
index 000000000..eebcfab1a
--- /dev/null
+++ b/highlighters/files/files-highlighter.zsh
@@ -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
+}
+
diff --git a/highlighters/files/files.md b/highlighters/files/files.md
new file mode 120000
index 000000000..0cd103fc7
--- /dev/null
+++ b/highlighters/files/files.md
@@ -0,0 +1 @@
+../../docs/highlighters/files.md
\ No newline at end of file

From 22362e02f73a40d0ea72fedbdedaf340f28dc026 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Mon, 3 Feb 2020 16:34:09 -0500
Subject: [PATCH 02/11] Renamed files.md to README.md

---
 highlighters/files/{files.md => README.md} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename highlighters/files/{files.md => README.md} (100%)

diff --git a/highlighters/files/files.md b/highlighters/files/README.md
similarity index 100%
rename from highlighters/files/files.md
rename to highlighters/files/README.md

From c432451c20ff7de300eaade49e99927bb59de327 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Tue, 4 Feb 2020 10:25:34 -0500
Subject: [PATCH 03/11] Added copyright boilerplate and fixed indentation

---
 docs/highlighters/files.md               |  28 +-
 highlighters/files/files-highlighter.zsh | 364 +++++++++++++----------
 2 files changed, 220 insertions(+), 172 deletions(-)

diff --git a/docs/highlighters/files.md b/docs/highlighters/files.md
index 9ca5687bf..8cde1250e 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 eebcfab1a..bb2460edb 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
-
-    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:]]##)}
+_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
-
-        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
+        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
+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
-
-    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
+_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
+    # 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
+    # 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
+    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
 }
 

From 3e1413eaf10cf5a39ceb0a8850f099f06d78e78c Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <bobqwatson@gmail.com>
Date: Fri, 14 Feb 2020 07:25:48 -0500
Subject: [PATCH 04/11] Empty matches in _ansi_to_zle()

---
 highlighters/files/files-highlighter.zsh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
index bb2460edb..665c7bb82 100644
--- a/highlighters/files/files-highlighter.zsh
+++ b/highlighters/files/files-highlighter.zsh
@@ -41,6 +41,7 @@ _zsh_highlight_highlighter_files_ansi_to_zle()
     seq=${seq#(#b)(*)=}
     (( $#match )) || continue
     _zsh_highlight_highlighter_files_ansi_to_zle1 $seq $var\[$match[1]\]
+    unset match
   done
 }
 

From e80505a73e45f2aa249fcf031eccc51042260416 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <bobqwatson@gmail.com>
Date: Fri, 14 Feb 2020 07:32:17 -0500
Subject: [PATCH 05/11] Allow for empty patterns

---
 highlighters/files/files-highlighter.zsh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
index 665c7bb82..fd7505880 100644
--- a/highlighters/files/files-highlighter.zsh
+++ b/highlighters/files/files-highlighter.zsh
@@ -108,7 +108,7 @@ 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
+  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 ;;
@@ -202,7 +202,7 @@ _zsh_highlight_highlighter_files_paint()
 
     # Regular file: check file patterns
     if [[ -z "$col" ]]; then
-      for key val in ${(kv)ZSH_HIGHLIGHT_FILE_PATTERNS}; do
+      for key val in "${(@kv)ZSH_HIGHLIGHT_FILE_PATTERNS}"; do
         if [[ $basename = $~key ]]; then
           col=$val
           break

From 174f2047133aef84120ac96fa9d60ea50f210560 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Fri, 14 Feb 2020 09:16:15 -0500
Subject: [PATCH 06/11] Better handling of empty styles

---
 highlighters/files/files-highlighter.zsh | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
index fd7505880..c1ed648a7 100644
--- a/highlighters/files/files-highlighter.zsh
+++ b/highlighters/files/files-highlighter.zsh
@@ -35,6 +35,9 @@ 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()
 {
+  emulate -L zsh
+  setopt local_options extended_glob
+
   local match mbegin mend seq
   local var=$1; shift
   for seq in "${(@s.:.)1}"; do
@@ -106,13 +109,16 @@ _zsh_highlight_highlighter_files_ansi_to_zle1()
 # Extract ZSH_HIGHLIGHT_FILE_TYPES and ZSH_HIGHLIGHT_FILE_PATTERNS from LS_COLORS
 zsh_highlight_files_extract_ls_colors()
 {
+  emulate -L zsh
+  setopt local_options extended_glob
+
   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) ;;
+      *)  ZSH_HIGHLIGHT_FILE_PATTERNS+=("$key" "$val") ;;
     esac
   done
 }
@@ -121,6 +127,9 @@ zsh_highlight_files_extract_ls_colors()
 # errors
 _zsh_highlight_highlighter_files_fn_expand()
 {
+  emulate -L zsh
+  setopt local_options extended_glob
+
   local fn=$1
   local match expandable tail
   local -a mbegin mend
@@ -145,7 +154,7 @@ _zsh_highlight_highlighter_files_predicate()
 _zsh_highlight_highlighter_files_paint()
 {
   emulate -L zsh
-  setopt localoptions extended_glob
+  setopt local_options extended_glob
 
   zmodload -F zsh/stat b:zstat
 
@@ -202,7 +211,7 @@ _zsh_highlight_highlighter_files_paint()
 
     # Regular file: check file patterns
     if [[ -z "$col" ]]; then
-      for key val in "${(@kv)ZSH_HIGHLIGHT_FILE_PATTERNS}"; do
+      for key val in "${(@)ZSH_HIGHLIGHT_FILE_PATTERNS}"; do
         if [[ $basename = $~key ]]; then
           col=$val
           break

From fdd40e902c26593e57269b69c3d9ecd5f71d8d8c Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Fri, 14 Feb 2020 10:06:43 -0500
Subject: [PATCH 07/11] Test cases for files highlighter

---
 highlighters/files/test-data/patterns1.zsh | 43 ++++++++++++++++
 highlighters/files/test-data/patterns2.zsh | 45 ++++++++++++++++
 highlighters/files/test-data/types1.zsh    | 58 +++++++++++++++++++++
 highlighters/files/test-data/types2.zsh    | 60 ++++++++++++++++++++++
 4 files changed, 206 insertions(+)
 create mode 100755 highlighters/files/test-data/patterns1.zsh
 create mode 100755 highlighters/files/test-data/patterns2.zsh
 create mode 100755 highlighters/files/test-data/types1.zsh
 create mode 100755 highlighters/files/test-data/types2.zsh

diff --git a/highlighters/files/test-data/patterns1.zsh b/highlighters/files/test-data/patterns1.zsh
new file mode 100755
index 000000000..5206a8ebb
--- /dev/null
+++ b/highlighters/files/test-data/patterns1.zsh
@@ -0,0 +1,43 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# 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.
+# -------------------------------------------------------------------------------------------------
+# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=zsh sw=2 ts=2 et
+# -------------------------------------------------------------------------------------------------
+
+BUFFER=$': file.tar file.tgz file.webm'
+
+LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
+
+zsh_highlight_files_extract_ls_colors
+
+touch file.tar file.tgz file.webm
+
+expected_region_highlight=(
+    "3 10 bold,fg=1"
+    "12 19 bold,fg=1"
+    '21 29 bold,fg=5'
+)
diff --git a/highlighters/files/test-data/patterns2.zsh b/highlighters/files/test-data/patterns2.zsh
new file mode 100755
index 000000000..822566d31
--- /dev/null
+++ b/highlighters/files/test-data/patterns2.zsh
@@ -0,0 +1,45 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# 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.
+# -------------------------------------------------------------------------------------------------
+# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=zsh sw=2 ts=2 et
+# -------------------------------------------------------------------------------------------------
+
+BUFFER=$': file.tar file.tgz Makefile #file.bak# file.PgP file.flv'
+
+ZSH_HIGHLIGHT_FILE_PATTERNS=('Makefile' 'fg=#F0BE45,bold' 'SConstruct' 'fg=#F0BE45,bold' 'CMakeLists.txt' 'fg=#F0BE45,bold' 'BUILD' 'fg=#F0BE45,bold' 'README*' 'fg=#F0BE45,bold' '(#i)*.png' 'fg=#B50769' '(#i)*.jpeg' 'fg=#B50769' '(#i)*.jpg' 'fg=#B50769' '(#i)*.gif' 'fg=#B50769' '(#i)*.bmp' 'fg=#B50769' '(#i)*.tiff' 'fg=#B50769' '(#i)*.tif' 'fg=#B50769' '(#i)*.ppm' 'fg=#B50769' '(#i)*.pgm' 'fg=#B50769' '(#i)*.pbm' 'fg=#B50769' '(#i)*.pnm' 'fg=#B50769' '(#i)*.webp' 'fg=#B50769' '(#i)*.heic' 'fg=#B50769' '(#i)*.raw' 'fg=#B50769' '(#i)*.arw' 'fg=#B50769' '(#i)*.svg' 'fg=#B50769' '(#i)*.stl' 'fg=#B50769' '(#i)*.eps' 'fg=#B50769' '(#i)*.dvi' 'fg=#B50769' '(#i)*.ps' 'fg=#B50769' '(#i)*.cbr' 'fg=#B50769' '(#i)*.jpf' 'fg=#B50769' '(#i)*.cbz' 'fg=#B50769' '(#i)*.xpm' 'fg=#B50769' '(#i)*.ico' 'fg=#B50769' '(#i)*.cr2' 'fg=#B50769' '(#i)*.orf' 'fg=#B50769' '(#i)*.nef' 'fg=#B50769' '(#i)*.avi' 'fg=#D33682' '(#i)*.flv' 'fg=#D33682' '(#i)*.m2v' 'fg=#D33682' '(#i)*.m4v' 'fg=#D33682' '(#i)*.mkv' 'fg=#D33682' '(#i)*.mov' 'fg=#D33682' '(#i)*.mp4' 'fg=#D33682' '(#i)*.mpeg' 'fg=#D33682' '(#i)*.mpg' 'fg=#D33682' '(#i)*.ogm' 'fg=#D33682' '(#i)*.ogv' 'fg=#D33682' '(#i)*.vob' 'fg=#D33682' '(#i)*.wmv' 'fg=#D33682' '(#i)*.webm' 'fg=#D33682' '(#i)*.m2ts' 'fg=#D33682' '(#i)*.aac' 'fg=#F1559C' '(#i)*.m4a' 'fg=#F1559C' '(#i)*.mp3' 'fg=#F1559C' '(#i)*.ogg' 'fg=#F1559C' '(#i)*.wma' 'fg=#F1559C' '(#i)*.mka' 'fg=#F1559C' '(#i)*.opus' 'fg=#F1559C' '(#i)*.alac' 'fg=#F1559C' '(#i)*.ape' 'fg=#F1559C' '(#i)*.flac' 'fg=#F1559C' '(#i)*.wav' 'fg=#F1559C' '(#i)*.asc' 'fg=#6A7F00' '(#i)*.enc' 'fg=#6A7F00' '(#i)*.gpg' 'fg=#6A7F00' '(#i)*.pgp' 'fg=#6A7F00' '(#i)*.sig' 'fg=#6A7F00' '(#i)*.signature' 'fg=#6A7F00' '(#i)*.pfx' 'fg=#6A7F00' '(#i)*.p12' 'fg=#6A7F00' '(#i)*.djvu' 'fg=#878AE0' '(#i)*.doc' 'fg=#878AE0' '(#i)*.docx' 'fg=#878AE0' '(#i)*.dvi' 'fg=#878AE0' '(#i)*.eml' 'fg=#878AE0' '(#i)*.eps' 'fg=#878AE0' '(#i)*.fotd' 'fg=#878AE0' '(#i)*.odp' 'fg=#878AE0' '(#i)*.odt' 'fg=#878AE0' '(#i)*.pdf' 'fg=#878AE0' '(#i)*.ppt' 'fg=#878AE0' '(#i)*.pptx' 'fg=#878AE0' '(#i)*.rtf' 'fg=#878AE0' '(#i)*.xls' 'fg=#878AE0' '(#i)*.xlsx' 'fg=#878AE0' '(#i)*.zip' 'fg=#657B83,bold' '(#i)*.tar' 'fg=#657B83,bold' '(#i)*.Z' 'fg=#657B83,bold' '(#i)*.z' 'fg=#657B83,bold' '(#i)*.gz' 'fg=#657B83,bold' '(#i)*.bz2' 'fg=#657B83,bold' '(#i)*.a' 'fg=#657B83,bold' '(#i)*.ar' 'fg=#657B83,bold' '(#i)*.7z' 'fg=#657B83,bold' '(#i)*.iso' 'fg=#657B83,bold' '(#i)*.dmg' 'fg=#657B83,bold' '(#i)*.tc' 'fg=#657B83,bold' '(#i)*.rar' 'fg=#657B83,bold' '(#i)*.par' 'fg=#657B83,bold' '(#i)*.tgz' 'fg=#657B83,bold' '(#i)*.xz' 'fg=#657B83,bold' '(#i)*.txz' 'fg=#657B83,bold' '(#i)*.lzma' 'fg=#657B83,bold' '(#i)*.deb' 'fg=#657B83,bold' '(#i)*.rpm' 'fg=#657B83,bold' '(#i)*.zst' 'fg=#657B83,bold' '*~' 'fg=#586E75' '\#*\#' 'fg=#586E75' '(#i)*.tmp' 'fg=#586E75' '(#i)*.swp' 'fg=#586E75' '(#i)*.swo' 'fg=#586E75' '(#i)*.swn' 'fg=#586E75' '(#i)*.bak' 'fg=#586E75' '(#i)*.bk' 'fg=#586E75' '(#i)*.class' 'fg=#5158A9' '(#i)*.elc' 'fg=#5158A9' '(#i)*.o' 'fg=#5158A9' '(#i)*.pyc' 'fg=#5158A9')
+
+
+touch file.tar file.tgz Makefile '#file.bak#' file.PgP file.flv
+
+expected_region_highlight=(
+    '3 10 fg=#657B83,bold'
+    '12 19 fg=#657B83,bold'
+    '21 28 fg=#F0BE45,bold'
+    '30 39 fg=#586E75'
+    '41 48 fg=#6A7F00'
+    '50 57 fg=#D33682'
+)
diff --git a/highlighters/files/test-data/types1.zsh b/highlighters/files/test-data/types1.zsh
new file mode 100755
index 000000000..878e0639d
--- /dev/null
+++ b/highlighters/files/test-data/types1.zsh
@@ -0,0 +1,58 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# 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.
+# -------------------------------------------------------------------------------------------------
+# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=zsh sw=2 ts=2 et
+# -------------------------------------------------------------------------------------------------
+
+BUFFER=$': file.fi file.di file.ln file.pi file.or file.ex file.su file.sg file.ow file.tw'
+
+LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
+
+zsh_highlight_files_extract_ls_colors
+
+touch file.fi
+mkdir file.di
+ln -s file.fi file.ln
+mkfifo file.pi
+ln -s bad file.or
+touch file.ex; chmod 755 file.ex
+touch file.su; chmod u+s file.su
+touch file.sg; chmod g+s file.sg
+touch file.ow; chmod o+w file.ow
+touch file.tw; chmod o+wt file.tw
+
+expected_region_highlight=(
+    '11 17 bold,fg=4'
+    '19 25 bold,fg=6'
+    '27 33 bg=0,fg=3'
+    '35 41 bg=0,fg=1,bold'
+    '43 49 bold,fg=2'
+    '51 57 fg=7,bg=1'
+    '59 65 fg=0,bg=3'
+    '67 73 fg=4,bg=2'
+    '75 81 fg=4,bg=2'
+)
diff --git a/highlighters/files/test-data/types2.zsh b/highlighters/files/test-data/types2.zsh
new file mode 100755
index 000000000..c8ab8818c
--- /dev/null
+++ b/highlighters/files/test-data/types2.zsh
@@ -0,0 +1,60 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# 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.
+# -------------------------------------------------------------------------------------------------
+# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
+# vim: ft=zsh sw=2 ts=2 et
+# -------------------------------------------------------------------------------------------------
+
+BUFFER=$': file.fi file.di file.ln file.pi file.or file.ex file.su file.sg file.ow file.tw file.di/file.fi'
+
+ZSH_HIGHLIGHT_FILE_TYPES=('cd' 'fg=#EA6630' 'su' 'fg=#878AE0,bold' 'ex' 'fg=#BDD040' 'bd' 'fg=#AC3000' 'ln' 'fg=#B58900' 'tw' 'fg=#268BD2,bold,underline' 'or' 'fg=#FC5246,bold' 'fi' 'fg=#93A1A1' 'lp' 'fg=#657B83' 'sg' 'fg=#878AE0' 'di' 'fg=#268BD2,bold' 'ow' 'fg=#DC322F,underline' 'pi' 'fg=#D33682' 'so' 'fg=#D33682,bold')
+
+touch file.fi
+mkdir file.di
+ln -s file.fi file.ln
+mkfifo file.pi
+ln -s bad file.or
+touch file.ex; chmod 755 file.ex
+touch file.su; chmod u+s file.su
+touch file.sg; chmod g+s file.sg
+touch file.ow; chmod o+w file.ow
+mkdir file.tw; chmod o+wt file.tw
+touch file.di/file.fi
+
+expected_region_highlight=(
+    '3 9 fg=#93A1A1'
+    '11 17 fg=#268BD2,bold'
+    '19 25 fg=#B58900'
+    '27 33 fg=#D33682'
+    '35 41 fg=#FC5246,bold'
+    '43 49 fg=#BDD040'
+    '51 57 fg=#878AE0,bold'
+    '59 65 fg=#878AE0'
+    '67 73 fg=#DC322F,underline'
+    '75 81 fg=#268BD2,bold,underline'
+    '83 90 fg=#657B83'
+    '91 97 fg=#93A1A1'
+)

From e151a8ee26da19d93b6f2328766410a3b9247876 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Fri, 14 Feb 2020 10:07:30 -0500
Subject: [PATCH 08/11] Fixed su/sg/ow detection

---
 highlighters/files/files-highlighter.zsh | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
index c1ed648a7..b624fc495 100644
--- a/highlighters/files/files-highlighter.zsh
+++ b/highlighters/files/files-highlighter.zsh
@@ -35,9 +35,6 @@ 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()
 {
-  emulate -L zsh
-  setopt local_options extended_glob
-
   local match mbegin mend seq
   local var=$1; shift
   for seq in "${(@s.:.)1}"; do
@@ -50,9 +47,6 @@ _zsh_highlight_highlighter_files_ansi_to_zle()
 
 _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
@@ -127,9 +121,6 @@ zsh_highlight_files_extract_ls_colors()
 # errors
 _zsh_highlight_highlighter_files_fn_expand()
 {
-  emulate -L zsh
-  setopt local_options extended_glob
-
   local fn=$1
   local match expandable tail
   local -a mbegin mend
@@ -200,10 +191,12 @@ _zsh_highlight_highlighter_files_paint()
 
     # Regular file: more special cases
     if [[ -z "$col" ]]; then
-      if [[ $mode[4] = s ]]; then
+      if [[ $mode[4] = S ]]; then
         col=$ZSH_HIGHLIGHT_FILE_TYPES[su]  # setuid root
-      elif [[ $mode[7] = s ]]; then
+      elif [[ $mode[7] = S ]]; then
         col=$ZSH_HIGHLIGHT_FILE_TYPES[sg]  # setgid root
+      elif [[ $mode[9] = w ]]; then
+        col=$ZSH_HIGHLIGHT_FILE_TYPES[ow]  # other-writable
       elif [[ $mode[4] = x ]]; then
         col=$ZSH_HIGHLIGHT_FILE_TYPES[ex]  # Executable
       fi

From 9ffd67d21b7e4af93ca1e308e5560bace480d452 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Fri, 14 Feb 2020 10:24:06 -0500
Subject: [PATCH 09/11] Declared LS_COLORS local in tests

---
 highlighters/files/test-data/patterns1.zsh | 2 +-
 highlighters/files/test-data/types1.zsh    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/highlighters/files/test-data/patterns1.zsh b/highlighters/files/test-data/patterns1.zsh
index 5206a8ebb..abbba8ae1 100755
--- a/highlighters/files/test-data/patterns1.zsh
+++ b/highlighters/files/test-data/patterns1.zsh
@@ -30,7 +30,7 @@
 
 BUFFER=$': file.tar file.tgz file.webm'
 
-LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
+local LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
 
 zsh_highlight_files_extract_ls_colors
 
diff --git a/highlighters/files/test-data/types1.zsh b/highlighters/files/test-data/types1.zsh
index 878e0639d..a4442cc33 100755
--- a/highlighters/files/test-data/types1.zsh
+++ b/highlighters/files/test-data/types1.zsh
@@ -30,7 +30,7 @@
 
 BUFFER=$': file.fi file.di file.ln file.pi file.or file.ex file.su file.sg file.ow file.tw'
 
-LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
+local LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
 
 zsh_highlight_files_extract_ls_colors
 

From d511fa39fac9427b7b9bf266f51fa63a5ce25c6d Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Mon, 17 Feb 2020 16:38:58 -0500
Subject: [PATCH 10/11] Suppress unrecognized keys from LS_COLORS

---
 highlighters/files/files-highlighter.zsh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
index b624fc495..11f997feb 100644
--- a/highlighters/files/files-highlighter.zsh
+++ b/highlighters/files/files-highlighter.zsh
@@ -112,6 +112,7 @@ zsh_highlight_files_extract_ls_colors()
     case $key in
       di|fi|ln|pi|so|bd|cd|or|ex|su|sg|ow|tw)
         ZSH_HIGHLIGHT_FILE_TYPES[$key]=$val ;;
+      lc|rc|ec|rs|no|mi|do|st|ca|mh|cl) ;; # Recognized by LS_COLORS but not by us
       *)  ZSH_HIGHLIGHT_FILE_PATTERNS+=("$key" "$val") ;;
     esac
   done

From b127a06e6f3c76df11ac674187429275a7d13ed2 Mon Sep 17 00:00:00 2001
From: Joe Rabinoff <jrabinoff6@math.gatech.edu>
Date: Mon, 17 Feb 2020 17:05:15 -0500
Subject: [PATCH 11/11] More options to highlight path component

---
 docs/highlighters/files.md               |  2 +-
 highlighters/files/files-highlighter.zsh | 15 ++++++++++++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/docs/highlighters/files.md b/docs/highlighters/files.md
index 8cde1250e..86bc3e66b 100644
--- a/docs/highlighters/files.md
+++ b/docs/highlighters/files.md
@@ -36,7 +36,7 @@ according to that style (following `LS_COLORS`):
 * `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
+* `lp` - if set, the path component of a filename is highlighted using this style, unless it is set to `same`, in which case the path component is highlighted the same as the file
 
 If a file would be highlighted `fi`, then it can be highlighted according to the
 filename using `ZSH_HIGHLIGHT_FILE_PATTERNS` instead.  This array has the form
diff --git a/highlighters/files/files-highlighter.zsh b/highlighters/files/files-highlighter.zsh
index 11f997feb..4dcf30034 100644
--- a/highlighters/files/files-highlighter.zsh
+++ b/highlighters/files/files-highlighter.zsh
@@ -219,10 +219,19 @@ _zsh_highlight_highlighter_files_paint()
     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]")
+      if (( end > start + $#basename )); then
+        # There is a path component
+        if [[ $ZSH_HIGHLIGHT_FILE_TYPES[lp] = "same" ]]; then
+          region_highlight+=("$start $end $col")
+        else
+          if (( ${+ZSH_HIGHLIGHT_FILE_TYPES[lp]} )); then
+            region_highlight+=("$start $(( end - $#basename )) $ZSH_HIGHLIGHT_FILE_TYPES[lp]")
+          fi
+          region_highlight+=("$(( end - $#basename )) $end $col")
+        fi
+      else
+        region_highlight+=("$start $end $col")
       fi
-      region_highlight+=("$(( end - $#basename )) $end $col")
     fi
 
     start=$end