Big refactoring.
* Don't override user defined styles * Better modularisation of highlighters * Allow to define which highlighters are activated * Allow to define the order in which they are defined * Minor performance optimizations * Fixed some variables leak * Improve documentation * Brackets highlighter: use ZSH_HIGHLIGHT_STYLES instead of a specific array
This commit is contained in:
		
							parent
							
								
									19f16752bb
								
							
						
					
					
						commit
						0772ddd346
					
				
							
								
								
									
										58
									
								
								README.md
								
								
								
								
							
							
						
						
									
										58
									
								
								README.md
								
								
								
								
							|  | @ -1,73 +1,47 @@ | |||
| zsh-syntax-highlighting  | ||||
| ========================================================================================================== | ||||
| zsh-syntax-highlighting | ||||
| ======================= | ||||
| 
 | ||||
| **[Fish shell](http://www.fishshell.com) like syntax highlighting for [Zsh](http://www.zsh.org).** | ||||
| 
 | ||||
| *Requirements: zsh 4.3.9 or superior.* | ||||
| *Requirements: zsh 4.3.9+.* | ||||
| 
 | ||||
| 
 | ||||
| ## Try it | ||||
| 
 | ||||
| Here is a one-liner to try it without installing or modifying anything: | ||||
| 
 | ||||
|     wget --no-check-certificate --output-document=/tmp/zsh-syntax-highlighting.zsh https://github.com/nicoulaj/zsh-syntax-highlighting/raw/master/zsh-syntax-highlighting.zsh && . /tmp/zsh-syntax-highlighting.zsh | ||||
| 
 | ||||
| 
 | ||||
| ## Install it | ||||
| 
 | ||||
| How to install | ||||
| -------------- | ||||
| 
 | ||||
| ### In your ~/.zshrc | ||||
| 
 | ||||
| * Download the script or clone this repository: | ||||
| 
 | ||||
|       git clone git://github.com/nicoulaj/zsh-syntax-highlighting.git | ||||
|         git clone git://github.com/nicoulaj/zsh-syntax-highlighting.git | ||||
| 
 | ||||
| * Source the script **at the end** of `~/.zshrc`: | ||||
| 
 | ||||
|       source /path/to/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh | ||||
|         source /path/to/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh | ||||
| 
 | ||||
| * Source `~/.zshrc`  to take changes into account: | ||||
| 
 | ||||
|       source ~/.zshrc | ||||
|         source ~/.zshrc | ||||
| 
 | ||||
| 
 | ||||
| ### With oh-my-zsh | ||||
| 
 | ||||
| * Download the script or clone this repository in [oh-my-zsh](http://github.com/robbyrussell/oh-my-zsh) plugins directory: | ||||
| 
 | ||||
|       cd ~/.oh-my-zsh/plugins/ | ||||
|       git clone git://github.com/nicoulaj/zsh-syntax-highlighting.git | ||||
|         cd ~/.oh-my-zsh/plugins/ | ||||
|         git clone git://github.com/nicoulaj/zsh-syntax-highlighting.git | ||||
| 
 | ||||
| * Activate the plugin in `~/.zshrc` (in **last** position): | ||||
| 
 | ||||
|       plugins=( [plugins...] zsh-syntax-highlighting) | ||||
|         plugins=( [plugins...] zsh-syntax-highlighting) | ||||
| 
 | ||||
| * Source `~/.zshrc`  to take changes into account: | ||||
|      | ||||
|       source ~/.zshrc | ||||
|         source ~/.zshrc | ||||
| 
 | ||||
| 
 | ||||
| ## Tweak it | ||||
| How to tweak | ||||
| ------------ | ||||
| 
 | ||||
| Optionally, you can override the default styles used for highlighting. The styles are declared in the `ZSH_HIGHLIGHT_STYLES` array. You can override styles this way: | ||||
| 
 | ||||
|     # To differentiate aliases from other command types | ||||
|     ZSH_HIGHLIGHT_STYLES[alias]='fg=magenta,bold' | ||||
|      | ||||
|     # To have paths colored instead of underlined | ||||
|     ZSH_HIGHLIGHT_STYLES[path]='fg=cyan' | ||||
|      | ||||
|     # To disable highlighting of globbing expressions | ||||
|     ZSH_HIGHLIGHT_STYLES[globbing]='none' | ||||
| 
 | ||||
| You can tweak the styles used to colorize matching brackets by overriding the `ZSH_HIGHLIGHT_MATCHING_BRACKETS_STYLES`. | ||||
| 
 | ||||
|     ZSH_HIGHLIGHT_MATCHING_BRACKETS_STYLES=( | ||||
|       'fg=blue,bold'    # Style for first level of imbrication | ||||
|       'fg=green,bold'   # Style for second level of imbrication | ||||
|       'fg=magenta,bold' # etc... Put as many styles as you wish, or leave | ||||
|       'fg=yellow,bold'  # empty to disable brackets matching. | ||||
|       'fg=cyan,bold' | ||||
|     ) | ||||
| 
 | ||||
| This must be done **after** the script is sourced, otherwise your styles will be overwritten. The syntax for declaring styles is [documented here](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC135). | ||||
| Syntax highlighting is done by pluggable highlighter scripts, see the [highlighters directory](highlighters) | ||||
| for documentation and configuration settings. | ||||
|  |  | |||
|  | @ -0,0 +1,47 @@ | |||
| zsh-syntax-highlighting / highlighters | ||||
| ====================================== | ||||
| 
 | ||||
| Syntax highlighting is done by pluggable highlighters: | ||||
| 
 | ||||
| * [***main***](main) - the base highlighter, and the only one active by default. | ||||
| * [***brackets***](brackets) - matches brackets and parenthesis. | ||||
| * [***pattern***](pattern) - matches user-defined patterns. | ||||
| 
 | ||||
| 
 | ||||
| How to activate highlighters | ||||
| ---------------------------- | ||||
| 
 | ||||
| To activate an highlighter, add it to the `ZSH_HIGHLIGHT_HIGHLIGHTERS` array in `~/.zshrc`, for example: | ||||
| 
 | ||||
|     ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern) | ||||
| 
 | ||||
| 
 | ||||
| How to tweak highlighters | ||||
| ------------------------- | ||||
| 
 | ||||
| Highlighters look up styles from the `ZSH_HIGHLIGHT_STYLES` array. Navigate into each highlighter directory to see what styles it defines and how to configure it. | ||||
| 
 | ||||
| 
 | ||||
| How to implement a new highlighter | ||||
| ---------------------------------- | ||||
| 
 | ||||
| To create your own ***myhighlighter*** highlighter: | ||||
|   | ||||
| * Create your script at **highlighters/*myhighlighter*/*myhighlighter*-highlighter.zsh**. | ||||
| * Implement the `_zsh_highlight_myhighlighter_highlighter_predicate` function. This function must return 0 when the highlighter needs to be called, for example: | ||||
| 
 | ||||
|         _zsh_highlight_myhighlighter_highlighter_predicate() { | ||||
|           # Call this highlighter in SVN repositories | ||||
|           [[ -d .svn ]] | ||||
|         } | ||||
| 
 | ||||
| * Implement the `_zsh_highlight_myhighlighter_highlighter` function. This function does the actual syntax highlighting, by modifying `region_highlight`, for example: | ||||
| 
 | ||||
|         _zsh_highlight_myhighlighter_highlighter() { | ||||
|           # Colorize the whole buffer with blue background | ||||
|           region_highlight+=(0 $#BUFFER bg=blue) | ||||
|         } | ||||
| 
 | ||||
| * Activate your highlighter in `~/.zshrc`: | ||||
| 
 | ||||
|         ZSH_HIGHLIGHT_HIGHLIGHTERS+=(myhighlighter) | ||||
|  | @ -0,0 +1,28 @@ | |||
| zsh-syntax-highlighting / highlighters / brackets | ||||
| ================================================= | ||||
| 
 | ||||
| This is the ***brackets*** highlighter, that highlights brackets, parenthesis and matches them. | ||||
| 
 | ||||
| 
 | ||||
| How to activate it | ||||
| ------------------ | ||||
| To activate it, add it to `ZSH_HIGHLIGHT_HIGHLIGHTERS`: | ||||
| 
 | ||||
|     ZSH_HIGHLIGHT_HIGHLIGHTERS=( [...] brackets) | ||||
| 
 | ||||
| 
 | ||||
| How to tweak it | ||||
| --------------- | ||||
| This highlighter defines the following styles: | ||||
| * `bracket-error` - unmatched brackets | ||||
| * `bracket-level-N` - brackets with nest level N | ||||
| 
 | ||||
| To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`, for example in `~/.zshrc`: | ||||
| 
 | ||||
|     # To define styles for nested brackets up to level 4 | ||||
|     ZSH_HIGHLIGHT_STYLES[bracket-level-1]='fg=blue,bold' | ||||
|     ZSH_HIGHLIGHT_STYLES[bracket-level-2]='fg=red,bold' | ||||
|     ZSH_HIGHLIGHT_STYLES[bracket-level-3]='fg=yellow,bold' | ||||
|     ZSH_HIGHLIGHT_STYLES[bracket-level-4]='fg=magenta,bold' | ||||
| 
 | ||||
| The syntax for declaring styles is [documented here](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC135). | ||||
|  | @ -29,29 +29,24 @@ | |||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| 
 | ||||
| ZSH_HIGHLIGHT_STYLES+=( | ||||
|   bracket-error                 'fg=red,bold' | ||||
| ) | ||||
| # Define default styles. | ||||
| : ${ZSH_HIGHLIGHT_STYLES[bracket-error]:=fg=red,bold} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[bracket-level-1]:=fg=blue,bold} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[bracket-level-2]:=fg=green,bold} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[bracket-level-3]:=fg=magenta,bold} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[bracket-level-4]:=fg=yellow,bold} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[bracket-level-5]:=fg=cyan,bold} | ||||
| 
 | ||||
| # Colors for bracket levels. | ||||
| # Put as many color as you wish. | ||||
| # Leave it as an empty array to disable. | ||||
| ZSH_HIGHLIGHT_MATCHING_BRACKETS_STYLES=( | ||||
|   'fg=blue,bold' | ||||
|   'fg=green,bold' | ||||
|   'fg=magenta,bold' | ||||
|   'fg=yellow,bold' | ||||
|   'fg=cyan,bold' | ||||
| ) | ||||
| 
 | ||||
| # Whether the bracket match highlighting shound be called or not. | ||||
| _zsh_highlight_bracket-match-p() { | ||||
|   _zsh_highlight_cursor-moved-p || _zsh_highlight_buffer-modified-p | ||||
| # Whether the brackets highlighter should be called or not. | ||||
| _zsh_highlight_brackets_highlighter_predicate() | ||||
| { | ||||
|   _zsh_highlight_cursor_moved || _zsh_highlight_buffer_modified | ||||
| } | ||||
| 
 | ||||
| # Bracket match highlighting. | ||||
| _zsh_highlight_bracket-match() { | ||||
|   bracket_color_size=${#ZSH_HIGHLIGHT_MATCHING_BRACKETS_STYLES} | ||||
| # Brackets highlighting function. | ||||
| _zsh_highlight_brackets_highlighter() | ||||
| { | ||||
|   bracket_color_size=${#ZSH_HIGHLIGHT_STYLES[(I)bracket-level-*]} | ||||
|   if ((bracket_color_size > 0)); then | ||||
|     typeset -A levelpos lastoflevel matching revmatching | ||||
|     ((level = 0)) | ||||
|  | @ -73,7 +68,7 @@ _zsh_highlight_bracket-match() { | |||
|       if ((level < 1)); then | ||||
|         region_highlight+=("$((pos - 1)) $pos "$ZSH_HIGHLIGHT_STYLES[bracket-error]) | ||||
|       else | ||||
|         region_highlight+=("$((pos - 1)) $pos "$ZSH_HIGHLIGHT_MATCHING_BRACKETS_STYLES[(( (level - 1) % bracket_color_size + 1 ))]) | ||||
|         region_highlight+=("$((pos - 1)) $pos "$ZSH_HIGHLIGHT_STYLES[bracket-level-$(( (level - 1) % bracket_color_size + 1 ))]) | ||||
|       fi | ||||
|     done | ||||
|     ((c = CURSOR + 1)) | ||||
|  | @ -85,5 +80,3 @@ _zsh_highlight_bracket-match() { | |||
|     fi | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| _zsh_highlight_add-highlighter _zsh_highlight_bracket-match | ||||
|  | @ -0,0 +1,55 @@ | |||
| zsh-syntax-highlighting / highlighters / main | ||||
| ============================================= | ||||
| 
 | ||||
| This is the ***main*** highlighter, that highlights: | ||||
| 
 | ||||
| * Commands | ||||
| * Options | ||||
| * Arguments | ||||
| * Paths | ||||
| * Strings | ||||
| 
 | ||||
| How to activate it | ||||
| ------------------ | ||||
| To activate it, add it to `ZSH_HIGHLIGHT_HIGHLIGHTERS`: | ||||
| 
 | ||||
|     ZSH_HIGHLIGHT_HIGHLIGHTERS=( [...] main) | ||||
| 
 | ||||
| This highlighter is active by default. | ||||
| 
 | ||||
| 
 | ||||
| How to tweak it | ||||
| --------------- | ||||
| This highlighter defines the following styles: | ||||
| * `unknown-token` - unknown tokens / errors | ||||
| * `reserved-word` - shell reserved words | ||||
| * `alias` - aliases | ||||
| * `builtin` - shell builtin commands | ||||
| * `function` - functions | ||||
| * `command` - commands | ||||
| * `hashed-command` - hashed commands | ||||
| * `path` - paths | ||||
| * `globbing` - globbing expressions | ||||
| * `history-expansion` - history expansion expressions | ||||
| * `single-hyphen-option` - single hyphen options | ||||
| * `double-hyphen-option` - double hyphen options | ||||
| * `back-quoted-argument` - backquoted expressions | ||||
| * `single-quoted-argument` - single quoted arguments | ||||
| * `double-quoted-argument` - double quoted arguments | ||||
| * `dollar-double-quoted-argument` -  dollar double quoted arguments | ||||
| * `back-double-quoted-argument` -  back double quoted arguments | ||||
| * `assign` - variable assignments | ||||
| * `default` - parts of the buffer that do not match anything | ||||
| 
 | ||||
| To override one of those styles, change its entry in `ZSH_HIGHLIGHT_STYLES`, for example in `~/.zshrc`: | ||||
| 
 | ||||
|     # To differentiate aliases from other command types | ||||
|     ZSH_HIGHLIGHT_STYLES[alias]='fg=magenta,bold' | ||||
|      | ||||
|     # To have paths colored instead of underlined | ||||
|     ZSH_HIGHLIGHT_STYLES[path]='fg=cyan' | ||||
|      | ||||
|     # To disable highlighting of globbing expressions | ||||
|     ZSH_HIGHLIGHT_STYLES[globbing]='none' | ||||
| 
 | ||||
| The syntax for declaring styles is [documented here](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC135). | ||||
|  | @ -0,0 +1,164 @@ | |||
| #!/usr/bin/env zsh | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| # Copyright (c) 2010-2011 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 | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| 
 | ||||
| # Define default styles. | ||||
| : ${ZSH_HIGHLIGHT_STYLES[default]:=none} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[unknown-token]:=fg=red,bold} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[reserved-word]:=fg=yellow} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[alias]:=fg=green} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[builtin]:=fg=green} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[function]:=fg=green} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[command]:=fg=green} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[hashed-command]:=fg=green} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[path]:=underline} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[globbing]:=fg=blue} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[history-expansion]:=fg=blue} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[single-hyphen-option]:=none} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[double-hyphen-option]:=none} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[back-quoted-argument]:=none} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[single-quoted-argument]:=fg=yellow} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[double-quoted-argument]:=fg=yellow} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]:=fg=cyan} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]:=fg=cyan} | ||||
| : ${ZSH_HIGHLIGHT_STYLES[assign]:=none} | ||||
| 
 | ||||
| # Tokens that are always immediately followed by a command. | ||||
| ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS=( | ||||
|   '|' '||' ';' '&' '&&' 'noglob' 'nocorrect' 'builtin' | ||||
| ) | ||||
| 
 | ||||
| # Whether the highlighter should be called or not. | ||||
| _zsh_highlight_main_highlighter_predicate() | ||||
| { | ||||
|   _zsh_highlight_buffer_modified | ||||
| } | ||||
| 
 | ||||
| # Main syntax highlighting function. | ||||
| _zsh_highlight_main_highlighter() | ||||
| { | ||||
|   setopt localoptions extendedglob bareglobqual | ||||
|   local start_pos=0 end_pos highlight_glob=true new_expression=true arg style | ||||
|   region_highlight=() | ||||
|   for arg in ${(z)BUFFER}; do | ||||
|     local substr_color=0 | ||||
|     [[ $start_pos -eq 0 && $arg = 'noglob' ]] && highlight_glob=false | ||||
|     ((start_pos+=${#BUFFER[$start_pos+1,-1]}-${#${BUFFER[$start_pos+1,-1]##[[:space:]]#}})) | ||||
|     ((end_pos=$start_pos+${#arg})) | ||||
|     if $new_expression; then | ||||
|       new_expression=false | ||||
|       res=$(LC_ALL=C builtin type -w $arg 2>/dev/null) | ||||
|       case $res in | ||||
|         *': reserved')  style=$ZSH_HIGHLIGHT_STYLES[reserved-word];; | ||||
|         *': alias')     style=$ZSH_HIGHLIGHT_STYLES[alias] | ||||
|                         local aliased_command="${"$(alias $arg)"#*=}" | ||||
|                         [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS:#"$aliased_command"} && -z ${(M)ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS:#"$arg"} ]] && ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS+=($arg) | ||||
|                         ;; | ||||
|         *': builtin')   style=$ZSH_HIGHLIGHT_STYLES[builtin];; | ||||
|         *': function')  style=$ZSH_HIGHLIGHT_STYLES[function];; | ||||
|         *': command')   style=$ZSH_HIGHLIGHT_STYLES[command];; | ||||
|         *': hashed')    style=$ZSH_HIGHLIGHT_STYLES[hashed-command];; | ||||
|         *)              if _zsh_highlight_main_highlighter_check_assign; then | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[assign] | ||||
|                           new_expression=true | ||||
|                         elif _zsh_highlight_main_highlighter_check_path; then | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[path] | ||||
|                         elif [[ $arg[0,1] = $histchars[0,1] ]]; then | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[history-expansion] | ||||
|                         else | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[unknown-token] | ||||
|                         fi | ||||
|                         ;; | ||||
|       esac | ||||
|     else | ||||
|       case $arg in | ||||
|         '--'*)   style=$ZSH_HIGHLIGHT_STYLES[double-hyphen-option];; | ||||
|         '-'*)    style=$ZSH_HIGHLIGHT_STYLES[single-hyphen-option];; | ||||
|         "'"*"'") style=$ZSH_HIGHLIGHT_STYLES[single-quoted-argument];; | ||||
|         '"'*'"') style=$ZSH_HIGHLIGHT_STYLES[double-quoted-argument] | ||||
|                  region_highlight+=("$start_pos $end_pos $style") | ||||
|                  _zsh_highlight_main_highlighter_highlight_string | ||||
|                  substr_color=1 | ||||
|                  ;; | ||||
|         '`'*'`') style=$ZSH_HIGHLIGHT_STYLES[back-quoted-argument];; | ||||
|         *"*"*)   $highlight_glob && style=$ZSH_HIGHLIGHT_STYLES[globbing] || style=$ZSH_HIGHLIGHT_STYLES[default];; | ||||
|         *)       if _zsh_highlight_main_highlighter_check_path; then | ||||
|                    style=$ZSH_HIGHLIGHT_STYLES[path] | ||||
|                  elif [[ $arg[0,1] = $histchars[0,1] ]]; then | ||||
|                    style=$ZSH_HIGHLIGHT_STYLES[history-expansion] | ||||
|                  else | ||||
|                    style=$ZSH_HIGHLIGHT_STYLES[default] | ||||
|                  fi | ||||
|                  ;; | ||||
|       esac | ||||
|     fi | ||||
|     [[ $substr_color = 0 ]] && region_highlight+=("$start_pos $end_pos $style") | ||||
|     [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS:#"$arg"} ]] && new_expression=true | ||||
|     start_pos=$end_pos | ||||
|   done | ||||
| } | ||||
| 
 | ||||
| # Check if the argument is variable assignment | ||||
| _zsh_highlight_main_highlighter_check_assign() | ||||
| { | ||||
|     setopt localoptions extended_glob | ||||
|     [[ ${(Q)arg} == [[:alpha:]_]([[:alnum:]_])#=* ]] | ||||
| } | ||||
| 
 | ||||
| # Check if the argument is a path. | ||||
| _zsh_highlight_main_highlighter_check_path() | ||||
| { | ||||
|   [[ -z ${(Q)arg} ]] && return 1 | ||||
|   [[ -e ${(Q)arg} ]] && return 0 | ||||
|   [[ ! -e ${(Q)arg:h} ]] && return 1 | ||||
|   [[ ${#BUFFER} == $end_pos && -n $(print ${(Q)arg}*(N)) ]] && return 0 | ||||
|   return 1 | ||||
| } | ||||
| 
 | ||||
| # Highlight special chars inside double-quoted strings | ||||
| _zsh_highlight_main_highlighter_highlight_string() | ||||
| { | ||||
|   setopt localoptions noksharrays | ||||
|   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=$ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument];; | ||||
|       "\\") style=$ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument] | ||||
|             (( k += 1 )) # Color following char too. | ||||
|             (( i += 1 )) # Skip parsing the escaped char. | ||||
|             ;; | ||||
|       *)    continue;; | ||||
|     esac | ||||
|     region_highlight+=("$j $k $style") | ||||
|   done | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| zsh-syntax-highlighting / highlighters / pattern | ||||
| ================================================ | ||||
| 
 | ||||
| This is the ***pattern*** highlighter, that highlights user defined patterns. | ||||
| 
 | ||||
| 
 | ||||
| How to activate it | ||||
| ------------------ | ||||
| To activate it, add it to `ZSH_HIGHLIGHT_HIGHLIGHTERS`: | ||||
| 
 | ||||
|     ZSH_HIGHLIGHT_HIGHLIGHTERS=( [...] pattern) | ||||
| 
 | ||||
| 
 | ||||
| How to tweak it | ||||
| --------------- | ||||
| To use this highlighter, associate patterns with styles in the `ZSH_HIGHLIGHT_PATTERNS` array, for example in `~/.zshrc`: | ||||
| 
 | ||||
|     # To have commands starting with `rm -rf` in red: | ||||
|     ZSH_HIGHLIGHT_PATTERNS+=('rm -rf *' 'fg=white,bold,bg=red') | ||||
| 
 | ||||
| The syntax for declaring styles is [documented here](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC135). | ||||
|  | @ -29,35 +29,31 @@ | |||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| 
 | ||||
| # A simple keyword highlighting extension for zsh-syntax-highlighting. | ||||
| 
 | ||||
| # To use this, please do the following steps. | ||||
| # 1) Source this file after zsh-syntax-highlighting.zsh | ||||
| # % source zsh-syntax-highlighting.zsh | ||||
| # % source contrib/keyword.zsh | ||||
| # 2) Add keyword and color pairs to `ZSH_HIGHLIGHT_KEYWORD_KEYWORDS`. | ||||
| # % ZSH_HIGHLIGHT_KEYWORD_KEYWORDS+=('rm -rf *' 'fg=white,bold,bg=red') | ||||
| # 3) Please see the effect. | ||||
| # % ;# rm -rf /tmp/doesnotexist | ||||
| 
 | ||||
| # List of keyword and color pairs. | ||||
| typeset -gA ZSH_HIGHLIGHT_KEYWORD_KEYWORDS | ||||
| typeset -gA ZSH_HIGHLIGHT_PATTERNS | ||||
| 
 | ||||
| _zsh_highlight-keyword() { | ||||
| # Whether the pattern highlighter should be called or not. | ||||
| _zsh_highlight_pattern_highlighter_predicate() | ||||
| { | ||||
|   _zsh_highlight_buffer_modified | ||||
| } | ||||
| 
 | ||||
| # Pattern syntax highlighting function. | ||||
| _zsh_highlight_pattern_highlighter() | ||||
| { | ||||
|   setopt localoptions extendedglob | ||||
|   for pattern in ${(k)ZSH_HIGHLIGHT_KEYWORD_KEYWORDS}; do | ||||
|     _zsh_highlight-keyword-loop "$BUFFER" "$pattern" | ||||
|   for pattern in ${(k)ZSH_HIGHLIGHT_PATTERNS}; do | ||||
|     _zsh_highlight_pattern_highlighter_loop "$BUFFER" "$pattern" | ||||
|   done | ||||
| } | ||||
| 
 | ||||
| _zsh_highlight-keyword-loop() { | ||||
| _zsh_highlight_pattern_highlighter_loop() | ||||
| { | ||||
|   # This does *not* do its job syntactically, sorry. | ||||
|   local buf="$1" pat="$2" | ||||
|   local -a match mbegin mend | ||||
|   if [[ "$buf" == (#b)(*)(${~pat})* ]]; then | ||||
|     region_highlight+=("$((mbegin[2] - 1)) $mend[2] $ZSH_HIGHLIGHT_KEYWORD_KEYWORDS[$pat]") | ||||
|     region_highlight+=("$((mbegin[2] - 1)) $mend[2] $ZSH_HIGHLIGHT_PATTERNS[$pat]") | ||||
|     "$0" "$match[1]" "$pat"; return $? | ||||
|   fi | ||||
| } | ||||
| 
 | ||||
| _zsh_highlight_add-highlighter _zsh_highlight-keyword _zsh_highlight_buffer-modified-p | ||||
|  | @ -0,0 +1,20 @@ | |||
| zsh-syntax-highlighting / tests | ||||
| =============================== | ||||
| 
 | ||||
| Utility scripts for testing zsh-syntax-highlighting highlighters. | ||||
| 
 | ||||
| The tests expect the highlighter directory to contain a `test-data` directory with test data files. See the [main highlighter](../highlighters/main/test-data) for examples. | ||||
| 
 | ||||
| 
 | ||||
| highlighting test | ||||
| ----------------- | ||||
| [`test-highlighting.zsh`](test-highlighting.zsh) tests the correctness of the highlighting. Usage: | ||||
| 
 | ||||
|     zsh test-highlighting.zsh <HIGHLIGHTER NAME> | ||||
| 
 | ||||
| 
 | ||||
| performance test | ||||
| ---------------- | ||||
| [`test-perfs.zsh`](test-highlighting.zsh) measures the time spent doing the highlighting. Usage: | ||||
| 
 | ||||
|     zsh test-perfs.zsh <HIGHLIGHTER NAME> | ||||
|  | @ -29,14 +29,35 @@ | |||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| 
 | ||||
| # Check an highlighter was given as argument. | ||||
| [[ -n "$1" ]] || { | ||||
|   echo "You must provide the name of a valid highlighter as argument." >&2 | ||||
|   exit 1 | ||||
| } | ||||
| 
 | ||||
| # Check the highlighter is valid. | ||||
| [[ -f ${0:h:h}/highlighters/$1/$1-highlighter.zsh ]] || { | ||||
|   echo "Could not find highlighter '$1'." >&2 | ||||
|   exit 1 | ||||
| } | ||||
| 
 | ||||
| # Check the highlighter has test data. | ||||
| [[ -d ${0:h:h}/highlighters/$1/test-data ]] || { | ||||
|   echo "Highlighter '$1' has no test data." >&2 | ||||
|   exit 1 | ||||
| } | ||||
| 
 | ||||
| local -a errors highlight_zone | ||||
| local -A observed_result | ||||
| 
 | ||||
| # Load the main script. | ||||
| . $(dirname $0)/../zsh-syntax-highlighting.zsh | ||||
| . ${0:h:h}/zsh-syntax-highlighting.zsh | ||||
| 
 | ||||
| # Process each test data file in data/. | ||||
| for data_file in $(dirname $0)/data/*.zsh; do | ||||
| # Activate the highlighter. | ||||
| ZSH_HIGHLIGHT_HIGHLIGHTERS=($1) | ||||
| 
 | ||||
| # Process each test data file in test data directory. | ||||
| for data_file in ${0:h:h}/highlighters/$1/test-data/*; do | ||||
| 
 | ||||
|   # Load the data and prepare checking it. | ||||
|   BUFFER= ; expected_region_highlight=(); errors=() | ||||
|  | @ -55,7 +76,7 @@ for data_file in $(dirname $0)/data/*.zsh; do | |||
| 
 | ||||
|       # Process the data. | ||||
|       region_highlight=() | ||||
|       _zsh_highlight-zle-buffer | ||||
|       _zsh_highlight | ||||
| 
 | ||||
|       # Overlapping regions can be declared in region_highlight, so we first build an array of the | ||||
|       # observed highlighting. | ||||
|  |  | |||
|  | @ -29,11 +29,32 @@ | |||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| 
 | ||||
| # Load the main script. | ||||
| . $(dirname $0)/../zsh-syntax-highlighting.zsh | ||||
| # Check an highlighter was given as argument. | ||||
| [[ -n "$1" ]] || { | ||||
|   echo "You must provide the name of a valid highlighter as argument." >&2 | ||||
|   exit 1 | ||||
| } | ||||
| 
 | ||||
| # Process each test data file in data/. | ||||
| for data_file in $(dirname $0)/data/*.zsh; do | ||||
| # Check the highlighter is valid. | ||||
| [[ -f ${0:h:h}/highlighters/$1/$1-highlighter.zsh ]] || { | ||||
|   echo "Could not find highlighter '$1'." >&2 | ||||
|   exit 1 | ||||
| } | ||||
| 
 | ||||
| # Check the highlighter has test data. | ||||
| [[ -d ${0:h:h}/highlighters/$1/test-data ]] || { | ||||
|   echo "Highlighter '$1' has no test data." >&2 | ||||
|   exit 1 | ||||
| } | ||||
| 
 | ||||
| # Load the main script. | ||||
| . ${0:h:h}/zsh-syntax-highlighting.zsh | ||||
| 
 | ||||
| # Activate the highlighter. | ||||
| ZSH_HIGHLIGHT_HIGHLIGHTERS=($1) | ||||
| 
 | ||||
| # Process each test data file in test data directory. | ||||
| for data_file in ${0:h:h}/highlighters/$1/test-data/*; do | ||||
| 
 | ||||
|   # Load the data and prepare checking it. | ||||
|   BUFFER= | ||||
|  | @ -45,9 +66,9 @@ for data_file in $(dirname $0)/data/*.zsh; do | |||
|     echo "KO\n   - 'BUFFER' is not declared or blank." | ||||
|   else | ||||
| 
 | ||||
|     # Measure the time taken by _zsh_highlight-zle-buffer. | ||||
|     # Measure the time taken by _zsh_highlight. | ||||
|     TIMEFMT="%*Es" | ||||
|     time ( BUFFER="$BUFFER" && _zsh_highlight-zle-buffer) | ||||
|     time ( BUFFER="$BUFFER" && _zsh_highlight) | ||||
| 
 | ||||
|   fi | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,255 +33,81 @@ | |||
| # Core highlighting update system | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| # Array used by highlighters to declare overridable styles. | ||||
| typeset -gA ZSH_HIGHLIGHT_STYLES | ||||
| # Array declaring active highlighters names. | ||||
| typeset -ga ZSH_HIGHLIGHT_HIGHLIGHTERS | ||||
| 
 | ||||
| # An `object' implemented by below 3 arrays' elements could be called a | ||||
| # `highlighter', registered by `_zsh_highlight_add-highlighter`. In other words, these | ||||
| # arrays are indexed and tied by their own functionality. If they have been | ||||
| # arranged inconsistently, things goes wrong. | ||||
| # Please see `_zsh_highlight-zle-buffer` and `_zsh_highlight_add-highlighter`. | ||||
| 
 | ||||
| # Actual recolorize functions to be called. | ||||
| typeset -a zsh_highlight_functions; zsh_highlight_functions=() | ||||
| 
 | ||||
| # Predicate functions whether its recolorize function should be called or not. | ||||
| typeset -a zsh_highlight_predicates; zsh_highlight_predicates=() | ||||
| 
 | ||||
| # Highlight storages for each recolorize functions. | ||||
| typeset -a zsh_highlight_caches; zsh_highlight_caches=() | ||||
| 
 | ||||
| _zsh_highlight-zle-buffer() { | ||||
| # Update ZLE buffer syntax highlighting. | ||||
| # | ||||
| # 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=$? | ||||
| 
 | ||||
|   # Do not highlight if there are pending inputs (copy/paste). | ||||
|   [[ $PENDING -gt 0 ]] && return $ret | ||||
| 
 | ||||
|   { | ||||
|     local -a funinds | ||||
|     local -i rh_size=$#region_highlight | ||||
|     for i in {1..${#zsh_highlight_functions}}; do | ||||
|       local pred=${zsh_highlight_predicates[i]} cache_place=${zsh_highlight_caches[i]} | ||||
|       if _zsh_highlight-zle-buffer-p "$rh_size" "$pred"; then | ||||
|         if ((${#${(P)cache_place}} > 0)); then | ||||
|           region_highlight=(${region_highlight:#(${(P~j.|.)cache_place})}) | ||||
|           local -a empty; empty=(); : ${(PA)cache_place::=$empty} | ||||
|         fi | ||||
|         funinds+=$i | ||||
|     local -a selected_highlighters | ||||
|     local cache_place | ||||
| 
 | ||||
|     # Select which highlighters in ZSH_HIGHLIGHT_HIGHLIGHTERS need to be invoked. | ||||
|     local highlighter; for highlighter in $ZSH_HIGHLIGHT_HIGHLIGHTERS; do | ||||
| 
 | ||||
|       # If highlighter needs to be invoked | ||||
|       if "_zsh_highlight_${highlighter}_highlighter_predicate"; then | ||||
| 
 | ||||
|         # Mark the highlighter as selected for update. | ||||
|         selected_highlighters+=($highlighter) | ||||
| 
 | ||||
|         # Remove what was stored in its cache from region_highlight. | ||||
|         cache_place="_zsh_highlight_${highlighter}_highlighter_cache" | ||||
|         [[ ${#${(P)cache_place}} -gt 0 ]] && region_highlight=(${region_highlight:#(${(P~j.|.)cache_place})}) | ||||
|       fi | ||||
|     done | ||||
|     for i in $funinds; do | ||||
|       local func=${zsh_highlight_functions[i]} cache_place=${zsh_highlight_caches[i]} | ||||
|       local -a rh; rh=($region_highlight) | ||||
| 
 | ||||
|     # Invoke each selected highlighter and store the result in its cache. | ||||
|     local -a region_highlight_copy | ||||
|     for highlighter in $selected_highlighters; do | ||||
|       cache_place="_zsh_highlight_${highlighter}_highlighter_cache" | ||||
|       region_highlight_copy=($region_highlight) | ||||
|       { | ||||
|         "$func" | ||||
|         "_zsh_highlight_${highlighter}_highlighter" | ||||
|       } always  { | ||||
|         : ${(PA)cache_place::=${region_highlight:#(${(~j.|.)rh})}} | ||||
|         : ${(PA)cache_place::=${region_highlight:#(${(~j.|.)region_highlight_copy})}} | ||||
|       } | ||||
|     done | ||||
| 
 | ||||
|   } always { | ||||
|     ZSH_PRIOR_CURSOR=$CURSOR | ||||
|     ZSH_PRIOR_HIGHLIGHTED_BUFFER=$BUFFER | ||||
|     _ZSH_HIGHLIGHT_PRIOR_BUFFER=$BUFFER | ||||
|     _ZSH_HIGHLIGHT_PRIOR_CURSOR=$CURSOR | ||||
|     return $ret | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| # Whether supplied highlight_predicate satisfies or not. | ||||
| _zsh_highlight-zle-buffer-p() { | ||||
|   local region_highlight_size="$1" highlight_predicate="$2" | ||||
|   # If any highlightings are not taken into account, asume it is needed. | ||||
|   # This holds for some up/down-history commands, for example. | ||||
|   ((region_highlight_size == 0)) || "$highlight_predicate" | ||||
| } | ||||
| 
 | ||||
| # Whether the command line buffer is modified or not. | ||||
| _zsh_highlight_buffer-modified-p() { | ||||
|   [[ ${ZSH_PRIOR_HIGHLIGHTED_BUFFER:-} != $BUFFER ]] | ||||
| } | ||||
| 
 | ||||
| # Whether the cursor is moved or not. | ||||
| _zsh_highlight_cursor-moved-p() { | ||||
|   ((ZSH_PRIOR_CURSOR != $CURSOR)) | ||||
| } | ||||
| 
 | ||||
| # Register an highlighter. | ||||
| _zsh_highlight_add-highlighter() { | ||||
|   zsh_highlight_functions+="$1" | ||||
|   zsh_highlight_predicates+="${2-${1}-p}" | ||||
|   zsh_highlight_caches+="${3-${1//-/_}}" | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| # Main highlighter | ||||
| # API/utility functions for highlighters | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| ZSH_HIGHLIGHT_STYLES+=( | ||||
|   default                       'none' | ||||
|   unknown-token                 'fg=red,bold' | ||||
|   reserved-word                 'fg=yellow' | ||||
|   alias                         'fg=green' | ||||
|   builtin                       'fg=green' | ||||
|   function                      'fg=green' | ||||
|   command                       'fg=green' | ||||
|   hashed-command                'fg=green' | ||||
|   path                          'underline' | ||||
|   globbing                      'fg=blue' | ||||
|   history-expansion             'fg=blue' | ||||
|   single-hyphen-option          'none' | ||||
|   double-hyphen-option          'none' | ||||
|   back-quoted-argument          'none' | ||||
|   single-quoted-argument        'fg=yellow' | ||||
|   double-quoted-argument        'fg=yellow' | ||||
|   dollar-double-quoted-argument 'fg=cyan' | ||||
|   back-double-quoted-argument   'fg=cyan' | ||||
|   assign                        'none' | ||||
| ) | ||||
| # Array used by highlighters to declare user overridable styles. | ||||
| typeset -gA ZSH_HIGHLIGHT_STYLES | ||||
| 
 | ||||
| # Tokens that are always immediately followed by a command. | ||||
| ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS=( | ||||
|   '|' '||' ';' '&' '&&' 'noglob' 'nocorrect' 'builtin' | ||||
| ) | ||||
| 
 | ||||
| # Check if the argument is variable assignment | ||||
| _zsh_highlight_check-assign() { | ||||
|     setopt localoptions extended_glob | ||||
|     [[ ${(Q)arg} == [[:alpha:]_]([[:alnum:]_])#=* ]] | ||||
| # 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 ]] | ||||
| } | ||||
| 
 | ||||
| # Check if the argument is a path. | ||||
| _zsh_highlight_check-path() { | ||||
|   [[ -z ${(Q)arg} ]] && return 1 | ||||
|   [[ -e ${(Q)arg} ]] && return 0 | ||||
|   [[ ! -e ${(Q)arg:h} ]] && return 1 | ||||
|   [[ ${#BUFFER} == $end_pos && -n $(print ${(Q)arg}*(N)) ]] && return 0 | ||||
|   return 1 | ||||
| } | ||||
| 
 | ||||
| # Highlight special chars inside double-quoted strings | ||||
| _zsh_highlight_highlight_string() { | ||||
|   setopt localoptions noksharrays | ||||
|   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=$ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument];; | ||||
|       "\\") style=$ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument] | ||||
|             (( k += 1 )) # Color following char too. | ||||
|             (( i += 1 )) # Skip parsing the escaped char. | ||||
|             ;; | ||||
|       *)    continue;; | ||||
|     esac | ||||
|     region_highlight+=("$j $k $style") | ||||
|   done | ||||
| } | ||||
| 
 | ||||
| # Core syntax highlighting. | ||||
| _zsh_main-highlight() { | ||||
|   setopt localoptions extendedglob bareglobqual | ||||
|   local start_pos=0 end_pos highlight_glob=true new_expression=true arg style | ||||
|   region_highlight=() | ||||
|   for arg in ${(z)BUFFER}; do | ||||
|     local substr_color=0 | ||||
|     [[ $start_pos -eq 0 && $arg = 'noglob' ]] && highlight_glob=false | ||||
|     ((start_pos+=${#BUFFER[$start_pos+1,-1]}-${#${BUFFER[$start_pos+1,-1]##[[:space:]]#}})) | ||||
|     ((end_pos=$start_pos+${#arg})) | ||||
|     if $new_expression; then | ||||
|       new_expression=false | ||||
|       res=$(LC_ALL=C builtin type -w $arg 2>/dev/null) | ||||
|       case $res in | ||||
|         *': reserved')  style=$ZSH_HIGHLIGHT_STYLES[reserved-word];; | ||||
|         *': alias')     style=$ZSH_HIGHLIGHT_STYLES[alias] | ||||
|                         local aliased_command="${"$(alias $arg)"#*=}" | ||||
|                         [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS:#"$aliased_command"} && -z ${(M)ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS:#"$arg"} ]] && ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS+=($arg) | ||||
|                         ;; | ||||
|         *': builtin')   style=$ZSH_HIGHLIGHT_STYLES[builtin];; | ||||
|         *': function')  style=$ZSH_HIGHLIGHT_STYLES[function];; | ||||
|         *': command')   style=$ZSH_HIGHLIGHT_STYLES[command];; | ||||
|         *': hashed')    style=$ZSH_HIGHLIGHT_STYLES[hashed-command];; | ||||
|         *)              if _zsh_highlight_check-assign; then | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[assign] | ||||
|                           new_expression=true | ||||
|                         elif _zsh_highlight_check-path; then | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[path] | ||||
|                         elif [[ $arg[0,1] = $histchars[0,1] ]]; then | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[history-expansion] | ||||
|                         else | ||||
|                           style=$ZSH_HIGHLIGHT_STYLES[unknown-token] | ||||
|                         fi | ||||
|                         ;; | ||||
|       esac | ||||
|     else | ||||
|       case $arg in | ||||
|         '--'*)   style=$ZSH_HIGHLIGHT_STYLES[double-hyphen-option];; | ||||
|         '-'*)    style=$ZSH_HIGHLIGHT_STYLES[single-hyphen-option];; | ||||
|         "'"*"'") style=$ZSH_HIGHLIGHT_STYLES[single-quoted-argument];; | ||||
|         '"'*'"') style=$ZSH_HIGHLIGHT_STYLES[double-quoted-argument] | ||||
|                  region_highlight+=("$start_pos $end_pos $style") | ||||
|                  _zsh_highlight_highlight_string | ||||
|                  substr_color=1 | ||||
|                  ;; | ||||
|         '`'*'`') style=$ZSH_HIGHLIGHT_STYLES[back-quoted-argument];; | ||||
|         *"*"*)   $highlight_glob && style=$ZSH_HIGHLIGHT_STYLES[globbing] || style=$ZSH_HIGHLIGHT_STYLES[default];; | ||||
|         *)       if _zsh_highlight_check-path; then | ||||
|                    style=$ZSH_HIGHLIGHT_STYLES[path] | ||||
|                  elif [[ $arg[0,1] = $histchars[0,1] ]]; then | ||||
|                    style=$ZSH_HIGHLIGHT_STYLES[history-expansion] | ||||
|                  else | ||||
|                    style=$ZSH_HIGHLIGHT_STYLES[default] | ||||
|                  fi | ||||
|                  ;; | ||||
|       esac | ||||
|     fi | ||||
|     [[ $substr_color = 0 ]] && region_highlight+=("$start_pos $end_pos $style") | ||||
|     [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_FOLLOWED_BY_COMMANDS:#"$arg"} ]] && new_expression=true | ||||
|     start_pos=$end_pos | ||||
|   done | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| # Setup functions | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| # Intercept specified ZLE events to have highlighting triggered. | ||||
| _zsh_highlight_bind-events() { | ||||
| 
 | ||||
|   # Resolve event names what have to be bound to. | ||||
|   zmodload zsh/zleparameter 2>/dev/null || { | ||||
|     echo 'zsh-syntax-highlighting:zmodload error. exiting.' >&2 | ||||
|     return -1 | ||||
|   } | ||||
|   local -a events; : ${(A)events::=${@:#(_*|orig-*|.run-help|.which-command)}} | ||||
| 
 | ||||
|   # Bind the events to _zsh_highlight-zle-buffer. | ||||
|   local clean_event | ||||
|   for event in $events; do | ||||
|     if [[ "$widgets[$event]" == completion:* ]]; then | ||||
|       eval "zle -C orig-$event ${${${widgets[$event]}#*:}/:/ } ; $event() { builtin zle orig-$event && _zsh_highlight-zle-buffer } ; zle -N $event" | ||||
|     else | ||||
|       case $event in | ||||
|         accept-and-menu-complete) | ||||
|           eval "$event() { builtin zle .$event && _zsh_highlight-zle-buffer } ; zle -N $event" | ||||
|           ;; | ||||
|         .*) | ||||
|           clean_event=$event[2,${#event}] # Remove the leading dot in the event name | ||||
|           case ${widgets[$clean_event]-} in | ||||
|             (completion|user):*) | ||||
|               ;; | ||||
|             *) | ||||
|               eval "$clean_event() { builtin zle $event && _zsh_highlight-zle-buffer } ; zle -N $clean_event" | ||||
|               ;; | ||||
|           esac | ||||
|           ;; | ||||
|         *) | ||||
|           ;; | ||||
|       esac | ||||
|     fi | ||||
|   done | ||||
| } | ||||
| 
 | ||||
| # Load highlighters from specified directory if it exists. | ||||
| _zsh_highlight_load-highlighters() { | ||||
|   [[ -d $1 ]] && for highlighter_def ($1/*.zsh) . $highlighter_def | ||||
| # Whether the cursor has moved or not. | ||||
| # | ||||
| # Returns 0 if the cursor has moved since _zsh_highlight was last called. | ||||
| _zsh_highlight_cursor_moved() | ||||
| { | ||||
|   ((_ZSH_HIGHLIGHT_PRIOR_CURSOR != $CURSOR)) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -289,11 +115,57 @@ _zsh_highlight_load-highlighters() { | |||
| # Setup | ||||
| # ------------------------------------------------------------------------------------------------- | ||||
| 
 | ||||
| # Bind highlighting to all known events. | ||||
| _zsh_highlight_bind-events "${(@f)"$(zle -la)"}" | ||||
| # Load ZSH module zsh/zleparameter, needed to override user defined widgets. | ||||
| zmodload zsh/zleparameter 2>/dev/null || { | ||||
|   echo 'zsh-syntax-highlighting: failed loading zsh/zleparameter, exiting.' >&2 | ||||
|   return -1 | ||||
| } | ||||
| 
 | ||||
| # Register the main highlighter. | ||||
| _zsh_highlight_add-highlighter _zsh_main-highlight _zsh_highlight_buffer-modified-p | ||||
| # Resolve highlighters directory location. | ||||
| highlighters_dir="${ZSH_HIGHLIGHT_HIGHLIGHTERS_DIR:-${${(%):-%N}:A:h}/highlighters}" | ||||
| [[ -d $highlighters_dir ]] || { | ||||
|   echo "zsh-syntax-highlighting: highlighters directory '$highlighters_dir' not found, exiting." >&2 | ||||
|   return -1 | ||||
| } | ||||
| 
 | ||||
| # Load additional highlighters if available. | ||||
| _zsh_highlight_load-highlighters "${${(%):-%N}:h}/highlighters" | ||||
| # Override ZLE widgets to make them invoke _zsh_highlight. | ||||
| for event in ${${(f)"$(zle -la)"}:#(_*|orig-*|.run-help|.which-command)}; do | ||||
|   if [[ "$widgets[$event]" == completion:* ]]; then | ||||
|     eval "zle -C orig-$event ${${${widgets[$event]}#*:}/:/ } ; $event() { builtin zle orig-$event && _zsh_highlight } ; zle -N $event" | ||||
|   else | ||||
|     case $event in | ||||
|       accept-and-menu-complete) | ||||
|         eval "$event() { builtin zle .$event && _zsh_highlight } ; zle -N $event" | ||||
|         ;; | ||||
|       .*) | ||||
|         clean_event=$event[2,${#event}] # Remove the leading dot in the event name | ||||
|         case ${widgets[$clean_event]-} in | ||||
|           (completion|user):*) | ||||
|             ;; | ||||
|           *) | ||||
|             eval "$clean_event() { builtin zle $event && _zsh_highlight } ; zle -N $clean_event" | ||||
|             ;; | ||||
|         esac | ||||
|         ;; | ||||
|       *) | ||||
|         ;; | ||||
|     esac | ||||
|   fi | ||||
| done | ||||
| unset event clean_event | ||||
| 
 | ||||
| # Load highlighters from highlighters directory and check they define required functions. | ||||
| for highlighter_dir ($highlighters_dir/*/); do | ||||
|   highlighter="${highlighter_dir:t}" | ||||
|   [[ -f "$highlighter_dir/${highlighter}-highlighter.zsh" ]] && { | ||||
|     . "$highlighter_dir/${highlighter}-highlighter.zsh" | ||||
|     type "_zsh_highlight_${highlighter}_highlighter" &> /dev/null && | ||||
|     type "_zsh_highlight_${highlighter}_highlighter_predicate" &> /dev/null || { | ||||
|       echo "zsh-syntax-highlighting: '${highlighter}' highlighter should define both required functions '_zsh_highlight_${highlighter}_highlighter' and '_zsh_highlight_${highlighter}_highlighter_predicate' in '${highlighter_dir}/${highlighter}-highlighter.zsh'." >&2 | ||||
|     } | ||||
|   } | ||||
| done | ||||
| unset highlighter highlighter_dir highlighters_dir | ||||
| 
 | ||||
| # Initialize the array of active highlighters if needed. | ||||
| [[ $#ZSH_HIGHLIGHT_HIGHLIGHTERS -eq 0 ]] && ZSH_HIGHLIGHT_HIGHLIGHTERS=(main) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue