├── .github └── workflows │ └── test.yml ├── .gitignore ├── .hypothesis ├── examples │ ├── 3829dcef94528797 │ │ └── 1086a78797317d2d │ ├── 3ea86dbcb01b162b │ │ └── 1086a78797317d2d │ ├── 6a13d6a94003c708 │ │ └── 1086a78797317d2d │ ├── 7375ce819d42ab0d │ │ └── 1086a78797317d2d │ ├── 77dae7b8778b88e0 │ │ ├── 1086a78797317d2d │ │ └── bec021b4f368e306 │ ├── 7a02f7143aa5bd0f │ │ └── 1086a78797317d2d │ ├── bb3263574321e5ea │ │ └── 1086a78797317d2d │ ├── c6871e3a81e8b20d │ │ └── 1086a78797317d2d │ └── f7b253aa616ff3a5 │ │ ├── 25be50f1a45836e1 │ │ ├── 74844d13d1d969b6 │ │ └── aad329b8ac08c355 └── unicode_data │ ├── 15.0.0 │ └── charmap.json.gz │ └── 15.1.0 │ └── charmap.json.gz ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── dfa.svg └── railroad.svg ├── build.rs ├── e2e ├── .gitignore ├── capture_postamble.zsh ├── capture_preamble.zsh ├── common.py ├── conftest.py ├── requirements.txt ├── test_bash.py ├── test_fish.py ├── test_validation.py ├── test_zsh.py └── test_zsh_pty.py ├── examples ├── complgen.usage ├── darcs.usage ├── mygit.usage └── mygrep.usage ├── proptest-regressions └── dfa.txt ├── pytest.ini ├── run-e2e-tests.bash └── src ├── bash.rs ├── dfa.rs ├── fish.rs ├── grammar.rs ├── lib.rs ├── main.rs ├── regex.rs ├── scrape.rs └── zsh.rs /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Build 20 | run: cargo build 21 | - name: Run tests 22 | run: cargo test 23 | - name: Run e2e tests 24 | run: ./run-e2e-tests.bash 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /venv 3 | -------------------------------------------------------------------------------- /.hypothesis/examples/3829dcef94528797/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/3ea86dbcb01b162b/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/6a13d6a94003c708/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/7375ce819d42ab0d/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/77dae7b8778b88e0/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/77dae7b8778b88e0/bec021b4f368e306: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.hypothesis/examples/7a02f7143aa5bd0f/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/bb3263574321e5ea/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/c6871e3a81e8b20d/1086a78797317d2d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.hypothesis/examples/f7b253aa616ff3a5/25be50f1a45836e1: -------------------------------------------------------------------------------- 1 | " -------------------------------------------------------------------------------- /.hypothesis/examples/f7b253aa616ff3a5/74844d13d1d969b6: -------------------------------------------------------------------------------- 1 | " -------------------------------------------------------------------------------- /.hypothesis/examples/f7b253aa616ff3a5/aad329b8ac08c355: -------------------------------------------------------------------------------- 1 | ?( -------------------------------------------------------------------------------- /.hypothesis/unicode_data/15.0.0/charmap.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adaszko/complgen/8ae6de12165b2c29d13babcf9a782b164a43289c/.hypothesis/unicode_data/15.0.0/charmap.json.gz -------------------------------------------------------------------------------- /.hypothesis/unicode_data/15.1.0/charmap.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adaszko/complgen/8ae6de12165b2c29d13babcf9a782b164a43289c/.hypothesis/unicode_data/15.1.0/charmap.json.gz -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## Unreleased 9 | ## 0.4.0 10 | ### Changed 11 | 12 | - Breaking: Simplified CLI interface (there's no subcommands anymore; aot is now implicit) 13 | 14 | ### Removed 15 | 16 | - Breaking: JIT mode has been removed (its functioning changed over time, rendering it largely redundant) 17 | 18 | ### Added 19 | 20 | - Nontail-position commands 21 | - Descriptions under fish and zsh are now deduplicated 22 | 23 | ### Fixed 24 | 25 | - Breaking: Tail commands detection is more precise now, resulting in more rejected grammars (that would have previously been silently ambiguous) 26 | - Breaking: Two adjacent literals used in subword context are now rejected as an error as this may lead to surprising behavior (https://github.com/adaszko/complgen/issues/63) 27 | - Bash: Bug in `prefix{{{ shell command }}}` case 28 | 29 | ## 0.3.0 30 | ### Added 31 | 32 | - Fish,AOT: Implemented fallbacks 33 | - Fish,JIT: Implemented fallbacks 34 | 35 | ### Fixed 36 | 37 | - Fish,JIT: Descriptions were wrongly being made part of the completion 38 | - Bash: Respect `completion-ignore-case` readline setting 39 | 40 | ## 0.2.0 41 | ### Changed 42 | 43 | - **Breaking**: `{{{ ... }}}` commands and many predefined nonterminals (e.g. ``, etc) are now allowed 44 | in fewer places to keep grammars unambiguous. It statically safeguards against some bugs in completion 45 | scripts. 46 | - **Breaking**: Releases aren't published via Homebrew anymore -- use `cargo install`. 47 | - **Breaking**: JIT completion now emits shell scripts (as opposed to plain strings) in all shells. Integration scripts need to be adjusted accordingly. Details in README.md. 48 | 49 | ### Fixed 50 | 51 | - Autoloading of ZSH completion scripts works now (#38) 52 | 53 | ### Added 54 | 55 | - Fallback completions. It's not implemented across the board yet. See README for details. 56 | 57 | ## 0.1.8 58 | ### Changed 59 | 60 | - **Breaking**: `complgen complete` has been renamed to `complgen jit` to better reflect it's for just-in-time completion 61 | - **Breaking**: `complgen compile` has been renamed to `complgen aot` to better reflect it's for ahead-of-time completion script generation 62 | 63 | ### Fixed 64 | 65 | - Bash,AOT: Completion trailing spaces are now added precisely (#35) 66 | - Bash,JIT: Completion trailing spaces are now added precisely (#35) 67 | - Zsh,JIT: Completion trailing spaces are now added precisely (#35) 68 | - Bash,AOT: Further improve $COMP_WORDBREAKS characters handling 69 | - Bash,JIT: Further improve $COMP_WORDBREAKS characters handling 70 | 71 | ## 0.1.7 72 | ### Fixed 73 | 74 | - Bash,JIT: Shell integration should now handle $COMP_WORDBREAKS characters correctly 75 | - Bash,JIT: Fixed Bash shell integration 76 | 77 | ## 0.1.6 78 | ### Fixed 79 | 80 | - ZSH,JIT: Completing in the middle of a word (with `complete_in_word` option set) works now 81 | - ZSH,JIT: Completing paths tcsh style (f/b/b -> foo/bar/baz) works now 82 | 83 | ### Changed 84 | 85 | - Breaking: `complgen complete` CLI interface has changed. Shell integration configuration needs to be updated. See README. 86 | 87 | ## 0.1.5 88 | 89 | ### Fixed 90 | 91 | - JIT completion bug: Grammar `cmd +{{{ echo foo }}}` was being completed ad infinitum. 92 | 93 | ## 0.1.4 94 | 95 | ### Added 96 | 97 | - In zsh, for the grammar `--color=(always|never)` and input `--color=`, you will now see `always` and 98 | `never`, not `--color=always` and `--color=never`. This generalized to all subword completions of course. 99 | - Descriptions can now contain escaped characters, e.g. a quote character or a backslash. 100 | - More readable parsing errors using the chic Rust crate 101 | - Scraper is now based on a bunch of regexes instead of a complicated parser. This simplifies the code a lot. 102 | 103 | ### Changed 104 | 105 | - If multiple literals have the same decription, they're now grouped into a single line (this can be 106 | controlled with `zstyle ':completion:*' list-grouped true/false`) 107 | 108 | ### Removed 109 | 110 | - Single brackets external commands as they're superfluous (replaced with triple brackets ones) 111 | 112 | ## 0.1.3 113 | ### Fixed 114 | 115 | - More compact zsh completions in JIT mode 116 | - Zsh,JIT: Only consider completions with descriptions when aligning completions for better appearance 117 | - Remove leftover parenthesis in ZSH subword descriptions 118 | 119 | ## 0.1.2 120 | ### Fixed 121 | 122 | - A bug in Bash output where order of arguments to `mapfile` was wrong 123 | 124 | ## 0.1.1 125 | ### Added 126 | 127 | - Binary releases on GitHub 128 | 129 | ### Fixed 130 | 131 | - Bug in parser where descriptions were being distributed too generously. 132 | 133 | ## 0.1.0 134 | ### Added 135 | 136 | - Add a Homebrew tap formula for automatic updates on new versions. 137 | 138 | - "Distributive" descriptions: you can now use a shorthand descriptions: 139 | `mygrep (--color= | --color ) "use markers to highlight the matching strings"` 140 | and the "use marker..." description is going to apply to both `--color=` and `--color ...` so you don't need to repeat it. 141 | 142 | - Improve performance when running on `darcs.usage` example by 4x :O 143 | - Only the completed part appears in ZSH description now instead of the entire shell word (less noise, more like native ZSH) 144 | - Zsh descriptions now look like the ones produced by _arguments for consistency 145 | - Only emit subword processing shell script code if it's actually used in the grammar to conserve space 146 | - Write ZSH completion each on separate lines if any contains a description to better mimic what _arguments does 147 | - New CLI subcommand: `complgen check` that checks the passed grammar and doesn't write annything to disk. 148 | 149 | ### Fixed 150 | 151 | - In Bash integration script, `grep --color=` didn't complete anything. 152 | 153 | - Bug in JIT mode: Completing subdirectory files wasn't working due to the entered prefix not being passed 154 | properly. 155 | 156 | - Output proper completion prefix in subword completion in shell integration (JIT mode). Even though 157 | completions were produced by complgen, shells were filtering them out due to lack of a proper prefix. 158 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | This document is intended to lower the bar for contributing to `complgen`. 2 | 3 | # How it works 4 | 5 | `complgen` is architected somewhat like a compiler: it has several transformation stages and data flows only 6 | in one direction like in a pipeline. 7 | 8 | The stages are as follows: 9 | 10 | 1. Parse a `.usage` file into a Rust data structure 11 | 1. Convert the data structure into a regular expression (in the textbook sense, not in the programmar sense) 12 | 1. Convert the regular expression into a Deterministic Finite Automaton (DFA) 13 | * For details, see [Compilers Principles, Techniques and 14 | Tools](https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools) (aka The Dragon 15 | Book), 2nd edition, section 3.9.5, "Converting a Regular Expression Directly to a DFA" 16 | 1. Minimize the DFA 17 | * For details, see [Engineering a Compiler](https://www.amazon.com/Engineering-Compiler-Keith-D-Cooper/dp/0128154128), 3rd edition, section "2.4.4 DFA to Minimal DFA" 18 | * And also section 3.9.6, "Minimizing the Number of States of a DFA" from The Dragon Book. 19 | 1. Emit a shell completion script 20 | * Bash: [Creating a bash completion script](https://iridakos.com/programming/2018/03/01/bash-programmable-completion-tutorial) 21 | * Fish: [Writing your own completions — fish-shell documentation](https://fishshell.com/docs/current/completions.html) 22 | * ZSH (zsh's completion system can be somewhat arcane in places): 23 | * [zsh-completions/zsh-completions-howto.org](https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org) 24 | * [ZSH – Writing own completion functions](https://askql.wordpress.com/2011/01/11/zsh-writing-own-completion/) 25 | * [Dynamic zsh autocomplete for custom commands](https://unix.stackexchange.com/questions/239528/dynamic-zsh-autocomplete-for-custom-commands/240192#240192) 26 | * [Writing zsh completion scripts](https://blog.mads-hartmann.com/2017/08/06/writing-zsh-completion-scripts.html) 27 | * [Current Word Completion](https://jonathanh.co.uk/blog/current-word-completion/) 28 | 29 | `complgen` is based on [compleat](https://github.com/mbrubeck/compleat), so it may also be useful sometimes to 30 | reference it. 31 | 32 | # Visualizations 33 | 34 | To ease understanding and debugging, some of the stages can generate visualizations (see output of `complgen 35 | --help` for the relevant option name). 36 | 37 | For the following grammar: 38 | 39 | ``` 40 | grep [