25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
9.9 KiB

  1. # -------------------------------------------------------------------------------------------------
  2. # Copyright (c) 2010-2020 zsh-syntax-highlighting contributors
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without modification, are permitted
  6. # provided that the following conditions are met:
  7. #
  8. # * Redistributions of source code must retain the above copyright notice, this list of conditions
  9. # and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright notice, this list of
  11. # conditions and the following disclaimer in the documentation and/or other materials provided
  12. # with the distribution.
  13. # * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
  14. # may be used to endorse or promote products derived from this software without specific prior
  15. # written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  18. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  19. # FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  20. # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  23. # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  24. # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. # -------------------------------------------------------------------------------------------------
  26. # -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
  27. # vim: ft=zsh sw=2 ts=2 et
  28. # -------------------------------------------------------------------------------------------------
  29. # Set $0 to the expected value, regardless of functionargzero.
  30. 0=${(%):-%N}
  31. fpath+=(${0:P:h})
  32. if true; then
  33. # $0 is reliable
  34. typeset -g ZSH_HIGHLIGHT_VERSION=$(<"${0:A:h}"/.version)
  35. typeset -g ZSH_HIGHLIGHT_REVISION=$(<"${0:A:h}"/.revision-hash)
  36. if [[ $ZSH_HIGHLIGHT_REVISION == \$Format:* ]]; then
  37. # When running from a source tree without 'make install', $ZSH_HIGHLIGHT_REVISION
  38. # would be set to '$Format:%H$' literally. That's an invalid value, and obtaining
  39. # the valid value (via `git rev-parse HEAD`, as Makefile does) might be costly, so:
  40. ZSH_HIGHLIGHT_REVISION=HEAD
  41. fi
  42. fi
  43. # This function takes a single argument F and returns True iff F is an autoload stub.
  44. _zsh_highlight__function_is_autoload_stub_p() {
  45. if zmodload -e zsh/parameter; then
  46. #(( ${+functions[$1]} )) &&
  47. [[ "$functions[$1]" == *"builtin autoload -X"* ]]
  48. else
  49. #[[ $(type -wa -- "$1") == *'function'* ]] &&
  50. [[ "${${(@f)"$(which -- "$1")"}[2]}" == $'\t'$histchars[3]' undefined' ]]
  51. fi
  52. # Do nothing here: return the exit code of the if.
  53. }
  54. # Return True iff the argument denotes a function name.
  55. _zsh_highlight__is_function_p() {
  56. if zmodload -e zsh/parameter; then
  57. (( ${+functions[$1]} ))
  58. else
  59. [[ $(type -wa -- "$1") == *'function'* ]]
  60. fi
  61. }
  62. # This function takes a single argument F and returns True iff F denotes the
  63. # name of a callable function. A function is callable if it is fully defined
  64. # or if it is marked for autoloading and autoloading it at the first call to it
  65. # will succeed. In particular, if a function has been marked for autoloading
  66. # but is not available in $fpath, then this function will return False therefor.
  67. #
  68. # See users/21671 http://www.zsh.org/cgi-bin/mla/redirect?USERNUMBER=21671
  69. _zsh_highlight__function_callable_p() {
  70. if _zsh_highlight__is_function_p "$1" &&
  71. ! _zsh_highlight__function_is_autoload_stub_p "$1"
  72. then
  73. # Already fully loaded.
  74. return 0 # true
  75. else
  76. # "$1" is either an autoload stub, or not a function at all.
  77. #
  78. # Use a subshell to avoid affecting the calling shell.
  79. #
  80. # We expect 'autoload +X' to return non-zero if it fails to fully load
  81. # the function.
  82. ( autoload -U +X -- "$1" 2>/dev/null )
  83. return $?
  84. fi
  85. }
  86. # -------------------------------------------------------------------------------------------------
  87. # Core highlighting update system
  88. # -------------------------------------------------------------------------------------------------
  89. # Use workaround for bug in ZSH?
  90. # zsh-users/zsh@48cadf4 http://www.zsh.org/mla/workers//2017/msg00034.html
  91. autoload -Uz is-at-least
  92. if is-at-least 5.4; then
  93. typeset -g zsh_highlight__pat_static_bug=false
  94. else
  95. typeset -g zsh_highlight__pat_static_bug=true
  96. fi
  97. # Array declaring active highlighters names.
  98. typeset -ga ZSH_HIGHLIGHT_HIGHLIGHTERS
  99. # -------------------------------------------------------------------------------------------------
  100. # API/utility functions for highlighters
  101. # -------------------------------------------------------------------------------------------------
  102. # Array used by highlighters to declare user overridable styles.
  103. typeset -gA ZSH_HIGHLIGHT_STYLES
  104. # Whether the command line buffer has been modified or not.
  105. #
  106. # Returns 0 if the buffer has changed since _zsh_highlight was last called.
  107. _zsh_highlight_buffer_modified()
  108. {
  109. [[ "${_ZSH_HIGHLIGHT_PRIOR_BUFFER:-}" != "$BUFFER" ]]
  110. }
  111. # Whether the cursor has moved or not.
  112. #
  113. # Returns 0 if the cursor has moved since _zsh_highlight was last called.
  114. _zsh_highlight_cursor_moved()
  115. {
  116. [[ -n $CURSOR ]] && [[ -n ${_ZSH_HIGHLIGHT_PRIOR_CURSOR-} ]] && (($_ZSH_HIGHLIGHT_PRIOR_CURSOR != $CURSOR))
  117. }
  118. # Add a highlight defined by ZSH_HIGHLIGHT_STYLES.
  119. #
  120. # Should be used by all highlighters aside from 'pattern' (cf. ZSH_HIGHLIGHT_PATTERN).
  121. # Overwritten in tests/test-highlighting.zsh when testing.
  122. _zsh_highlight_add_highlight()
  123. {
  124. local -i start end
  125. local highlight
  126. start=$1
  127. end=$2
  128. shift 2
  129. for highlight; do
  130. if (( $+ZSH_HIGHLIGHT_STYLES[$highlight] )); then
  131. region_highlight+=("$start $end $ZSH_HIGHLIGHT_STYLES[$highlight], memo=zsh-syntax-highlighting")
  132. break
  133. fi
  134. done
  135. }
  136. # -------------------------------------------------------------------------------------------------
  137. # Setup functions
  138. # -------------------------------------------------------------------------------------------------
  139. # Load highlighters from directory.
  140. #
  141. # Arguments:
  142. # 1) Path to the highlighters directory.
  143. _zsh_highlight_load_highlighters()
  144. {
  145. # Check the directory exists.
  146. [[ -d "$1" ]] || {
  147. print -r -- >&2 "zsh-syntax-highlighting: highlighters directory ${(qq)1} not found."
  148. return 1
  149. }
  150. # Load highlighters from highlighters directory and check they define required functions.
  151. local highlighter highlighter_dir
  152. for highlighter_dir ($1/*/(/)); do
  153. highlighter="${highlighter_dir:t}"
  154. [[ -f "$highlighter_dir${highlighter}-highlighter.zsh" ]] &&
  155. . "$highlighter_dir${highlighter}-highlighter.zsh"
  156. if [[ -f "${highlighter_dir}_zsh_highlight_highlighter_${highlighter}_paint" ]] &&
  157. [[ -f "${highlighter_dir}_zsh_highlight_highlighter_${highlighter}_predicate" ]]; then
  158. # New (0.8.0) autoload style highlighter
  159. fpath+=(${highlighter_dir%/})
  160. autoload -Uz "_zsh_highlight_highlighter_${highlighter}_paint" "_zsh_highlight_highlighter_${highlighter}_predicate"
  161. else
  162. if type "_zsh_highlight_highlighter_${highlighter}_paint" &> /dev/null &&
  163. type "_zsh_highlight_highlighter_${highlighter}_predicate" &> /dev/null;
  164. then
  165. # New (0.5.0) function names
  166. elif type "_zsh_highlight_${highlighter}_highlighter" &> /dev/null &&
  167. type "_zsh_highlight_${highlighter}_highlighter_predicate" &> /dev/null;
  168. then
  169. # Old (0.4.x) function names
  170. if false; then
  171. # TODO: only show this warning for plugin authors/maintainers, not for end users
  172. print -r -- >&2 "zsh-syntax-highlighting: warning: ${(qq)highlighter} highlighter uses deprecated entry point names; please ask its maintainer to update it: https://github.com/zsh-users/zsh-syntax-highlighting/issues/329"
  173. fi
  174. # Make it work.
  175. eval "_zsh_highlight_highlighter_${(q)highlighter}_paint() { _zsh_highlight_${(q)highlighter}_highlighter \"\$@\" }"
  176. eval "_zsh_highlight_highlighter_${(q)highlighter}_predicate() { _zsh_highlight_${(q)highlighter}_highlighter_predicate \"\$@\" }"
  177. else
  178. print -r -- >&2 "zsh-syntax-highlighting: ${(qq)highlighter} highlighter should define both required functions '_zsh_highlight_highlighter_${highlighter}_paint' and '_zsh_highlight_highlighter_${highlighter}_predicate' in ${(qq):-"$highlighter_dir${highlighter}-highlighter.zsh"}."
  179. fi
  180. fi
  181. done
  182. }
  183. # -------------------------------------------------------------------------------------------------
  184. # Setup
  185. # -------------------------------------------------------------------------------------------------
  186. autoload -Uz _zsh_highlight_internal
  187. # Resolve highlighters directory location.
  188. _zsh_highlight_load_highlighters "${ZSH_HIGHLIGHT_HIGHLIGHTERS_DIR:-${${0:A}:h}/highlighters}" || {
  189. print -r -- >&2 'zsh-syntax-highlighting: failed loading highlighters, exiting.'
  190. return 1
  191. }
  192. # Reset scratch variables when commandline is done.
  193. _zsh_highlight_preexec_hook()
  194. {
  195. typeset -g _ZSH_HIGHLIGHT_PRIOR_BUFFER=
  196. typeset -gi _ZSH_HIGHLIGHT_PRIOR_CURSOR=
  197. }
  198. autoload -Uz add-zsh-hook
  199. add-zsh-hook preexec _zsh_highlight_preexec_hook 2>/dev/null || {
  200. print -r -- >&2 'zsh-syntax-highlighting: failed loading add-zsh-hook.'
  201. }
  202. # Load zsh/parameter module if available
  203. zmodload zsh/parameter 2>/dev/null || true
  204. # Initialize the array of active highlighters if needed.
  205. [[ $#ZSH_HIGHLIGHT_HIGHLIGHTERS -eq 0 ]] && ZSH_HIGHLIGHT_HIGHLIGHTERS=(main)
  206. if (( $+X_ZSH_HIGHLIGHT_DIRS_BLACKLIST )); then
  207. print >&2 'zsh-syntax-highlighting: X_ZSH_HIGHLIGHT_DIRS_BLACKLIST is deprecated. Please use ZSH_HIGHLIGHT_DIRS_BLACKLIST.'
  208. ZSH_HIGHLIGHT_DIRS_BLACKLIST=($X_ZSH_HIGHLIGHT_DIRS_BLACKLIST)
  209. unset X_ZSH_HIGHLIGHT_DIRS_BLACKLIST
  210. fi