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) # history-search-multi-word - zsh plugin
[![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]
# 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. Binds `Ctrl-R` to a widget that searches for multiple keywords in an `AND` fashion. In other words, you
In other words, you can enter multiple words, and history entries that match can enter multiple words, and history entries that match all of them are returned. Additionally, search matches are syntax highlighted.
all of them will be found. The entries 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) [![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 HSMW has a feature called **context viewing** see all occurrences of a command together with
with surrounding commands: surrounding commands:
[![asciicast](https://asciinema.org/a/155704.png)](https://asciinema.org/a/155704) [![asciicast](https://asciinema.org/a/155704.png)](https://asciinema.org/a/155704)
Set: Set:
```zsh ```bash
zstyle :plugin:history-search-multi-word reset-prompt-protect 1 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 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
`zdharma-continuum/fast-syntax-highlighting`, `zsh-users/zsh-syntax-highlighting`, widgets (e.g., `fast-syntax-highlighting`, `zsh-syntax-highlighting`,
`zsh-users/zsh-autosuggestions` and other plugins that hook up into Zshell by `zsh-autosuggestions`), use `sched` :
overloading Zle widgets. You could e.g. use `sched` in following way:
```zsh ```bash
PROMPT=%B%F{yellow}%D{%H:%M:%S}%B%b%f PROMPT=%B%F{yellow}%D{%H:%M:%S}%B%b%f
schedprompt() { schedprompt() {
zle && zle reset-prompt zle && zle reset-prompt
sched +1 schedprompt sched +1 schedprompt
} }
zmodload -i zsh/sched zmodload -i zsh/sched
schedprompt schedprompt
``` ```
to refresh the clock in prompt every second. The `reset-prompt-protect` zstyle To refresh the clock in prompt every second. The `reset-prompt-protect` zstyle should be `1`
needs to be set to 1 for correct cooperation with HSMW. Or, you could use `zle for proper cooperation with HSMW. Or, you could use `zle .reset-prompt` (i.e., with the dot in
.reset-prompt` (i.e. with the dot in front) to call the original, not front) to call the original, not overloaded (e.g., F-Sy-H, zsh-autosuggestions, etc.) `reset-prompt` widget.
overloaded (by F-Sy-H, zsh-autosuggestsions, etc.) `reset-prompt` widget.
# News ## Installation
* 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 The plugin is **plugin manager agnostic**.
- `^`  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 To install, clone the `history-search-multi-word` repository and add the following snippet to your
- Hash holding paths that shouldn't be grepped (globbed) blacklist for slow disks, mounts, etc.: `.zshrc`
```zsh ```bash
typeset -gA FAST_BLIST_PATTERNS source <LOCATION-WHERE-REPOSITORY >/history-search-multi-word.plugin.zsh
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
``` ```
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 the 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 directory to
`~/.oh-my-zsh/custom/plugins`).
### [Zinit](https://github.com/zdharma-continuum/zinit) ### [Zinit](https://github.com/zdharma-continuum/zinit)
Add `zinit load zdharma-continuum/history-search-multi-word` to your `.zshrc` file. Add the following snippet to your `.zshrc`:
Zinit will handle cloning the plugin for you automatically the next time you
start zsh. ```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 ### Antigen
Add `antigen bundle zdharma-continuum/history-search-multi-word` to your `.zshrc` file. Add `antigen bundle zdharma-continuum/history-search-multi-word` to your `.zshrc` file. Antigen will
Antigen will handle cloning the plugin for you automatically the next time you automatically handle cloning the plugin for you the next time you start zsh. You can also add the
start zsh. You can also add the plugin to a running zsh with `antigen bundle plugin to a running zsh with `antigen bundle zdharma-continuum/history-search-multi-word` for
zdharma-continuum/history-search-multi-word` for testing before adding it to your testing before adding it to your `.zshrc`.
`.zshrc`.
### Oh-My-Zsh ### Oh-My-Zsh
1. `cd ~/.oh-my-zsh/custom/plugins` 1. `cd ~/.oh-my-zsh/custom/plugins`
2. `git clone git@github.com:zdharma-continuum/history-search-multi-word.git` 1. `git clone git@github.com:zdharma-continuum/history-search-multi-word.git`
3. Add `history-search-multi-word` to your plugin list 1. Add `history-search-multi-word` to your plugin list
### Zgen ### Zgen
Add `zgen load zdharma-continuum/history-search-multi-word` to your .zshrc file in the same ```zsh
place you're doing your other `zgen load` calls in. 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) ### [Sheldon](https://github.com/rossmacarthur/sheldon)
Run 1. Run
```bash ```bash
sheldon add history-search-multi-word --github zdharma-continuum/history-search-multi-word 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 ### 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 ```bash
source /usr/share/zsh/plugins/history-search-multi-word/history-search-multi-word.plugin.zsh 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 ```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)
## Zstyles 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)
```zsh zstyle ":plugin:history-search-multi-word" check-paths "yes" # Whether to check paths for existence and mark with magenta (default true)
zstyle ":history-search-multi-word" page-size "8" # Number of entries to show (default is $LINES/3) zstyle ":plugin:history-search-multi-word" clear-on-cancel "no" # Whether pressing Ctrl-C or ESC should clear entered query
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" 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
``` ```
## Syntax highlighting ### Syntax highlighting
Syntax highlighting is customized via `HSMW_HIGHLIGHT_STYLES` associative array. Syntax highlighting is customized via `HSMW_HIGHLIGHT_STYLES` associative array. It has keys like
It has keys like `reserved-word`, `alias`, `command`, `path`, etc. which are assigned `reserved-word`, `alias`, `command`, `path`, etc., which are assigned with strings like
with strings like `fg=blue,bold`, to configure how given elements are to be `fg=blue,bold` to configure how given elements are to be colored. If you assign this array before
colored. If you assign this array before or after loading `hsmw` you will change the defaults. Complete list or after loading `hsmw`, you will change the defaults. The complete list of available keys is
of available keys is [at the beginning](https://github.com/zdharma-continuum/history-search-multi-word/blob/master/hsmw-highlight#L34-L62) [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 of `hsmw-highlight` file. Example `~/.zshrc` addition that sets `path` key paths that exist will
paths that exist will be highlighted with background magenta, foreground white, bold: be highlighted with background magenta, foreground white, bold:
```zsh ```bash
typeset -gA HSMW_HIGHLIGHT_STYLES typeset -gA HSMW_HIGHLIGHT_STYLES
HSMW_HIGHLIGHT_STYLES[path]="bg=magenta,fg=white,bold" 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 ```zsh
typeset -gA HSMW_HIGHLIGHT_STYLES typeset -gA HSMW_HIGHLIGHT_STYLES
HSMW_HIGHLIGHT_STYLES[single-hyphen-option]="fg=cyan"
HSMW_HIGHLIGHT_STYLES[double-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" HSMW_HIGHLIGHT_STYLES[commandseparator]="fg=241,bg=17"
``` ```
[gitter-image]: https://badges.gitter.im/zdharma-continuum/community.svg <!-- vim:set ft=markdown tw=100 fo+=1n: -->
[gitter-link]: https://gitter.im/zdharma-continuum/community

View file

@ -1,5 +1,9 @@
# -*- Mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- #!/usr/bin/env zsh
# vim:ft=zsh:sw=4:sts=4:et #
# -*- 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 # To use (when not using as plugin) copy to site-functions and issue
# (add to ~/.zshrc): # (add to ~/.zshrc):
@ -50,431 +54,431 @@ trap '(( __hsmw_hcw_call_count -- )); return 0;' INT
if (( ${+functions[_hsmw_main]} == 0 )); then if (( ${+functions[_hsmw_main]} == 0 )); then
_hsmw_main() { _hsmw_main() {
# First call or restart? # First call or restart?
if [[ "$__hsmw_hcw_call_count" -le 1 || "$__hsmw_hcw_restart" = "1" ]]; then if [[ "$__hsmw_hcw_call_count" -le 1 || "$__hsmw_hcw_restart" = "1" ]]; then
if [[ "$__hsmw_hcw_call_count" -le 1 ]]; then if [[ "$__hsmw_hcw_call_count" -le 1 ]]; then
# Read configuration data # 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' 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 -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 -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 -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 zstyle -T ":plugin:history-search-multi-word" check-paths && __hsmw_no_check_paths=0 || __hsmw_no_check_paths=1
-hsmw-highlight-init -hsmw-highlight-init
fi fi
# '0' will get changed into $to_display limit # '0' will get changed into $to_display limit
[[ "$NO_MOVE" != 1 ]] && { [[ "$NO_MOVE" != 1 ]] && {
[[ "$WIDGET" = *-word || "$WIDGET" = *-pforwards ]] && __hsmw_hcw_index="1" [[ "$WIDGET" = *-word || "$WIDGET" = *-pforwards ]] && __hsmw_hcw_index="1"
[[ "$WIDGET" = *-backwards || "$WIDGET" = *-pbackwards ]] && __hsmw_hcw_index="0" [[ "$WIDGET" = *-backwards || "$WIDGET" = *-pbackwards ]] && __hsmw_hcw_index="0"
} }
__hsmw_hcw_widget_name="${${${WIDGET%-backwards}%-pbackwards}%-pforwards}" __hsmw_hcw_widget_name="${${${WIDGET%-backwards}%-pbackwards}%-pforwards}"
__hsmw_hcw_found=( ) __hsmw_hcw_found=( )
__hsmw_hcw_finished="0" __hsmw_hcw_finished="0"
__hsmw_hcw_restart="0" __hsmw_hcw_restart="0"
__hsmw_page_start_idx=0 __hsmw_page_start_idx=0
__hsmw_prev_offset=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 else
# Showing context? __hsmw_hcw_found=( "${(u@)history[(R)*$~search_pattern*]}" )
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 fi
done
fi
# Find history entries matching pattern *word1*~^*word2*~^*word3* etc. integer max_index="${#__hsmw_hcw_found[@]}"
local search_buffer="${BUFFER%% ##}" search_pattern="" colsearch_pattern="" nl=$'\n' MATCH MBEGIN MEND if [[ "$max_index" -le "0" ]]; then
local specch="][*?|#~^()><\\" POSTDISPLAY=$'\n'"No matches found"
search_buffer="${search_buffer//(#b)((\[?##\])|([$specch]))/${${match[2]:+$match[2]}:-\\${match[3]}}}" return 0
search_buffer="${search_buffer/(#s)\\\^/(#s)}" fi
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 # Pagination, index value guards
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
integer max_index="${#__hsmw_hcw_found[@]}" integer page_size="$__hsmw_page_size"
if [[ "$max_index" -le "0" ]]; then [[ "$page_size" -gt "$max_index" ]] && page_size="$max_index"
POSTDISPLAY=$'\n'"No matches found" [[ "$__hsmw_hcw_index" -le 0 ]] && __hsmw_hcw_index="$max_index"
return 0 [[ "$__hsmw_hcw_index" -gt "$max_index" ]] && __hsmw_hcw_index=1
fi 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_start_idx != __hsmw_page_start_idx )) && {
[[ "$page_size" -gt "$max_index" ]] && page_size="$max_index" __hsmw_disp_list=( "${(@)__hsmw_hcw_found[page_start_idx,page_start_idx+page_size-1]}" )
[[ "$__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 ))
# # Don't do @ splitting, it's slower
# Prepare display __hsmw_disp_list_newlines=( $__hsmw_disp_list )
#
(( page_start_idx != __hsmw_page_start_idx )) && { # Replace all new lines with "\n" text
__hsmw_disp_list=( "${(@)__hsmw_hcw_found[page_start_idx,page_start_idx+page_size-1]}" ) __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 # The same with newlines adapted for syntax highlighting
__hsmw_disp_list_newlines=( $__hsmw_disp_list ) __hsmw_disp_list_newlines=( "${(@)__hsmw_disp_list_newlines//$'\n'/ $nl}" )
__hsmw_disp_list_newlines=( "${(@)__hsmw_disp_list_newlines/(#m)*/ ${MATCH[1,COLUMNS-8]}}" )
# 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" )
} }
_hsmw_shappend() { #
__hsmw_region_highlight_data+=( "$(( offset + $1 - 1 )) $(( offset + $2 )) ${__hsmw_hl_color}" ) # Detect where "> .." entry starts, add the ">" mark
} #
functions -M hsmw_append 2 2 _hsmw_shappend
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 fi
_hsmw_main _hsmw_main
_hsmw_simulate_widget() { _hsmw_simulate_widget() {
(( __hsmw_hcw_call_count ++ )) (( __hsmw_hcw_call_count ++ ))
_hsmw_main _hsmw_main
} }
_hsmw_self_insert() { _hsmw_self_insert() {
LBUFFER+="${KEYS[-1]}" LBUFFER+="${KEYS[-1]}"
__hsmw_hcw_restart="1" __hsmw_hcw_restart="1"
_hsmw_simulate_widget _hsmw_simulate_widget
} }
_hsmw_backward_delete_char() { _hsmw_backward_delete_char() {
LBUFFER="${LBUFFER%?}" LBUFFER="${LBUFFER%?}"
__hsmw_hcw_restart="1" __hsmw_hcw_restart="1"
_hsmw_simulate_widget _hsmw_simulate_widget
} }
_hsmw_delete_char() { _hsmw_delete_char() {
RBUFFER="${RBUFFER#?}" RBUFFER="${RBUFFER#?}"
__hsmw_hcw_restart="1" __hsmw_hcw_restart="1"
_hsmw_simulate_widget _hsmw_simulate_widget
} }
_hsmw_cancel_accept() { _hsmw_cancel_accept() {
(( __hsmw_conc )) && BUFFER="" (( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc unset __hsmw_conc
__hsmw_hcw_index=-1 __hsmw_hcw_index=-1
zle .accept-line zle .accept-line
} }
_hsmw_backward_kill_word() { _hsmw_backward_kill_word() {
zle .backward-kill-word zle .backward-kill-word
__hsmw_hcw_restart="1" __hsmw_hcw_restart="1"
_hsmw_simulate_widget _hsmw_simulate_widget
} }
_hsmw_reset_prompt() { _hsmw_reset_prompt() {
zle .reset-prompt zle .reset-prompt
local NO_MOVE=1 local NO_MOVE=1
_hsmw_simulate_widget _hsmw_simulate_widget
} }
_hsmw_jump_entry() { _hsmw_jump_entry() {
local entry local entry
if (( __hsmw_ctx )); 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]}"
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 integer final_hist_found_idx the_index
final_hist_found_idx=__hsmw_ctx_text_idx+__hsmw_ctx_which-1 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_found[final_hist_found_idx]}"
the_index+=__hsmw_ctx_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 else
entry="${__hsmw_hcw_found[__hsmw_hcw_index]}" (( __hsmw_conc )) && BUFFER=""
unset __hsmw_conc
fi 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 # Restore self-insert, backward-delete-char, delete-char
# Load config of reset-prompt protection zle -A hsmw-saved-self-insert self-insert
local __hsmw_reset_prompt_protect zle -A hsmw-saved-backward-delete-char backward-delete-char
zstyle -t ":plugin:history-search-multi-word" reset-prompt-protect && __hsmw_reset_prompt_protect=1 || __hsmw_reset_prompt_protect=0 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 # Restore ourselves
bindkey -N hsmw emacs 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}" zle -A hsmw-saved-"$pdown_widget" "$pdown_widget"
local up_widget="${down_widget}-backwards" zle -A hsmw-saved-"$pup_widget" "$pup_widget"
local pdown_widget="${down_widget}-pforwards" zle -D hsmw-saved-"$pdown_widget" hsmw-saved-"$pup_widget"
local pup_widget="${down_widget}-pbackwards"
# Manual, termcap, terminfo if (( ${+functions[azhw:zle-line-pre-redraw]} )); then
bindkey -M hsmw '^[OA' "$up_widget" functions[azhw:zle-line-pre-redraw]=${functions[zle-line-pre-redraw-bkp]}
bindkey -M hsmw '^[OB' "$down_widget" fi
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) if (( ${+functions[azhw:zle-line-finish]} )); then
bindkey -M hsmw '^[[D' .backward-char functions[azhw:zle-line-finish]=${functions[zle-line-finish-bkp]}
bindkey -M hsmw '^[[C' .forward-char fi
[[ -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 # Full reinitialisation at next call
bindkey -M hsmw '^P' "$up_widget" __hsmw_hcw_call_count="0"
bindkey -M hsmw '^N' "$down_widget"
bindkey -M hsmw '^L' "$down_widget"
# Page Up, Page Down keys zle reset-prompt
[[ -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 # Free memory
zle -N -- hsmw-context-main #__hsmw_hcw_found=( )
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=( )
elif (( __hsmw_hcw_call_count > 0 )); then elif (( __hsmw_hcw_call_count > 0 )); then
(( __hsmw_hcw_call_count -- )) (( __hsmw_hcw_call_count -- ))
fi fi

View file

@ -1,5 +1,9 @@
# -*- Mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- #!/usr/bin/env zsh
# vim:ft=zsh:sw=4:sts=4:et #
# -*- 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: # 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}]} ]] if [[ ${zsh_loaded_plugins[-1]} != */history-search-multi-word && -z ${fpath[(r)${0:h}]} ]]
then then
fpath+=( "${0:h}" ) fpath+=( "${0:h}" )
fi fi
autoload history-search-multi-word hsmw-context-main 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-pbackwards history-search-multi-word
zle -N history-search-multi-word-pforwards history-search-multi-word zle -N history-search-multi-word-pforwards history-search-multi-word
[[ ${+termcap[Co]} = 1 && ${termcap[Co]} = 256 ]] && { [[ ${+termcap[Co]} = 1 && ${termcap[Co]} = 256 ]] && {
zstyle -s ":history-search-multi-word" highlight-color tmp || \ zstyle -s ":history-search-multi-word" highlight-color tmp || \
zstyle ":history-search-multi-word" highlight-color "bg=17" zstyle ":history-search-multi-word" highlight-color "bg=17"
typeset -gA HSMW_HIGHLIGHT_STYLES typeset -gA HSMW_HIGHLIGHT_STYLES
[[ ${HSMW_HIGHLIGHT_STYLES[variable]} = none ]] && \ [[ ${HSMW_HIGHLIGHT_STYLES[variable]} = none ]] && \
HSMW_HIGHLIGHT_STYLES[variable]="fg=112" HSMW_HIGHLIGHT_STYLES[variable]="fg=112"
} }
bindkey "^R" history-search-multi-word 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; -*- #!/usr/bin/env zsh
# vim:ft=zsh:sw=4:sts=4:et #
# -*- 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" __hsmw_ctx_prev_idx="$__hsmw_ctx_idx"
[[ "$WIDGET" = *-word ]] && (( __hsmw_ctx_idx -- )) [[ "$WIDGET" = *-word ]] && (( __hsmw_ctx_idx -- ))
[[ "$WIDGET" = *-backwards ]] && (( __hsmw_ctx_idx ++ )) [[ "$WIDGET" = *-backwards ]] && (( __hsmw_ctx_idx ++ ))
[[ "$WIDGET" = *-pforwards ]] && (( __hsmw_ctx_idx = __hsmw_ctx_idx - __hsmw_page_size )) [[ "$WIDGET" = *-pforwards ]] && (( __hsmw_ctx_idx = __hsmw_ctx_idx - __hsmw_page_size ))
[[ "$WIDGET" = *-pbackwards ]] && (( __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_up() {
(( __hsmw_ctx_which -- )) (( __hsmw_ctx_which -- ))
(( __hsmw_ctx_which < 0 )) && __hsmw_ctx_which=${#__hsmw_ctx_found}-1 (( __hsmw_ctx_which < 0 )) && __hsmw_ctx_which=${#__hsmw_ctx_found}-1
__hsmw_ctx_idx=0 __hsmw_ctx_idx=0
_hsmw_ctx_main _hsmw_ctx_main
} }
_hsmw_ctx_down() { _hsmw_ctx_down() {
(( __hsmw_ctx_which ++ )) (( __hsmw_ctx_which ++ ))
(( __hsmw_ctx_which >= ${#__hsmw_ctx_found} )) && __hsmw_ctx_which=0 (( __hsmw_ctx_which >= ${#__hsmw_ctx_found} )) && __hsmw_ctx_which=0
__hsmw_ctx_idx=0 __hsmw_ctx_idx=0
_hsmw_ctx_main _hsmw_ctx_main
} }
_hsmw_ctx_off() { _hsmw_ctx_off() {
__hsmw_ctx_to_search="" __hsmw_ctx=0
__hsmw_ctx_found=( ) __hsmw_ctx_found=( )
__hsmw_ctx_which=0 __hsmw_ctx_idx=0
__hsmw_ctx_idx=0 __hsmw_ctx_page_start_idx=0
__hsmw_ctx_page_start_idx=0 __hsmw_ctx_prev_offset=0
__hsmw_ctx_prev_offset=0 __hsmw_ctx_to_search=""
__hsmw_ctx=0 __hsmw_ctx_which=0
# Reset main state so that it re-highlights
# Reset main state so that it re-highlights __hsmw_prev_offset=0
__hsmw_prev_offset=0 zle -la _hsmw_ctx_down && zle -D _hsmw_ctx_down
zle -la _hsmw_ctx_up && zle -D _hsmw_ctx_up
zle -la _hsmw_ctx_down && zle -D _hsmw_ctx_down bindkey -M hsmw '^N' "history-search-multi-word"
zle -la _hsmw_ctx_up && zle -D _hsmw_ctx_up bindkey -M hsmw '^P' "history-search-multi-word-backwards"
(( ${1}+0 )) && _hsmw_simulate_widget
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 if [[ "$WIDGET" = "hsmw-context-main" ]]; then
__hsmw_ctx=1-__hsmw_ctx __hsmw_ctx=1-__hsmw_ctx
if (( __hsmw_ctx == 0 )); then if (( __hsmw_ctx == 0 )); then
_hsmw_ctx_off 1 _hsmw_ctx_off 1
return return
fi fi
zle -N _hsmw_ctx_down
zle -N _hsmw_ctx_down zle -N _hsmw_ctx_up
zle -N _hsmw_ctx_up bindkey -M hsmw '^N' "_hsmw_ctx_down"
bindkey -M hsmw '^N' "_hsmw_ctx_down" bindkey -M hsmw '^P' "_hsmw_ctx_up"
bindkey -M hsmw '^P' "_hsmw_ctx_up"
fi fi
_hsmw_ctx_main() { _hsmw_ctx_main() {
# The repeat will make the matching work on a fresh heap arena
# The repeat will make the matching work on a fresh heap arena local to_search="${__hsmw_hcw_found[__hsmw_hcw_index]}" nl=$'\n'
local to_search="${__hsmw_hcw_found[__hsmw_hcw_index]}" nl=$'\n' to_search="${to_search//(#m)[][*?|#~^()><\\]/\\$MATCH}"
to_search="${to_search//(#m)[][*?|#~^()><\\]/\\$MATCH}" if [[ "$to_search" != "$__hsmw_ctx_to_search" ]]; then
__hsmw_ctx_to_search="$to_search"
if [[ "$to_search" != "$__hsmw_ctx_to_search" ]]; then repeat 1; do
__hsmw_ctx_to_search="$to_search" __hsmw_ctx_found=( "${(@kv)history[(R)$to_search]}" )
repeat 1; do __hsmw_ctx_text_idx="${__hsmw_ctx_found[(I)$to_search]}"
__hsmw_ctx_found=( "${(@kv)history[(R)$to_search]}" ) if [[ "$__hsmw_ctx_text_idx" = "0" ]]; then
__hsmw_ctx_text_idx="${__hsmw_ctx_found[(I)$to_search]}" _hsmw_ctx_off 1
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 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 fi
else
# region_highlight[-1]=()
# Pagination, index value guards fi
# __hsmw_ctx_page_start_idx=page_start_idx
__hsmw_ctx_prev_offset=offset
integer page_size="$__hsmw_page_size" region_highlight+=( "$(( offset + ${#txt_before} )) $(( offset + ${#txt_before} + ${#entry} + 1 )) $__hsmw_active" )
[[ "$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" )
} }
_hsmw_ctx_main _hsmw_ctx_main

View file

@ -1,32 +1,11 @@
# -*- Mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- #!/usr/bin/env zsh
# vim:ft=zsh:sw=2:sts=2:et #
# -*- mode: sh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
# ------------------------------------------------------------------------------------------------- #
# Copyright (c) 2010-2016 zsh-syntax-highlighting contributors # Copyright (c) 2010-2016 zsh-syntax-highlighting contributors
# Copyright (c) 2016-2017 Sebastian Gniazdowski (modifications) # Copyright (c) 2016-2017 Sebastian Gniazdowski (modifications)
# All rights reserved. # Copyright (c) 2021-2022 zdharma-continuum and contributors
#
# 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.
# -------------------------------------------------------------------------------------------------
typeset -gA __hsmw_highlight_main__command_type_cache typeset -gA __hsmw_highlight_main__command_type_cache
@ -103,60 +82,41 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
'|&' 3 '|&' 3
'&!' 3 '&!' 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() { -hsmw-highlight-main-type() {
REPLY=$__hsmw_highlight_main__command_type_cache[(e)$1] REPLY=$__hsmw_highlight_main__command_type_cache[(e)$1]
[[ -z "$REPLY" ]] && { [[ -z "$REPLY" ]] && {
if zmodload -e zsh/parameter; then if zmodload -e zsh/parameter; then
if (( $+aliases[(e)$1] )); then if (( $+aliases[(e)$1] )); then
REPLY=alias REPLY=alias
elif (( $+functions[(e)$1] )); then elif (( $+functions[(e)$1] )); then
REPLY=function REPLY=function
elif (( $+builtins[(e)$1] )); then elif (( $+builtins[(e)$1] )); then
REPLY=builtin REPLY=builtin
elif (( $+commands[(e)$1] )); then elif (( $+commands[(e)$1] )); then
REPLY=command REPLY=command
elif (( $+saliases[(e)${1##*.}] )); then elif (( $+saliases[(e)${1##*.}] )); then
REPLY='suffix alias' REPLY='suffix alias'
elif (( $reswords[(Ie)$1] )); then elif (( $reswords[(Ie)$1] )); then
REPLY=reserved REPLY=reserved
# zsh 5.2 and older have a bug whereby running 'type -w ./sudo' implicitly elif [[ $1 != */* || "${+ZSH_ARGZERO}" = "1" ]] && ! builtin type -w -- $1 >/dev/null 2>&1; then
# runs 'hash ./sudo=/usr/local/bin/./sudo' (assuming /usr/local/bin/sudo REPLY=none
# exists and is in $PATH). Avoid triggering the bug, at the expense of fi
# 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
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" ]] && { [[ "$REPLY" = "none" ]] && {
[[ -d "$1" ]] && REPLY="dirpath" || { [[ -d "$1" ]] && REPLY="dirpath" || {
for cdpath_dir in $cdpath; do for cdpath_dir in $cdpath; do
[[ -d "$cdpath_dir/$1" ]] && { REPLY="dirpath"; break; } [[ -d "$cdpath_dir/$1" ]] && { REPLY="dirpath"; break; }
done 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. # Main syntax highlighting function.
-hsmw-highlight-process() -hsmw-highlight-process() {
{
emulate -L zsh emulate -L zsh
setopt extendedglob bareglobqual nonomatch noksharrays 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 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 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 # Processing buffer
local proc_buf="$buf" needle local proc_buf="$buf" needle
for arg in ${interactive_comments-${(z)buf}} \ for arg in ${interactive_comments-${(z)buf}} ${interactive_comments+${(zZ+c+)buf}}; do
${interactive_comments+${(zZ+c+)buf}}; do
# Initialize $next_word to its default value? # Initialize $next_word to its default value?
(( in_redirection )) && (( --in_redirection )) (( in_redirection )) && (( --in_redirection ))
(( in_redirection == 0 )) && next_word=2 # else Stall $next_word. (( 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 already_added=0
style=unknown-token style=unknown-token
if (( this_word & 1 )); then 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. # Compute the new $start_pos and $end_pos, skipping over whitespace in $buf.
if [[ $arg == ';' ]] ; then 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]' needle=$'[;\n]'
offset=$(( ${proc_buf[(i)$needle]} - 1 )) offset=$(( ${proc_buf[(i)$needle]} - 1 ))
(( start_pos += offset )) (( start_pos += offset ))
(( end_pos = start_pos + $#arg )) (( 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 if [[ "${proc_buf[offset+1]}" = $'\n' ]]; then
(( in_array_assignment )) && (( this_word = 2 )) || { (( this_word = 1 )); highlight_glob=1; } (( in_array_assignment )) && (( this_word = 2 )) || { (( this_word = 1 )); highlight_glob=1; }
in_redirection=0 in_redirection=0
@ -309,7 +205,6 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
start_pos=$end_pos start_pos=$end_pos
continue continue
else else
# One more short path  for ';' command separator
(( in_array_assignment )) && (( this_word = 2 )) || { (( this_word = 1 )); highlight_glob=1; } (( in_array_assignment )) && (( this_word = 2 )) || { (( this_word = 1 )); highlight_glob=1; }
in_redirection=0 in_redirection=0
[[ "${HSMW_HIGHLIGHT_STYLES[commandseparator]}" != "none" ]] && reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[commandseparator]}") [[ "${HSMW_HIGHLIGHT_STYLES[commandseparator]}" != "none" ]] && reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[commandseparator]}")
@ -322,28 +217,22 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
else else
offset=0 offset=0
if [[ "$proc_buf" = (#b)(#s)(([[:space:]]|\\[[:space:]])##)* ]]; then if [[ "$proc_buf" = (#b)(#s)(([[:space:]]|\\[[:space:]])##)* ]]; then
# The first, outer parenthesis offset="${mend[1]}"
offset="${mend[1]}"
fi fi
((start_pos+=offset)) ((start_pos+=offset))
((end_pos=start_pos+${#arg})) ((end_pos=start_pos+${#arg}))
# No-hit will result in value 0
arg_type=${__HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]} arg_type=${__HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]}
fi fi
proc_buf="${proc_buf[offset + $#arg + 1,len]}" 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 [[ -n ${interactive_comments+'set'} && $arg[1] == $histchars[3] ]]; then
if (( this_word & 3 )); then if (( this_word & 3 )); then
style=comment style=comment
else else
style=unknown-token # prematurely terminated style=unknown-token # prematurely terminated
fi fi
# ADD
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[$style]}") reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[$style]}")
start_pos=$end_pos start_pos=$end_pos
continue continue
@ -364,242 +253,211 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
# Parse the sudo command line # Parse the sudo command line
if (( this_word & 4 )); then if (( this_word & 4 )); then
case "$arg" in case "$arg" in
# Flag that requires an argument # Flag that requires an argument
'-'[Cgprtu]) '-'[Cgprtu])
(( this_word & 1 )) && (( this_word = this_word ^ 1 )) (( this_word & 1 )) && (( this_word = this_word ^ 1 ))
(( next_word = 8 )) (( next_word = 8 ))
;; ;;
# This prevents misbehavior with sudo -u -otherargument # This prevents misbehavior with sudo -u -otherargument
'-'*) '-'*)
(( this_word & 1 )) && (( this_word = this_word ^ 1 )) (( this_word & 1 )) && (( this_word = this_word ^ 1 ))
(( next_word = next_word | 1 )) (( next_word = next_word | 1 ))
(( next_word = next_word | 4 )) (( next_word = next_word | 4 ))
;; ;;
*) ;; *) ;;
esac esac
elif (( this_word & 8 )); then elif (( this_word & 8 )); then
(( next_word = next_word | 4 )) (( next_word = next_word | 4 ))
(( next_word = next_word | 1 )) (( next_word = next_word | 1 ))
fi fi
fi fi
expanded_path="" expanded_path=""
# The Great Fork: is this a command word? Is this a non-command word? # The Great Fork: is this a command word? Is this a non-command word?
if (( this_word & 16 )) && [[ $arg == 'always' ]]; then if (( this_word & 16 )) && [[ $arg == 'always' ]]; then
# try-always construct # try-always construct
style=reserved-word # de facto a reserved word, although not de jure style=reserved-word # de facto a reserved word, although not de jure
(( next_word = 1 )) (( next_word = 1 ))
elif (( this_word & 1 )) && (( in_redirection == 0 )); then # $arg is the command word elif (( this_word & 1 )) && (( in_redirection == 0 )); then # $arg is the command word
cur_cmd="$arg" cur_cmd="$arg"
if (( arg_type == 1 )); then if (( arg_type == 1 )); then
style=precommand style=precommand
elif [[ "$arg" = "sudo" ]]; then elif [[ "$arg" = "sudo" ]]; then
style=precommand style=precommand
(( next_word & 2 )) && (( next_word = next_word ^ 2 )) (( next_word & 2 )) && (( next_word = next_word ^ 2 ))
(( next_word = next_word | 4 )) (( next_word = next_word | 4 ))
(( next_word = next_word | 1 )) (( next_word = next_word | 1 ))
else else
# Special-case: command word is '$foo', like that, without braces or anything. 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}
# That's not entirely correct --- if the parameter's value happens to be a reserved else
# word, the parameter expansion will be highlighted as a reserved word --- but that : ${expanded_path::=${(Q)~arg}}
# incorrectness is outweighed by the usability improvement of permitting the use of -hsmw-highlight-main-type $expanded_path
# parameters that refer to commands, functions, and builtins. fi
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 case $REPLY in
reserved) # reserved word reserved) # reserved word
style=reserved-word style=reserved-word
if [[ $arg == $'\x7b' ]]; then if [[ $arg == $'\x7b' ]]; then
braces_stack='Y'"$braces_stack" braces_stack='Y'"$braces_stack"
elif [[ $arg == $'\x7d' && $braces_stack[1] == "Y" ]]; then 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]=""
braces_stack[1]="" style=reserved-word
style=reserved-word (( next_word = next_word | 16 ))
(( next_word = next_word | 16 )) elif [[ $arg == "[[" ]]; then
elif [[ $arg == "[[" ]]; then braces_stack='A'"$braces_stack"
braces_stack='A'"$braces_stack" fi
fi ;;
;; 'suffix alias') style=suffix-alias ;;
'suffix alias') style=suffix-alias;; alias)
alias) insane_alias=0
insane_alias=0 case $arg in
case $arg in '='*)
# Issue #263: aliases with '=' on their LHS. :
# ;;
# There are three cases: *'='*)
# insane_alias=1
# - Unsupported, breaks 'alias -L' output, but invokable: ;;
('='*) :;; *)
# - Unsupported, not invokable: :
(*'='*) insane_alias=1;; ;;
# - The common case: esac
(*) :;; if (( insane_alias )); then
esac style=unknown-token
if (( insane_alias )); then else
style=unknown-token style=alias
else zmodload -e zsh/parameter && alias_target=${aliases[$arg]} || alias_target="${"$(alias -- $arg)"#*=}"
style=alias [[ ${__HSMW_HIGHLIGHT_TOKENS_TYPES[$alias_target]} = "1" && "$arg_type" != "1" ]] && __HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]="1"
zmodload -e zsh/parameter && alias_target=${aliases[$arg]} || alias_target="${"$(alias -- $arg)"#*=}" fi
[[ ${__HSMW_HIGHLIGHT_TOKENS_TYPES[$alias_target]} = "1" && "$arg_type" != "1" ]] && __HSMW_HIGHLIGHT_TOKENS_TYPES[$arg]="1" ;;
fi builtin)
;; style=builtin ;;
builtin) style=builtin;; function)
function) style=function;; style=() ;;
command) style=command;; command)
hashed) style=hashed-command;; style=command ;;
dirpath) style=path;; hashed)
none) # Assign? style=hashed-command ;;
if [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[[^\]]#\])(|[+])=* ]] || [[ $arg == [0-9]##(|[+])=* ]]; then dirpath)
style=assign style=path ;;
# Assignment to a scalar parameter or to array none)
# (For array assignments, the command doesn't start until the ")" token.) if [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[[^\]]#\])(|[+])=* ]] || [[ $arg == [0-9]##(|[+])=* ]]; then
[[ $arg[-1] == '(' ]] && in_array_assignment=1 || (( next_word = next_word | 1 )) style=assign
elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then [[ $arg[-1] == '(' ]] && in_array_assignment=1 || (( next_word = next_word | 1 ))
style=history-expansion elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then
elif [[ $arg[1] == $histchars[2] ]]; then style=history-expansion
style=history-expansion elif [[ $arg[1] == $histchars[2] ]]; then
elif (( arg_type == 3 )); then style=history-expansion
# This highlights empty commands (semicolon follows nothing) as an error. elif (( arg_type == 3 )); then
# Zsh accepts them, though. (( this_word & 2 )) && style=commandseparator
(( this_word & 2 )) && style=commandseparator elif [[ $arg[1,2] == '((' ]]; then
elif [[ $arg[1,2] == '((' ]]; then reply+=("$start_pos $(( start_pos + 2 )) ${HSMW_HIGHLIGHT_STYLES[reserved-word]}")
# Arithmetic evaluation. already_added=1
# [[ $arg[-2,-1] == '))' ]] && reply+=("$(( end_pos - 2 )) $end_pos ${HSMW_HIGHLIGHT_STYLES[reserved-word]}")
# Note: prior to zsh-5.1.1-52-g4bed2cf (workers/36669), the ${(z)...} elif [[ $arg == '()' ]]; then
# splitter would only output the '((' token if the matching '))' had style=reserved-word
# been typed. Therefore, under those versions of zsh, BUFFER="(( 42" elif [[ $arg == $'\x28' ]]; then
# would be highlighted as an error until the matching "))" are typed. style=reserved-word
# braces_stack='R'"$braces_stack"
# We highlight just the opening parentheses, as a reserved word; this elif [[ $arg == $'\x29' ]]; then
# is how [[ ... ]] is highlighted, too. [[ $braces_stack[1] == "R" ]] && { braces_stack[1]=""; style=reserved-word; }
elif (( this_word & 14 )); then
# ADD style=default
reply+=("$start_pos $(( start_pos + 2 )) ${HSMW_HIGHLIGHT_STYLES[reserved-word]}") fi
already_added=1 ;;
# ADD *)
[[ $arg[-2,-1] == '))' ]] && reply+=("$(( end_pos - 2 )) $end_pos ${HSMW_HIGHLIGHT_STYLES[reserved-word]}") already_added=1
elif [[ $arg == '()' ]]; then ;;
# anonymous function esac
style=reserved-word fi
elif [[ $arg == $'\x28' ]]; then elif (( in_redirection + this_word & 14 )); 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 $arg in case $arg in
']]') ']]')
style=reserved-word style=reserved-word
[[ $braces_stack[1] == "A" ]] && braces_stack[1]="" [[ $braces_stack[1] == "A" ]] && braces_stack[1]=""
;; ;;
']') ']')
style=builtin style=builtin
;; ;;
$'\x28') $'\x28')
# '(' inside [[ style=reserved-word
style=reserved-word braces_stack='R'"$braces_stack"
braces_stack='R'"$braces_stack" ;;
;;
$'\x29') # subshell or end of array assignment $'\x29') # subshell or end of array assignment
if (( in_array_assignment )); then if (( in_array_assignment )); then
style=assign style=assign
in_array_assignment=0 in_array_assignment=0
(( next_word = next_word | 1 )) (( next_word = next_word | 1 ))
elif [[ $braces_stack[1] == "R" ]]; then elif [[ $braces_stack[1] == "R" ]]; then
braces_stack[1]="" braces_stack[1]=""
style=reserved-word style=reserved-word
fi;; fi ;;
$'\x28\x29') # possibly a function definition $'\x28\x29')
# || false # TODO: or if the previous word was a command word (( multi_func_def )) && (( next_word = next_word | 1 ))
(( multi_func_def )) && (( next_word = next_word | 1 )) style=reserved-word
style=reserved-word reply[-1]=()
# Remove possible annoying unknown-token style, or misleading function style ;;
reply[-1]=() '--'*)
;; style=double-hyphen-option ;;
'--'*) style=double-hyphen-option;; '-'*)
'-'*) style=single-hyphen-option;; style=single-hyphen-option ;;
"'"*) style=single-quoted-argument;; "'"*)
style=single-quoted-argument ;;
'"'*) '"'*)
# ADD reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[double-quoted-argument]}")
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[double-quoted-argument]}") -hsmw-highlight-string
-hsmw-highlight-string already_added=1
already_added=1 ;;
;; \$\*)
\$\'*) reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[dollar-quoted-argument]}")
# ADD -hsmw-highlight-dollar-string
reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[dollar-quoted-argument]}") already_added=1
-hsmw-highlight-dollar-string ;;
already_added=1
;;
\$[^\(]*) \$[^\(]*)
style=variable style=variable
;; ;;
'`'*) style=back-quoted-argument;; '`'*)
style=back-quoted-argument
;;
[*?]*|*[^\\][*?]*) [*?]*|*[^\\][*?]*)
(( highlight_glob )) && style=globbing || style=default;; (( highlight_glob )) && style=globbing || style=default
*) if [[ $arg = $'\x7d' && $braces_stack[1] == "Y" && "$right_brace_is_recognised_everywhere" = "1" ]]; then ;;
# right brace *)
# Parsing rule: # { if [[ $arg = $'\x7d' && $braces_stack[1] == "Y" ]] && [[ "$right_brace_is_recognised_everywhere" = "1" ]]; then
# braces_stack[1]=""
# Additionally, `tt(})' is recognized in any position if neither the style=reserved-word
# tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set.""" (( next_word = next_word | 16 ))
braces_stack[1]="" elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then
style=reserved-word style=history-expansion
(( next_word = next_word | 16 )) elif (( arg_type == 3 )); then
elif [[ $arg[1] = $histchars[1] && -n "${arg[2]}" ]]; then style=commandseparator
style=history-expansion elif (( in_redirection == 2 )); then
elif (( arg_type == 3 )); then style=redirection
style=commandseparator else
elif (( in_redirection == 2 )); then if (( __hsmw_no_check_paths == 0 )) && -hsmw-highlight-check-path; then
style=redirection reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[path]}")
else already_added=1
if (( __hsmw_no_check_paths == 0 )) && -hsmw-highlight-check-path; then
# ADD
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 if [[ -n "$HSMW_HIGHLIGHT_STYLES[path_pathseparator]" && "$HSMW_HIGHLIGHT_STYLES[path]" != "$HSMW_HIGHLIGHT_STYLES[path_pathseparator]" ]]; then
for (( pos = start_pos; pos <= end_pos; pos++ )) ; do local pos
# ADD for (( pos = start_pos; pos <= end_pos; pos++ )) ; do
[[ ${buf[pos]} == "/" ]] && reply+=("$(( pos - 1 )) $pos ${HSMW_HIGHLIGHT_STYLES[path_pathseparator]}") [[ ${buf[pos]} == "/" ]] && reply+=("$(( pos - 1 )) $pos ${HSMW_HIGHLIGHT_STYLES[path_pathseparator]}")
done done
} fi
else else
style=default style=default
fi fi
fi fi
;; ;;
esac esac
fi fi
# ADD
(( already_added == 0 )) && [[ "${HSMW_HIGHLIGHT_STYLES[$style]}" != "none" ]] && reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[$style]}") (( already_added == 0 )) && [[ "${HSMW_HIGHLIGHT_STYLES[$style]}" != "none" ]] && reply+=("$start_pos $end_pos ${HSMW_HIGHLIGHT_STYLES[$style]}")
if (( arg_type == 3 )); then if (( arg_type == 3 )); then
if [[ $arg == ';' ]] && (( in_array_assignment )); then if [[ $arg == ';' ]] && (( in_array_assignment )); then
# literal newline inside an array assignment
(( next_word = 2 )) (( next_word = 2 ))
elif [[ -n "${braces_stack[(r)A]}" ]]; then elif [[ -n "${braces_stack[(r)A]}" ]]; then
(( next_word = 2 )) (( next_word = 2 ))
@ -608,109 +466,85 @@ __HSMW_HIGHLIGHT_TOKENS_TYPES=(
highlight_glob=1 highlight_glob=1
fi fi
elif (( arg_type == 1 || arg_type == 2 )) && (( this_word & 1 )); then elif (( arg_type == 1 || arg_type == 2 )) && (( this_word & 1 )); then
(( next_word = 1 )) (( next_word = 1 ))
elif [[ $arg == "repeat" ]] && (( this_word & 1 )); then elif [[ $arg == "repeat" ]] && (( this_word & 1 )); then
# skip the repeat-count word
in_redirection=2 in_redirection=2
# The redirection mechanism assumes $this_word describes the word (( thisword = 3 ))
# 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 ))
fi fi
start_pos=$end_pos start_pos=$end_pos
# This is the default/common codepath. (( in_redirection == 0 )) && (( this_word = next_word ))
(( in_redirection == 0 )) && (( this_word = next_word )) #else # Stall $this_word.
done done
return 0 return 0
} }
# Check if $arg is a path. -hsmw-highlight-check-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()
{
: ${expanded_path:=${(Q)~arg}} : ${expanded_path:=${(Q)~arg}}
[[ -n "${FAST_BLIST_PATTERNS[(k)$expanded_path]}" ]] && return 1 [[ -n "${FAST_BLIST_PATTERNS[(k)$expanded_path]}" ]] && return 1
[[ -z $expanded_path ]] && return 1 [[ -z $expanded_path ]] && return 1
[[ -e $expanded_path ]] && return 0 [[ -e $expanded_path ]] && return 0
# Search the path in CDPATH, only for CD command if [[ "$cur_cmd" = "cd" ]]; then
[[ "$cur_cmd" = "cd" ]] && for cdpath_dir in $cdpath ; do for cdpath_dir in $cdpath ; do
[[ -e "$cdpath_dir/$expanded_path" ]] && return 0 if [[ -e "$cdpath_dir/$expanded_path" ]]; then
done return 0
fi
done
fi
# It's not a path.
return 1 return 1
} }
# Highlight special chars inside double-quoted strings -hsmw-highlight-string() {
-hsmw-highlight-string()
{
mybuf="$arg" mybuf="$arg"
idx=start_pos 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 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]}" ]] && { if [[ -n "${match[7]}" ]]; then
# Skip following char it is quoted. Choice is
# made to not highlight such quoting
idx+=${mbegin[1]}+1 idx+=${mbegin[1]}+1
mybuf="${match[7]:1}" mybuf="${match[7]:1}"
} || { else
idx+=${mbegin[1]}-1 idx+=${mbegin[1]}-1
end_idx=idx+${mend[1]}-${mbegin[1]}+1 end_idx=idx+${mend[1]}-${mbegin[1]}+1
mybuf="${match[8]}" mybuf="${match[8]}"
# ADD
reply+=("$idx $end_idx ${HSMW_HIGHLIGHT_STYLES[back-or-dollar-double-quoted-argument]}") reply+=("$idx $end_idx ${HSMW_HIGHLIGHT_STYLES[back-or-dollar-double-quoted-argument]}")
idx=end_idx idx=end_idx
} fi
done done
} }
# Highlight special chars inside dollar-quoted strings -hsmw-highlight-dollar-string() {
-hsmw-highlight-dollar-string()
{
local i j k style local i j k style
local AA local AA
integer c 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 )) (( j = i + start_pos - 1 ))
(( k = j + 1 )) (( k = j + 1 ))
case "$arg[$i]" in case $arg[$i] in
"\\") style=back-dollar-quoted-argument \\)
for (( c = i + 1 ; c <= end_pos - start_pos ; c += 1 )); do style=back-dollar-quoted-argument
[[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break for (( c = i + 1 ; c <= end_pos - start_pos ; c += 1 )); do
done [[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break
AA=$arg[$i+1,$c-1] done
# Matching for HEX and OCT values like \0xA6, \xA6 or \012 AA=$arg[$i+1,$c-1]
if [[ "$AA" =~ "^(x|X)[0-9a-fA-F]{1,2}" 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
|| "$AA" =~ "^[0-7]{1,3}" (( k += $#MATCH ))
|| "$AA" =~ "^u[0-9a-fA-F]{1,4}" (( i += $#MATCH ))
|| "$AA" =~ "^U[0-9a-fA-F]{1,8}" else
]]; then if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then
(( k += $#MATCH )) style=unknown-token
(( i += $#MATCH )) fi
else (( k += 1 )) # Color following char too.
if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then (( i += 1 )) # Skip parsing the escaped char.
# \x not followed by hex digits is probably an error fi
style=unknown-token ;;
fi *)
(( k += 1 )) # Color following char too. continue
(( i += 1 )) # Skip parsing the escaped char. ;;
fi
;;
*) continue ;;
esac esac
# ADD
reply+=("$j $k ${HSMW_HIGHLIGHT_STYLES[$style]}") reply+=("$j $k ${HSMW_HIGHLIGHT_STYLES[$style]}")
done done
} }