style: format zsh and markdown to zinit convention (#8)

* style: format zsh & markdown files and update copyright notice

Signed-off-by: Vladislav Doster <mvdoster@gmail.com>
This commit is contained in:
vladislav doster 2022-07-01 10:41:59 -05:00 committed by GitHub
parent 698e889ebc
commit 458e75c16d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 957 additions and 1557 deletions

114
CHANGELOG.md Normal file
View file

@ -0,0 +1,114 @@
## 14-07-2020
- If an `[…]` string will occur in the search query, it'll be interpreted as pattern. So that it's
possible to enter as the search query e.g.: `print ["a-zA-Z0-9_-]` or `print [^[:alpha:]]`, etc.
## 28-10-2019
- `^` if first matches beginning of the command's string, $ if last its end. So that it's
possible to enter `'^ls'` and have only commands starting with `ls` matched.
## 25-05-2018
- Hash holding paths that shouldn't be grepped (globbed) blacklist for slow disks, mounts, etc.:
```zsh
typeset -gA FAST_BLIST_PATTERNS
FAST_BLIST_PATTERNS[/mount/nfs1/*]=1
FAST_BLIST_PATTERNS[/mount/disk2/*]=1
```
## 13-06-2017
- Canceling search doesn't clear entered query. Change to previous behavior via:
```zsh
zstyle ":plugin:history-search-multi-word" clear-on-cancel "yes"
```
## 12-04-2017
- Page size can be relative to screen height, e.g.:
```zsh
zstyle ":history-search-multi-word" page-size "LINES/4"
```
## 05-04-2017
- 17% performance optimization
## 27-01-2017
- Input-driven case-sensivity of search if your query contains capital latin letters, search will
be case-sensitive
## 12-11-2016
- HSMW can now show context of selected history entry! Just hit `Ctrl-K`,
[video](https://asciinema.org/a/92516)
- More performance optimizations
## 31-10-2016
- Newlines do not disturb the parser anymore, and are also highlighted with a dark color
[video](https://asciinema.org/a/91159)
## 27-10-2016
- New optimizations **30%** speed up of syntax highlighting!
- Architectural change syntax highlighting is now computed rarely, so any possible performance
problems are now solved, in advance!
## 24-10-2016
- Workaround for Zsh versions like 5.0.2 has been added **Ctrl-V** and **ESC** cancel search. On
such Zsh versions Ctrl-C might not work. Fully problem-free Zsh version will be the upcoming 5.3,
where I have together with Zsh Hackers fully fixed the Ctrl-C issue.
## 22-10-2016
- Search process has been optimized by 20%! History sizes like 100000 are now supported.
- Active history entry can be `underline`, `standout` (i.e. inverse video), `bold`, `bg=blue`, etc.
with the new Zstyle `:plugin:history-search-multi-word / active` (see Zstyles section)
[video](https://asciinema.org/a/90214).
## 16-10-2016
- More optimizations of syntax highlighting (40% in total for the two days) new video above.
## 15-10-2016
- The compact, already optimized (by me)
[zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) part has been
further optimized by 21%! Also, more tokens are highlighted variable expressions like
`"${(@)var[1,3]}"` (when quoted).
## 11-10-2016
- Syntax highlighting of history adapted, fine crafted, **small** part of
[zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) to color what
`hsmw` shows:
![syntax highlighting](http://imagizer.imageshack.us/a/img921/1503/bMAF59.gif)
## 20-09-2016
- Keys Page Up and Page Down work and page-wise move along history. Also, `Ctrl-P`, `Ctrl-N` move to
previous and next entries.
## 19-09-2016
- Better immunity to [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) and
[zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) home, end, left
and right cursor keys now work smoothly.
## 25-05-2016
- Cooperation with [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) plugin
- Configuration option to set page size, example use:
```zsh
zstyle ":history-search-multi-word" page-size "5"
```

View file

@ -1,441 +0,0 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [2018-08-14, received $30](#2018-08-14-received-30)
- [2018-08-03, received $8](#2018-08-03-received-8)
- [2018-08-02, received $3 from Patreon](#2018-08-02-received-3-from-patreon)
- [2018-07-31, received $7](#2018-07-31-received-7)
- [2018-07-28, received $2](#2018-07-28-received-2)
- [2018-07-25, received $3](#2018-07-25-received-3)
- [2018-07-20, received $3](#2018-07-20-received-3)
- [2018-06-17, received ~$155 (200 CAD)](#2018-06-17-received-155-200-cad)
- [2018-06-10, received $10](#2018-06-10-received-10)
- [2018-05-25, received $50](#2018-05-25-received-50)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
Below are reports about what is being done with donations, i.e. which commits
are created thanks to them, which new features are added, etc. From the money
I receive I buy myself coffee and organize the time to work on the requested
features, sometimes many days in a row.
## 2018-08-14, received $30
* **Project**: **[Zplugin](https://github.com/zdharma-continuum/zinit)**
* **Goal**: Create a binary Zsh module with one Zplugin optimization and optionally some
other features.
* **Status**: The job is done.
Thanks to this donation I have finally started to code **[binary Zplugin module](
https://github.com/zdharma-continuum/zinit#quick-start-module-only)**, which is a big step onward
in evolution of Zplugin. I've implemented and published the module with 3 complete
features: 1) `load` optimization, 2) autocompilation of scripts, 3) profiling of script
load times.
Commit list:
```
2018-08-22 7b96fad doc: mod-install.sh
2018-08-22 ba1ba64 module: Update zpmod usage text
2018-08-22 b0d72e8 zplugin,*autoload: `module' command, manages new zdharma/zplugin module
2018-08-22 706bbb3 Update Zsh source files to latest
2018-08-20 b77426f module: source-study builds report with milliseconds without fractions
2018-08-20 c3cc09b module: Updated zpmod_usage, i.a. with `source-study' sub-command
2018-08-20 6190295 module: Go back to subcommand-interface to `zpmod'; simple option parser
2018-08-20 881005f module: Report on sourcing times is shown on `zpmod -S`. Done generation
2018-08-19 e5d046a module: Correct conditions on zwc file vs. script file (after stats)
2018-08-19 1282c21 module: Duration of sourcing a file is measured and stored into a hash
2018-08-18 e080153 module: Overload both `source' and `.' builtins
2018-08-18 580efb8 module: Invoke bin_zcompile with -U option (i.e. no alias expansion)
2018-08-18 b7d9836 module: Custom `source' ensures script is compiled, compiles if not
2018-08-18 1e75a47 module: Code cleanup, vim folding
2018-08-18 a4a02f3 module: Finally working `source'/`.' overload (used options translating)
2018-08-16 99bba56 module: zpmod_usage gained content
2018-08-16 04703cd module: Add the main builtin zpmod with report-append which is working
2018-08-16 cd6dc19 module: my_ztrdup_glen, zp_unmetafy_zalloc
2018-08-16 6d44e36 module: Cleanup, `source' overload after patron leoj3n restarted module
```
## 2018-08-03, received $8
* **Project**: **[zdharma/history-search-multi-word](https://github.com/zdharma/history-search-multi-word)**
* **Goal**: Allow calling `zle reset-prompt` (Zshell feature).
* **Status**: The job is done.
A user wanted to be able to call `reset-prompt` Zshell widget without disturbing my project
`history-search-multi-word`. I've implemented the necessary changes to HSMW.
Commit list:
```
2018-08-04 9745d3d hsmw: reset-prompt-protect zstyle allow users to run zle reset-prompt
2018-08-04 ce48a53 hsmw: More typo-like lackings of % substitution
2018-08-04 7e2d79b hsmw: A somewhat typo, missing % substitution
```
## 2018-08-02, received $3 from Patreon
* **Project**: **[zdharma/fast-syntax-highlighting](https://github.com/zdharma/fast-syntax-highlighting)**
* **Goal**: No goal set up.
* **Status**: Bug-fixing work.
I did bug-fixing run on `fast-syntax-highlighting`, spotted many small and sometimes important things to
improve. Did one bigger thing added global-aliases functionality.
Commit list:
```
2018-08-02 1e854f5 -autoload.ch: Don't check existence for arguments that are variables
2018-08-02 14cdc5e *-string-*: Support highlighter cooperation in presence of $PREBUFFER
2018-08-02 2d8f0e4 *-highlight: Correctly highlight $VAR, $~VAR, ${+VAR}, etc. in strings
2018-08-02 e3032d9 *-highlight: ${#PREBUFFER} -> __PBUFLEN, equal performance
2018-08-02 f0a7121 *-highlight: Make case conditions and brackets highlighter compatible
2018-08-02 781f68e *-highlight: Recognize more case-item-end tokens
2018-08-02 206c122 *-highlight: Remove unused 4th __arg_type
2018-08-02 c6da477 *-string-*: Handle 'abc\' no slash-quoting here. Full quoting support
2018-08-02 52e0176 *-string-*: Fix bug, third level was getting wrong style
2018-08-02 5edbfae -git.ch: Support "--message=..." syntax (commit)
2018-08-02 669d4b7 -git.ch: Handle "--" argument (stops options)
2018-08-02 4fae1f2 -make.ch: Handle make's -f option
2018-08-02 3fd32fe -make.ch: Handle make's -C option
2018-08-02 31751f5 -make.ch: Recognize options that obtain argument
2018-08-02 e480f18 -make.ch: Fix reply-var clash, gained consistency
2018-08-02 0e8bc1e Updated README.md
2018-08-02 eee0034 images: global-alias.png
2018-08-02 00b41ef *-highlight,themes,fast-theme: Support for global aliases #41
```
## 2018-07-31, received $7
* **Project**: **[zdharma/fast-syntax-highlighting](https://github.com/zdharma/fast-syntax-highlighting)**
* **Goal**: Implement ideal brackets highlighting.
* **Status**: The job is done.
When a source code is edited e.g. in `Notepad++` or some IDE, then most often brackets are somehow matched to
each other, so that the programmer can detect mistakes. `Fast-syntax-highlighting` too gained that feature. It
was done in such a way that FSH cannot make any mistake, colors will perfectly match brackets to each other.
Commit list:
```
2018-07-31 2889860 *-highlight: Correct place to initialize $_FAST_COMPLEX_BRACKETS
2018-07-31 2bde2a9 Performance status -15/8/8
2018-07-31 5078261 *-highlight,README: Brackets highlighter active by default
2018-07-31 2ee3073 *-highlight,*string-*: Brackets in [[..]], ((..)), etc. handled normally
2018-07-31 776b12d plugin.zsh: $_ZSH_HIGHLIGHT_MAIN_CACHE -> $_FAST_MAIN_CACHE
2018-07-30 2867712 plugin.zsh: Fix array parameter created without declaring #43
2018-07-30 cbe5fc8 Updated README.md
2018-07-30 2bd3291 images: brackets.gif
2018-07-30 ef23a96 *-string-*: Bug-fix, correctly use theme styles
2018-07-30 9046f82 plugin.zsh: Attach the new brackets highlighter; F_H[use_brackets]=1
2018-07-30 b33a5fd fast-theme: Support 4 new styles (for brackets)
2018-07-30 a03f004 themes: Add 4 new styles (brackets)
2018-07-30 2448cdc *-string-*: Additional highlight of bracket under cursor; more styles
2018-07-30 5e1795e *-string-*: Highlighter for brackets, handles all quotings; detached
```
## 2018-07-28, received $2
* **Project**: **[zdharma/fast-syntax-highlighting](https://github.com/zdharma/fast-syntax-highlighting)**
* **Goal**: Distinguish file and directory when highlighting
* **Status**: The job is done.
A user requested that when `fast-syntax-highlighting` colorizes the command line it should use different
styles (e.g. colors) for token that's a *file* and that's a *directory*. It was a reasonable idea and I've
implemented it.
Commit list:
```
2018-07-28 7f48e04 themes: Extend all themes with new style `path-to-dir'
2018-07-28 c7c6a91 fast-theme: Support for new style `path-to-dir'
2018-07-28 264676c *-highlight: Differentiate path and to-dir path. New style: path-to-dir
```
## 2018-07-25, received $3
* **Project**: **[zdharma/zshelldoc](https://github.com/zdharma/zshelldoc)**
* **Goal**: Implement documenting of used environment variables.
* **Status**: The job is done.
Zshelldoc generates code-documentation like Doxygen or Javadoc, etc. User requested a
new feature: the generated docs should enumerate environment variables used and/or
exported by every function. Everything went fine and this feature has been implemented.
Commit list:
```
2018-07-26 f63ea25 Updated README.md
2018-07-26 3af0cf7 *detect: Get `var' from ${var:-...} and ${...:+${var}} and other subst
2018-07-25 2932510 *adoc: Better language in output document (about exported vars) #5
2018-07-25 f858dd8 *adoc: Include (in the output document) data on env-vars used #5
2018-07-25 80e3763 *adoc: Include data on exports (environment) in the output document #5
2018-07-25 ca576e2 *detect: Detect which env-vars are used, store meta-data in data/ #5
2018-07-25 f369dcc *detect: Function `find-variables' reported "$" as a variable, fixed #5
2018-07-25 e243dab *detect: Function `find-variables' #5
2018-07-25 5b34bb1 *transform: Detect exports done by function/script-body, store #5
```
## 2018-07-20, received $3
* **Project**: **[zdharma/zshelldoc](https://github.com/zdharma/zshelldoc)**
* **Goal**: Implement stripping of leading `#` char from functions' descriptions.
* **Status**: The job is done.
A user didn't like that functions' descriptions in the JavaDoc-like document (generated with Zshelldoc) all
contain a leading `#` character. I've added stripping of this character (it is there in the processed source
code) controlled by a new Zshelldoc option.
Commit list:
```
2018-07-20 172c220 zsd,*adoc,README: Option --scomm to strip "#" from function descriptions
```
## 2018-06-17, received ~$155 (200 CAD)
* **Project**: **[zdharma/fast-syntax-highlighting](https://github.com/zdharma/fast-syntax-highlighting)**
* **Goal**: No goal set up.
* **Status**: Done intense research.
I've created 2 new branches: `Hue-optimization` (33 commits) and `Tidbits-feature` (22 commits). Those were
branches with architectural changes and extraordinary features. The changes yielded to be too slow, and I had
to withdraw the merge. Below are fixing and optimizing commits (i.e. the valuable ones) that I've restored
from the two branches into master.
Commit list:
```
2018-07-21 dab6576 *-highlight: Merge-restore: remove old comments
2018-07-21 637521f *-highlight: Merge-restore: a threshold on # of zle .redisplay calls
2018-07-21 4163d4d *-highlight: Merge-restore: optimize four $__arg[1] = ... cases
2018-07-21 0f01195 *-highlight: Merge-restore: can remove one (Q) dequoting
2018-07-21 39a4ec6 *-highlight: Merge-restore: $v = A* is faster than $v[1] = A, tests:
2018-07-21 99d6b33 *-highlight: Merge-restore: optimize-out ${var:1} Bash syntax
2018-07-21 719c092 *-highlight: Merge-restore: allow $V/cmd, "$V/cmd, "$V/cmd", "${V}/cmd"
2018-07-21 026941d *-highlight: Merge-restore: stack pop in single instruction, not two
2018-07-21 3467e3d *-highlight: Merge-restore: more reasonable redirection-detecting code
2018-07-21 00d25ee *-highlight: Merge-restore: one active_command="$__arg" not needed (?)
2018-07-21 1daa6b3 *-highlight: Merge-restore: simplify ; and \n code short-paths
2018-07-21 55d65be *-highlight: Merge-restore: proc_buf advancement via patterns (not (i))
2018-07-21 cc55546 *-highlight: Merge-restore: pattern matching to replace (i) flag
```
## 2018-06-10, received $10
* **Project**: **[zdharma/fast-syntax-highlighting](https://github.com/zdharma/fast-syntax-highlighting)**
* **Goal**: No goal set up.
* **Status**: Done intense experimenting.
I was working on *chromas* command-specific colorization. I've added `which` and
`printf` colorization, then added asynchronous path checking (needed on slow network
drives), then coded experimental `ZPath` feature for chromas, but it couldn't be optimized
so I had to resign of it.
Commit list:
```
2018-06-12 c4ed1c6 Optimization the same idea as in previous patch, better method
2018-06-12 c36feef Optimization a) don't index large buffer, b) with negative index
2018-06-12 2f03829 Performance status 2298 / 1850
2018-06-12 14f5159 New working feature ZPath. It requires optimization
2018-06-12 e027c40 -which.ch: One of commands can apparently return via stderr (#27)
2018-06-11 5b8004f New chroma `ruby', works like chroma `perl', checks syntax via -ce opts
2018-06-10 ca2e18b *-highlight: Async path checking has now 8-second cache
2018-06-10 e071469 *-highlight: Remove path-exists queue clearing
2018-06-10 5a6684c *-highlight: Support for asynchronous path checking
2018-06-10 1d7d6f5 New chroma: `printf', highlights special sequences like %s, %20s, etc.
2018-06-10 8f59868 -which.ch: Update main comment on purpose of this chroma
2018-06-10 5f4ece2 -which.ch: Added `whatis', it has only 1st line if output used
2018-06-10 e2d173e -which.ch: Uplift: handle `which' called on a function, /usr/bin/which
```
## 2018-05-25, received $50
* **Project**: **[zdharma/fast-syntax-highlighting](https://github.com/zdharma/fast-syntax-highlighting)**
* **Goal**: No goal set up.
* **Status**: New ideas and features.
I was working from May, 25 to June, 9 and came up with key ideas and implemented them. First were *themes*
that were very special because they were using `INI` files instead of some Zsh-script format. Creating themes
for `fast-syntax-highlighting` is thus easy and fun. Then I came up with *chromas*, command-specific
highlighting, which redefine how syntax-highlighting for Zshell works detailed highlighting for e.g. Git
became possible, the user is informed about e.g. a mistake even before running a command. Overall 178 commits
in 16 days.
```
2018-06-09 3f72e6c -git.ch: `revert' works almost like `checkout', attach `revert' there
2018-06-09 b892743 Updated CHROMA_GUIDE.adoc
2018-06-09 f05643d Revert "Revert "Updated CHROMA_GUIDE.md""
2018-06-09 729bf7f Revert "Revert "CHROMA_GUIDE: Remove redundant comments, uplift""
2018-06-09 48a4e0c Revert "CHROMA_GUIDE: Remove redundant comments, uplift"
2018-06-09 55ede0a Revert "Updated CHROMA_GUIDE.md"
2018-06-09 17a28ba New chroma `-docker.ch' that verifies image ID passed to `image rm'
2018-06-09 868812a -make.ch,*-make-targets: Check Makefile exists, use 7 second cache, #24
2018-06-09 73df278 -sh.ch: Attach fish, has -c option, though different syntax, let's try
2018-06-09 3a73b8e Updated CHROMA_GUIDE.md
2018-06-09 29d04c8 CHROMA_GUIDE: Remove redundant comments, uplift
2018-06-09 22ce1d8 -sh.ch,*-highlight: Attach to 2 other shells, Zsh and Bash
2018-06-09 f54e44f New chroma `-sh.ch', colorizes code passed to `sh' with -c option
2018-06-09 f5d2375 CHROMA_GUIDE: Add example code block (rendered broken in mdown)
2018-06-09 08f4b28 CHROMA_GUIDE: Switch to asciidoc (rename)
2018-06-09 4e03609 CHROMA_GUIDE.md
2018-06-09 bbcf2d6 -source.ch: Word "source" should be highlighted as builtin
2018-06-09 6739b8b New chroma `source' to handle . and source builtins
2018-06-09 b961211 gitignore: ignore more paths
2018-06-09 59d5d09 Updated README.md
2018-06-09 f6d4d19 Updated README.md
2018-06-09 eb31324 Update README.md (figlet logo)
2018-06-09 71dcc5f Performance status 298 / 479
2018-06-09 00c5f8f *-highlight: Add comments
2018-06-09 232903c -awk.ch: Highlight `sub' function, not working {, } highlighting
2018-06-09 b5241ba *-highlight: Much better $( ) recursion, would say problems-free, maybe
2018-06-08 6c69437 *-highlight: Larger buffer (110 -> 250) for $( ) matching
2018-06-08 f2b7a96 -awk.ch: Syntax check code passed to awk. Awk is very forgiving, though
2018-06-08 c53d8ba -vim.ch: Pass almost everything to big-loop, check if vim exists
2018-06-08 7fbf7cd chroma: New chroma `vim', shows last opened files under prompt
2018-06-08 06e4570 gitignore: Extend .gitignore
2018-06-08 3184ba1 chroma: All chroma functions end chroma mode on e.g. | and similar
2018-06-08 070077d *-highlight,-example.ch: Rename arg_type -> __arg_type, use it to end
2018-06-08 6c2411e -awk.ch: Use the new theme style `subtle-bg'
2018-06-08 9ec8d63 themes: All themes (remaining 4) to support `subtle-bg' style
2018-06-08 66e848b fast-theme: New theme key `subtle-bg', default & clean.ini support it
2018-06-08 1e794f9 -awk.ch: More keywords highlighted
2018-06-08 f3bbaca -awk.ch: Don't highlight keywords when they only contain proper keyword
2018-06-08 e4d5283 -awk.ch: Fix mistake (indices), was highlighting 1 extra trailing letter
2018-06-08 eebbb19 -awk.ch: Initialize FSH_LIST
2018-06-08 8ec24ca *-highlight: Missing math function for awk
2018-06-08 d8e423a -awk.ch: Highlight more keywords, via more general code
2018-06-07 ee26e66 Commit missing -fast-make-targets
2018-06-07 9d4f2b5 New chroma `-awk.ch', colorizes regex characters and a keyword (print)
2018-06-07 def5133 -example.ch: Add comments
2018-06-07 f31a2d0 New chroma -make.ch, verifies if target is correct
2018-06-07 623b8ce -perl.ch: Use correct keys in FAST_HIGHLIGHT hash
2018-06-07 090f420 themes: Make all themes provide {in,}correct-subtle styles
2018-06-07 2201fb6 New -perl.ch chroma, syntax-checks perl code; 2 new theme entries
2018-06-06 4b9598e *-highlight: Fix bug in math highlight allow variables starting with _
2018-06-06 708afec *-highlight: Fix FAST_BLIST_PATTERNS not expanding path to absolute one
2018-06-06 caef05a -example.ch: Update, fix typos, remove unused code
2018-06-06 3fb192a Updated README.md
2018-06-06 6de0c82 images: git_chroma.png
2018-06-06 2852fdd -grep.ch (new): Special highlighting for grep -grep.ch chroma function
2018-06-06 f216785 -example.ch: Added comments
2018-06-06 4ab5b36 -example.ch: Add comments
2018-06-06 380cd12 -example.ch: Added comments
2018-06-06 c8947cc -example.ch: Add comments
2018-06-06 f2e273e -example.ch: Add comments
2018-06-06 2f3565b plugin.zsh: Fix parse error
2018-06-06 4f1a9bd plugin.zsh: Added $fpath handling, to match what README contains
2018-06-06 cc9adb5 -example.ch: Change and extend comments
2018-06-06 3128fff -git.ch: More intelligent `checkout' highlighting ref is first
2018-06-06 4b6f54b -git.ch: Support for `checkout' subcommand
2018-06-06 1930d37 -example.ch: Added example chroma function
2018-06-05 d79cd85 -git.ch: Add comments
2018-06-05 1473c9e -git.ch: Add comments
2018-06-05 0cb1419 -git.ch: Message passed after -m is checked for the 72 chars boundary
2018-06-05 3f99944 -git.ch: Architectural uplift of git chroma
2018-06-05 e044d13 -git.ch: Single place to add entry to $reply (target: region_highlight)
2018-06-05 3a84364 -git.ch: Handle quoted non-option arguments, also partly quoted: "abc
2018-06-05 d635bf4 -fast-run-git-command, it handles cache automatically, decimates source
2018-06-05 102ea78 -git.ch: Smart handling of `git push', remotes and branches are verified
2018-06-04 be88850 Performance status [+] 39+77=116 / -26+24=-2
2018-06-04 0e033f8 Experimental chroma support, currently active only on command `git'
2018-06-04 43ae221 *-highlight: Emacs mode-line
2018-06-04 938ad29 test: New "-git" parsing option, test results, -git.ch included
2018-06-04 e433fbc fast-theme: Explicitly return 0; added Emacs mode-line
2018-06-04 66e9b3c *-highlight: Detection of $( ) now doesn't go for $(( )) as a candidate
2018-06-04 488a580 chroma: Empty chroma function for `git'
2018-06-04 f54d770 *-highlight: Rename $cur_cmd to $active_command
2018-06-04 3f24e68 *-highlight: Make sudo and always-block compatible with `case' handling
2018-06-02 cd82637 themes: forest.ini to support 3 new `case' styles
2018-06-02 e1e993e themes: safari.ini & zdharma.ini to support 3 new `case' styles
2018-06-02 2e78a02 themes: clean.ini & default.ini to support 3 new `case' styles
2018-06-02 c1c3aab themes: free.ini to support 3 new `case' styles
2018-06-02 70a7e18 fast-theme,*-highlight: 3 new styles for `case' higlighting
2018-06-02 8d90dc2 *-highlight: Support for `case' highlighting
2018-06-02 10d291c *-highlight: Softer state manipulation, less rigid =1 etc. assignments
2018-06-02 6159507 *-highlight: Don't highlight closing ) with style `assign'
2018-06-02 1fc2450 *-highlight: One complex math command optimization, top of the loop
2018-06-02 cc49247 *-highlight: Fix improper state after assignment (command | regular)
2018-06-02 02942b8 Updated README.md
2018-06-02 5e28259 images: eval_cmp.png
2018-06-02 df92fed *-highlight: Fix removal of trailing "/' when recursing in eval
2018-06-02 4f61938 Performance status 46 / 44
2018-06-02 a5ade0e *-highlight: Recursive highlighting of eval string argument
2018-06-02 e91847b *-highlight: Don't recurse when not at main *-process call
2018-06-02 fca8603 *-highlight: Support assignments of arrays when key is taken from array
2018-06-02 5d70f01 *-highlight: Math highlighting recognizes ${+VAR}
2018-06-02 c48eb0d *-highlight: Math colorizing recognizes variables in braces ${HISTISZE}
2018-06-02 53dd85a *-highlight: Allow -- for precommand modifiers command & exec
2018-06-02 d9fe110 *-highlight: Detect globbing also when `##' occurs
2018-06-02 55c923d Performance status 132 / 66
2018-06-02 3bd8f07 themes: safari.ini to have globbing color specifically selected
2018-06-02 2b55260 themes: free.ini to have globbing color specifically selected
2018-06-02 494868e themes: clean.ini to have globbing color specifically selected
2018-06-01 fca6b3d images: herestring.png #9
2018-06-01 f9842c1 themes: forest.ini to use underline instead of bg color #9
2018-06-01 c25c539 themes: Small tune-up of forest & zdharma themes for here-string #9
2018-06-01 988d504 themes: Rudimentary (all same) configuration of here-string tokens #9
2018-06-01 99842d2 fast-theme,*-highlight: Support for here-string, can use bg color #9
2018-06-01 f739c30 Updated README.md
2018-06-01 7fa8451 images: execfd.png execfd_cmp.png
2018-06-01 d7384f1 themes: All themes gained `exec-descriptor=` key, now supported by code
2018-06-01 d66d140 themes: Fix improper effect of s/red/.../ substitution in clean,forest
2018-06-01 f7ee5e2 fast-theme,*-highlight: Support highlighting of {FD} etc. passed to exec
2018-06-01 e5c5534 *-highlight: Proper states for precmd (command,exec) option handling
2018-06-01 647b198 images: New cmdsubst.png
2018-06-01 74bdc4c Updated README.md
2018-06-01 86eb15e images: theme.png
2018-06-01 5169e82 Updated README.md
2018-06-01 1c462b7 Updated README.md
2018-06-01 4c21da4 images: cmdsubst.png
2018-06-01 b39996e *-highlight: Switch theme to secondary when descending into $() #15
2018-06-01 bf96045 themes: Equip all themes with key `secondary' (an alternate theme) #15
2018-06-01 aa1b112 fast-theme: Generate secondary theme (from key `secondary' in theme) #15
2018-06-01 6dd3bd3 *-highlight: Support for multiple active themes #15
2018-06-01 8a32944 *-highlight: Fix "$() found?" comparison
2018-06-01 3651605 *-highlight: Significant change: the parser is called recursively on $()
2018-05-31 882d88b test,*-highlight: New -ooo performance test; highlighter takes arguments
2018-05-31 5ba1178 *-highlight: Optimization - compute __arg length once
2018-05-30 b2a0126 *-highlight: Allow multiple separate options for `command', `exec' (#10)
2018-05-30 5804e9a *-highlight: Correct state after option for precommand (#10)
2018-05-30 1247b64 *-highlight: Simpler and more accurate option-testing for exec, command (#10)
2018-05-30 d87fed4 *-highlight: Correctly highlight options for `command' and `exec' (#10)
2018-05-30 8c3e75e *-highlight: Double-hyphen (--) stops option recognition and colorizing
2018-05-30 1c5a56c *-highlight: Support ${VAR} at command position (not only $VAR)
2018-05-30 f19d761 Updated README.md
2018-05-30 4a27351 images: for-loop
2018-05-30 4d650de themes: zdharma.ini to support for-loop
2018-05-30 45cafbc themes: safari.ini to support for-loop
2018-05-30 8bb9ee0 themes: free.ini to support for-loop
2018-05-30 f25a059 themes: forest.ini to support for-loop
2018-05-29 093d79e themes: default.ini to support for-loop
2018-05-29 446cb7b clean.ini,fast-theme: Clean-theme & theme subsystem to support for-loop
2018-05-29 1bb701f *-highlight: Move $variable highlighting from case to if-block
2018-05-29 b8413e9 *-highlight: For-loop highlighting, working, needs few upgrades
2018-05-28 7bec6e5 *-highlight: Three more simple vs. complex math operation optimizations
2018-05-27 baae683 *-highlight: Optimise complex math command into single one with & and ~
2018-05-27 2dc3103 *-highlight: Optimise complex math command into single one with & and ~
2018-05-27 291f905 _fast-theme: Update -t/--test description
2018-05-27 ec305f6 fast-theme: Help message treats about -t/--test
2018-05-27 0e1d19a Updated README.md
2018-05-27 5c3c911 Updated README.md
2018-05-26 76af248 themes: A fix for zdharma theme, 61 -> 63, a lighter color for builtins
2018-05-26 8eca0f2 *fast-theme: Ability to test theme after setting it (-t/--test)
2018-05-26 d3a7922 *-highlight: Fix in_array_assignment setting when closing ) found
2018-05-26 796c482 *-highlight: Make parameters' names exotic blank-var detection to work
2018-05-26 ae3913f _fast-theme: Complete theme names
2018-05-26 d212945 *-highlight,plugin.zsh,default.ini: Uplift of fg=112-fix code
2018-05-26 ee56f65 *-highlight,plugin.zsh: Final fix for fg=112 assignment  use zstyle
2018-05-26 391f5a4 fast-theme: Set `theme' zstyle in `:plugin:fast...' to given theme
2018-05-26 e0dc086 plugin.zsh: Fix the fg=112 assignment done for `variable' style
2018-05-26 17c9286 Updated README.md
2018-05-26 4774c1c fast-theme: Add completion for this function
2018-05-26 d971f39 fast-theme: Detect lack of theme name in arguments
2018-05-26 74f0d4d fast-theme: Use standard option parsing (zparseopts) and typical options
2018-05-26 d9c6180 New theme: `forest'
2018-05-26 419c156 New theme: `zdharma'
2018-05-26 a7735df gitignore
2018-05-26 99db69a New theme: `free'
2018-05-26 73619ff New theme: `clean'
2018-05-25 52307fb Theme support, 1 extra theme `safari'
2018-05-25 41df55b *-highlight: (k) subscript flag is sufficient, no need for (K)
2018-05-25 cb21c05 Updated README.md
2018-05-25 a580cff *-highlight: FAST_BLIST_PATTERNS
```

256
README.md
View file

@ -1,248 +1,158 @@
[![License (GPL version 3)](https://img.shields.io/badge/license-GNU%20GPL%20version%203-blue.svg?style=flat-square)](./LICENSE)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](./LICENSE)
![ZSH 5.0.0](https://img.shields.io/badge/zsh-v5.0.0-orange.svg?style=flat-square)
[![Gitter][gitter-image]][gitter-link]
# history-search-multi-word - zsh plugin
# Introduction
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Gitter](https://img.shields.io/gitter/room/zdharma-continuum/zinit.svg?style=flat-square)](https://gitter.im/zdharma-continuum/zinit)
Binds `Ctrl-R` to a widget that searches for multiple keywords in `AND` fashion.
In other words, you can enter multiple words, and history entries that match
all of them will be found. The entries are syntax highlighted.
Binds `Ctrl-R` to a widget that searches for multiple keywords in an `AND` fashion. In other words, you
can enter multiple words, and history entries that match all of them are returned. Additionally, search matches are syntax highlighted.
Video  view on [asciinema](https://asciinema.org/a/88954). You can resize the video by pressing `Ctrl-+` or `Cmd-+`.
Video view on [asciinema](https://asciinema.org/a/88954). You can resize the video by pressing
`Ctrl-+` or `Cmd-+`.
[![asciicast](https://asciinema.org/a/88954.png)](https://asciinema.org/a/88954)
HSMW has feature called **context viewing**  see all occurrences of a command together
with surrounding commands:
HSMW has a feature called **context viewing** see all occurrences of a command together with
surrounding commands:
[![asciicast](https://asciinema.org/a/155704.png)](https://asciinema.org/a/155704)
Set:
```zsh
zstyle :plugin:history-search-multi-word reset-prompt-protect 1
```bash
zstyle :plugin:history-search-multi-word reset-prompt-protect 1
```
to be able to use `zle reset-prompt` in your e.g. `sched` calls, in presence of
`zdharma-continuum/fast-syntax-highlighting`, `zsh-users/zsh-syntax-highlighting`,
`zsh-users/zsh-autosuggestions` and other plugins that hook up into Zshell by
overloading Zle widgets. You could e.g. use `sched` in following way:
In order to use `zle reset-prompt` in function calls (e.g. `sched`) in addition to plugins that hook up into Zshell by overloading Zle
widgets (e.g., `fast-syntax-highlighting`, `zsh-syntax-highlighting`,
`zsh-autosuggestions`), use `sched` :
```zsh
```bash
PROMPT=%B%F{yellow}%D{%H:%M:%S}%B%b%f
schedprompt() {
zle && zle reset-prompt
sched +1 schedprompt
zle && zle reset-prompt
sched +1 schedprompt
}
zmodload -i zsh/sched
schedprompt
```
to refresh the clock in prompt every second. The `reset-prompt-protect` zstyle
needs to be set to 1 for correct cooperation with HSMW. Or, you could use `zle
.reset-prompt` (i.e. with the dot in front) to call the original, not
overloaded (by F-Sy-H, zsh-autosuggestsions, etc.) `reset-prompt` widget.
To refresh the clock in prompt every second. The `reset-prompt-protect` zstyle should be `1`
for proper cooperation with HSMW. Or, you could use `zle .reset-prompt` (i.e., with the dot in
front) to call the original, not overloaded (e.g., F-Sy-H, zsh-autosuggestions, etc.) `reset-prompt` widget.
# News
* 14-07-2020
- If an `[…]` string will occur in the search query, it'll be interpreted as
pattern. So that it's possible to enter as the search query e.g.: `print
["a-zA-Z0-9_-]` or `print [^[:alpha:]]`, etc.
## Installation
* 28-10-2019
- `^`  if first matches beginning of the command's string, $  if last
its end. So that it's possible to enter `'^ls'` and have only commands
starting with `ls` matched.
The plugin is **plugin manager agnostic**.
* 25-05-2018
- Hash holding paths that shouldn't be grepped (globbed) blacklist for slow disks, mounts, etc.:
To install, clone the `history-search-multi-word` repository and add the following snippet to your
`.zshrc`
```zsh
typeset -gA FAST_BLIST_PATTERNS
FAST_BLIST_PATTERNS[/mount/nfs1/*]=1
FAST_BLIST_PATTERNS[/mount/disk2/*]=1
```
* 13-06-2017
- Canceling search doesn't clear entered query. Change to previous behavior via:
```zsh
zstyle ":plugin:history-search-multi-word" clear-on-cancel "yes"
```
* 12-04-2017
- Page size can be relative to screen height, e.g.:
```zsh
zstyle ":history-search-multi-word" page-size "LINES/4"
```
* 05-04-2017
- 17% performance optimization
* 27-01-2017
- Input-driven case-sensivity of search  if your query contains capital latin letters, search will be case-sensitive
* 12-11-2016
- HSMW can now show context of selected history entry! Just hit `Ctrl-K`, [video](https://asciinema.org/a/92516)
- More performance optimizations
* 31-10-2016
- Newlines do not disturb the parser anymore, and are also highlighted with a dark color  [video](https://asciinema.org/a/91159)
* 27-10-2016
- New optimizations **30%** speed up of syntax highlighting!
- Architectural change  syntax highlighting is now computed rarely, so any possible performance problems are now solved, in advance!
* 24-10-2016
- Workaround for Zsh versions like 5.0.2 has been added  **Ctrl-V** and **ESC** cancel search. On such Zsh
versions Ctrl-C might not work. Fully problem-free Zsh version will be the upcoming 5.3, where
I have together with Zsh Hackers fully fixed the Ctrl-C issue.
* 22-10-2016
- Search process has been optimized by 20%! History sizes like 100000 are now supported.
- Active history entry can be `underline`, `standout` (i.e. inverse video), `bold`, `bg=blue`, etc. with
the new Zstyle `:plugin:history-search-multi-word / active` (see Zstyles section)  [video](https://asciinema.org/a/90214).
* 16-10-2016
- More optimizations of syntax highlighting (40% in total for the two days) new video above.
* 15-10-2016
- The compact, already optimized (by me) [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) part has been further optimized by 21%!
Also, more tokens are highlighted  variable expressions like `"${(@)var[1,3]}"` (when quoted).
* 11-10-2016
- Syntax highlighting of history  adapted, fine crafted, **small** part of [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting)
to color what `hsmw` shows:
![syntax highlighting](http://imagizer.imageshack.us/a/img921/1503/bMAF59.gif)
* 20-09-2016
- Keys Page Up and Page Down work and page-wise move along history. Also, `Ctrl-P`, `Ctrl-N`
move to previous and next entries.
* 19-09-2016
- Better immunity to [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)
and [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) home,
end, left and right cursor keys now work smoothly.
* 25-05-2016
- Cooperation with
[zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)
plugin
- Configuration option to set page size, example use:
```zsh
zstyle ":history-search-multi-word" page-size "5"
```
# Installation
**The plugin is "standalone"**, which means that only sourcing it is needed. So to
install, unpack `history-search-multi-word` somewhere and add
```zsh
source {where-hsmw-is}/history-search-multi-word.plugin.zsh
```bash
source <LOCATION-WHERE-REPOSITORY >/history-search-multi-word.plugin.zsh
```
to `zshrc`.
If using a plugin manager, then `Zinit` is recommended, but you can use any
other too, and also install with `Oh My Zsh` (by copying directory to
`~/.oh-my-zsh/custom/plugins`).
If using a plugin manager, then `Zinit` is recommended, but you can use any other too, and also
install with `Oh My Zsh` (by copying the directory to `~/.oh-my-zsh/custom/plugins`).
### [Zinit](https://github.com/zdharma-continuum/zinit)
Add `zinit load zdharma-continuum/history-search-multi-word` to your `.zshrc` file.
Zinit will handle cloning the plugin for you automatically the next time you
start zsh.
Add the following snippet to your `.zshrc`:
```bash
zinit load zdharma-continuum/history-search-multi-word
```
Zinit will automatically handle cloning the plugin for you the next time you start zsh.
### Antigen
Add `antigen bundle zdharma-continuum/history-search-multi-word` to your `.zshrc` file.
Antigen will handle cloning the plugin for you automatically the next time you
start zsh. You can also add the plugin to a running zsh with `antigen bundle
zdharma-continuum/history-search-multi-word` for testing before adding it to your
`.zshrc`.
Add `antigen bundle zdharma-continuum/history-search-multi-word` to your `.zshrc` file. Antigen will
automatically handle cloning the plugin for you the next time you start zsh. You can also add the
plugin to a running zsh with `antigen bundle zdharma-continuum/history-search-multi-word` for
testing before adding it to your `.zshrc`.
### Oh-My-Zsh
1. `cd ~/.oh-my-zsh/custom/plugins`
2. `git clone git@github.com:zdharma-continuum/history-search-multi-word.git`
3. Add `history-search-multi-word` to your plugin list
1. `git clone git@github.com:zdharma-continuum/history-search-multi-word.git`
1. Add `history-search-multi-word` to your plugin list
### Zgen
Add `zgen load zdharma-continuum/history-search-multi-word` to your .zshrc file in the same
place you're doing your other `zgen load` calls in.
```zsh
zgen load zdharma-continuum/history-search-multi-word
```
to your .zshrc file in the same place
you're doing your other `zgen load` calls in.
### [Sheldon](https://github.com/rossmacarthur/sheldon)
Run
1. Run
```bash
sheldon add history-search-multi-word --github zdharma-continuum/history-search-multi-word
```
and add `bindkey "^R" history-search-multi-word` to `.zshrc` to enable the keybinding.
To add the `ctrl-R` keybinding, add the following snippet to your `.zshrc`
```bash
bindkey "^R" history-search-multi-word
```
### Arch Linux
1. Install [`zsh-history-search-multi-word-git`](https://aur.archlinux.org/packages/zsh-history-search-multi-word-git/) from the [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository).
1. Install
[`zsh-history-search-multi-word-git`](https://aur.archlinux.org/packages/zsh-history-search-multi-word-git/)
from the [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository).
2. Add the following to your `.zshrc`:
1. Add the following to your `.zshrc`
```sh
source /usr/share/zsh/plugins/history-search-multi-word/history-search-multi-word.plugin.zsh
```
```bash
source /usr/share/zsh/plugins/history-search-multi-word/history-search-multi-word.plugin.zsh
```
3. Start a new terminal session
1. Start a new terminal session via `exec zsh`
## Options
# Customizing
## Zstyles
```zsh
zstyle ":history-search-multi-word" page-size "8" # Number of entries to show (default is $LINES/3)
zstyle ":history-search-multi-word" highlight-color "fg=yellow,bold" # Color in which to highlight matched, searched text (default bg=17 on 256-color terminals)
zstyle ":plugin:history-search-multi-word" synhl "yes" # Whether to perform syntax highlighting (default true)
zstyle ":plugin:history-search-multi-word" active "underline" # Effect on active history entry. Try: standout, bold, bg=blue (default underline)
zstyle ":plugin:history-search-multi-word" check-paths "yes" # Whether to check paths for existence and mark with magenta (default true)
zstyle ":plugin:history-search-multi-word" clear-on-cancel "no" # Whether pressing Ctrl-C or ESC should clear entered query
```bash
zstyle ":history-search-multi-word" highlight-color "fg=yellow,bold" # Color in which to highlight matched, searched text (default bg=17 on 256-color terminals)
zstyle ":history-search-multi-word" page-size "8" # Number of entries to show (default is $LINES/3)
zstyle ":plugin:history-search-multi-word" active "underline" # Effect on active history entry. Try: standout, bold, bg=blue (default underline)
zstyle ":plugin:history-search-multi-word" check-paths "yes" # Whether to check paths for existence and mark with magenta (default true)
zstyle ":plugin:history-search-multi-word" clear-on-cancel "no" # Whether pressing Ctrl-C or ESC should clear entered query
zstyle ":plugin:history-search-multi-word" synhl "yes" # Whether to perform syntax highlighting (default true)
```
## Syntax highlighting
### Syntax highlighting
Syntax highlighting is customized via `HSMW_HIGHLIGHT_STYLES` associative array.
It has keys like `reserved-word`, `alias`, `command`, `path`, etc. which are assigned
with strings like `fg=blue,bold`, to configure how given elements are to be
colored. If you assign this array before or after loading `hsmw` you will change the defaults. Complete list
of available keys is [at the beginning](https://github.com/zdharma-continuum/history-search-multi-word/blob/master/hsmw-highlight#L34-L62)
of `hsmw-highlight` file. Example `~/.zshrc` addition that sets `path` key
paths that exist will be highlighted with background magenta, foreground white, bold:
Syntax highlighting is customized via `HSMW_HIGHLIGHT_STYLES` associative array. It has keys like
`reserved-word`, `alias`, `command`, `path`, etc., which are assigned with strings like
`fg=blue,bold` to configure how given elements are to be colored. If you assign this array before
or after loading `hsmw`, you will change the defaults. The complete list of available keys is
[at the beginning](https://github.com/zdharma-continuum/history-search-multi-word/blob/master/hsmw-highlight#L34-L62)
of `hsmw-highlight` file. Example `~/.zshrc` addition that sets `path` key paths that exist will
be highlighted with background magenta, foreground white, bold:
```zsh
```bash
typeset -gA HSMW_HIGHLIGHT_STYLES
HSMW_HIGHLIGHT_STYLES[path]="bg=magenta,fg=white,bold"
```
Following code will enable coloring of options of form "-o" and "--option", with cyan:
#### Enable coloring of options of form "-o" and "--option", with cyan:
```zsh
typeset -gA HSMW_HIGHLIGHT_STYLES
HSMW_HIGHLIGHT_STYLES[single-hyphen-option]="fg=cyan"
HSMW_HIGHLIGHT_STYLES[double-hyphen-option]="fg=cyan"
HSMW_HIGHLIGHT_STYLES[single-hyphen-option]="fg=cyan"
```
Following code will use 256 colors to highlight command separators (like ";" or "&&"):
#### 256 colors to highlight command separators (e.g., ;, &&, and ||):
```zsh
```bash
HSMW_HIGHLIGHT_STYLES[commandseparator]="fg=241,bg=17"
```
[gitter-image]: https://badges.gitter.im/zdharma-continuum/community.svg
[gitter-link]: https://gitter.im/zdharma-continuum/community
<!-- vim:set ft=markdown tw=100 fo+=1n: -->

View file

@ -1,5 +1,9 @@
# -*- Mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# vim:ft=zsh:sw=4:sts=4:et
#!/usr/bin/env zsh
#
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
#
# Copyright (c) 2016-2020 Sebastian Gniazdowski and contributors
# Copyright (c) 2021-2022 zdharma-continuum and contributors
# To use (when not using as plugin) copy to site-functions and issue
# (add to ~/.zshrc):
@ -50,431 +54,431 @@ trap '(( __hsmw_hcw_call_count -- )); return 0;' INT
if (( ${+functions[_hsmw_main]} == 0 )); then
_hsmw_main() {
# First call or restart?
if [[ "$__hsmw_hcw_call_count" -le 1 || "$__hsmw_hcw_restart" = "1" ]]; then
if [[ "$__hsmw_hcw_call_count" -le 1 ]]; then
# Read configuration data
zstyle -s ':history-search-multi-word' page-size __hsmw_page_size || __hsmw_page_size=$(( LINES / 3 ))
zstyle -s ':history-search-multi-word' highlight-color __hsmw_hl_color || __hsmw_hl_color="fg=yellow,bold"
zstyle -T ":plugin:history-search-multi-word" synhl && __hsmw_synhl=1 || __hsmw_synhl=0
zstyle -s ":plugin:history-search-multi-word" active __hsmw_active || __hsmw_active="underline"
zstyle -T ":plugin:history-search-multi-word" check-paths && __hsmw_no_check_paths=0 || __hsmw_no_check_paths=1
-hsmw-highlight-init
fi
_hsmw_main() {
# First call or restart?
if [[ "$__hsmw_hcw_call_count" -le 1 || "$__hsmw_hcw_restart" = "1" ]]; then
if [[ "$__hsmw_hcw_call_count" -le 1 ]]; then
# Read configuration data
zstyle -s ':history-search-multi-word' page-size __hsmw_page_size || __hsmw_page_size=$(( LINES / 3 ))
zstyle -s ':history-search-multi-word' highlight-color __hsmw_hl_color || __hsmw_hl_color="fg=yellow,bold"
zstyle -T ":plugin:history-search-multi-word" synhl && __hsmw_synhl=1 || __hsmw_synhl=0
zstyle -s ":plugin:history-search-multi-word" active __hsmw_active || __hsmw_active="underline"
zstyle -T ":plugin:history-search-multi-word" check-paths && __hsmw_no_check_paths=0 || __hsmw_no_check_paths=1
-hsmw-highlight-init
fi
# '0' will get changed into $to_display limit
[[ "$NO_MOVE" != 1 ]] && {
[[ "$WIDGET" = *-word || "$WIDGET" = *-pforwards ]] && __hsmw_hcw_index="1"
[[ "$WIDGET" = *-backwards || "$WIDGET" = *-pbackwards ]] && __hsmw_hcw_index="0"
}
__hsmw_hcw_widget_name="${${${WIDGET%-backwards}%-pbackwards}%-pforwards}"
__hsmw_hcw_found=( )
__hsmw_hcw_finished="0"
__hsmw_hcw_restart="0"
__hsmw_page_start_idx=0
__hsmw_prev_offset=0
# '0' will get changed into $to_display limit
[[ "$NO_MOVE" != 1 ]] && {
[[ "$WIDGET" = *-word || "$WIDGET" = *-pforwards ]] && __hsmw_hcw_index="1"
[[ "$WIDGET" = *-backwards || "$WIDGET" = *-pbackwards ]] && __hsmw_hcw_index="0"
}
__hsmw_hcw_widget_name="${${${WIDGET%-backwards}%-pbackwards}%-pforwards}"
__hsmw_hcw_found=( )
__hsmw_hcw_finished="0"
__hsmw_hcw_restart="0"
__hsmw_page_start_idx=0
__hsmw_prev_offset=0
(( __hsmw_ctx )) && (( ${+functions[_hsmw_ctx_off]} )) && _hsmw_ctx_off 0
(( __hsmw_ctx )) && (( ${+functions[_hsmw_ctx_off]} )) && _hsmw_ctx_off 0
else
# Showing context?
if (( __hsmw_ctx )); then
hsmw-context-main
return
fi
# Consecutive call
[[ "$NO_MOVE" != 1 ]] && {
[[ "$WIDGET" = *-word ]] && (( __hsmw_hcw_index ++ ))
[[ "$WIDGET" = *-backwards ]] && (( __hsmw_hcw_index -- ))
[[ "$WIDGET" = *-pforwards ]] && (( __hsmw_hcw_index = __hsmw_hcw_index + __hsmw_page_size ))
[[ "$WIDGET" = *-pbackwards ]] && (( __hsmw_hcw_index = __hsmw_hcw_index - __hsmw_page_size ))
}
fi
# Find history entries matching pattern *word1*~^*word2*~^*word3* etc.
local search_buffer="${BUFFER%% ##}" search_pattern="" colsearch_pattern="" nl=$'\n' MATCH MBEGIN MEND
local specch="][*?|#~^()><\\"
search_buffer="${search_buffer//(#b)((\[?##\])|([$specch]))/${${match[2]:+$match[2]}:-\\${match[3]}}}"
search_buffer="${search_buffer/(#s)\\\^/(#s)}"
search_buffer="${search_buffer/\$(#e)/(#e)}"
search_buffer="${search_buffer##[ ]##}"
# Pattern will be *foo*~^*bar* (inventor: Mikael Magnusson)
# It's: foo and not what doesn't contain bar, etc.
search_pattern="${search_buffer// ##/*~^*}"
colsearch_pattern="${search_buffer// ##/|}"
if [[ "${#__hsmw_hcw_found[@]}" -eq "0" ]]; then
# The repeat will make the matching work on a fresh heap arena
repeat 1; do
if [[ "$search_pattern" != *[A-Z]* ]]; then
# Tip: these are equal:
#__hsmw_hcw_found=( "${(@M)history:#(#i)*$~search_pattern*}" )
[[ -z "$search_pattern" ]] && __hsmw_hcw_found=( ${(u@)history} ) || __hsmw_hcw_found=( "${(u@)history[(R)(#i)*$~search_pattern*]}" )
else
# Showing context?
if (( __hsmw_ctx )); then
hsmw-context-main
return
fi
# Consecutive call
[[ "$NO_MOVE" != 1 ]] && {
[[ "$WIDGET" = *-word ]] && (( __hsmw_hcw_index ++ ))
[[ "$WIDGET" = *-backwards ]] && (( __hsmw_hcw_index -- ))
[[ "$WIDGET" = *-pforwards ]] && (( __hsmw_hcw_index = __hsmw_hcw_index + __hsmw_page_size ))
[[ "$WIDGET" = *-pbackwards ]] && (( __hsmw_hcw_index = __hsmw_hcw_index - __hsmw_page_size ))
}
__hsmw_hcw_found=( "${(u@)history[(R)*$~search_pattern*]}" )
fi
done
fi
# Find history entries matching pattern *word1*~^*word2*~^*word3* etc.
local search_buffer="${BUFFER%% ##}" search_pattern="" colsearch_pattern="" nl=$'\n' MATCH MBEGIN MEND
local specch="][*?|#~^()><\\"
search_buffer="${search_buffer//(#b)((\[?##\])|([$specch]))/${${match[2]:+$match[2]}:-\\${match[3]}}}"
search_buffer="${search_buffer/(#s)\\\^/(#s)}"
search_buffer="${search_buffer/\$(#e)/(#e)}"
search_buffer="${search_buffer##[ ]##}"
# Pattern will be *foo*~^*bar* (inventor: Mikael Magnusson)
# It's: foo and not what doesn't contain bar, etc.
search_pattern="${search_buffer// ##/*~^*}"
colsearch_pattern="${search_buffer// ##/|}"
integer max_index="${#__hsmw_hcw_found[@]}"
if [[ "$max_index" -le "0" ]]; then
POSTDISPLAY=$'\n'"No matches found"
return 0
fi
if [[ "${#__hsmw_hcw_found[@]}" -eq "0" ]]; then
# The repeat will make the matching work on a fresh heap arena
repeat 1; do
if [[ "$search_pattern" != *[A-Z]* ]]; then
# Tip: these are equal:
#__hsmw_hcw_found=( "${(@M)history:#(#i)*$~search_pattern*}" )
[[ -z "$search_pattern" ]] && __hsmw_hcw_found=( ${(u@)history} ) || __hsmw_hcw_found=( "${(u@)history[(R)(#i)*$~search_pattern*]}" )
else
__hsmw_hcw_found=( "${(u@)history[(R)*$~search_pattern*]}" )
fi
done
fi
#
# Pagination, index value guards
#
integer max_index="${#__hsmw_hcw_found[@]}"
if [[ "$max_index" -le "0" ]]; then
POSTDISPLAY=$'\n'"No matches found"
return 0
fi
integer page_size="$__hsmw_page_size"
[[ "$page_size" -gt "$max_index" ]] && page_size="$max_index"
[[ "$__hsmw_hcw_index" -le 0 ]] && __hsmw_hcw_index="$max_index"
[[ "$__hsmw_hcw_index" -gt "$max_index" ]] && __hsmw_hcw_index=1
integer page_start_idx=$(( ((__hsmw_hcw_index-1)/page_size)*page_size+1 ))
integer on_page_idx=$(( (__hsmw_hcw_index-1) % page_size + 1 ))
#
# Pagination, index value guards
#
#
# Prepare display
#
integer page_size="$__hsmw_page_size"
[[ "$page_size" -gt "$max_index" ]] && page_size="$max_index"
[[ "$__hsmw_hcw_index" -le 0 ]] && __hsmw_hcw_index="$max_index"
[[ "$__hsmw_hcw_index" -gt "$max_index" ]] && __hsmw_hcw_index=1
integer page_start_idx=$(( ((__hsmw_hcw_index-1)/page_size)*page_size+1 ))
integer on_page_idx=$(( (__hsmw_hcw_index-1) % page_size + 1 ))
(( page_start_idx != __hsmw_page_start_idx )) && {
__hsmw_disp_list=( "${(@)__hsmw_hcw_found[page_start_idx,page_start_idx+page_size-1]}" )
#
# Prepare display
#
# Don't do @ splitting, it's slower
__hsmw_disp_list_newlines=( $__hsmw_disp_list )
(( page_start_idx != __hsmw_page_start_idx )) && {
__hsmw_disp_list=( "${(@)__hsmw_hcw_found[page_start_idx,page_start_idx+page_size-1]}" )
# Replace all new lines with "\n" text
__hsmw_disp_list=( "${(@)__hsmw_disp_list//$'\n'/\\n}" )
# Truncate to display width, preceede by two spaces
__hsmw_disp_list=( "${(@)__hsmw_disp_list/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
# Don't do @ splitting, it's slower
__hsmw_disp_list_newlines=( $__hsmw_disp_list )
# Replace all new lines with "\n" text
__hsmw_disp_list=( "${(@)__hsmw_disp_list//$'\n'/\\n}" )
# Truncate to display width, preceede by two spaces
__hsmw_disp_list=( "${(@)__hsmw_disp_list/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
# The same with newlines adapted for syntax highlighting
__hsmw_disp_list_newlines=( "${(@)__hsmw_disp_list_newlines//$'\n'/ $nl}" )
__hsmw_disp_list_newlines=( "${(@)__hsmw_disp_list_newlines/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
}
#
# Detect where "> .." entry starts, add the ">" mark
#
local txt_before="${(F)${(@)__hsmw_disp_list[1,on_page_idx-1]}}"
local entry="${__hsmw_disp_list[on_page_idx]}"
local text="${(F)__hsmw_disp_list}"
integer replace_idx=${#txt_before}+2
(( replace_idx == 2 )) && replace_idx=1
text[replace_idx]=">"
#
# Colorify
#
local preamble=$'\n'"Ctrl-K context, Ctrl-J bump. Entry #$__hsmw_hcw_index of $max_index"$'\n'
integer offset=${#preamble}+${#BUFFER}
POSTDISPLAY="$preamble$text"
if (( page_start_idx != __hsmw_page_start_idx || offset != __hsmw_prev_offset )); then
region_highlight=( )
if (( __hsmw_synhl )); then
integer pre_index=$offset
local line
for line in "${__hsmw_disp_list_newlines[@]}"; do
reply=( )
-hsmw-highlight-process "$line" "$pre_index"
region_highlight+=( $reply )
pre_index+=${#line}+1
done
fi
if [[ -n "$colsearch_pattern" ]]; then
__hsmw_region_highlight_data=( )
: "${text//(#mi)(${~colsearch_pattern})/$(( hsmw_append(MBEGIN,MEND) ))}"
region_highlight+=( $__hsmw_region_highlight_data )
fi
else
region_highlight[-1]=()
fi
__hsmw_page_start_idx=page_start_idx
__hsmw_prev_offset=offset
region_highlight+=( "$(( offset + ${#txt_before} )) $(( offset + ${#txt_before} + ${#entry} + 1 )) $__hsmw_active" )
# The same with newlines adapted for syntax highlighting
__hsmw_disp_list_newlines=( "${(@)__hsmw_disp_list_newlines//$'\n'/ $nl}" )
__hsmw_disp_list_newlines=( "${(@)__hsmw_disp_list_newlines/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
}
_hsmw_shappend() {
__hsmw_region_highlight_data+=( "$(( offset + $1 - 1 )) $(( offset + $2 )) ${__hsmw_hl_color}" )
}
functions -M hsmw_append 2 2 _hsmw_shappend
#
# Detect where "> .." entry starts, add the ">" mark
#
local txt_before="${(F)${(@)__hsmw_disp_list[1,on_page_idx-1]}}"
local entry="${__hsmw_disp_list[on_page_idx]}"
local text="${(F)__hsmw_disp_list}"
integer replace_idx=${#txt_before}+2
(( replace_idx == 2 )) && replace_idx=1
text[replace_idx]=">"
#
# Colorify
#
local preamble=$'\n'"Ctrl-K context, Ctrl-J bump. Entry #$__hsmw_hcw_index of $max_index"$'\n'
integer offset=${#preamble}+${#BUFFER}
POSTDISPLAY="$preamble$text"
if (( page_start_idx != __hsmw_page_start_idx || offset != __hsmw_prev_offset )); then
region_highlight=( )
if (( __hsmw_synhl )); then
integer pre_index=$offset
local line
for line in "${__hsmw_disp_list_newlines[@]}"; do
reply=( )
-hsmw-highlight-process "$line" "$pre_index"
region_highlight+=( $reply )
pre_index+=${#line}+1
done
fi
if [[ -n "$colsearch_pattern" ]]; then
__hsmw_region_highlight_data=( )
: "${text//(#mi)(${~colsearch_pattern})/$(( hsmw_append(MBEGIN,MEND) ))}"
region_highlight+=( $__hsmw_region_highlight_data )
fi
else
region_highlight[-1]=()
fi
__hsmw_page_start_idx=page_start_idx
__hsmw_prev_offset=offset
region_highlight+=( "$(( offset + ${#txt_before} )) $(( offset + ${#txt_before} + ${#entry} + 1 )) $__hsmw_active" )
}
_hsmw_shappend() {
__hsmw_region_highlight_data+=( "$(( offset + $1 - 1 )) $(( offset + $2 )) ${__hsmw_hl_color}" )
}
functions -M hsmw_append 2 2 _hsmw_shappend
fi
_hsmw_main
_hsmw_simulate_widget() {
(( __hsmw_hcw_call_count ++ ))
_hsmw_main
(( __hsmw_hcw_call_count ++ ))
_hsmw_main
}
_hsmw_self_insert() {
LBUFFER+="${KEYS[-1]}"
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
LBUFFER+="${KEYS[-1]}"
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
}
_hsmw_backward_delete_char() {
LBUFFER="${LBUFFER%?}"
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
LBUFFER="${LBUFFER%?}"
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
}
_hsmw_delete_char() {
RBUFFER="${RBUFFER#?}"
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
RBUFFER="${RBUFFER#?}"
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
}
_hsmw_cancel_accept() {
(( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
__hsmw_hcw_index=-1
zle .accept-line
(( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
__hsmw_hcw_index=-1
zle .accept-line
}
_hsmw_backward_kill_word() {
zle .backward-kill-word
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
zle .backward-kill-word
__hsmw_hcw_restart="1"
_hsmw_simulate_widget
}
_hsmw_reset_prompt() {
zle .reset-prompt
local NO_MOVE=1
_hsmw_simulate_widget
zle .reset-prompt
local NO_MOVE=1
_hsmw_simulate_widget
}
_hsmw_jump_entry() {
local entry
if (( __hsmw_ctx )); then
local entry
if (( __hsmw_ctx )); then
integer final_hist_found_idx the_index
final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1
the_index="${__hsmw_ctx_found[final_hist_found_idx]}"
the_index+=__hsmw_ctx_idx
entry="${history[$the_index]}"
else
entry="${__hsmw_hcw_found[__hsmw_hcw_index]}"
fi
print -S "$entry"
}
if [[ "$__hsmw_hcw_call_count" -eq "1" ]]; then
# Load config of reset-prompt protection
local __hsmw_reset_prompt_protect
zstyle -t ":plugin:history-search-multi-word" reset-prompt-protect && __hsmw_reset_prompt_protect=1 || __hsmw_reset_prompt_protect=0
# Make the hsmw keymap a copy of the current main
bindkey -N hsmw emacs
local down_widget="${${${WIDGET%-backwards}%-pbackwards}%-pforwards}"
local up_widget="${down_widget}-backwards"
local pdown_widget="${down_widget}-pforwards"
local pup_widget="${down_widget}-pbackwards"
# Manual, termcap, terminfo
bindkey -M hsmw '^[OA' "$up_widget"
bindkey -M hsmw '^[OB' "$down_widget"
bindkey -M hsmw '^[[A' "$up_widget"
bindkey -M hsmw '^[[B' "$down_widget"
[[ -n "$termcap[ku]" ]] && bindkey -M hsmw "$termcap[ku]" "$up_widget"
[[ -n "$termcap[kd]" ]] && bindkey -M hsmw "$termcap[kd]" "$down_widget"
[[ -n "$termcap[kD]" ]] && bindkey -M hsmw "$termcap[kD]" .delete-char
[[ -n "$terminfo[kcuu1]" ]] && bindkey -M hsmw "$terminfo[kcuu1]" "$up_widget"
[[ -n "$terminfo[kcud1]" ]] && bindkey -M hsmw "$terminfo[kcud1]" "$down_widget"
[[ -n "$terminfo[kdch1]" ]] && bindkey -M hsmw "$terminfo[kdch1]" .delete-char
# More bindkeys, to remove influence of plugins that overload things (z-sy-h, z-au-s)
bindkey -M hsmw '^[[D' .backward-char
bindkey -M hsmw '^[[C' .forward-char
[[ -n "$termcap[kl]" ]] && bindkey -M hsmw "$termcap[kl]" .backward-char
[[ -n "$termcap[kr]" ]] && bindkey -M hsmw "$termcap[kr]" .forward-char
[[ -n "$terminfo[kcub1]" ]] && bindkey -M hsmw "$terminfo[kcub1]" .backward-char
[[ -n "$terminfo[kcuf1]" ]] && bindkey -M hsmw "$terminfo[kcuf1]" .forward-char
# Now Home/End keys, first few recorded in my .zshrc during the years sequences
bindkey -M hsmw "\e[1~" .beginning-of-line
bindkey -M hsmw "\e[7~" .beginning-of-line
bindkey -M hsmw "\e[H" .beginning-of-line
bindkey -M hsmw "\e[4~" .end-of-line
bindkey -M hsmw "\e[F" .end-of-line
bindkey -M hsmw "\e[8~" .end-of-line
[[ -n "$termcap[kh]" ]] && bindkey -M hsmw "$termcap[kh]" .beginning-of-line
[[ -n "$termcap[@7]" ]] && bindkey -M hsmw "$termcap[@7]" .end-of-line
[[ -n "$terminfo[khome]" ]] && bindkey -M hsmw "$terminfo[khome]" .beginning-of-line
[[ -n "$terminfo[kend]" ]] && bindkey -M hsmw "$terminfo[kend]" .end-of-line
# The same for Ctrl-E, Ctrl-F
bindkey -M hsmw '^A' .beginning-of-line
bindkey -M hsmw '^E' .end-of-line
# Additional keys
bindkey -M hsmw '^[b' .backward-word
bindkey -M hsmw '^[B' .backward-word
bindkey -M hsmw '^[f' .forward-word
bindkey -M hsmw '^[F' .forward-word
bindkey -M hsmw '^[w' .forward-word
bindkey -M hsmw '^[W' .forward-word
bindkey -M hsmw '^U' .kill-whole-line
zle -N _hsmw_backward_kill_word
bindkey -M hsmw '^W' _hsmw_backward_kill_word
# Additional keys
bindkey -M hsmw '^P' "$up_widget"
bindkey -M hsmw '^N' "$down_widget"
bindkey -M hsmw '^L' "$down_widget"
# Page Up, Page Down keys
[[ -n "$termcap[kP]" ]] && bindkey -M hsmw "$termcap[kP]" "$pup_widget"
[[ -n "$termcap[kN]" ]] && bindkey -M hsmw "$termcap[kN]" "$pdown_widget"
[[ -n "$terminfo[kpp]" ]] && bindkey -M hsmw "$terminfo[kpp]" "$pup_widget"
[[ -n "$terminfo[knp]" ]] && bindkey -M hsmw "$terminfo[knp]" "$pdown_widget"
# Context binding
zle -N -- hsmw-context-main
bindkey -M hsmw '^K' hsmw-context-main
# Needed for Fedora 23, zsh-5.1.1
# The self-insert widget is overloaded below
bindkey -M hsmw ' ' self-insert
# Removal of default Ctrl-R binding
bindkey -M hsmw '^R' "$down_widget"
# Jump binding
zle -N -- _hsmw_jump_entry
bindkey -M hsmw '^J' _hsmw_jump_entry
# Substitute self-insert, backward-delete-char, delete-char
zle -A self-insert hsmw-saved-self-insert
zle -N self-insert _hsmw_self_insert
zle -A backward-delete-char hsmw-saved-backward-delete-char
zle -N backward-delete-char _hsmw_backward_delete_char
zle -A delete-char hsmw-saved-delete-char
zle -N delete-char _hsmw_delete_char
(( __hsmw_reset_prompt_protect )) && zle -A reset-prompt hsmw-saved-reset-prompt
(( __hsmw_reset_prompt_protect )) && zle -N reset-prompt _hsmw_reset_prompt
if (( ${+functions[azhw:zle-line-pre-redraw]} )); then
functions[zle-line-pre-redraw-bkp]=${functions[azhw:zle-line-pre-redraw]}
functions[azhw:zle-line-pre-redraw]=":"
fi
if (( ${+functions[azhw:zle-line-finish]} )); then
functions[zle-line-finish-bkp]=${functions[azhw:zle-line-finish]}
functions[azhw:zle-line-finish]=":"
fi
# OMZ does funny things with zle-keymap-select
zle -la zle-keymap-select && {
zle -A zle-keymap-select hsmw-saved-zle-keymap-select
zle -D zle-keymap-select
}
zle -la zle-line-pre-redraw && {
zle -A zle-line-pre-redraw hsmw-saved-zle-line-pre-redraw
zle -D zle-line-pre-redraw
}
# Override ourselves with what we actually are
# because zsh-autosuggestions change us
zle -A "$down_widget" hsmw-saved-"$down_widget"
zle -A "$up_widget" hsmw-saved-"$up_widget"
zle -N "$down_widget" _hsmw_simulate_widget
zle -N "$up_widget" _hsmw_simulate_widget
zle -A "$pdown_widget" hsmw-saved-"$pdown_widget"
zle -A "$pup_widget" hsmw-saved-"$pup_widget"
zle -N "$pdown_widget" _hsmw_simulate_widget
zle -N "$pup_widget" _hsmw_simulate_widget
# Add Ctrl-V binding to cancel search
# A workaround for Zsh versions like 5.0.2
zle -N _hsmw_cancel_accept
bindkey -M hsmw "^V" _hsmw_cancel_accept
bindkey -M hsmw "^[" _hsmw_cancel_accept
# Load cancel behavior
local __hsmw_conc
zstyle -t ":plugin:history-search-multi-word" clear-on-cancel && __hsmw_conc=1 || __hsmw_conc=0
# Trap INT to manually interrupt Zle to work around a bug
__hsmw_recedit_trap_executed=0
trap '(( __hsmw_recedit_trap_executed == 0 )) && zle && { __hsmw_recedit_trap_executed=1; zle .send-break; }' INT
if zle .recursive-edit -K hsmw; then
trap '' INT
if [[ "$__hsmw_hcw_index" -gt "0" ]]; then
if (( __hsmw_ctx )); then
integer final_hist_found_idx the_index
final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1
the_index="${__hsmw_ctx_found[final_hist_found_idx]}"
the_index+=__hsmw_ctx_idx
entry="${history[$the_index]}"
BUFFER="${history[$the_index]}"
else
BUFFER="${__hsmw_hcw_found[__hsmw_hcw_index]}"
fi
CURSOR="${#BUFFER}"
else
entry="${__hsmw_hcw_found[__hsmw_hcw_index]}"
(( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
fi
else
trap '' INT
(( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
fi
print -S "$entry"
}
POSTDISPLAY=""
(( ${+functions[_hsmw_ctx_off]} )) && _hsmw_ctx_off 0
if [[ "$__hsmw_hcw_call_count" -eq "1" ]]; then
# Load config of reset-prompt protection
local __hsmw_reset_prompt_protect
zstyle -t ":plugin:history-search-multi-word" reset-prompt-protect && __hsmw_reset_prompt_protect=1 || __hsmw_reset_prompt_protect=0
# Restore self-insert, backward-delete-char, delete-char
zle -A hsmw-saved-self-insert self-insert
zle -A hsmw-saved-backward-delete-char backward-delete-char
zle -A hsmw-saved-delete-char delete-char
(( __hsmw_reset_prompt_protect )) && zle -A hsmw-saved-reset-prompt reset-prompt
zle -D hsmw-saved-self-insert hsmw-saved-backward-delete-char hsmw-saved-delete-char
(( __hsmw_reset_prompt_protect )) && zle -D hsmw-saved-reset-prompt
zle -la hsmw-saved-zle-keymap-select && {
zle -A hsmw-saved-zle-keymap-select zle-keymap-select
zle -D hsmw-saved-zle-keymap-select
}
zle -la zle-line-pre-redraw && {
zle -A hsmw-saved-zle-line-pre-redraw zle-line-pre-redraw
zle -D hsmw-saved-zle-line-pre-redraw
}
# Make the hsmw keymap a copy of the current main
bindkey -N hsmw emacs
# Restore ourselves
zle -A hsmw-saved-"$down_widget" "$down_widget"
zle -A hsmw-saved-"$up_widget" "$up_widget"
zle -D hsmw-saved-"$down_widget" hsmw-saved-"$up_widget"
local down_widget="${${${WIDGET%-backwards}%-pbackwards}%-pforwards}"
local up_widget="${down_widget}-backwards"
local pdown_widget="${down_widget}-pforwards"
local pup_widget="${down_widget}-pbackwards"
zle -A hsmw-saved-"$pdown_widget" "$pdown_widget"
zle -A hsmw-saved-"$pup_widget" "$pup_widget"
zle -D hsmw-saved-"$pdown_widget" hsmw-saved-"$pup_widget"
# Manual, termcap, terminfo
bindkey -M hsmw '^[OA' "$up_widget"
bindkey -M hsmw '^[OB' "$down_widget"
bindkey -M hsmw '^[[A' "$up_widget"
bindkey -M hsmw '^[[B' "$down_widget"
[[ -n "$termcap[ku]" ]] && bindkey -M hsmw "$termcap[ku]" "$up_widget"
[[ -n "$termcap[kd]" ]] && bindkey -M hsmw "$termcap[kd]" "$down_widget"
[[ -n "$termcap[kD]" ]] && bindkey -M hsmw "$termcap[kD]" .delete-char
[[ -n "$terminfo[kcuu1]" ]] && bindkey -M hsmw "$terminfo[kcuu1]" "$up_widget"
[[ -n "$terminfo[kcud1]" ]] && bindkey -M hsmw "$terminfo[kcud1]" "$down_widget"
[[ -n "$terminfo[kdch1]" ]] && bindkey -M hsmw "$terminfo[kdch1]" .delete-char
if (( ${+functions[azhw:zle-line-pre-redraw]} )); then
functions[azhw:zle-line-pre-redraw]=${functions[zle-line-pre-redraw-bkp]}
fi
# More bindkeys, to remove influence of plugins that overload things (z-sy-h, z-au-s)
bindkey -M hsmw '^[[D' .backward-char
bindkey -M hsmw '^[[C' .forward-char
[[ -n "$termcap[kl]" ]] && bindkey -M hsmw "$termcap[kl]" .backward-char
[[ -n "$termcap[kr]" ]] && bindkey -M hsmw "$termcap[kr]" .forward-char
[[ -n "$terminfo[kcub1]" ]] && bindkey -M hsmw "$terminfo[kcub1]" .backward-char
[[ -n "$terminfo[kcuf1]" ]] && bindkey -M hsmw "$terminfo[kcuf1]" .forward-char
# Now Home/End keys, first few recorded in my .zshrc during the years sequences
bindkey -M hsmw "\e[1~" .beginning-of-line
bindkey -M hsmw "\e[7~" .beginning-of-line
bindkey -M hsmw "\e[H" .beginning-of-line
bindkey -M hsmw "\e[4~" .end-of-line
bindkey -M hsmw "\e[F" .end-of-line
bindkey -M hsmw "\e[8~" .end-of-line
[[ -n "$termcap[kh]" ]] && bindkey -M hsmw "$termcap[kh]" .beginning-of-line
[[ -n "$termcap[@7]" ]] && bindkey -M hsmw "$termcap[@7]" .end-of-line
[[ -n "$terminfo[khome]" ]] && bindkey -M hsmw "$terminfo[khome]" .beginning-of-line
[[ -n "$terminfo[kend]" ]] && bindkey -M hsmw "$terminfo[kend]" .end-of-line
# The same for Ctrl-E, Ctrl-F
bindkey -M hsmw '^A' .beginning-of-line
bindkey -M hsmw '^E' .end-of-line
# Additional keys
bindkey -M hsmw '^[b' .backward-word
bindkey -M hsmw '^[B' .backward-word
bindkey -M hsmw '^[f' .forward-word
bindkey -M hsmw '^[F' .forward-word
bindkey -M hsmw '^[w' .forward-word
bindkey -M hsmw '^[W' .forward-word
bindkey -M hsmw '^U' .kill-whole-line
zle -N _hsmw_backward_kill_word
bindkey -M hsmw '^W' _hsmw_backward_kill_word
if (( ${+functions[azhw:zle-line-finish]} )); then
functions[azhw:zle-line-finish]=${functions[zle-line-finish-bkp]}
fi
# Additional keys
bindkey -M hsmw '^P' "$up_widget"
bindkey -M hsmw '^N' "$down_widget"
bindkey -M hsmw '^L' "$down_widget"
# Full reinitialisation at next call
__hsmw_hcw_call_count="0"
# Page Up, Page Down keys
[[ -n "$termcap[kP]" ]] && bindkey -M hsmw "$termcap[kP]" "$pup_widget"
[[ -n "$termcap[kN]" ]] && bindkey -M hsmw "$termcap[kN]" "$pdown_widget"
[[ -n "$terminfo[kpp]" ]] && bindkey -M hsmw "$terminfo[kpp]" "$pup_widget"
[[ -n "$terminfo[knp]" ]] && bindkey -M hsmw "$terminfo[knp]" "$pdown_widget"
zle reset-prompt
# Context binding
zle -N -- hsmw-context-main
bindkey -M hsmw '^K' hsmw-context-main
# Needed for Fedora 23, zsh-5.1.1
# The self-insert widget is overloaded below
bindkey -M hsmw ' ' self-insert
# Removal of default Ctrl-R binding
bindkey -M hsmw '^R' "$down_widget"
# Jump binding
zle -N -- _hsmw_jump_entry
bindkey -M hsmw '^J' _hsmw_jump_entry
# Substitute self-insert, backward-delete-char, delete-char
zle -A self-insert hsmw-saved-self-insert
zle -N self-insert _hsmw_self_insert
zle -A backward-delete-char hsmw-saved-backward-delete-char
zle -N backward-delete-char _hsmw_backward_delete_char
zle -A delete-char hsmw-saved-delete-char
zle -N delete-char _hsmw_delete_char
(( __hsmw_reset_prompt_protect )) && zle -A reset-prompt hsmw-saved-reset-prompt
(( __hsmw_reset_prompt_protect )) && zle -N reset-prompt _hsmw_reset_prompt
if (( ${+functions[azhw:zle-line-pre-redraw]} )); then
functions[zle-line-pre-redraw-bkp]=${functions[azhw:zle-line-pre-redraw]}
functions[azhw:zle-line-pre-redraw]=":"
fi
if (( ${+functions[azhw:zle-line-finish]} )); then
functions[zle-line-finish-bkp]=${functions[azhw:zle-line-finish]}
functions[azhw:zle-line-finish]=":"
fi
# OMZ does funny things with zle-keymap-select
zle -la zle-keymap-select && {
zle -A zle-keymap-select hsmw-saved-zle-keymap-select
zle -D zle-keymap-select
}
zle -la zle-line-pre-redraw && {
zle -A zle-line-pre-redraw hsmw-saved-zle-line-pre-redraw
zle -D zle-line-pre-redraw
}
# Override ourselves with what we actually are
# because zsh-autosuggestions change us
zle -A "$down_widget" hsmw-saved-"$down_widget"
zle -A "$up_widget" hsmw-saved-"$up_widget"
zle -N "$down_widget" _hsmw_simulate_widget
zle -N "$up_widget" _hsmw_simulate_widget
zle -A "$pdown_widget" hsmw-saved-"$pdown_widget"
zle -A "$pup_widget" hsmw-saved-"$pup_widget"
zle -N "$pdown_widget" _hsmw_simulate_widget
zle -N "$pup_widget" _hsmw_simulate_widget
# Add Ctrl-V binding to cancel search
# A workaround for Zsh versions like 5.0.2
zle -N _hsmw_cancel_accept
bindkey -M hsmw "^V" _hsmw_cancel_accept
bindkey -M hsmw "^[" _hsmw_cancel_accept
# Load cancel behavior
local __hsmw_conc
zstyle -t ":plugin:history-search-multi-word" clear-on-cancel && __hsmw_conc=1 || __hsmw_conc=0
# Trap INT to manually interrupt Zle to work around a bug
__hsmw_recedit_trap_executed=0
trap '(( __hsmw_recedit_trap_executed == 0 )) && zle && { __hsmw_recedit_trap_executed=1; zle .send-break; }' INT
if zle .recursive-edit -K hsmw; then
trap '' INT
if [[ "$__hsmw_hcw_index" -gt "0" ]]; then
if (( __hsmw_ctx )); then
integer final_hist_found_idx the_index
final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1
the_index="${__hsmw_ctx_found[final_hist_found_idx]}"
the_index+=__hsmw_ctx_idx
BUFFER="${history[$the_index]}"
else
BUFFER="${__hsmw_hcw_found[__hsmw_hcw_index]}"
fi
CURSOR="${#BUFFER}"
else
(( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
fi
else
trap '' INT
(( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
fi
POSTDISPLAY=""
(( ${+functions[_hsmw_ctx_off]} )) && _hsmw_ctx_off 0
# Restore self-insert, backward-delete-char, delete-char
zle -A hsmw-saved-self-insert self-insert
zle -A hsmw-saved-backward-delete-char backward-delete-char
zle -A hsmw-saved-delete-char delete-char
(( __hsmw_reset_prompt_protect )) && zle -A hsmw-saved-reset-prompt reset-prompt
zle -D hsmw-saved-self-insert hsmw-saved-backward-delete-char hsmw-saved-delete-char
(( __hsmw_reset_prompt_protect )) && zle -D hsmw-saved-reset-prompt
zle -la hsmw-saved-zle-keymap-select && {
zle -A hsmw-saved-zle-keymap-select zle-keymap-select
zle -D hsmw-saved-zle-keymap-select
}
zle -la zle-line-pre-redraw && {
zle -A hsmw-saved-zle-line-pre-redraw zle-line-pre-redraw
zle -D hsmw-saved-zle-line-pre-redraw
}
# Restore ourselves
zle -A hsmw-saved-"$down_widget" "$down_widget"
zle -A hsmw-saved-"$up_widget" "$up_widget"
zle -D hsmw-saved-"$down_widget" hsmw-saved-"$up_widget"
zle -A hsmw-saved-"$pdown_widget" "$pdown_widget"
zle -A hsmw-saved-"$pup_widget" "$pup_widget"
zle -D hsmw-saved-"$pdown_widget" hsmw-saved-"$pup_widget"
if (( ${+functions[azhw:zle-line-pre-redraw]} )); then
functions[azhw:zle-line-pre-redraw]=${functions[zle-line-pre-redraw-bkp]}
fi
if (( ${+functions[azhw:zle-line-finish]} )); then
functions[azhw:zle-line-finish]=${functions[zle-line-finish-bkp]}
fi
# Full reinitialisation at next call
__hsmw_hcw_call_count="0"
zle reset-prompt
# Free memory
#__hsmw_hcw_found=( )
# Free memory
#__hsmw_hcw_found=( )
elif (( __hsmw_hcw_call_count > 0 )); then
(( __hsmw_hcw_call_count -- ))
(( __hsmw_hcw_call_count -- ))
fi

View file

@ -1,5 +1,9 @@
# -*- Mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# vim:ft=zsh:sw=4:sts=4:et
#!/usr/bin/env zsh
#
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
#
# Copyright (c) 2016-2020 Sebastian Gniazdowski and contributors
# Copyright (c) 2021-2022 zdharma-continuum and contributors
#
# No plugin manager is needed to use this file. All that is needed is adding:
@ -16,7 +20,7 @@ HSMW_REPO_DIR="${0:h}"
if [[ ${zsh_loaded_plugins[-1]} != */history-search-multi-word && -z ${fpath[(r)${0:h}]} ]]
then
fpath+=( "${0:h}" )
fpath+=( "${0:h}" )
fi
autoload history-search-multi-word hsmw-context-main
@ -25,10 +29,10 @@ zle -N history-search-multi-word-backwards history-search-multi-word
zle -N history-search-multi-word-pbackwards history-search-multi-word
zle -N history-search-multi-word-pforwards history-search-multi-word
[[ ${+termcap[Co]} = 1 && ${termcap[Co]} = 256 ]] && {
zstyle -s ":history-search-multi-word" highlight-color tmp || \
zstyle ":history-search-multi-word" highlight-color "bg=17"
typeset -gA HSMW_HIGHLIGHT_STYLES
[[ ${HSMW_HIGHLIGHT_STYLES[variable]} = none ]] && \
HSMW_HIGHLIGHT_STYLES[variable]="fg=112"
zstyle -s ":history-search-multi-word" highlight-color tmp || \
zstyle ":history-search-multi-word" highlight-color "bg=17"
typeset -gA HSMW_HIGHLIGHT_STYLES
[[ ${HSMW_HIGHLIGHT_STYLES[variable]} = none ]] && \
HSMW_HIGHLIGHT_STYLES[variable]="fg=112"
}
bindkey "^R" history-search-multi-word

View file

@ -1,170 +1,145 @@
# -*- Mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# vim:ft=zsh:sw=4:sts=4:et
#!/usr/bin/env zsh
#
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
#
# Copyright (c) 2016-2020 Sebastian Gniazdowski and contributors
# Copyright (c) 2021-2022 zdharma-continuum and contributors
__hsmw_ctx_prev_idx="$__hsmw_ctx_idx"
[[ "$WIDGET" = *-word ]] && (( __hsmw_ctx_idx -- ))
[[ "$WIDGET" = *-backwards ]] && (( __hsmw_ctx_idx ++ ))
[[ "$WIDGET" = *-pforwards ]] && (( __hsmw_ctx_idx = __hsmw_ctx_idx - __hsmw_page_size ))
[[ "$WIDGET" = *-pbackwards ]] && (( __hsmw_ctx_idx = __hsmw_ctx_idx + __hsmw_page_size ))
_hsmw_ctx_up() {
(( __hsmw_ctx_which -- ))
(( __hsmw_ctx_which < 0 )) && __hsmw_ctx_which=${#__hsmw_ctx_found}-1
__hsmw_ctx_idx=0
_hsmw_ctx_main
(( __hsmw_ctx_which -- ))
(( __hsmw_ctx_which < 0 )) && __hsmw_ctx_which=${#__hsmw_ctx_found}-1
__hsmw_ctx_idx=0
_hsmw_ctx_main
}
_hsmw_ctx_down() {
(( __hsmw_ctx_which ++ ))
(( __hsmw_ctx_which >= ${#__hsmw_ctx_found} )) && __hsmw_ctx_which=0
__hsmw_ctx_idx=0
_hsmw_ctx_main
(( __hsmw_ctx_which ++ ))
(( __hsmw_ctx_which >= ${#__hsmw_ctx_found} )) && __hsmw_ctx_which=0
__hsmw_ctx_idx=0
_hsmw_ctx_main
}
_hsmw_ctx_off() {
__hsmw_ctx_to_search=""
__hsmw_ctx_found=( )
__hsmw_ctx_which=0
__hsmw_ctx_idx=0
__hsmw_ctx_page_start_idx=0
__hsmw_ctx_prev_offset=0
__hsmw_ctx=0
# Reset main state so that it re-highlights
__hsmw_prev_offset=0
zle -la _hsmw_ctx_down && zle -D _hsmw_ctx_down
zle -la _hsmw_ctx_up && zle -D _hsmw_ctx_up
bindkey -M hsmw '^N' "history-search-multi-word"
bindkey -M hsmw '^P' "history-search-multi-word-backwards"
(( ${1}+0 )) && _hsmw_simulate_widget
__hsmw_ctx=0
__hsmw_ctx_found=( )
__hsmw_ctx_idx=0
__hsmw_ctx_page_start_idx=0
__hsmw_ctx_prev_offset=0
__hsmw_ctx_to_search=""
__hsmw_ctx_which=0
# Reset main state so that it re-highlights
__hsmw_prev_offset=0
zle -la _hsmw_ctx_down && zle -D _hsmw_ctx_down
zle -la _hsmw_ctx_up && zle -D _hsmw_ctx_up
bindkey -M hsmw '^N' "history-search-multi-word"
bindkey -M hsmw '^P' "history-search-multi-word-backwards"
(( ${1}+0 )) && _hsmw_simulate_widget
}
if [[ "$WIDGET" = "hsmw-context-main" ]]; then
__hsmw_ctx=1-__hsmw_ctx
if (( __hsmw_ctx == 0 )); then
_hsmw_ctx_off 1
return
fi
zle -N _hsmw_ctx_down
zle -N _hsmw_ctx_up
bindkey -M hsmw '^N' "_hsmw_ctx_down"
bindkey -M hsmw '^P' "_hsmw_ctx_up"
__hsmw_ctx=1-__hsmw_ctx
if (( __hsmw_ctx == 0 )); then
_hsmw_ctx_off 1
return
fi
zle -N _hsmw_ctx_down
zle -N _hsmw_ctx_up
bindkey -M hsmw '^N' "_hsmw_ctx_down"
bindkey -M hsmw '^P' "_hsmw_ctx_up"
fi
_hsmw_ctx_main() {
# The repeat will make the matching work on a fresh heap arena
local to_search="${__hsmw_hcw_found[__hsmw_hcw_index]}" nl=$'\n'
to_search="${to_search//(#m)[][*?|#~^()><\\]/\\$MATCH}"
if [[ "$to_search" != "$__hsmw_ctx_to_search" ]]; then
__hsmw_ctx_to_search="$to_search"
repeat 1; do
__hsmw_ctx_found=( "${(@kv)history[(R)$to_search]}" )
__hsmw_ctx_text_idx="${__hsmw_ctx_found[(I)$to_search]}"
if [[ "$__hsmw_ctx_text_idx" = "0" ]]; then
_hsmw_ctx_off 1
return 0
fi
__hsmw_ctx_found[__hsmw_ctx_text_idx]=()
done
fi
integer final_hist_found_idx
final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1
integer the_index="${__hsmw_ctx_found[final_hist_found_idx]}"
the_index=the_index+__hsmw_ctx_idx
integer max_index=$(( ${${(k)history[@]}[1]} + 1 ))
if [[ "$max_index" -le "0" ]]; then
POSTDISPLAY=$'\n'"No matches found"
# The repeat will make the matching work on a fresh heap arena
local to_search="${__hsmw_hcw_found[__hsmw_hcw_index]}" nl=$'\n'
to_search="${to_search//(#m)[][*?|#~^()><\\]/\\$MATCH}"
if [[ "$to_search" != "$__hsmw_ctx_to_search" ]]; then
__hsmw_ctx_to_search="$to_search"
repeat 1; do
__hsmw_ctx_found=( "${(@kv)history[(R)$to_search]}" )
__hsmw_ctx_text_idx="${__hsmw_ctx_found[(I)$to_search]}"
if [[ "$__hsmw_ctx_text_idx" = "0" ]]; then
_hsmw_ctx_off 1
return 0
fi
__hsmw_ctx_found[__hsmw_ctx_text_idx]=()
done
fi
integer final_hist_found_idx
final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1
integer the_index="${__hsmw_ctx_found[final_hist_found_idx]}"
the_index=the_index+__hsmw_ctx_idx
integer max_index=$(( ${${(k)history[@]}[1]} + 1 ))
if [[ "$max_index" -le "0" ]]; then
POSTDISPLAY=$'\n'"No matches found"
return 0
fi
#
# Pagination, index value guards
#
integer page_size="$__hsmw_page_size"
[[ "$page_size" -gt "$max_index" ]] && page_size="$max_index"
[[ "$the_index" -le 0 ]] && { __hsmw_ctx_idx="$__hsmw_ctx_prev_idx"; the_index=1; }
[[ "$the_index" -gt "$(( max_index - 1))" ]] && { __hsmw_ctx_idx="$__hsmw_ctx_prev_idx"; the_index="$(( max_index - 1 ))"; }
integer page_start_idx=$(( ((the_index-1)/page_size)*page_size+1 ))
integer on_page_idx=$(( page_size - (the_index - page_start_idx) ))
#
# Prepare display
#
if [[ "$page_start_idx" != "$__hsmw_ctx_page_start_idx" ]]; then
integer idx
__hsmw_ctx_disp_list=( )
for (( idx = page_start_idx + page_size - 1; idx >= page_start_idx ; idx -- )); do
__hsmw_ctx_disp_list+=( "${history[$idx]}" )
done
# Don't do @ splitting, it's slower
__hsmw_ctx_disp_list_newlines=( "${__hsmw_ctx_disp_list[@]}" )
# Replace all new lines with "\n" text
__hsmw_ctx_disp_list=( "${(@)__hsmw_ctx_disp_list//$'\n'/\\n}" )
# Truncate to display width, preceede by two spaces
__hsmw_ctx_disp_list=( "${(@)__hsmw_ctx_disp_list/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
# The same with newlines adapted for syntax highlighting
__hsmw_ctx_disp_list_newlines=( "${(@)__hsmw_ctx_disp_list_newlines//$'\n'/ $nl}" )
__hsmw_ctx_disp_list_newlines=( "${(@)__hsmw_ctx_disp_list_newlines/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
fi
#
# Detect where "> .." entry starts, add the ">" mark
#
local txt_before="${(F)${(@)__hsmw_ctx_disp_list[1,on_page_idx-1]}}"
local entry="${__hsmw_ctx_disp_list[on_page_idx]}"
local text="${(F)__hsmw_ctx_disp_list}"
integer replace_idx=${#txt_before}+2
(( replace_idx == 2 )) && replace_idx=1
text[replace_idx]=">"
#
# Colorify
#
local preamble=$'\n'"Showing context of history entry. Ctrl-K to return to search."
local preamble2=$'\n'"Ctrl-N/P: next/previous occurence. Occurence #$(( __hsmw_ctx_which + 1 )) of ${#__hsmw_ctx_found}"
preamble2=${(r:${#preamble}:: :)preamble2}$'\n'
preamble+=$preamble2
integer offset=${#preamble}+${#BUFFER}
POSTDISPLAY="$preamble$text"
if (( page_start_idx != __hsmw_ctx_page_start_idx || offset != __hsmw_ctx_prev_offset )); then
region_highlight=( "${#BUFFER} $offset bg=22" )
if (( __hsmw_synhl )); then
integer pre_index=$offset
local line
for line in "${__hsmw_ctx_disp_list_newlines[@]}"; do
reply=( )
-hsmw-highlight-process "$line" "$pre_index"
region_highlight+=( $reply )
pre_index+=${#line}+1
done
fi
#
# Pagination, index value guards
#
integer page_size="$__hsmw_page_size"
[[ "$page_size" -gt "$max_index" ]] && page_size="$max_index"
[[ "$the_index" -le 0 ]] && { __hsmw_ctx_idx="$__hsmw_ctx_prev_idx"; the_index=1; }
[[ "$the_index" -gt "$(( max_index - 1))" ]] && { __hsmw_ctx_idx="$__hsmw_ctx_prev_idx"; the_index="$(( max_index - 1 ))"; }
integer page_start_idx=$(( ((the_index-1)/page_size)*page_size+1 ))
integer on_page_idx=$(( page_size - (the_index - page_start_idx) ))
#
# Prepare display
#
if [[ "$page_start_idx" != "$__hsmw_ctx_page_start_idx" ]]; then
integer idx
__hsmw_ctx_disp_list=( )
for (( idx = page_start_idx + page_size - 1; idx >= page_start_idx ; idx -- )); do
__hsmw_ctx_disp_list+=( "${history[$idx]}" )
done
# Don't do @ splitting, it's slower
__hsmw_ctx_disp_list_newlines=( "${__hsmw_ctx_disp_list[@]}" )
# Replace all new lines with "\n" text
__hsmw_ctx_disp_list=( "${(@)__hsmw_ctx_disp_list//$'\n'/\\n}" )
# Truncate to display width, preceede by two spaces
__hsmw_ctx_disp_list=( "${(@)__hsmw_ctx_disp_list/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
# The same with newlines adapted for syntax highlighting
__hsmw_ctx_disp_list_newlines=( "${(@)__hsmw_ctx_disp_list_newlines//$'\n'/ $nl}" )
__hsmw_ctx_disp_list_newlines=( "${(@)__hsmw_ctx_disp_list_newlines/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
fi
#
# Detect where "> .." entry starts, add the ">" mark
#
local txt_before="${(F)${(@)__hsmw_ctx_disp_list[1,on_page_idx-1]}}"
local entry="${__hsmw_ctx_disp_list[on_page_idx]}"
local text="${(F)__hsmw_ctx_disp_list}"
integer replace_idx=${#txt_before}+2
(( replace_idx == 2 )) && replace_idx=1
text[replace_idx]=">"
#
# Colorify
#
local preamble=$'\n'"Showing context of history entry. Ctrl-K to return to search."
local preamble2=$'\n'"Ctrl-N/P: next/previous occurence. Occurence #$(( __hsmw_ctx_which + 1 )) of ${#__hsmw_ctx_found}"
preamble2=${(r:${#preamble}:: :)preamble2}$'\n'
preamble+=$preamble2
integer offset=${#preamble}+${#BUFFER}
POSTDISPLAY="$preamble$text"
if (( page_start_idx != __hsmw_ctx_page_start_idx || offset != __hsmw_ctx_prev_offset )); then
region_highlight=( "${#BUFFER} $offset bg=22" )
if (( __hsmw_synhl )); then
integer pre_index=$offset
local line
for line in "${__hsmw_ctx_disp_list_newlines[@]}"; do
reply=( )
-hsmw-highlight-process "$line" "$pre_index"
region_highlight+=( $reply )
pre_index+=${#line}+1
done
fi
else
region_highlight[-1]=()
fi
__hsmw_ctx_page_start_idx=page_start_idx
__hsmw_ctx_prev_offset=offset
region_highlight+=( "$(( offset + ${#txt_before} )) $(( offset + ${#txt_before} + ${#entry} + 1 )) $__hsmw_active" )
else
region_highlight[-1]=()
fi
__hsmw_ctx_page_start_idx=page_start_idx
__hsmw_ctx_prev_offset=offset
region_highlight+=( "$(( offset + ${#txt_before} )) $(( offset + ${#txt_before} + ${#entry} + 1 )) $__hsmw_active" )
}
_hsmw_ctx_main

View file

@ -1,32 +1,11 @@
# -*- Mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
# vim:ft=zsh:sw=2:sts=2:et
# -------------------------------------------------------------------------------------------------
#!/usr/bin/env zsh
#
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
#
# Copyright (c) 2010-2016 zsh-syntax-highlighting contributors
# Copyright (c) 2016-2017 Sebastian Gniazdowski (modifications)
# 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.
# -------------------------------------------------------------------------------------------------
# Copyright (c) 2021-2022 zdharma-continuum and contributors
typeset -gA __hsmw_highlight_main__command_type_cache
@ -103,60 +82,41 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
'|&' 3
'&!' 3
'&|' 3
# ### 'case' syntax, but followed by a pattern, not by a command
# ';;' ';&' ';|'
)
# Get the type of a command.
#
# Uses the zsh/parameter module if available to avoid forks, and a
# wrapper around 'type -w' as fallback.
#
# Takes a single argument.
#
# The result will be stored in REPLY.
-hsmw-highlight-main-type() {
REPLY=$__hsmw_highlight_main__command_type_cache[(e)$1]
[[ -z "$REPLY" ]] && {
if zmodload -e zsh/parameter; then
if (( $+aliases[(e)$1] )); then
REPLY=alias
elif (( $+functions[(e)$1] )); then
REPLY=function
elif (( $+builtins[(e)$1] )); then
REPLY=builtin
elif (( $+commands[(e)$1] )); then
REPLY=command
elif (( $+saliases[(e)${1##*.}] )); then
REPLY='suffix alias'
elif (( $reswords[(Ie)$1] )); then
REPLY=reserved
# zsh 5.2 and older have a bug whereby running 'type -w ./sudo' implicitly
# runs 'hash ./sudo=/usr/local/bin/./sudo' (assuming /usr/local/bin/sudo
# exists and is in $PATH). Avoid triggering the bug, at the expense of
# falling through to the $() below, incurring a fork. (Issue #354.)
#
# The second disjunct mimics the isrelative() C call from the zsh bug.
elif [[ $1 != */* || "${+ZSH_ARGZERO}" = "1" ]] && ! builtin type -w -- $1 >/dev/null 2>&1; then
REPLY=none
if zmodload -e zsh/parameter; then
if (( $+aliases[(e)$1] )); then
REPLY=alias
elif (( $+functions[(e)$1] )); then
REPLY=function
elif (( $+builtins[(e)$1] )); then
REPLY=builtin
elif (( $+commands[(e)$1] )); then
REPLY=command
elif (( $+saliases[(e)${1##*.}] )); then
REPLY='suffix alias'
elif (( $reswords[(Ie)$1] )); then
REPLY=reserved
elif [[ $1 != */* || "${+ZSH_ARGZERO}" = "1" ]] && ! builtin type -w -- $1 >/dev/null 2>&1; then
REPLY=none
fi
fi
fi
[[ -z "$REPLY" ]] && REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)##*: }"
[[ -z "$REPLY" ]] && REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)##*: }"
[[ "$REPLY" = "none" ]] && {
[[ -d "$1" ]] && REPLY="dirpath" || {
for cdpath_dir in $cdpath; do
[[ -d "$cdpath_dir/$1" ]] && { REPLY="dirpath"; break; }
done
[[ "$REPLY" = "none" ]] && {
[[ -d "$1" ]] && REPLY="dirpath" || {
for cdpath_dir in $cdpath; do
[[ -d "$cdpath_dir/$1" ]] && { REPLY="dirpath"; break; }
done
}
}
}
__hsmw_highlight_main__command_type_cache[(e)$1]=$REPLY
__hsmw_highlight_main__command_type_cache[(e)$1]=$REPLY
}
}
@ -199,8 +159,7 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
}
# Main syntax highlighting function.
-hsmw-highlight-process()
{
-hsmw-highlight-process() {
emulate -L zsh
setopt extendedglob bareglobqual nonomatch noksharrays
@ -218,64 +177,13 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
integer arg_type=0 MBEGIN MEND in_redirection len=${#buf} already_added offset idx end_idx this_word=1 next_word=0 insane_alias
local -a match mbegin mend
# integer BIT_start=1 BIT_regular=2 BIT_sudo_opt=4 BIT_sudo_arg=8 BIT_always=16
# State machine
#
# The states are:
# - :start: Command word
# - :sudo_opt: A leading-dash option to sudo (such as "-u" or "-i")
# - :sudo_arg: The argument to a sudo leading-dash option that takes one,
# when given as a separate word; i.e., "foo" in "-u foo" (two
# words) but not in "-ufoo" (one word).
# - :regular: "Not a command word", and command delimiters are permitted.
# Mainly used to detect premature termination of commands.
# - :always: The word 'always' in the «{ foo } always { bar }» syntax.
#
# When the kind of a word is not yet known, $this_word / $next_word may contain
# multiple states. For example, after "sudo -i", the next word may be either
# another --flag or a command name, hence the state would include both :start:
# and :sudo_opt:.
#
# The tokens are always added with both leading and trailing colons to serve as
# word delimiters (an improvised array); [[ $x == *:foo:* ]] and x=${x//:foo:/}
# will DTRT regardless of how many elements or repetitions $x has..
#
# Handling of redirections: upon seeing a redirection token, we must stall
# the current state --- that is, the value of $this_word --- for two iterations
# (one for the redirection operator, one for the word following it representing
# the redirection target). Therefore, we set $in_redirection to 2 upon seeing a
# redirection operator, decrement it each iteration, and stall the current state
# when it is non-zero. Thus, upon reaching the next word (the one that follows
# the redirection operator and target), $this_word will still contain values
# appropriate for the word immediately following the word that preceded the
# redirection operator.
#
# The "the previous word was a redirection operator" state is not communicated
# to the next iteration via $next_word/$this_word as usual, but via
# $in_redirection. The value of $next_word from the iteration that processed
# the operator is discarded.
#
# Processing buffer
local proc_buf="$buf" needle
for arg in ${interactive_comments-${(z)buf}} \
${interactive_comments+${(zZ+c+)buf}}; do
for arg in ${interactive_comments-${(z)buf}} ${interactive_comments+${(zZ+c+)buf}}; do
# Initialize $next_word to its default value?
(( in_redirection )) && (( --in_redirection ))
(( in_redirection == 0 )) && next_word=2 # else Stall $next_word.
# Initialize per-"simple command" [zshmisc(1)] variables:
#
# $already_added (see next paragraph)
# $style how to highlight $arg
# $in_array_assignment boolean flag for "between '(' and ')' of array assignment"
# $highlight_glob boolean flag for "'noglob' is in effect"
#
# $already_added is set to 1 to disable adding an entry to region_highlight
# for this iteration. Currently, that is done for "" and $'' strings,
# which add the entry early so escape sequences within the string override
# the string's color.
already_added=0
style=unknown-token
if (( this_word & 1 )); then
@ -285,22 +193,10 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
# Compute the new $start_pos and $end_pos, skipping over whitespace in $buf.
if [[ $arg == ';' ]] ; then
# We're looking for either a semicolon or a newline, whichever comes
# first. Both of these are rendered as a ";" (SEPER) by the ${(z)..}
# flag.
#
# We can't use the (Z+n+) flag because that elides the end-of-command
# token altogether, so 'echo foo\necho bar' (two commands) becomes
# indistinguishable from 'echo foo echo bar' (one command with three
# words for arguments).
needle=$'[;\n]'
offset=$(( ${proc_buf[(i)$needle]} - 1 ))
(( start_pos += offset ))
(( end_pos = start_pos + $#arg ))
# Do not run default code for case when there is a new line
# It shouldn't be treated as ';', i.e. shouldn't be highlighted
# as unknown-token when appears after command-starting arg like "{"
if [[ "${proc_buf[offset+1]}" = $'\n' ]]; then
(( in_array_assignment )) && (( this_word = 2 )) || { (( this_word = 1 )); highlight_glob=1; }
in_redirection=0
@ -309,7 +205,6 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
start_pos=$end_pos
continue
else
# One more short path  for ';' command separator
(( in_array_assignment )) && (( this_word = 2 )) || { (( this_word = 1 )); highlight_glob=1; }
in_redirection=0
[[ "${HSMW_HIGHLIGHT_STYLES[commandseparator]}" != "none" ]] && reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[commandseparator]}")
@ -322,28 +217,22 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
else
offset=0
if [[ "$proc_buf" = (#b)(#s)(([[:space:]]|\\[[:space:]])##)* ]]; then
# The first, outer parenthesis
offset="${mend[1]}"
offset="${mend[1]}"
fi
((start_pos+=offset))
((end_pos=start_pos+${#arg}))
# No-hit will result in value 0
arg_type=${__HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]}
fi
proc_buf="${proc_buf[offset + $#arg + 1,len]}"
# Handle the INTERACTIVE_COMMENTS option.
#
# We use the (Z+c+) flag so the entire comment is presented as one token in $arg.
if [[ -n ${interactive_comments+'set'} && $arg[1] == $histchars[3] ]]; then
if (( this_word & 3 )); then
style=comment
else
style=unknown-token # prematurely terminated
fi
# ADD
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[$style]}")
start_pos=$end_pos
continue
@ -364,242 +253,211 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
# Parse the sudo command line
if (( this_word & 4 )); then
case "$arg" in
# Flag that requires an argument
# Flag that requires an argument
'-'[Cgprtu])
(( this_word & 1 )) && (( this_word = this_word ^ 1 ))
(( next_word = 8 ))
;;
# This prevents misbehavior with sudo -u -otherargument
(( this_word & 1 )) && (( this_word = this_word ^ 1 ))
(( next_word = 8 ))
;;
# This prevents misbehavior with sudo -u -otherargument
'-'*)
(( this_word & 1 )) && (( this_word = this_word ^ 1 ))
(( next_word = next_word | 1 ))
(( next_word = next_word | 4 ))
;;
(( this_word & 1 )) && (( this_word = this_word ^ 1 ))
(( next_word = next_word | 1 ))
(( next_word = next_word | 4 ))
;;
*) ;;
esac
elif (( this_word & 8 )); then
(( next_word = next_word | 4 ))
(( next_word = next_word | 1 ))
fi
fi
fi
expanded_path=""
expanded_path=""
# The Great Fork: is this a command word? Is this a non-command word?
if (( this_word & 16 )) && [[ $arg == 'always' ]]; then
# try-always construct
style=reserved-word # de facto a reserved word, although not de jure
(( next_word = 1 ))
elif (( this_word & 1 )) && (( in_redirection == 0 )); then # $arg is the command word
cur_cmd="$arg"
if (( arg_type == 1 )); then
style=precommand
elif [[ "$arg" = "sudo" ]]; then
style=precommand
(( next_word & 2 )) && (( next_word = next_word ^ 2 ))
(( next_word = next_word | 4 ))
(( next_word = next_word | 1 ))
else
# Special-case: command word is '$foo', like that, without braces or anything.
#
# That's not entirely correct --- if the parameter's value happens to be a reserved
# word, the parameter expansion will be highlighted as a reserved word --- but that
# incorrectness is outweighed by the usability improvement of permitting the use of
# parameters that refer to commands, functions, and builtins.
if [[ ${arg[1]} == \$ ]] && (( ${+parameters} )) && [[ ${arg:1} = (#m)([a-zA-Z_][a-zA-Z0-9_]#|[0-9]##) ]] && (( ${+parameters[${MATCH}]} )); then
-hsmw-highlight-main-type ${(P)MATCH}
else
: ${expanded_path::=${(Q)~arg}}
-hsmw-highlight-main-type $expanded_path
fi
# The Great Fork: is this a command word? Is this a non-command word?
if (( this_word & 16 )) && [[ $arg == 'always' ]]; then
# try-always construct
style=reserved-word # de facto a reserved word, although not de jure
(( next_word = 1 ))
elif (( this_word & 1 )) && (( in_redirection == 0 )); then # $arg is the command word
cur_cmd="$arg"
if (( arg_type == 1 )); then
style=precommand
elif [[ "$arg" = "sudo" ]]; then
style=precommand
(( next_word & 2 )) && (( next_word = next_word ^ 2 ))
(( next_word = next_word | 4 ))
(( next_word = next_word | 1 ))
else
if [[ ${arg[1]} == \$ ]] && (( ${+parameters} )) && [[ ${arg:1} = (#m)([a-zA-Z_][a-zA-Z0-9_]#|[0-9]##) ]] && (( ${+parameters[${MATCH}]} )); then
-hsmw-highlight-main-type ${(P)MATCH}
else
: ${expanded_path::=${(Q)~arg}}
-hsmw-highlight-main-type $expanded_path
fi
case $REPLY in
reserved) # reserved word
style=reserved-word
if [[ $arg == $'\x7b' ]]; then
braces_stack='Y'"$braces_stack"
elif [[ $arg == $'\x7d' && $braces_stack[1] == "Y" ]]; then
# We're at command word, so no need to check $right_brace_is_recognised_everywhere
braces_stack[1]=""
style=reserved-word
(( next_word = next_word | 16 ))
elif [[ $arg == "[[" ]]; then
braces_stack='A'"$braces_stack"
fi
;;
'suffix alias') style=suffix-alias;;
alias)
insane_alias=0
case $arg in
# Issue #263: aliases with '=' on their LHS.
#
# There are three cases:
#
# - Unsupported, breaks 'alias -L' output, but invokable:
('='*) :;;
# - Unsupported, not invokable:
(*'='*) insane_alias=1;;
# - The common case:
(*) :;;
esac
if (( insane_alias )); then
style=unknown-token
else
style=alias
zmodload -e zsh/parameter && alias_target=${aliases[$arg]} || alias_target="${"$(alias -- $arg)"#*=}"
[[ ${__HSMW_HIGHLIGHT_TOKENS_TYPES[$alias_target]} = "1" && "$arg_type" != "1" ]] && __HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]="1"
fi
;;
builtin) style=builtin;;
function) style=function;;
command) style=command;;
hashed) style=hashed-command;;
dirpath) style=path;;
none) # Assign?
if [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[[^\]]#\])(|[+])=* ]] || [[ $arg == [0-9]##(|[+])=* ]]; then
style=assign
# Assignment to a scalar parameter or to array
# (For array assignments, the command doesn't start until the ")" token.)
[[ $arg[-1] == '(' ]] && in_array_assignment=1 || (( next_word = next_word | 1 ))
elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then
style=history-expansion
elif [[ $arg[1] == $histchars[2] ]]; then
style=history-expansion
elif (( arg_type == 3 )); then
# This highlights empty commands (semicolon follows nothing) as an error.
# Zsh accepts them, though.
(( this_word & 2 )) && style=commandseparator
elif [[ $arg[1,2] == '((' ]]; then
# Arithmetic evaluation.
#
# Note: prior to zsh-5.1.1-52-g4bed2cf (workers/36669), the ${(z)...}
# splitter would only output the '((' token if the matching '))' had
# been typed. Therefore, under those versions of zsh, BUFFER="(( 42"
# would be highlighted as an error until the matching "))" are typed.
#
# We highlight just the opening parentheses, as a reserved word; this
# is how [[ ... ]] is highlighted, too.
# ADD
reply+=("$start_pos $(( start_pos + 2 )) ${HSMW_HIGHLIGHT_STYLES[reserved-word]}")
already_added=1
# ADD
[[ $arg[-2,-1] == '))' ]] && reply+=("$(( end_pos - 2 )) $end_pos ${HSMW_HIGHLIGHT_STYLES[reserved-word]}")
elif [[ $arg == '()' ]]; then
# anonymous function
style=reserved-word
elif [[ $arg == $'\x28' ]]; then
# subshell
style=reserved-word
braces_stack='R'"$braces_stack"
elif [[ $arg == $'\x29' ]]; then
[[ $braces_stack[1] == "R" ]] && { braces_stack[1]=""; style=reserved-word; }
elif (( this_word & 14 )); then
style=default
fi
;;
*)
# ADD
# reply+=("$start_pos $end_pos commandtypefromthefuture-$REPLY")
already_added=1
;;
esac
fi
# in_redirection || BIT_regular || BIT_sudo_opt || BIT_sudo_arg
elif (( in_redirection + this_word & 14 ))
then # $arg is a non-command word
case $REPLY in
reserved) # reserved word
style=reserved-word
if [[ $arg == $'\x7b' ]]; then
braces_stack='Y'"$braces_stack"
elif [[ $arg == $'\x7d' && $braces_stack[1] == "Y" ]]; then
braces_stack[1]=""
style=reserved-word
(( next_word = next_word | 16 ))
elif [[ $arg == "[[" ]]; then
braces_stack='A'"$braces_stack"
fi
;;
'suffix alias') style=suffix-alias ;;
alias)
insane_alias=0
case $arg in
'='*)
:
;;
*'='*)
insane_alias=1
;;
*)
:
;;
esac
if (( insane_alias )); then
style=unknown-token
else
style=alias
zmodload -e zsh/parameter && alias_target=${aliases[$arg]} || alias_target="${"$(alias -- $arg)"#*=}"
[[ ${__HSMW_HIGHLIGHT_TOKENS_TYPES[$alias_target]} = "1" && "$arg_type" != "1" ]] && __HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]="1"
fi
;;
builtin)
style=builtin ;;
function)
style=() ;;
command)
style=command ;;
hashed)
style=hashed-command ;;
dirpath)
style=path ;;
none)
if [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[[^\]]#\])(|[+])=* ]] || [[ $arg == [0-9]##(|[+])=* ]]; then
style=assign
[[ $arg[-1] == '(' ]] && in_array_assignment=1 || (( next_word = next_word | 1 ))
elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then
style=history-expansion
elif [[ $arg[1] == $histchars[2] ]]; then
style=history-expansion
elif (( arg_type == 3 )); then
(( this_word & 2 )) && style=commandseparator
elif [[ $arg[1,2] == '((' ]]; then
reply+=("$start_pos $(( start_pos + 2 )) ${HSMW_HIGHLIGHT_STYLES[reserved-word]}")
already_added=1
[[ $arg[-2,-1] == '))' ]] && reply+=("$(( end_pos - 2 )) $end_pos ${HSMW_HIGHLIGHT_STYLES[reserved-word]}")
elif [[ $arg == '()' ]]; then
style=reserved-word
elif [[ $arg == $'\x28' ]]; then
style=reserved-word
braces_stack='R'"$braces_stack"
elif [[ $arg == $'\x29' ]]; then
[[ $braces_stack[1] == "R" ]] && { braces_stack[1]=""; style=reserved-word; }
elif (( this_word & 14 )); then
style=default
fi
;;
*)
already_added=1
;;
esac
fi
elif (( in_redirection + this_word & 14 )); then
case $arg in
']]')
style=reserved-word
[[ $braces_stack[1] == "A" ]] && braces_stack[1]=""
;;
style=reserved-word
[[ $braces_stack[1] == "A" ]] && braces_stack[1]=""
;;
']')
style=builtin
;;
style=builtin
;;
$'\x28')
# '(' inside [[
style=reserved-word
braces_stack='R'"$braces_stack"
;;
style=reserved-word
braces_stack='R'"$braces_stack"
;;
$'\x29') # subshell or end of array assignment
if (( in_array_assignment )); then
style=assign
in_array_assignment=0
(( next_word = next_word | 1 ))
elif [[ $braces_stack[1] == "R" ]]; then
braces_stack[1]=""
style=reserved-word
fi;;
$'\x28\x29') # possibly a function definition
# || false # TODO: or if the previous word was a command word
(( multi_func_def )) && (( next_word = next_word | 1 ))
style=reserved-word
# Remove possible annoying unknown-token style, or misleading function style
reply[-1]=()
;;
'--'*) style=double-hyphen-option;;
'-'*) style=single-hyphen-option;;
"'"*) style=single-quoted-argument;;
if (( in_array_assignment )); then
style=assign
in_array_assignment=0
(( next_word = next_word | 1 ))
elif [[ $braces_stack[1] == "R" ]]; then
braces_stack[1]=""
style=reserved-word
fi ;;
$'\x28\x29')
(( multi_func_def )) && (( next_word = next_word | 1 ))
style=reserved-word
reply[-1]=()
;;
'--'*)
style=double-hyphen-option ;;
'-'*)
style=single-hyphen-option ;;
"'"*)
style=single-quoted-argument ;;
'"'*)
# ADD
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[double-quoted-argument]}")
-hsmw-highlight-string
already_added=1
;;
\$\'*)
# ADD
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[dollar-quoted-argument]}")
-hsmw-highlight-dollar-string
already_added=1
;;
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[double-quoted-argument]}")
-hsmw-highlight-string
already_added=1
;;
\$\*)
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[dollar-quoted-argument]}")
-hsmw-highlight-dollar-string
already_added=1
;;
\$[^\(]*)
style=variable
;;
'`'*) style=back-quoted-argument;;
style=variable
;;
'`'*)
style=back-quoted-argument
;;
[*?]*|*[^\\][*?]*)
(( highlight_glob )) && style=globbing || style=default;;
*) if [[ $arg = $'\x7d' && $braces_stack[1] == "Y" && "$right_brace_is_recognised_everywhere" = "1" ]]; then
# right brace
# Parsing rule: # {
#
# Additionally, `tt(})' is recognized in any position if neither the
# tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set."""
braces_stack[1]=""
style=reserved-word
(( next_word = next_word | 16 ))
elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then
style=history-expansion
elif (( arg_type == 3 )); then
style=commandseparator
elif (( in_redirection == 2 )); then
style=redirection
else
if (( __hsmw_no_check_paths == 0 )) && -hsmw-highlight-check-path; then
# ADD
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[path]}")
already_added=1
(( highlight_glob )) && style=globbing || style=default
;;
*)
if [[ $arg = $'\x7d' && $braces_stack[1] == "Y" ]] && [[ "$right_brace_is_recognised_everywhere" = "1" ]]; then
braces_stack[1]=""
style=reserved-word
(( next_word = next_word | 16 ))
elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then
style=history-expansion
elif (( arg_type == 3 )); then
style=commandseparator
elif (( in_redirection == 2 )); then
style=redirection
else
if (( __hsmw_no_check_paths == 0 )) && -hsmw-highlight-check-path; then
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[path]}")
already_added=1
[[ -n "$HSMW_HIGHLIGHT_STYLES[path_pathseparator]" && "$HSMW_HIGHLIGHT_STYLES[path]" != "$HSMW_HIGHLIGHT_STYLES[path_pathseparator]" ]] && {
local pos
for (( pos = start_pos; pos <= end_pos; pos++ )) ; do
# ADD
[[ ${buf[pos]} == "/" ]] && reply+=("$(( pos - 1 )) $pos ${HSMW_HIGHLIGHT_STYLES[path_pathseparator]}")
done
}
else
style=default
fi
fi
;;
if [[ -n "$HSMW_HIGHLIGHT_STYLES[path_pathseparator]" && "$HSMW_HIGHLIGHT_STYLES[path]" != "$HSMW_HIGHLIGHT_STYLES[path_pathseparator]" ]]; then
local pos
for (( pos = start_pos; pos <= end_pos; pos++ )) ; do
[[ ${buf[pos]} == "/" ]] && reply+=("$(( pos - 1 )) $pos ${HSMW_HIGHLIGHT_STYLES[path_pathseparator]}")
done
fi
else
style=default
fi
fi
;;
esac
fi
# ADD
(( already_added == 0 )) && [[ "${HSMW_HIGHLIGHT_STYLES[$style]}" != "none" ]] && reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[$style]}")
if (( arg_type == 3 )); then
if [[ $arg == ';' ]] && (( in_array_assignment )); then
# literal newline inside an array assignment
(( next_word = 2 ))
elif [[ -n "${braces_stack[(r)A]}" ]]; then
(( next_word = 2 ))
@ -608,109 +466,85 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
highlight_glob=1
fi
elif (( arg_type == 1 || arg_type == 2 )) && (( this_word & 1 )); then
(( next_word = 1 ))
(( next_word = 1 ))
elif [[ $arg == "repeat" ]] && (( this_word & 1 )); then
# skip the repeat-count word
in_redirection=2
# The redirection mechanism assumes $this_word describes the word
# following the redirection. Make it so.
#
# That word can be a command word with shortloops (`repeat 2 ls`)
# or a command separator (`repeat 2; ls` or `repeat 2; do ls; done`).
#
# The repeat-count word will be handled like a redirection target.
(( this_word = 3 ))
(( thisword = 3 ))
fi
start_pos=$end_pos
# This is the default/common codepath.
(( in_redirection == 0 )) && (( this_word = next_word )) #else # Stall $this_word.
(( in_redirection == 0 )) && (( this_word = next_word ))
done
return 0
}
# Check if $arg is a path.
# If yes, return 0 and in $REPLY the style to use.
# Else, return non-zero (and the contents of $REPLY is undefined).
-hsmw-highlight-check-path()
{
-hsmw-highlight-check-path() {
: ${expanded_path:=${(Q)~arg}}
[[ -n "${FAST_BLIST_PATTERNS[(k)$expanded_path]}" ]] && return 1
[[ -z $expanded_path ]] && return 1
[[ -e $expanded_path ]] && return 0
# Search the path in CDPATH, only for CD command
[[ "$cur_cmd" = "cd" ]] && for cdpath_dir in $cdpath ; do
[[ -e "$cdpath_dir/$expanded_path" ]] && return 0
done
if [[ "$cur_cmd" = "cd" ]]; then
for cdpath_dir in $cdpath ; do
if [[ -e "$cdpath_dir/$expanded_path" ]]; then
return 0
fi
done
fi
# It's not a path.
return 1
}
# Highlight special chars inside double-quoted strings
-hsmw-highlight-string()
{
-hsmw-highlight-string() {
mybuf="$arg"
idx=start_pos
while [[ "$mybuf" = (#b)[^\$\\]#((\$(#B)([a-zA-Z_:][a-zA-Z0-9_:]#|[0-9]##)(#b)(\[[^\]]#\])(#c0,1))|(\$[{](\([a-zA-Z0@%#]##\))(#c0,1)[a-zA-Z0-9_:#]##(\[[^\]]#\])(#c0,1)[}])|[\\][\'\"\$]|[\\](*))(*) ]]; do
[[ -n "${match[7]}" ]] && {
# Skip following char it is quoted. Choice is
# made to not highlight such quoting
while [[ "$mybuf" = (#b)[^\$\\]#((\$(#B)([a-zA-Z_:][a-zA-Z0-9_:]#|[0-9]##)(#b)(\[[^\]]#\])(#c0,1))|(\$[{](\([a-zA-Z0@%#]##\))(#c0,1)[a-zA-Z0-9_:#]##(\[[^\]]#\])(#c0,1)[}])|[\\][\"\'\$]|[\\](*))(*) ]]; do
if [[ -n "${match[7]}" ]]; then
idx+=${mbegin[1]}+1
mybuf="${match[7]:1}"
} || {
else
idx+=${mbegin[1]}-1
end_idx=idx+${mend[1]}-${mbegin[1]}+1
mybuf="${match[8]}"
# ADD
reply+=("$idx $end_idx ${HSMW_HIGHLIGHT_STYLES[back-or-dollar-double-quoted-argument]}")
idx=end_idx
}
fi
done
}
# Highlight special chars inside dollar-quoted strings
-hsmw-highlight-dollar-string()
{
-hsmw-highlight-dollar-string() {
local i j k style
local AA
integer c
# Starting dollar-quote is at 1:2, so start parsing at offset 3 in the string.
for (( i = 3 ; i < end_pos - start_pos ; i += 1 )) ; do
for (( i = 3 ; i < end_pos - start_pos ; i += 1 )); do
(( j = i + start_pos - 1 ))
(( k = j + 1 ))
case "$arg[$i]" in
"\\") style=back-dollar-quoted-argument
for (( c = i + 1 ; c <= end_pos - start_pos ; c += 1 )); do
[[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break
done
AA=$arg[$i+1,$c-1]
# Matching for HEX and OCT values like \0xA6, \xA6 or \012
if [[ "$AA" =~ "^(x|X)[0-9a-fA-F]{1,2}"
|| "$AA" =~ "^[0-7]{1,3}"
|| "$AA" =~ "^u[0-9a-fA-F]{1,4}"
|| "$AA" =~ "^U[0-9a-fA-F]{1,8}"
]]; then
(( k += $#MATCH ))
(( i += $#MATCH ))
else
if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then
# \x not followed by hex digits is probably an error
style=unknown-token
fi
(( k += 1 )) # Color following char too.
(( i += 1 )) # Skip parsing the escaped char.
fi
;;
*) continue ;;
case $arg[$i] in
\\)
style=back-dollar-quoted-argument
for (( c = i + 1 ; c <= end_pos - start_pos ; c += 1 )); do
[[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break
done
AA=$arg[$i+1,$c-1]
if [[ "$AA" =~ "^(x|X)[0-9a-fA-F]{1,2}" || "$AA" =~ "^[0-7]{1,3}" || "$AA" =~ "^u[0-9a-fA-F]{1,4}" || "$AA" =~ "^U[0-9a-fA-F]{1,8}" ]]; then
(( k += $#MATCH ))
(( i += $#MATCH ))
else
if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then
style=unknown-token
fi
(( k += 1 )) # Color following char too.
(( i += 1 )) # Skip parsing the escaped char.
fi
;;
*)
continue
;;
esac
# ADD
reply+=("$j $k ${HSMW_HIGHLIGHT_STYLES[$style]}")
done
}