diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..cd50b8a
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,75 @@
+---
+name: Tests
+on:
+ push:
+ paths-ignore:
+ - '**.md'
+ - '**.png'
+ pull_request:
+ paths-ignore:
+ - '**.md'
+ - '**.png'
+ schedule:
+ - cron: '29 7 * * 1'
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ version:
+ - master
+ - 5.9
+ - 5.8.1
+ - 5.8
+ - 5.7.1
+ - 5.7
+ - 5.6.2
+ - 5.6.1
+ - 5.6
+ - 5.5.1
+ - 5.5
+ - 5.4.2
+ - 5.4.1
+ - 5.4
+ - 5.3.1
+ - 5.3
+ - 5.2
+ - 5.1.1
+ - 5.1
+ - 5.0.8
+ - 5.0.7
+ - 5.0.6
+ - 5.0.5
+ - 5.0.4
+ - 5.0.3
+ - 5.0.2
+ - 5.0.1
+ - 5.0.0
+ - 4.3.17
+ - 4.3.16
+ - 4.3.15
+ - 4.3.14
+ - 4.3.13
+ - 4.3.12
+ - 4.3.11
+ container:
+ image: ghcr.io/zsh-users/zsh:${{ matrix.version }}
+ steps:
+ - uses: actions/checkout@v4
+ - run: install_packages bsdmainutils make procps
+ - run: make test
+
+ notify:
+ runs-on: ubuntu-latest
+ needs: test
+ if: failure() && (github.repository_owner == 'zsh-users')
+ steps:
+ -
+ name: Notify IRC
+ uses: Gottox/irc-message-action@v2
+ with:
+ channel: '#zsh-syntax-highlighting'
+ nickname: zsyh-gh-bot
+ message: '${{ github.ref }} failed tests: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 4ee2765..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-language: generic
-sudo: required
-
-env:
- - ZSH=master
- - ZSH=5.8
- - ZSH=5.7.1
- - ZSH=5.7
- - ZSH=5.6.2
- - ZSH=5.6.1
- - ZSH=5.6
- - ZSH=5.5.1
- - ZSH=5.5
- - ZSH=5.4.2
- - ZSH=5.4.1
- - ZSH=5.4
- - ZSH=5.3.1
- - ZSH=5.3
- - ZSH=5.2
- - ZSH=5.1.1
- - ZSH=5.1
- - ZSH=5.0.8
- - ZSH=5.0.7
- - ZSH=5.0.6
- - ZSH=5.0.5
- - ZSH=5.0.4
- - ZSH=5.0.3
- - ZSH=5.0.2
- - ZSH=5.0.1
- - ZSH=5.0.0
- - ZSH=4.3.17
- - ZSH=4.3.16
- - ZSH=4.3.15
- - ZSH=4.3.14
- - ZSH=4.3.13
- - ZSH=4.3.12
- - ZSH=4.3.11
-
-script: docker run -v $PWD:/work -w /work zshusers/zsh:${ZSH} /bin/sh -c 'install_packages make procps bsdmainutils && make test'
-
-notifications:
- webhooks:
- urls:
- - https://webhooks.gitter.im/e/367e241cdea60cb2070b
- on_success: change
- on_failure: always
- on_start: never
- irc:
- channels:
- - "chat.freenode.net#zsh-syntax-highlighting"
- on_success: change
- on_failure: always
- on_start: never
- use_notice: true
- template:
- - "%{repository}/%{branch}#%{build_number}: %{message} Changes : %{compare_url} | Build : %{build_url}"
diff --git a/.version b/.version
index 41c20b3..d182dc9 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-0.8.0-alpha1-pre-redrawhook
+0.8.1-dev
diff --git a/HACKING.md b/HACKING.md
index 6fd195c..ddd39a4 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -95,5 +95,5 @@ zstyle ':completion:*:*:*:*:globbed-files' ignored-patterns {'*/',}zsh-syntax-hi
IRC channel
-----------
-We're on #zsh-syntax-highlighting on freenode.
+We're on #zsh-syntax-highlighting on Libera.Chat.
diff --git a/INSTALL.md b/INSTALL.md
index fc0f752..2e1286d 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -3,31 +3,67 @@ How to install
### Using packages
+First, install the package:
+
* Arch Linux: [community/zsh-syntax-highlighting][arch-package] / [AUR/zsh-syntax-highlighting-git][AUR-package]
* Debian: `zsh-syntax-highlighting` package [in `stretch`][debian-package] (or in [OBS repository][obs-repository])
* Fedora: [zsh-syntax-highlighting package][fedora-package-alt] in Fedora 24+ (or in [OBS repository][obs-repository])
* FreeBSD: `pkg install zsh-syntax-highlighting` (port name: [`shells/zsh-syntax-highlighting`][freebsd-port])
-* Gentoo: [mv overlay][gentoo-overlay]
-* Mac OS X / Homebrew: [brew install zsh-syntax-highlighting][brew-package]
-* Ubuntu: `zsh-syntax-highlighting` package [in Xenial][ubuntu-package] (or in [OBS repository][obs-repository])
-* RHEL / CentOS / Scientific Linux: `zsh-syntax-highlighting` package in [OBS repository][obs-repository]
+* Gentoo: [app-shells/zsh-syntax-highlighting][gentoo-repository]
+* Mac OS X / Homebrew: `brew install zsh-syntax-highlighting` ([formula][brew-package])
+* NetBSD: `pkg_add zsh-syntax-highlighting` (port name: [`shells/zsh-syntax-highlighting`][netbsd-port])
+* OpenBSD: `pkg_add zsh-syntax-highlighting` (port name: [`shells/zsh-syntax-highlighting`][openbsd-port])
* openSUSE / SLE: `zsh-syntax-highlighting` package in [OBS repository][obs-repository]
+* RHEL / CentOS / Scientific Linux: `zsh-syntax-highlighting` package in [OBS repository][obs-repository]
+* Ubuntu: `zsh-syntax-highlighting` package [in Xenial][ubuntu-package] (or in [OBS repository][obs-repository])
* Void Linux: `zsh-syntax-highlighting package` [in XBPS][void-package]
[arch-package]: https://www.archlinux.org/packages/zsh-syntax-highlighting
[AUR-package]: https://aur.archlinux.org/packages/zsh-syntax-highlighting-git
+[brew-package]: https://github.com/Homebrew/homebrew-core/blob/master/Formula/z/zsh-syntax-highlighting.rb
[debian-package]: https://packages.debian.org/zsh-syntax-highlighting
-[freebsd-port]: http://www.freshports.org/textproc/zsh-syntax-highlighting/
-[gentoo-overlay]: http://gpo.zugaina.org/app-shells/zsh-syntax-highlighting
-[brew-package]: https://github.com/Homebrew/homebrew-core/blob/master/Formula/zsh-syntax-highlighting.rb
-[ubuntu-package]: https://launchpad.net/ubuntu/+source/zsh-syntax-highlighting
[fedora-package]: https://apps.fedoraproject.org/packages/zsh-syntax-highlighting
[fedora-package-alt]: https://bodhi.fedoraproject.org/updates/?packages=zsh-syntax-highlighting
+[freebsd-port]: https://www.freshports.org/textproc/zsh-syntax-highlighting/
+[gentoo-repository]: https://packages.gentoo.org/packages/app-shells/zsh-syntax-highlighting
+[netbsd-port]: http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/shells/zsh-syntax-highlighting/
[obs-repository]: https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-syntax-highlighting&package=zsh-syntax-highlighting
+[openbsd-port]: https://cvsweb.openbsd.org/ports/shells/zsh-syntax-highlighting/
+[ubuntu-package]: https://launchpad.net/ubuntu/+source/zsh-syntax-highlighting
[void-package]: https://github.com/void-linux/void-packages/tree/master/srcpkgs/zsh-syntax-highlighting
See also [repology's cross-distro index](https://repology.org/metapackage/zsh-syntax-highlighting/versions)
+Second, enable zsh-syntax-highlighting by sourcing the script. Running this command on the terminal will add the source line to the end of your .zshrc:
+
+* On most Linux distributions (except perhaps NixOS):
+
+ ```zsh
+ echo "source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc
+ ```
+
+* NetBSD and OpenBSD:
+
+ ```zsh
+ echo "source /usr/local/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc
+ ```
+
+* Mac OS X / Homebrew:
+
+ ```zsh
+ echo "source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc
+ ```
+
+Then restart zsh (such as by opening a new instance of your terminal emulator).
+
+ Alternatively, add the `source` command manually **at the end** of your `.zshrc`:
+
+* On most Linux distributions (except perhaps NixOS):
+`source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh`
+* NetBSD and OpenBSD:
+`source /usr/local/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh`
+
+Then restart zsh.
### In your ~/.zshrc
@@ -71,6 +107,12 @@ This list is incomplete as there are too many
Add `antigen bundle zsh-users/zsh-syntax-highlighting` as the last bundle in
your `.zshrc`.
+#### [Fig](https://fig.io)
+
+Click the `Install Plugin` button on the [Fig plugin page][fig-plugin].
+
+[fig-plugin]: https://fig.io/plugins/other/zsh-syntax-highlighting
+
#### [Oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh)
1. Clone this repository in oh-my-zsh's plugins directory:
@@ -98,15 +140,15 @@ Zsh-syntax-highlighting is included with Prezto. See the
Add `zgen load zsh-users/zsh-syntax-highlighting` to the end of your `.zshrc`.
+#### [zinit](https://github.com/zdharma-continuum/zinit)
+
+Add `zinit light zsh-users/zsh-syntax-highlighting` to the end of your
+`.zshrc`.
+
#### [zplug](https://github.com/zplug/zplug)
Add `zplug "zsh-users/zsh-syntax-highlighting", defer:2` to your `.zshrc`.
-#### [zplugin](https://github.com/psprint/zplugin)
-
-Add `zplugin load zsh-users/zsh-syntax-highlighting` to the end of your
-`.zshrc`.
-
### System-wide installation
diff --git a/README.md b/README.md
index 4951dba..4768b3d 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
-zsh-syntax-highlighting [![Build Status][build-status-image]][build-status-travis]
+zsh-syntax-highlighting [![Build Status][build-status-image]][build-status]
=======================
**[Fish shell][fish]-like syntax highlighting for [Zsh][zsh].**
*Requirements: zsh 4.3.11+.*
-[fish]: http://www.fishshell.com/
-[zsh]: http://www.zsh.org/
+[fish]: https://fishshell.com/
+[zsh]: https://www.zsh.org/
This package provides syntax highlighting for the shell zsh. It enables
highlighting of commands whilst they are typed at a zsh prompt into an
@@ -44,11 +44,23 @@ FAQ
### Why must `zsh-syntax-highlighting.zsh` be sourced at the end of the `.zshrc` file?
-`zsh-syntax-highlighting.zsh` wraps ZLE widgets. It must be sourced after all
-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
+zsh-syntax-highlighting works by hooking into the Zsh Line Editor (ZLE) and
+computing syntax highlighting for the command-line buffer as it stands at the
+time z-sy-h's hook is invoked.
+
+In zsh 5.2 and older,
+`zsh-syntax-highlighting.zsh` hooks into ZLE by wrapping ZLE widgets. It must
+be sourced after all custom widgets have been created (i.e., after all `zle -N`
+calls and after running `compinit`) in order to be able to wrap all of them.
+Widgets created after z-sy-h is sourced will work, but will not update the
syntax highlighting.
+In zsh newer than 5.8 (not including 5.8 itself),
+zsh-syntax-highlighting uses the `add-zle-hook-widget` facility to install
+a `zle-line-pre-redraw` hook. Hooks are run in order of registration,
+therefore, z-sy-h must be sourced (and register its hook) after anything else
+that adds hooks that modify the command-line buffer.
+
### Does syntax highlighting work during incremental history search?
Highlighting the command line during an incremental history search (by default bound to
@@ -61,7 +73,7 @@ enough information to allow computing the highlighting correctly.)
See issues [#288][i288] and [#415][i415] for details.
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
[i288]: https://github.com/zsh-users/zsh-syntax-highlighting/pull/288
[i415]: https://github.com/zsh-users/zsh-syntax-highlighting/pull/415
@@ -81,5 +93,5 @@ Syntax highlighting is done by pluggable highlighter scripts. See the
[documentation on highlighters](docs/highlighters.md) for details and
configuration settings.
-[build-status-image]: https://travis-ci.org/zsh-users/zsh-syntax-highlighting.svg?branch=master
-[build-status-travis]: https://travis-ci.org/zsh-users/zsh-syntax-highlighting
+[build-status]: https://github.com/zsh-users/zsh-syntax-highlighting/actions
+[build-status-image]: https://github.com/zsh-users/zsh-syntax-highlighting/workflows/Tests/badge.svg
diff --git a/changelog.md b/changelog.md
index 96ad507..8ee5088 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,96 @@
+# Changes in HEAD
+
+
+- Highlight `&>` `>&|` `>&!` `&>|` and `&>!` as redirection.
+ [#942]
+
+
+# Changes in 0.8.0
+
+This is a stable bugfix and feature release. Major new features and changes include:
+
+
+## Changes fixed as part of the switch to zle-line-pre-redraw
+
+The changes in this section were fixed by switching to a `zle-line-pre-redraw`-based
+implementation.
+
+Note: The new implementation will only be used on future zsh releases,
+numbered 5.8.1.1 and newer, due to interoperability issues with other plugins
+(issues #418 and #579). The underlying zsh feature has been available since
+zsh 5.3.
+
+Whilst under development, the new implementation was known as the
+"feature/redrawhook" topic branch.
+
+- Fixed: Highlighting not triggered after popping a buffer from the buffer stack
+ (using the `push-line` widget, default binding: `M-q`)
+ [#40]
+
+- Fixed: Invoking completion when there were no matches removed highlighting
+ [#90, #470]
+
+- Fixed: Two successive deletes followed by a yank only yanked the latest
+ delete, rather than both of them
+ [#150, #151, #160; cf. #183]
+
+- Presumed fixed: Completing `$(xsel)` results in an error message from `xsel`,
+ with pre-2017 versions of `xsel`. (For 2017 vintage and newer, see the issue
+ for details.)
+ [#154]
+
+- Fixed: When the standard `bracketed-paste-magic` widget is in use, pastes were slow
+ [#295]
+
+- Fixed: No way to prevent a widget from being wrapped
+ [#324]
+
+- Fixed: No highlighting while cycling menu completion
+ [#375]
+
+- Fixed: Does not coexist with the `IGNORE_EOF` option
+ [#377]
+
+- Fixed: The `undefined-key` widget was wrapped
+ [#421]
+
+- Fixed: Does not coexist with the standard `surround` family of widgets
+ [#520]
+
+- Fixed: First completed filename doesn't get `path` highlighting
+ [#632]
+
+
+## Other changes
+
+- Add issue #712 to the previous release's changelog (hereinafter).
+
+- Fix highlighting when using an alias twice inside another alias
+ [#769, #775]
+
+- Remove lint warning for `env` followed by a pipe
+ [#797]
+
+- Recognize `proxychains` as a precommand
+ [#814, #914]
+
+- Honor shwordsplit when expanding parameters
+ [#687, #818]
+
+- Skip highlighting when keys are still pending in more cases
+ [#835]
+
+- Recognize `grc` as a precommand
+
+- Recognize `torsocks` and `torift` as precommands
+ [#898]
+
+- Recognize `cpulimit` as a precommand
+ [#897]
+
+- Recognize `ktrace` as a precommand
+
+
# Changes in 0.8.0-alpha1-pre-redrawhook
## Notice about an improbable-but-not-impossible forward incompatibility
@@ -16,6 +109,25 @@ added to zsh at z-sy-h's initiative. The new feature is used in the fix
to issue #418.
+## Incompatible changes:
+
+- An unsuccessful completion (a ⮀ Tab press that doesn't change the
+ command line) no longer causes highlighting to be lost. Visual feedback can
+ alternatively be achieved by setting the `format` zstyle under the `warnings`
+ tag, for example,
+
+ zstyle ':completion:*:warnings' format '%F{red}No matches%f'
+
+ Refer to the [description of the `format` style in `zshcompsys(1)`]
+ [zshcompsys-Standard-Styles-format].
+
+ (#90, part of #245 (feature/redrawhook))
+
+[zshcompsys-Standard-Styles]: https://zsh.sourceforge.io/Doc/Release/Completion-System.html#Standard-Styles
+[zshcompsys-Standard-Styles-format]: https://zsh.sourceforge.io/Doc/Release/Completion-System.html#index-format_002c-completion-style
+
+
+
## Other changes:
- Document `$ZSH_HIGHLIGHT_MAXLENGTH`.
@@ -90,6 +202,8 @@ to issue #418.
- Recognize `env` as a precommand (e.g., `env FOO=bar ls`)
+- Recognize `ionice` as a precommand
+
- Recognize `strace` as a precommand
- Fix an error message on stderr before every prompt when the `WARN_NESTED_VAR` zsh option is set:
@@ -114,6 +228,9 @@ to issue #418.
- Improve performance of the `brackets` highlighter.
+- Fix highlighting of pre-command redirections (e.g., the `$fn` in `<$fn cat`)
+ [#712]
+
# Changes in version 0.7.1
@@ -208,7 +325,7 @@ This is a stable release, featuring bugfixes and minor improvements.
- The `isearch` and `suffix` [`$zle_highlight` settings][zshzle-Character-Highlighting].
(79e4d3d12405, 15db71abd0cc, b56ee542d619; requires zsh 5.3 for `$ISEARCHMATCH_ACTIVE` / `$SUFFIX_ACTIVE` support)
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
- Possible history expansions in double-quoted strings.
(76ea9e1df316)
@@ -654,7 +771,7 @@ in this area.
## Developer-visible changes:
-- Test harness converted to [TAP](http://testanything.org/tap-specification.html) format
+- Test harness converted to [TAP](https://testanything.org/tap-specification.html) format
(d99aa58aaaef, et seq)
- Run each test in a separate subprocess, isolating them from each other
diff --git a/docs/highlighters.md b/docs/highlighters.md
index bb72e54..fb64c3a 100644
--- a/docs/highlighters.md
+++ b/docs/highlighters.md
@@ -3,19 +3,21 @@ zsh-syntax-highlighting / highlighters
Syntax highlighting is done by pluggable highlighters:
-* `main` - the base highlighter, and the only one [active by default][1].
-* `brackets` - [matches brackets][2] and parenthesis.
-* `pattern` - matches [user-defined patterns][3].
-* `cursor` - matches [the cursor position][4].
-* `root` - highlights the whole command line [if the current user is root][5].
-* `line` - applied to [the whole command line][6].
+* `main` - the base highlighter, and the only one [active by default][main].
+* `brackets` - [matches brackets][brackets] and parenthesis.
+* `pattern` - matches [user-defined patterns][pattern].
+* `regexp` - matches [user-defined regular expressions][regexp].
+* `cursor` - matches [the cursor position][cursor].
+* `root` - highlights the whole command line [if the current user is root][root].
+* `line` - applied to [the whole command line][line].
-[1]: highlighters/main.md
-[2]: highlighters/brackets.md
-[3]: highlighters/pattern.md
-[4]: highlighters/cursor.md
-[5]: highlighters/root.md
-[6]: highlighters/line.md
+[main]: highlighters/main.md
+[brackets]: highlighters/brackets.md
+[pattern]: highlighters/pattern.md
+[regexp]: highlighters/regexp.md
+[cursor]: highlighters/cursor.md
+[root]: highlighters/root.md
+[line]: highlighters/line.md
Highlighter-independent settings
@@ -25,10 +27,10 @@ By default, all command lines are highlighted. However, it is possible to
prevent command lines longer than a fixed number of characters from being
highlighted by setting the variable `${ZSH_HIGHLIGHT_MAXLENGTH}` to the maximum
length (in characters) of command lines to be highlighter. This is useful when
-editing very long comand lines (for example, with the [`fned`][fned] utility
+editing very long command lines (for example, with the [`fned`][fned] utility
function). Example:
-[fned]: http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#index-zed
+[fned]: https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#index-zed
```zsh
ZSH_HIGHLIGHT_MAXLENGTH=512
@@ -38,16 +40,14 @@ ZSH_HIGHLIGHT_MAXLENGTH=512
How to activate highlighters
----------------------------
-To activate an highlighter, add it to the `ZSH_HIGHLIGHT_HIGHLIGHTERS` array in
-`~/.zshrc`, for example:
+To activate an highlighter, add it to the `ZSH_HIGHLIGHT_HIGHLIGHTERS` array.
+By default `ZSH_HIGHLIGHT_HIGHLIGHTERS` is `(main)`. For example to activate
+`brackets`, `pattern`, and `cursor` highlighters, in `~/.zshrc` do:
```zsh
-ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets pattern cursor)
+ZSH_HIGHLIGHT_HIGHLIGHTERS+=(brackets pattern cursor)
```
-By default, `$ZSH_HIGHLIGHT_HIGHLIGHTERS` is unset and only the `main`
-highlighter is active.
-
How to tweak highlighters
-------------------------
@@ -59,7 +59,7 @@ same as the syntax of "types of highlighting" of the zsh builtin
`$zle_highlight` array, which is documented in [the `zshzle(1)` manual
page][zshzle-Character-Highlighting].
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
Some highlighters support additional configuration parameters; see each
highlighter's documentation for details and examples.
diff --git a/docs/highlighters/brackets.md b/docs/highlighters/brackets.md
index 8410135..0101699 100644
--- a/docs/highlighters/brackets.md
+++ b/docs/highlighters/brackets.md
@@ -28,4 +28,4 @@ The syntax for values is the same as the syntax of "types of highlighting" of
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
manual page][zshzle-Character-Highlighting].
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
diff --git a/docs/highlighters/cursor.md b/docs/highlighters/cursor.md
index c4f22b8..3f87d42 100644
--- a/docs/highlighters/cursor.md
+++ b/docs/highlighters/cursor.md
@@ -21,4 +21,4 @@ The syntax for values is the same as the syntax of "types of highlighting" of
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
manual page][zshzle-Character-Highlighting].
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
diff --git a/docs/highlighters/line.md b/docs/highlighters/line.md
index 1081fe1..f76639e 100644
--- a/docs/highlighters/line.md
+++ b/docs/highlighters/line.md
@@ -21,4 +21,4 @@ The syntax for values is the same as the syntax of "types of highlighting" of
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
manual page][zshzle-Character-Highlighting].
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
diff --git a/docs/highlighters/main.md b/docs/highlighters/main.md
index cc6186b..4a27653 100644
--- a/docs/highlighters/main.md
+++ b/docs/highlighters/main.md
@@ -116,6 +116,6 @@ of that (new) kind will be highlighted by the style `arg0_$kind`,
where `$kind` is the output of `type -w` on the new kind of command word. If that
style is not defined, then the style `arg0` will be used instead.
-[zshmisc-Simple-Commands-And-Pipelines]: http://zsh.sourceforge.net/Doc/Release/Shell-Grammar.html#Simple-Commands-_0026-Pipelines
+[zshmisc-Simple-Commands-And-Pipelines]: https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#Simple-Commands-_0026-Pipelines
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
diff --git a/docs/highlighters/pattern.md b/docs/highlighters/pattern.md
index e67d79f..ecaa6a7 100644
--- a/docs/highlighters/pattern.md
+++ b/docs/highlighters/pattern.md
@@ -21,4 +21,4 @@ The syntax for values is the same as the syntax of "types of highlighting" of
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
manual page][zshzle-Character-Highlighting].
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
diff --git a/docs/highlighters/regexp.md b/docs/highlighters/regexp.md
index 5c8a89e..8c711a3 100644
--- a/docs/highlighters/regexp.md
+++ b/docs/highlighters/regexp.md
@@ -12,11 +12,44 @@ To use this highlighter, associate regular expressions with styles in the
```zsh
typeset -A ZSH_HIGHLIGHT_REGEXP
-ZSH_HIGHLIGHT_REGEXP+=('\bsudo\b' fg=123,bold)
+ZSH_HIGHLIGHT_REGEXP+=('^rm .*' fg=red,bold)
```
-This will highlight "sudo" only as a complete word, i.e., "sudo cmd", but not
-"sudoedit"
+This will highlight lines that start with a call to the `rm` command.
+
+The regular expressions flavour used is [PCRE][pcresyntax] when the
+`RE_MATCH_PCRE` option is set and POSIX Extended Regular Expressions (ERE),
+as implemented by the platform's C library, otherwise. For details on the
+latter, see [the `zsh/regex` module's documentation][MAN_ZSH_REGEX] and the
+`regcomp(3)` and `re_format(7)` manual pages on your system.
+
+For instance, to highlight `sudo` only as a complete word, i.e., `sudo cmd`,
+but not `sudoedit`, one might use:
+
+* When the `RE_MATCH_PCRE` is set:
+
+ ```zsh
+ typeset -A ZSH_HIGHLIGHT_REGEXP
+ ZSH_HIGHLIGHT_REGEXP+=('\bsudo\b' fg=123,bold)
+ ```
+
+* When the `RE_MATCH_PCRE` is unset, on platforms with GNU `libc` (e.g., many GNU/Linux distributions):
+
+ ```zsh
+ typeset -A ZSH_HIGHLIGHT_REGEXP
+ ZSH_HIGHLIGHT_REGEXP+=('\' fg=123,bold)
+ ```
+
+* When the `RE_MATCH_PCRE` is unset, on BSD-based platforms (e.g., macOS):
+
+ ```zsh
+ typeset -A ZSH_HIGHLIGHT_REGEXP
+ ZSH_HIGHLIGHT_REGEXP+=('[[:<:]]sudo[[:>:]]' fg=123,bold)
+ ```
+
+Note, however, that PCRE and POSIX ERE have a large common subset:
+for instance, the regular expressions `[abc]`, `a*`, and `(a|b)` have the same
+meaning in both flavours.
The syntax for values is the same as the syntax of "types of highlighting" of
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
@@ -25,6 +58,8 @@ manual page][zshzle-Character-Highlighting].
See also: [regular expressions tutorial][perlretut], zsh regexp operator `=~`
in [the `zshmisc(1)` manual page][zshmisc-Conditional-Expressions]
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
-[perlretut]: http://perldoc.perl.org/perlretut.html
-[zshmisc-Conditional-Expressions]: http://zsh.sourceforge.net/Doc/Release/Conditional-Expressions.html#Conditional-Expressions
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[perlretut]: https://perldoc.perl.org/perlretut
+[zshmisc-Conditional-Expressions]: https://zsh.sourceforge.io/Doc/Release/Conditional-Expressions.html#Conditional-Expressions
+[MAN_ZSH_REGEX]: https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-zsh_002fregex-Module
+[pcresyntax]: https://www.pcre.org/original/doc/html/pcresyntax.html
diff --git a/docs/highlighters/root.md b/docs/highlighters/root.md
index d120d20..8197e4b 100644
--- a/docs/highlighters/root.md
+++ b/docs/highlighters/root.md
@@ -22,4 +22,4 @@ The syntax for values is the same as the syntax of "types of highlighting" of
the zsh builtin `$zle_highlight` array, which is documented in [the `zshzle(1)`
manual page][zshzle-Character-Highlighting].
-[zshzle-Character-Highlighting]: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
+[zshzle-Character-Highlighting]: https://zsh.sourceforge.io/Doc/Release/Zsh-Line-Editor.html#Character-Highlighting
diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh
index e59c61c..3ec96d9 100644
--- a/highlighters/main/main-highlighter.zsh
+++ b/highlighters/main/main-highlighter.zsh
@@ -76,7 +76,7 @@ _zsh_highlight_main_add_region_highlight() {
integer start=$1 end=$2
shift 2
- if (( in_alias )); then
+ if (( $#in_alias )); then
[[ $1 == unknown-token ]] && alias_style=unknown-token
return
fi
@@ -254,10 +254,9 @@ _zsh_highlight_main__is_runnable() {
_zsh_highlight_main__is_redirection() {
# A redirection operator token:
# - starts with an optional single-digit number;
- # - then, has a '<' or '>' character;
- # - is not a process substitution [<(...) or >(...)].
- # - is not a numeric glob <->
- [[ $1 == (<0-9>|)(\<|\>)* ]] && [[ $1 != (\<|\>)$'\x28'* ]] && [[ $1 != *'<'*'-'*'>'* ]]
+ # - is one of the tokens listed in zshmisc(1)
+ # - however (z) normalizes ! to |
+ [[ ${1#[0-9]} == (\<|\<\>|(\>|\>\>)(|\|)|\<\<(|-)|\<\<\<|\<\&|\&\<|(\>|\>\>)\&(|\|)|\&(\>|\>\>)(|\||\!)) ]]
}
# Resolve alias.
@@ -349,6 +348,7 @@ _zsh_highlight_highlighter_main_paint()
'noglob' ''
# 'time' and 'nocorrect' shouldn't be added here; they're reserved words, not precommands.
+ # miscellaneous commands
'doas' aCu:Lns # as of OpenBSD's doas(1) dated September 4, 2016
'nice' n: # as of current POSIX spec
'pkexec' '' # doesn't take short options; immune to #121 because it's usually not passed --option flags
@@ -362,21 +362,21 @@ _zsh_highlight_highlighter_main_paint()
'env' u:i
'ionice' cn:t:pPu # util-linux 2.33.1-0.1
'strace' IbeaosXPpEuOS:ACdfhikqrtTvVxyDc # strace 4.26-0.2
-
- # As of OpenSSH 8.1p1
- 'ssh-agent' aEPt:csDd:k
- # suckless-tools v44
- # Argumentless flags that can't be followed by a command: -v
- 'tabbed' gnprtTuU:cdfhs
-
- # moreutils 0.62-1
- 'chronic' :ev
- 'ifne' :n
-
+ 'proxychains' f:q # proxychains 4.4.0
+ 'torsocks' idq:upaP # Torsocks 2.3.0
+ 'torify' idq:upaP # Torsocks 2.3.0
+ 'ssh-agent' aEPt:csDd:k # As of OpenSSH 8.1p1
+ 'tabbed' gnprtTuU:cdfhs:v # suckless-tools v44
+ 'chronic' :ev # moreutils 0.62-1
+ 'ifne' :n # moreutils 0.62-1
+ 'grc' :se # grc - a "generic colouriser" (that's their spelling, not mine)
+ 'cpulimit' elp:ivz # cpulimit 0.2
+ 'ktrace' fgpt:aBCcdiT
)
# Commands that would need to skip one positional argument:
# flock
# ssh
+ # _wanted (skip two)
if [[ $zsyh_user_options[ignorebraces] == on || ${zsyh_user_options[ignoreclosebraces]:-off} == on ]]; then
local right_brace_is_recognised_everywhere=false
@@ -476,7 +476,11 @@ _zsh_highlight_main_highlighter__try_expand_parameter()
;;
(*)
# scalar, presumably
- words=( ${(P)MATCH} )
+ if [[ $zsyh_user_options[shwordsplit] == on ]]; then
+ words=( ${(P)=MATCH} )
+ else
+ words=( ${(P)MATCH} )
+ fi
;;
esac
reply=( "${words[@]}" )
@@ -498,17 +502,18 @@ _zsh_highlight_main_highlighter__try_expand_parameter()
_zsh_highlight_main_highlighter_highlight_list()
{
integer start_pos end_pos=0 buf_offset=$1 has_end=$3
- # alias_style is the style to apply to an alias once in_alias=0
+ # alias_style is the style to apply to an alias once $#in_alias == 0
# Usually 'alias' but set to 'unknown-token' if any word expanded from
# the alias would be highlighted as unknown-token
# param_style is analogous for parameter expansions
local alias_style param_style last_arg arg buf=$4 highlight_glob=true saw_assignment=false style
local in_array_assignment=false # true between 'a=(' and the matching ')'
- # in_alias is equal to the number of shifts needed until arg=args[1] pops an
- # arg from BUFFER and not added by an alias.
+ # in_alias is an array of integers with each element equal to the number
+ # of shifts needed until arg=args[1] pops an arg from the next level up
+ # alias or from BUFFER.
# in_param is analogous for parameter expansions
- integer in_alias=0 in_param=0 len=$#buf
- local -a match mbegin mend list_highlights
+ integer in_param=0 len=$#buf
+ local -a in_alias match mbegin mend list_highlights
# seen_alias is a map of aliases already seen to avoid loops like alias a=b b=a
local -A seen_alias
# Pattern for parameter names
@@ -596,12 +601,23 @@ _zsh_highlight_main_highlighter_highlight_list()
last_arg=$arg
arg=$args[1]
shift args
- if (( in_alias )); then
- (( in_alias-- ))
- if (( in_alias == 0 )); then
+ if (( $#in_alias )); then
+ (( in_alias[1]-- ))
+ # Remove leading 0 entries
+ in_alias=($in_alias[$in_alias[(i)<1->],-1])
+ if (( $#in_alias == 0 )); then
seen_alias=()
# start_pos and end_pos are of the alias (previous $arg) here
_zsh_highlight_main_add_region_highlight $start_pos $end_pos $alias_style
+ else
+ # We can't unset keys that contain special characters (] \ and some others).
+ # More details: https://www.zsh.org/workers/43269
+ (){
+ local alias_name
+ for alias_name in ${(k)seen_alias[(R)<$#in_alias->]}; do
+ seen_alias=("${(@kv)seen_alias[(I)^$alias_name]}")
+ done
+ }
fi
fi
if (( in_param )); then
@@ -637,9 +653,9 @@ _zsh_highlight_main_highlighter_highlight_list()
fi
fi
- if (( in_alias == 0 && in_param == 0 )); then
+ if (( $#in_alias == 0 && in_param == 0 )); then
# Compute the new $start_pos and $end_pos, skipping over whitespace in $buf.
- [[ "$proc_buf" = (#b)(#s)(([ $'\t']|[\\]$'\n')#)(?|)* ]]
+ [[ "$proc_buf" = (#b)(#s)(''([ $'\t']|[\\]$'\n')#)(?|)* ]]
# The first, outer parenthesis
integer offset="${#match[1]}"
(( start_pos = end_pos + offset ))
@@ -693,11 +709,10 @@ _zsh_highlight_main_highlighter_highlight_list()
if [[ $res == "alias" ]]; then
# Mark insane aliases as unknown-token (cf. #263).
if [[ $arg == ?*=* ]]; then
- (( in_alias == 0 )) && in_alias=1
_zsh_highlight_main_add_region_highlight $start_pos $end_pos unknown-token
continue
fi
- seen_alias[$arg]=1
+ seen_alias[$arg]=$#in_alias
_zsh_highlight_main__resolve_alias $arg
local -a alias_args
# Elision is desired in case alias x=''
@@ -707,15 +722,15 @@ _zsh_highlight_main_highlighter_highlight_list()
alias_args=(${(z)REPLY})
fi
args=( $alias_args $args )
- if (( in_alias == 0 )); then
+ if (( $#in_alias == 0 )); then
alias_style=alias
- # Add one because we will in_alias-- on the next loop iteration so
- # this iteration should be considered in in_alias as well
- (( in_alias += $#alias_args + 1 ))
else
- # This arg is already included in the count, so no need to + 1.
- (( in_alias += $#alias_args ))
+ # Transfer the count of this arg to the new element about to be appended.
+ (( in_alias[1]-- ))
fi
+ # Add one because we will in_alias[1]-- on the next loop iteration so
+ # this iteration should be considered in in_alias as well
+ in_alias=( $(($#alias_args + 1)) $in_alias )
(( in_redirection++ )) # Stall this arg
continue
else
@@ -728,7 +743,7 @@ _zsh_highlight_main_highlighter_highlight_list()
# Analyse the current word.
if _zsh_highlight_main__is_redirection $arg ; then
if (( in_redirection == 1 )); then
- # Two consecuive redirection operators is an error.
+ # Two consecutive redirection operators is an error.
_zsh_highlight_main_add_region_highlight $start_pos $end_pos unknown-token
else
in_redirection=2
@@ -854,7 +869,7 @@ _zsh_highlight_main_highlighter_highlight_list()
style=commandseparator
elif [[ $this_word == *':start:'* ]] && [[ $arg == $'\n' ]]; then
style=commandseparator
- elif [[ $this_word == *':start:'* ]] && [[ $arg == ';' ]] && (( in_alias )); then
+ elif [[ $this_word == *':start:'* ]] && [[ $arg == ';' ]] && (( $#in_alias )); then
style=commandseparator
else
# Empty commands (semicolon follows nothing) are valid syntax.
@@ -879,6 +894,14 @@ _zsh_highlight_main_highlighter_highlight_list()
next_word=':start:'
highlight_glob=true
saw_assignment=false
+ (){
+ local alias_name
+ for alias_name in ${(k)seen_alias[(R)<$#in_alias->]}; do
+ # We can't unset keys that contain special characters (] \ and some others).
+ # More details: https://www.zsh.org/workers/43269
+ seen_alias=("${(@kv)seen_alias[(I)^$alias_name]}")
+ done
+ }
if [[ $arg != '|' && $arg != '|&' ]]; then
next_word+=':start_of_pipeline:'
fi
@@ -902,8 +925,8 @@ _zsh_highlight_main_highlighter_highlight_list()
next_word=${next_word//:regular:/}
next_word+=':sudo_opt:'
next_word+=':start:'
- if [[ $arg == 'exec' ]]; then
- # To allow "exec 2>&1;" where there's no command word
+ if [[ $arg == 'exec' || $arg == 'env' ]]; then
+ # To allow "exec 2>&1;" and "env | grep" where there's no command word
next_word+=':regular:'
fi
else
@@ -1146,7 +1169,7 @@ _zsh_highlight_main_highlighter_highlight_list()
fi
_zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
done
- (( in_alias == 1 )) && in_alias=0 _zsh_highlight_main_add_region_highlight $start_pos $end_pos $alias_style
+ (( $#in_alias )) && in_alias=() _zsh_highlight_main_add_region_highlight $start_pos $end_pos $alias_style
(( in_param == 1 )) && in_param=0 _zsh_highlight_main_add_region_highlight $start_pos $end_pos $param_style
[[ "$proc_buf" = (#b)(#s)(([[:space:]]|\\$'\n')#) ]]
REPLY=$(( end_pos + ${#match[1]} - 1 ))
@@ -1257,7 +1280,7 @@ _zsh_highlight_main_highlighter_check_path()
# If this word ends the buffer, check if it's the prefix of a valid path.
if (( has_end && (len == end_pos) )) &&
- (( ! in_alias )) &&
+ (( ! $#in_alias )) &&
[[ $WIDGET != zle-line-finish ]]; then
# TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
local -a tmp
diff --git a/highlighters/main/test-data/alias-brackets.zsh b/highlighters/main/test-data/alias-brackets.zsh
new file mode 100644
index 0000000..ede6c9a
--- /dev/null
+++ b/highlighters/main/test-data/alias-brackets.zsh
@@ -0,0 +1,41 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# Copyright (c) 2021 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
+# -------------------------------------------------------------------------------------------------
+
+# Have to use cat here as it must be a command that exists.
+# Otherwise, the test would fail with the first token being recognized
+# as an "unknown-token".
+alias ]=cat
+
+BUFFER='] /'
+
+expected_region_highlight=(
+ '1 1 alias' # ]
+ '3 3 path' # /
+)
diff --git a/highlighters/main/test-data/alias-reuse1.zsh b/highlighters/main/test-data/alias-reuse1.zsh
new file mode 100644
index 0000000..1fd61a0
--- /dev/null
+++ b/highlighters/main/test-data/alias-reuse1.zsh
@@ -0,0 +1,39 @@
+#!/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
+# -------------------------------------------------------------------------------------------------
+
+alias a=: b='a | a'
+
+BUFFER='b | b'
+
+expected_region_highlight=(
+ '1 1 alias' # b
+ '3 3 commandseparator' # |
+ '5 5 alias' # b
+)
diff --git a/highlighters/main/test-data/alias-reuse2.zsh b/highlighters/main/test-data/alias-reuse2.zsh
new file mode 100644
index 0000000..37251fb
--- /dev/null
+++ b/highlighters/main/test-data/alias-reuse2.zsh
@@ -0,0 +1,39 @@
+#!/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
+# -------------------------------------------------------------------------------------------------
+
+alias a=: b='a && a'
+
+BUFFER='b && b'
+
+expected_region_highlight=(
+ '1 1 alias' # b
+ '3 4 commandseparator' # &&
+ '6 6 alias' # b
+)
diff --git a/highlighters/main/test-data/alias-reuse3.zsh b/highlighters/main/test-data/alias-reuse3.zsh
new file mode 100644
index 0000000..5d7150a
--- /dev/null
+++ b/highlighters/main/test-data/alias-reuse3.zsh
@@ -0,0 +1,39 @@
+#!/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
+# -------------------------------------------------------------------------------------------------
+
+alias a=: b='a; a'
+
+BUFFER='b; b'
+
+expected_region_highlight=(
+ '1 1 alias' # b
+ '2 2 commandseparator' # ;
+ '4 4 alias' # b
+)
diff --git a/highlighters/main/test-data/alias-reuse4.zsh b/highlighters/main/test-data/alias-reuse4.zsh
new file mode 100644
index 0000000..7ad7038
--- /dev/null
+++ b/highlighters/main/test-data/alias-reuse4.zsh
@@ -0,0 +1,42 @@
+#!/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
+# -------------------------------------------------------------------------------------------------
+
+alias a=: b='a $(a)'
+
+BUFFER='b $(b)'
+
+expected_region_highlight=(
+ '1 1 alias' # b
+ '3 6 default' # $(b)
+ '3 6 command-substitution-unquoted' # $(b)
+ '3 4 command-substitution-delimiter-unquoted' # $(
+ '5 5 alias' # b
+ '6 6 command-substitution-delimiter-unquoted' # )
+)
diff --git a/highlighters/main/test-data/alias-reuse5.zsh b/highlighters/main/test-data/alias-reuse5.zsh
new file mode 100644
index 0000000..881401b
--- /dev/null
+++ b/highlighters/main/test-data/alias-reuse5.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
+# -------------------------------------------------------------------------------------------------
+
+alias a=: b='a < <(a)'
+
+BUFFER='b < <(b)'
+
+expected_region_highlight=(
+ '1 1 alias' # b
+ '3 3 redirection' # <
+ '5 8 default' # <(b)
+ '5 8 process-substitution' # <(b)
+ '5 6 process-substitution-delimiter' # <(
+ '7 7 alias' # b
+ '8 8 process-substitution-delimiter' # )
+)
diff --git a/highlighters/main/test-data/alias-self2.zsh b/highlighters/main/test-data/alias-self2.zsh
new file mode 100644
index 0000000..fd6ae03
--- /dev/null
+++ b/highlighters/main/test-data/alias-self2.zsh
@@ -0,0 +1,37 @@
+#!/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
+# -------------------------------------------------------------------------------------------------
+
+alias cat='cat | cat'
+
+BUFFER='cat'
+
+expected_region_highlight=(
+ '1 3 alias' # cat
+)
diff --git a/highlighters/main/test-data/block-assignment-no-command.zsh b/highlighters/main/test-data/block-assignment-no-command.zsh
new file mode 100644
index 0000000..ec52c98
--- /dev/null
+++ b/highlighters/main/test-data/block-assignment-no-command.zsh
@@ -0,0 +1,38 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# Copyright (c) 2022 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=$'{ a=42 }'
+
+expected_region_highlight=(
+ '1 1 reserved-word' # {
+ '3 6 assign' # a=42
+ '5 6 default' # 42
+ '8 8 reserved word "issue #854"' # }
+)
diff --git a/highlighters/main/test-data/multiple-redirections.zsh b/highlighters/main/test-data/multiple-redirections.zsh
index 778e712..1545c1b 100644
--- a/highlighters/main/test-data/multiple-redirections.zsh
+++ b/highlighters/main/test-data/multiple-redirections.zsh
@@ -27,7 +27,7 @@
# vim: ft=zsh sw=2 ts=2 et
# -------------------------------------------------------------------------------------------------
-BUFFER='ps aux | grep java | sort | uniq | tail | head'
+BUFFER='id bob | grep java | sort | uniq | tail | head'
expected_region_highlight=(
"1 2 command" # ps
diff --git a/highlighters/main/test-data/null-exec2-printenv.zsh b/highlighters/main/test-data/null-exec2-printenv.zsh
new file mode 100644
index 0000000..59a2cef
--- /dev/null
+++ b/highlighters/main/test-data/null-exec2-printenv.zsh
@@ -0,0 +1,38 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# Copyright (c) 2021 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=$'env | grep $needle'
+
+expected_region_highlight=(
+ '1 3 precommand' # env
+ '5 5 commandseparator' # |
+ '7 10 command' # grep
+ '12 18 default' # $needle
+)
diff --git a/highlighters/main/test-data/opt-shwordsplit1.zsh b/highlighters/main/test-data/opt-shwordsplit1.zsh
index 7455785..4a7689b 100644
--- a/highlighters/main/test-data/opt-shwordsplit1.zsh
+++ b/highlighters/main/test-data/opt-shwordsplit1.zsh
@@ -36,5 +36,5 @@ ed() { command ed "$@" }
BUFFER=$'$EDITOR'
expected_region_highlight=(
- '1 7 function "issue #687"' # $EDITOR
+ '1 7 function' # $EDITOR
)
diff --git a/highlighters/main/test-data/parameter-expansion-shwordsplit.zsh b/highlighters/main/test-data/parameter-expansion-shwordsplit.zsh
new file mode 100644
index 0000000..0bf6f4c
--- /dev/null
+++ b/highlighters/main/test-data/parameter-expansion-shwordsplit.zsh
@@ -0,0 +1,38 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# Copyright (c) 2021 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
+# -------------------------------------------------------------------------------------------------
+
+setopt sh_word_split
+local foo='echo foo'
+
+BUFFER='$foo'
+
+expected_region_highlight=(
+ '1 4 builtin' # $foo
+)
diff --git a/highlighters/main/test-data/parameter-to-global-alias.zsh b/highlighters/main/test-data/parameter-to-global-alias.zsh
index 2c4b9bb..63f95da 100644
--- a/highlighters/main/test-data/parameter-to-global-alias.zsh
+++ b/highlighters/main/test-data/parameter-to-global-alias.zsh
@@ -28,8 +28,12 @@
# vim: ft=zsh sw=2 ts=2 et
# -------------------------------------------------------------------------------------------------
-alias -g x=y
-local s=x
+if type global_alias >/dev/null; then
+ skip_test="Test is written on the assumption that 'global_alias' is not a valid command name, but that assumption does not hold"
+ return 0
+fi
+alias -g global_alias=y
+local s=global_alias
BUFFER=$'$s'
diff --git a/highlighters/main/test-data/precommand-killing1.zsh b/highlighters/main/test-data/precommand-killing1.zsh
index 80d279b..7598346 100644
--- a/highlighters/main/test-data/precommand-killing1.zsh
+++ b/highlighters/main/test-data/precommand-killing1.zsh
@@ -29,11 +29,12 @@
# -------------------------------------------------------------------------------------------------
hash sudo=false
+touch foo
-BUFFER='sudo -e /etc/passwd'
+BUFFER='sudo -e ./foo'
expected_region_highlight=(
'1 4 precommand' # sudo
'6 7 single-hyphen-option' # -e
- '9 19 path' # /etc/passwd
+ '9 13 path' # ./foo
)
diff --git a/highlighters/main/test-data/redirection-all.zsh b/highlighters/main/test-data/redirection-all.zsh
new file mode 100644
index 0000000..e8ffb5d
--- /dev/null
+++ b/highlighters/main/test-data/redirection-all.zsh
@@ -0,0 +1,95 @@
+#!/usr/bin/env zsh
+# -------------------------------------------------------------------------------------------------
+# Copyright (c) 2024 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=$': foo 9<>foo >foo 9>foo >|foo >\!foo >>foo >>|foo >>\!foo <<&9 <&- >&- <&p >&p >&foo &>foo >&|foo >&\!foo &>|foo &>\!foo >>&foo &>>foo >>&|foo >>&\!foo &>>|foo &>>\!foo'
+
+expected_region_highlight=(
+ '1 1 builtin' # :
+ '3 3 redirection' # <
+ '4 6 default' # foo
+ '8 9 redirection' # 9<
+ '10 12 default' # foo
+ '14 15 redirection' # <>
+ '16 18 default' # foo
+ '20 22 redirection' # 9<>
+ '23 25 default' # foo
+ '27 27 redirection' # >
+ '28 30 default' # foo
+ '32 33 redirection' # 9>
+ '34 36 default' # foo
+ '38 39 redirection' # >|
+ '40 42 default' # foo
+ '44 45 redirection' # >\!
+ '46 48 default' # foo
+ '50 51 redirection' # >>
+ '52 54 default' # foo
+ '56 58 redirection' # >>|
+ '59 61 default' # foo
+ '63 65 redirection' # >>\!
+ '66 68 default' # foo
+ '70 72 redirection' # <<<
+ '73 75 default' # foo
+ '77 78 redirection' # <&
+ '79 79 numeric-fd' # 9
+ '81 82 redirection' # >&
+ '83 83 numeric-fd' # 9
+ '85 86 redirection' # <&
+ '87 87 redirection' # -
+ '89 90 redirection' # >&
+ '91 91 redirection' # -
+ '93 94 redirection' # <&
+ '95 95 redirection' # p
+ '97 98 redirection' # >&
+ '99 99 redirection' # p
+ '101 102 redirection' # >&
+ '103 105 default' # foo
+ '107 108 redirection' # &>
+ '109 111 default' # foo
+ '113 115 redirection' # >&|
+ '116 118 default' # foo
+ '120 122 redirection' # >&\!
+ '123 125 default' # foo
+ '127 129 redirection' # &>|
+ '130 132 default' # foo
+ '134 136 redirection' # &>\!
+ '137 139 default' # foo
+ '141 143 redirection' # >>&
+ '144 146 default' # foo
+ '148 150 redirection' # &>>
+ '151 153 default' # foo
+ '155 158 redirection' # >>&|
+ '159 161 default' # foo
+ '163 166 redirection' # >>&\!
+ '167 169 default' # foo
+ '171 174 redirection' # &>>|
+ '175 177 default' # foo
+ '179 182 redirection' # &>>\!
+ '183 185 default' # foo
+)
diff --git a/highlighters/main/test-data/simple-redirection.zsh b/highlighters/main/test-data/simple-redirection.zsh
index e8c25e5..fb06f19 100644
--- a/highlighters/main/test-data/simple-redirection.zsh
+++ b/highlighters/main/test-data/simple-redirection.zsh
@@ -27,7 +27,7 @@
# vim: ft=zsh sw=2 ts=2 et
# -------------------------------------------------------------------------------------------------
-BUFFER='ps aux | grep java'
+BUFFER='id bob | grep java'
expected_region_highlight=(
"1 2 command" # ps
diff --git a/release.md b/release.md
index 8df4b9c..f8565e8 100644
--- a/release.md
+++ b/release.md
@@ -1,11 +1,12 @@
# Release procedure (for developers):
+- Ensure every `is-at-least` invocation passes a stable zsh release's version number as the first argument
- For minor (A.B.0) releases:
- Check whether the release uses any not-yet-released zsh features
- Check open issues and outstanding pull requests
- Confirm `make test` passes
- check with multiple zsh versions
- (easiest to check travis: https://travis-ci.org/zsh-users/zsh-syntax-highlighting/)
+ (easiest to check GitHub Actions: https://github.com/zsh-users/zsh-syntax-highlighting/actions)
- Update changelog.md
`tig --abbrev=12 --abbrev-commit 0.4.1..upstream/master`
- Make sure there are no local commits and that `git status` is clean;
diff --git a/tests/README.md b/tests/README.md
index cb3d943..eefeb54 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -104,7 +104,7 @@ By default, the results of all tests will be printed; to show only "interesting"
results (tests that failed but were expected to succeed, or vice-versa), run
`make quiet-test` (or `make test QUIET=y`).
-[TAP]: http://testanything.org/
+[TAP]: https://testanything.org/
Performance test
diff --git a/tests/generate.zsh b/tests/generate.zsh
index 8b16073..5696020 100755
--- a/tests/generate.zsh
+++ b/tests/generate.zsh
@@ -31,6 +31,9 @@
emulate -LR zsh
setopt localoptions extendedglob
+# Required for add-zle-hook-widget.
+zmodload zsh/zle
+
# Argument parsing.
if (( $# * $# - 7 * $# + 12 )) || [[ $1 == -* ]]; then
print -r -- >&2 "$0: usage: $0 BUFFER HIGHLIGHTER BASENAME [PREAMBLE]"
diff --git a/tests/test-highlighting.zsh b/tests/test-highlighting.zsh
index 30e93b1..8b564a8 100755
--- a/tests/test-highlighting.zsh
+++ b/tests/test-highlighting.zsh
@@ -31,6 +31,9 @@
setopt NO_UNSET WARN_CREATE_GLOBAL
+# Required for add-zle-hook-widget.
+zmodload zsh/zle
+
local -r root=${0:h:h}
local -a anon_argv; anon_argv=("$@")
diff --git a/tests/test-perfs.zsh b/tests/test-perfs.zsh
index ff083de..aa139aa 100755
--- a/tests/test-perfs.zsh
+++ b/tests/test-perfs.zsh
@@ -29,6 +29,9 @@
# -------------------------------------------------------------------------------------------------
+# Required for add-zle-hook-widget.
+zmodload zsh/zle
+
# Check an highlighter was given as argument.
[[ -n "$1" ]] || {
echo >&2 "Bail out! You must provide the name of a valid highlighter as argument."
diff --git a/zsh-syntax-highlighting.zsh b/zsh-syntax-highlighting.zsh
index f98dc4b..4295c93 100644
--- a/zsh-syntax-highlighting.zsh
+++ b/zsh-syntax-highlighting.zsh
@@ -49,12 +49,58 @@ if true; then
fi
fi
+# This function takes a single argument F and returns True iff F is an autoload stub.
+_zsh_highlight__function_is_autoload_stub_p() {
+ if zmodload -e zsh/parameter; then
+ #(( ${+functions[$1]} )) &&
+ [[ "$functions[$1]" == *"builtin autoload -X"* ]]
+ else
+ #[[ $(type -wa -- "$1") == *'function'* ]] &&
+ [[ "${${(@f)"$(which -- "$1")"}[2]}" == $'\t'$histchars[3]' undefined' ]]
+ fi
+ # Do nothing here: return the exit code of the if.
+}
+
+# Return True iff the argument denotes a function name.
+_zsh_highlight__is_function_p() {
+ if zmodload -e zsh/parameter; then
+ (( ${+functions[$1]} ))
+ else
+ [[ $(type -wa -- "$1") == *'function'* ]]
+ fi
+}
+
+# This function takes a single argument F and returns True iff F denotes the
+# name of a callable function. A function is callable if it is fully defined
+# or if it is marked for autoloading and autoloading it at the first call to it
+# will succeed. In particular, if F has been marked for autoloading
+# but is not available in $fpath, then calling this function on F will return False.
+#
+# See users/21671 https://www.zsh.org/cgi-bin/mla/redirect?USERNUMBER=21671
+_zsh_highlight__function_callable_p() {
+ if _zsh_highlight__is_function_p "$1" &&
+ ! _zsh_highlight__function_is_autoload_stub_p "$1"
+ then
+ # Already fully loaded.
+ return 0 # true
+ else
+ # "$1" is either an autoload stub, or not a function at all.
+ #
+ # Use a subshell to avoid affecting the calling shell.
+ #
+ # We expect 'autoload +X' to return non-zero if it fails to fully load
+ # the function.
+ ( autoload -U +X -- "$1" 2>/dev/null )
+ return $?
+ fi
+}
+
# -------------------------------------------------------------------------------------------------
# Core highlighting update system
# -------------------------------------------------------------------------------------------------
# Use workaround for bug in ZSH?
-# zsh-users/zsh@48cadf4 http://www.zsh.org/mla/workers//2017/msg00034.html
+# zsh-users/zsh@48cadf4 https://www.zsh.org/mla/workers/2017/msg00034.html
autoload -Uz is-at-least
if is-at-least 5.4; then
typeset -g zsh_highlight__pat_static_bug=false
@@ -77,7 +123,7 @@ _zsh_highlight()
typeset -r ret
# $region_highlight should be predefined, either by zle or by the test suite's mock (non-special) array.
- (( ${+region_highlight} )) || {
+ (( ${+region_highlight[@]} )) || {
echo >&2 'zsh-syntax-highlighting: error: $region_highlight is not defined'
echo >&2 'zsh-syntax-highlighting: (Check whether zsh-syntax-highlighting was installed according to the instructions.)'
return $ret
@@ -109,15 +155,7 @@ _zsh_highlight()
# C structs, so that none of the previous case patterns will match.
#
# In either case, fall back to a version check.
- #
- # The memo= feature was added to zsh in commit zsh-5.8-172-gdd6e702ee.
- # The version number at the time was 5.8.0.2-dev (see Config/version.mk).
- # Therefore, on 5.8.0.3 and newer the memo= feature is available.
- #
- # On zsh version 5.8.0.2 between the aforementioned commit and the
- # first Config/version.mk bump after it (which, at the time of writing,
- # is yet to come), this condition will false negative.
- if is-at-least 5.8.0.3; then
+ if is-at-least 5.9; then
integer -gr zsh_highlight__memo_feature=1
else
integer -gr zsh_highlight__memo_feature=0
@@ -173,7 +211,8 @@ _zsh_highlight()
[[ -n ${ZSH_HIGHLIGHT_MAXLENGTH:-} ]] && [[ $#BUFFER -gt $ZSH_HIGHLIGHT_MAXLENGTH ]] && return $ret
# Do not highlight if there are pending inputs (copy/paste).
- [[ $PENDING -gt 0 ]] && return $ret
+ (( KEYS_QUEUED_COUNT > 0 )) && return $ret
+ (( PENDING > 0 )) && return $ret
{
local cache_place
@@ -347,76 +386,117 @@ _zsh_highlight_add_highlight()
# $1 is name of widget to call
_zsh_highlight_call_widget()
{
- builtin zle "$@" &&
+ builtin zle "$@" &&
_zsh_highlight
}
-# Rebind all ZLE widgets to make them invoke _zsh_highlights.
-_zsh_highlight_bind_widgets()
-{
- setopt localoptions noksharrays
- typeset -F SECONDS
- local prefix=orig-s$SECONDS-r$RANDOM # unique each time, in case we're sourced more than once
-
- # Load ZSH module zsh/zleparameter, needed to override user defined widgets.
- zmodload zsh/zleparameter 2>/dev/null || {
- print -r -- >&2 'zsh-syntax-highlighting: failed loading zsh/zleparameter.'
- return 1
+# Decide whether to use the zle-line-pre-redraw codepath (colloquially known as
+# "feature/redrawhook", after the topic branch's name) or the legacy "bind all
+# widgets" codepath.
+#
+# We use the new codepath under two conditions:
+#
+# 1. If it's available, which we check by testing for add-zle-hook-widget's availability.
+#
+# 2. If zsh has the memo= feature, which is required for interoperability reasons.
+# See issues #579 and #735, and the issues referenced from them.
+#
+# We check this with a plain version number check, since a functional check,
+# as done by _zsh_highlight, can only be done from inside a widget
+# function — a catch-22.
+if is-at-least 5.9 && _zsh_highlight__function_callable_p add-zle-hook-widget
+then
+ autoload -U add-zle-hook-widget
+ _zsh_highlight__zle-line-finish() {
+ # Reset $WIDGET since the 'main' highlighter depends on it.
+ #
+ # Since $WIDGET is declared by zle as read-only in this function's scope,
+ # a nested function is required in order to shadow its built-in value;
+ # see "User-defined widgets" in zshall.
+ () {
+ local -h -r WIDGET=zle-line-finish
+ _zsh_highlight
+ }
}
+ _zsh_highlight__zle-line-pre-redraw() {
+ # Set $? to 0 for _zsh_highlight. Without this, subsequent
+ # zle-line-pre-redraw hooks won't run, since add-zle-hook-widget happens to
+ # call us with $? == 1 in the common case.
+ true && _zsh_highlight "$@"
+ }
+ _zsh_highlight_bind_widgets(){}
+ if [[ -o zle ]]; then
+ add-zle-hook-widget zle-line-pre-redraw _zsh_highlight__zle-line-pre-redraw
+ add-zle-hook-widget zle-line-finish _zsh_highlight__zle-line-finish
+ fi
+else
+ # Rebind all ZLE widgets to make them invoke _zsh_highlights.
+ _zsh_highlight_bind_widgets()
+ {
+ setopt localoptions noksharrays
+ typeset -F SECONDS
+ local prefix=orig-s$SECONDS-r$RANDOM # unique each time, in case we're sourced more than once
- # Override ZLE widgets to make them invoke _zsh_highlight.
- local -U widgets_to_bind
- widgets_to_bind=(${${(k)widgets}:#(.*|run-help|which-command|beep|set-local-history|yank|yank-pop)})
+ # Load ZSH module zsh/zleparameter, needed to override user defined widgets.
+ zmodload zsh/zleparameter 2>/dev/null || {
+ print -r -- >&2 'zsh-syntax-highlighting: failed loading zsh/zleparameter.'
+ return 1
+ }
- # 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)
+ # Override ZLE widgets to make them invoke _zsh_highlight.
+ local -U widgets_to_bind
+ widgets_to_bind=(${${(k)widgets}:#(.*|run-help|which-command|beep|set-local-history|yank|yank-pop)})
- # 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)
+ # 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)
- local cur_widget
- for cur_widget in $widgets_to_bind; do
- case ${widgets[$cur_widget]:-""} in
+ # 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)
- # Already rebound event: do nothing.
- user:_zsh_highlight_widget_*);;
+ local cur_widget
+ for cur_widget in $widgets_to_bind; do
+ case ${widgets[$cur_widget]:-""} in
- # The "eval"'s are required to make $cur_widget a closure: the value of the parameter at function
- # definition time is used.
- #
- # We can't use ${0/_zsh_highlight_widget_} because these widgets are always invoked with
- # NO_function_argzero, regardless of the option's setting here.
+ # Already rebound event: do nothing.
+ user:_zsh_highlight_widget_*);;
- # User defined widget: override and rebind old one with prefix "orig-".
- user:*) zle -N $prefix-$cur_widget ${widgets[$cur_widget]#*:}
- eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget ${(q)prefix}-${(q)cur_widget} -- \"\$@\" }"
- zle -N $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;;
+ # The "eval"'s are required to make $cur_widget a closure: the value of the parameter at function
+ # definition time is used.
+ #
+ # We can't use ${0/_zsh_highlight_widget_} because these widgets are always invoked with
+ # NO_function_argzero, regardless of the option's setting here.
- # Completion widget: override and rebind old one with prefix "orig-".
- completion:*) zle -C $prefix-$cur_widget ${${(s.:.)widgets[$cur_widget]}[2,3]}
- eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget ${(q)prefix}-${(q)cur_widget} -- \"\$@\" }"
- zle -N $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;;
+ # User defined widget: override and rebind old one with prefix "orig-".
+ user:*) zle -N $prefix-$cur_widget ${widgets[$cur_widget]#*:}
+ eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget ${(q)prefix}-${(q)cur_widget} -- \"\$@\" }"
+ zle -N $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;;
- # Builtin widget: override and make it call the builtin ".widget".
- builtin) eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget .${(q)cur_widget} -- \"\$@\" }"
- zle -N $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;;
+ # Completion widget: override and rebind old one with prefix "orig-".
+ completion:*) zle -C $prefix-$cur_widget ${${(s.:.)widgets[$cur_widget]}[2,3]}
+ eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget ${(q)prefix}-${(q)cur_widget} -- \"\$@\" }"
+ zle -N $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;;
- # Incomplete or nonexistent widget: Bind to z-sy-h directly.
- *)
- if [[ $cur_widget == zle-* ]] && (( ! ${+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 ${(qq)cur_widget}"
- print -r -- >&2 "zsh-syntax-highlighting: (This is sometimes caused by doing \`bindkey ${(q-)cur_widget}\` without creating the ${(qq)cur_widget} widget with \`zle -N\` or \`zle -C\`.)"
- fi
- esac
- done
-}
+ # Builtin widget: override and make it call the builtin ".widget".
+ builtin) eval "_zsh_highlight_widget_${(q)prefix}-${(q)cur_widget}() { _zsh_highlight_call_widget .${(q)cur_widget} -- \"\$@\" }"
+ zle -N $cur_widget _zsh_highlight_widget_$prefix-$cur_widget;;
+
+ # Incomplete or nonexistent widget: Bind to z-sy-h directly.
+ *)
+ if [[ $cur_widget == zle-* ]] && (( ! ${+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 ${(qq)cur_widget}"
+ print -r -- >&2 "zsh-syntax-highlighting: (This is sometimes caused by doing \`bindkey ${(q-)cur_widget}\` without creating the ${(qq)cur_widget} widget with \`zle -N\` or \`zle -C\`.)"
+ fi
+ esac
+ done
+ }
+fi
# Load highlighters from directory.
#