diff --git a/README.md b/README.md index ac8beaf..7f0fe28 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,24 @@ custom widgets have been created (i.e., after all `zle -N` calls and after running `compinit`). Widgets created later will work, but will not update the syntax highlighting. +### Why does syntax highlighting not work while searching history? + +_This problem is fixed in zsh 5.3 and newer._ + +Highlighting the command line during an incremental history search +(with the `history-incremental-search-backward` widget, which is +bound by default to Ctrl+R in zsh's emacs keymap) requires zsh 5.3 +or newer. + +Under zsh 5.2 and older, the zsh-default underlining of the matched portion +of the buffer remains available, but zsh-syntax-highlighting's additional +highlighting is unavailable. (Those versions of zsh do not provide enough +information to allow computing the highlighting correctly.) + +See [issue #288][i288] for details. + +[i288]: https://github.com/zsh-users/zsh-syntax-highlighting/pull/288 + ### How are new releases announced? There is currently no "push" announcements channel. However, the following diff --git a/highlighters/cursor/cursor-highlighter.zsh b/highlighters/cursor/cursor-highlighter.zsh index aa70f55..13479b9 100644 --- a/highlighters/cursor/cursor-highlighter.zsh +++ b/highlighters/cursor/cursor-highlighter.zsh @@ -34,15 +34,14 @@ # Whether the cursor highlighter should be called or not. _zsh_highlight_cursor_highlighter_predicate() { - # accept-* may trigger removal of cursor highlighting - [[ $WIDGET == accept-* ]] || - _zsh_highlight_cursor_moved + # remove cursor highlighting when the line is finished + [[ $WIDGET == zle-line-finish ]] || _zsh_highlight_cursor_moved } # Cursor highlighting function. _zsh_highlight_cursor_highlighter() { - [[ $WIDGET == accept-* ]] && return + [[ $WIDGET == zle-line-finish ]] && return _zsh_highlight_add_highlight $CURSOR $(( $CURSOR + 1 )) cursor } diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh index 7e62b90..701d0cc 100644 --- a/highlighters/main/main-highlighter.zsh +++ b/highlighters/main/main-highlighter.zsh @@ -62,9 +62,8 @@ # Whether the highlighter should be called or not. _zsh_highlight_main_highlighter_predicate() { - # accept-* may trigger removal of path_prefix highlighting - [[ $WIDGET == accept-* ]] || - _zsh_highlight_buffer_modified + # may need to remove path_prefix highlighting when the line ends + [[ $WIDGET == zle-line-finish ]] || _zsh_highlight_buffer_modified } # Helper to deal with tokens crossing line boundaries. @@ -596,7 +595,7 @@ _zsh_highlight_main_highlighter_check_path() # If this word ends the buffer, check if it's the prefix of a valid path. if [[ ${BUFFER[1]} != "-" && ${#BUFFER} == $end_pos ]] && - [[ $WIDGET != accept-* ]]; then + [[ $WIDGET != zle-line-finish ]]; then local -a tmp tmp=( ${expanded_path}*(N) ) (( $#tmp > 0 )) && REPLY=path_prefix && return 0 diff --git a/highlighters/main/test-data/path_prefix2.zsh b/highlighters/main/test-data/path_prefix2.zsh index ffe50cd..501928a 100644 --- a/highlighters/main/test-data/path_prefix2.zsh +++ b/highlighters/main/test-data/path_prefix2.zsh @@ -31,7 +31,7 @@ # Related to path_prefix.zsh BUFFER='ls /bin/s' -WIDGET=accept-line +WIDGET=zle-line-finish expected_region_highlight=( "4 9 default" # /bin/s diff --git a/zsh-syntax-highlighting.zsh b/zsh-syntax-highlighting.zsh index e401956..de3fea9 100644 --- a/zsh-syntax-highlighting.zsh +++ b/zsh-syntax-highlighting.zsh @@ -58,6 +58,13 @@ _zsh_highlight() # Store the previous command return code to restore it whatever happens. local ret=$? + # Remove all highlighting in isearch, so that only the underlining done by zsh itself remains. + # For details see FAQ entry 'Why does syntax highlighting not work while searching history?'. + if [[ $WIDGET == zle-isearch-update ]]; then + region_highlight=() + return $ret + fi + setopt localoptions warncreateglobal setopt localoptions noksharrays local REPLY # don't leak $REPLY into global scope @@ -250,8 +257,20 @@ _zsh_highlight_bind_widgets() } # Override ZLE widgets to make them invoke _zsh_highlight. + local -U widgets_to_bind + widgets_to_bind=(${${(k)widgets}:#(.*|orig-*|run-help|which-command|beep|set-local-history|yank)}) + + # Always wrap special zle-line-finish widget. This is needed to decide if the + # current line ends and special highlighting logic needs to be applied. + # E.g. remove cursor imprint, don't highlight partial paths, ... + widgets_to_bind+=(zle-line-finish) + + # Always wrap special zle-isearch-update widget to be notified of updates in isearch. + # This is needed because we need to disable highlighting in that case. + widgets_to_bind+=(zle-isearch-update) + local cur_widget - for cur_widget in ${${(k)widgets}:#(.*|orig-*|run-help|which-command|beep|set-local-history|yank)}; do + for cur_widget in $widgets_to_bind; do case $widgets[$cur_widget] in # Already rebound event: do nothing. @@ -277,8 +296,15 @@ _zsh_highlight_bind_widgets() builtin) eval "_zsh_highlight_widget_${(q)cur_widget}() { _zsh_highlight_call_widget .${(q)cur_widget} -- \"\$@\" }" zle -N $cur_widget _zsh_highlight_widget_$cur_widget;; + # Incomplete or nonexistent widget: Bind to z-sy-h directly. + *) + if [[ $cur_widget == zle-* ]] && [[ -z $widgets[$cur_widget] ]]; then + _zsh_highlight_widget_${cur_widget}() { :; _zsh_highlight } + zle -N $cur_widget _zsh_highlight_widget_$cur_widget + else # Default: unhandled case. - *) print -r -- >&2 "zsh-syntax-highlighting: unhandled ZLE widget '$cur_widget'" ;; + print -r -- >&2 "zsh-syntax-highlighting: unhandled ZLE widget '$cur_widget'" + fi esac done }