{"id":19973738,"url":"https://github.com/cgabriel5/nodecliac","last_synced_at":"2025-09-13T07:40:54.663Z","repository":{"id":42208951,"uuid":"167310837","full_name":"cgabriel5/nodecliac","owner":"cgabriel5","description":"Easy Bash completion for CLI programs.","archived":false,"fork":false,"pushed_at":"2023-07-18T20:34:54.000Z","size":31113,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-04T02:39:02.206Z","etag":null,"topics":["bash","bash-completion","cli"],"latest_commit_sha":null,"homepage":"https://cgabriel5.github.io/nodecliac/","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cgabriel5.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-01-24T05:48:38.000Z","updated_at":"2023-04-23T22:41:35.000Z","dependencies_parsed_at":"2025-05-04T02:45:36.161Z","dependency_job_id":null,"html_url":"https://github.com/cgabriel5/nodecliac","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cgabriel5/nodecliac","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgabriel5%2Fnodecliac","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgabriel5%2Fnodecliac/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgabriel5%2Fnodecliac/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgabriel5%2Fnodecliac/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cgabriel5","download_url":"https://codeload.github.com/cgabriel5/nodecliac/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgabriel5%2Fnodecliac/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274935950,"owners_count":25376832,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-13T02:00:10.085Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","bash-completion","cli"],"created_at":"2024-11-13T03:12:36.252Z","updated_at":"2025-09-13T07:40:54.613Z","avatar_url":"https://github.com/cgabriel5.png","language":"Nim","readme":"\u003ch1 align=\"center\"\u003enodecliac\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/cgabriel5/nodecliac/blob/gh-pages/website/media/logo.png?raw=true\" alt=\"nodecliac logo\" title=\"nodecliac logo\" width=\"125px\"\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003eEasy Bash completion for CLI programs\u003c/div\u003e\n\u003cbr\u003e\n\n\u003c!-- ##### Table of Contents\n\n- [Install](#install-normal)\n- [How It Works](#how-it-works)\n- [Syntax](#syntax)\n- [CLI](#cli)\n- [Registry](#registry)\n- [Hooks](#hooks)\n- [Packages](#packages)\n- [Support](#support)\n- [Contributing](#contributing)\n- [License](#license)\n --\u003e\n\n\u003ca name=\"install-normal\"\u003e\u003c/a\u003e\n\n## Install\n\n\u003c!-- Shorten install script URL: --\u003e\n\u003c!-- [https://saraford.net/2017/02/18/how-to-use-git-io-to-shorten-github-urls-and-create-vanity-urls-049/] --\u003e\n\u003c!-- [https://stackoverflow.com/questions/44347129/delete-git-io-shortened-url] --\u003e\n\u003c!-- [https://github.blog/2011-11-10-git-io-github-url-shortener/] --\u003e\n\u003c!-- [https://stackoverflow.com/questions/39065921/what-do-raw-githubusercontent-com-urls-represent] --\u003e\n\n\u003c!-- Using `bash -s`: [https://stackoverflow.com/a/51854728] --\u003e\n\u003c!-- [https://unix.stackexchange.com/a/339238] --\u003e\n\u003c!-- [https://unix.stackexchange.com/a/180826] --\u003e\n\n```sh\n$ bash \u003c(curl -Ls git.io/nodecliac) \u0026\u0026 source ~/.bashrc\n```\n\n\u003c!-- [https://stackoverflow.com/questions/17341122/link-and-execute-external-javascript-file-hosted-on-github] --\u003e\n\n\u003cdetails\u003e\u003csummary\u003eMore installation methods\u003c/summary\u003e\n\n\u003cbr\u003e\n\n**curl Install** (_explicit defaults_):\n\n```sh\n$ bash \u003c(curl -Ls git.io/nodecliac) --installer= --branch=master --rcfile=~/.bashrc \u0026\u0026 source ~/.bashrc\n```\n\n**wget Install** (_defaults_):\n\n```sh\n$ bash \u003c(wget -qO- git.io/nodecliac) \u0026\u0026 source ~/.bashrc\n```\n\n**Manual Install**: One can also install manually.\n\n\u003c!-- [https://askubuntu.com/a/86850] --\u003e\n\n1. First download the GitHub nodecliac [repository](https://github.com/cgabriel5/nodecliac/archive/master.zip).\n2. Next unzip the folder via `$ unzip nodecliac-*.zip` or by right-clicking and using the OS provided extractor utility.\n3. `cd` into the repository and install: `$ sudo chmod +x install.sh \u0026\u0026 ./install.sh --manual \u0026\u0026 source ~/.bashrc`\n4. Delete the downloaded `zip` folder, its extracted folder, and start using.\n\n**Checksum Install**: If desired, the install script file's integrity can be verified before running.\n\n[install.sh](https://raw.githubusercontent.com/cgabriel5/nodecliac/master/install.sh) `sha256sum` checksum: `2b4f37dae3cbe5cc81a0ce52f55a5d300445e3e3a68d9d7e97040504e1aec9da`\n\nCreate an executable shell file called `install.sh`, add the following, and run it.\n\n```sh\n#!/bin/bash\n\n# The script downloads the install script, generates its checksum, and checks\n# it against the valid sha256 sum value. If sums match the install script runs,\n# otherwise an error message is printed and this script is exited.\n\ninstall() {\n    url=\"git.io/nodecliac\"\n    is=\"$([[ \"$(command -v curl)\" ]] \u0026\u0026 sudo curl -Ls \"$url\" || sudo wget -qO- \"$url\")\"\n    x=($([[ \"$OSTYPE\" == \"darwin\"* ]] \u0026\u0026 shasum -a 256 \u003c\u003c\u003c \"$is\" || sha256sum \u003c\u003c\u003c \"$is\"))\n    c=\"2b4f37dae3cbe5cc81a0ce52f55a5d300445e3e3a68d9d7e97040504e1aec9da\"\n    err=\"\\033[1;31mError\\033[0m: Verification failed: checksums don't match.\"\n    [[ \"$c\" == \"$x\" ]] \u0026\u0026 bash \u003c(echo \"$is\") \\\n        --installer= \\\n        --branch=master \\\n        --rcfile=~/.bashrc \\\n        \u0026\u0026 source ~/.bashrc || echo -e \"$err\" \u0026\u0026 exit 1\n} \u0026\u0026 install\n```\n\n\u003c!-- [https://unix.stackexchange.com/a/538602] --\u003e\n\u003c!-- [https://unix.stackexchange.com/a/426838] --\u003e\n\u003c!-- [https://github.com/ESGF/esg-search/issues/84#issuecomment-214773499] --\u003e\n\u003c!-- [https://apple.stackexchange.com/a/310245] --\u003e\n\u003c!-- [https://explainshell.com/explain?cmd=%28curl%20-fsSL%20lsd.systemten.org%7C%7Cwget%20-q%20-O-%20lsd.systemten.org%29%7Cmksh.1#] --\u003e\n\u003c!-- # l=\"$(sha256sum \u003c\u003c\u003c \"$is\" | awk '$0=$1')\" --\u003e\n\u003c!-- # l=\"$(perl -ne 'print $1 if /^([^\\s]+)/' \u003c\u003c\u003c $(sha256sum \u003c\u003c\u003c \"$is\"))\" --\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eInstallation options\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- `--installer`: The installer to use. (default: `yarn` \u003e `npm` \u003e `binary`)\n  - `yarn`: Uses [yarn](https://yarnpkg.com/en/) to install.\n  - `npm`: Uses [Node.js](https://nodejs.org/en/)'s [npm](https://www.npmjs.com/get-npm) to install.\n  - `binary`: Uses nodecliac's [Nim](https://nim-lang.org/) Linux/macOS CLI tools.\n- `--branch`: An _existing_ nodecliac branch name to install. (default: `master`)\n- `--rcfile`: `bashrc` file to install nodecliac to. (default: `~/.bashrc`)\n- `--yes`: Automate install by saying yes to any prompt(s).\n- `--packages`: Install [collection](https://github.com/cgabriel5/nodecliac/tree/master/resources/packages) of pre-made completion packages.\n- `--manual`: Let's install script to take manual install route.\n- `--update`: Let's install script to take update router over fresh install route.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRequirements\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- [Perl](https://www.perl.org/get.html) `v5+`.\n- [Node.js](https://nodejs.org/en/) `v8+` if installing via `npm` or `yarn`.\n- [bash-completion](https://github.com/scop/bash-completion) `v1.3+`, preferably `v.2.1+`.\n- [Bash](https://www.gnu.org/software/bash/) `v4.3+`.\n  - `macOS`: Stock Bash is outdated (`v3.2`). Update via [Homebrew](https://brew.sh/) to [`v4.3+`](https://akrabat.com/upgrading-to-bash-4-on-macos/).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eUninstall\u003c/summary\u003e\n\n\u003cbr\u003e\n\n```sh\n$ nodecliac uninstall\n```\n\nIf a custom rcfile path was used during install provide it again during uninstall.\n\n```sh\n$ nodecliac uninstall --rcfile=path/to/.bashrc\n```\n\n\u003c/details\u003e\n\n\u003c!-- \u003cdetails\u003e\u003csummary\u003eDownload \u003ca href=\"https://stackoverflow.com/a/4568323\" target=\"_blank\" rel=\"nofollow\"\u003especific branch\u003c/a\u003e\u003c/summary\u003e\n\n```sh\n# yarn\n$ yarn global add cgabriel5/nodecliac#BRANCH_NAME \u0026\u0026 nodecliac setup\n\n# npm (requires sudo)\n$ sudo npm i -g cgabriel5/nodecliac#BRANCH_NAME \u0026\u0026 nodecliac setup\n\n# git\n$ git clone -b BRANCH_NAME --single-branch https://github.com/cgabriel5/nodecliac.git\n```\n\n\u003c/details\u003e --\u003e\n\n\u003ca name=\"what-is-nodecliac\"\u003e\u003c/a\u003e\n\n## What Is nodecliac?\n\n[`bash-completion`](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html) is awesome. It enhances the user experience by completing paths, file names, commands, flags, etc. Ironically enough, having to use [`Bash`](https://www.gnu.org/software/bash/) to add it to one's program puts some off from using it.\n\nnodecliac's approach is different. Rather than _directly_ using Bash, nodecliac provides a layer of abstraction. It lets one easily _map_ a program's commands with their flags in an **a**uto-**c**ompletion **map** (`.acmap`) file. Merely write the program's `.acmap`, compile to `.acdef`, and let nodecliac handle the rest. That's it.\n\nIf Bash _is_ needed, `.acmap` files are flexible enough to run shell code to generate matches. Better yet, write the necessary completion logic in a familiar language like [`Perl`](https://www.perl.org/), [`Python`](https://www.python.org/), [`Ruby`](https://www.ruby-lang.org/en/), etc., and use Bash as [glue code](https://en.wikipedia.org/wiki/Scripting_language#Glue_languages) to tie it all together.\n\nIn all, this project aims to `1` minimize the effort needed to add bash-completion so more programs support it, `2` provide a uniform bash-completion experience, and `3` to ultimately build a collection of community made completion packages for all to enjoy.\n\n_Why the name nodecliac?_ Originally it was made in mind for [Node.js](https://nodejs.org/en/) programs. However, as development continued it proved useful for non Node.js programs as well.\n\n\u003ca name=\"how-it-works\"\u003e\u003c/a\u003e\n\n## How It Works\n\nThe idea is simple. nodecliac uses two file types: **a**uto-**c**ompletion **map** (`.acmap`) and **a**uto-**c**ompletion **def**inition (`.acdef`). Those familiar with CSS preprocessors will quickly understand. Similar to how `.sass` and `.less` files are compiled to `.css` \u0026mdash; `.acmap` files must be compiled to `.acdef`.\n\nTherefore, an `.acmap` is a user generated file that uses a simple syntax to _map_ a program's commands with their flags. While an `.acdef` is a nodecliac generated _definition_ file. It's this file nodecliac uses to provide completions.\n\nOk, `1` but where do these files go? `2` How does nodecliac use them? Good questions. `1` **Files** will end up in the command's [completion package](./docs/packages/creating.md); a _folder_ containing the necessary files needed to provide completions for a command. `2` **Completion packages** will end up in nodecliac's [registry](#registry) (nodecliac's _collection_ of completion packages).\n\nWith that, nodecliac can provide Bash completions for programs by using their respective completion package stored in the registry.\n\n\u003cdetails\u003e\u003csummary\u003eExpand section\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./docs/diagrams/nodecliac_diagram.png?raw=true\" alt=\"nodecliac CLI diagram\" title=\"nodecliac CLI diagram\" width=\"75%\"\u003e\u003c/p\u003e\n\nWith the program's [completion package created](https://github.com/cgabriel5/nodecliac/blob/docs/docs/packages/creating.md) and stored in the [registry](#registry) the following is possible:\n\n1. **\u003ckbd\u003eTab\u003c/kbd\u003e key pressed**: Bash completion invokes nodecliac's completion function for the program.\n\n2. **CLI input analysis**: Input is parsed for commands, flags, positional arguments, etc.\n\n3. `.acdef` **lookup**: The program's `.acdef` is compared against the CLI input to return possible completions.\n\n_Complete details/events are oversimplified and condensed to get the main points across._\n\n\u003c/details\u003e\n\n\u003ca name=\"cli\"\u003e\u003c/a\u003e\n\n## CLI\n\n\u003cdetails\u003e\n  \u003csummary\u003eCLI commands/flags\u003c/summary\u003e\n\n###### Commands:\n\n- Main:\n  - [`make`](#cli-command-make)\n  - [`format`](#cli-command-format)\n- Helper:\n  - [`init`](#cli-command-init)\n  - [`bin`](#cli-command-bin)\n  - [`cache`](#cli-command-cache)\n  - [`setup`](#cli-command-setup)\n  - [`status`](#cli-command-status)\n  - [`uninstall`](#cli-command-uninstall)\n  - [`print`](#cli-command-print)\n  - [`registry`](#cli-command-registry)\n- Package:\n  - [`add`](#cli-command-add)\n  - [`remove`](#cli-command-remove)\n  - [`link`](#cli-command-link)\n  - [`unlink`](#cli-command-unlink)\n  - [`enable`](#cli-command-enable)\n  - [`disable`](#cli-command-disable)\n  - [`refresh`](#cli-command-refresh)\n\n---\n\n\u003ca name=\"cli-command-make\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003emake\u003c/i\u003e\u003c/b\u003e\n\n\u003e Compile `.acdef`.\n\n- `--source=`: (**required**): Path to `.acmap` file.\n- `--print`: Log output to console.\n\n###### Usage\n\n```sh\n$ nodecliac make --source path/to/program.acmap # Compile .acmap file to .acdef.\n```\n\n\u003cdetails\u003e\u003csummary\u003eTest/debugging flags (internal)\u003c/summary\u003e\n\n- `--trace`: Trace parsers (_for debugging_).\n- `--test`: Log output without file headers (_for tests_).\n\n\u003c/details\u003e\n\n---\n\n\u003ca name=\"cli-command-format\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eformat\u003c/i\u003e\u003c/b\u003e\n\n\u003e Format (prettify) `.acmap` file.\n\n- `--source=`: (**required**): Path to `.acmap` file.\n- `--strip-comments`: Remove comments when formatting.\n- `--indent=\"(s|t):Number\"`: Formatting indentation string:\n  - `s` for spaces or `t` for tabs followed by amount-per-indentation level.\n    - `t:1`: Use 1 tab per indentation level (_default_).\n    - `s:2`: Use 2 spaces per indentation level.\n- `--print`: Log output to console.\n\n###### Usage\n\n```sh\n# Prettify using 2 spaces per indentation level and print output.\n$ nodecliac format --source path/to/program.acmap --print --indent \"s:2\"\n```\n\n\u003cdetails\u003e\u003csummary\u003eTest/debugging flags (internal)\u003c/summary\u003e\n\n- `--trace`: Trace parsers (_for debugging_).\n- `--test`: Log output without file headers (_for tests_).\n\n\u003c/details\u003e\n\n---\n\n\u003ca name=\"cli-command-init\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003einit\u003c/i\u003e\u003c/b\u003e\n\n\u003e Starts nodecliac's completion package generator to easily scaffold a completion package.\n\n- `--force`: Overwrites existing folder of the same name.\n\n###### Usage\n\n```sh\n$ nodecliac init\n```\n\n---\n\n\u003ca name=\"cli-command-bin\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003ebin\u003c/i\u003e\u003c/b\u003e\n\n\u003e Prints nodecliac's bin location.\n\n- _No arguments_\n\n###### Usage\n\n```sh\n$ nodecliac bin # Binary location.\n```\n\n---\n\n\u003ca name=\"cli-command-cache\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003ecache\u003c/i\u003e\u003c/b\u003e\n\n\u003e Interact with nodecliac's [cache system](#caching).\n\n- `--clear`: Clears cache.\n- `--level=\u003clevel\u003e`:\n  - _Without_ argument it prints the current cache level.\n  - _With_ argument it sets cache level to provide level.\n    - Levels: `0`, `1`, `2`\n\n###### Usage\n\n```sh\n$ nodecliac cache --clear # Clear cache.\n$ nodecliac cache --level # Print cache level.\n$ nodecliac cache --level 1 # Set cache level to 1.\n```\n\n---\n\n\u003ca name=\"cli-command-setup\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003esetup\u003c/i\u003e\u003c/b\u003e\n\n\u003e Setup nodecliac.\n\n- `--force`: (**required** _if nodecliac is already setup)_: Overwrites old nodecliac setup and installs anew.\n- `--yes`: Automate install by saying yes to any prompt(s).\n- `--rcfile`: By default `~/.bashrc` is used. If another rcfile should be used provide its path.\n- **Note**: Setup appends `ncliac=~/.nodecliac/src/main/init.sh; [ -f \"$ncliac\" ] \u0026\u0026 . \"$ncliac\";` to rcfile.\n\n###### Usage\n\n```sh\n$ nodecliac setup # Setup nodecliac.\n$ nodecliac setup --force # Force nodecliac setup.\n$ nodecliac setup --force --yes # Force nodecliac setup and assume yes to any prompt(s).\n```\n\n---\n\n\u003ca name=\"cli-command-status\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003estatus\u003c/i\u003e\u003c/b\u003e\n\n\u003e Returns status of nodecliac (enabled or disabled).\n\n- `--enable`: Enables nodecliac.\n- `--disable`: Disables nodecliac.\n\n###### Usage\n\n```sh\n$ nodecliac status # Get nodecliac's status.\n$ nodecliac status --enable # Enable nodecliac.\n$ nodecliac status --disable # Disable nodecliac.\n```\n\n---\n\n\u003ca name=\"cli-command-uninstall\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003euninstall\u003c/i\u003e\u003c/b\u003e\n\n\u003e Uninstalls nodecliac.\n\n- `--rcfile`: Path of rcfile used in setup to remove changes from.\n\n###### Usage\n\n```sh\n$ nodecliac uninstall # Remove nodecliac.\n```\n\n---\n\n\u003ca name=\"cli-command-print\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eprint\u003c/i\u003e\u003c/b\u003e\n\n\u003e Print acmap/def file contents for files in registry.\n\n- `--command=`: Name of command (uses available packages in registry).\n- **Note**: Command is rather pointless and is primarily used to showcase `command-string`s.\n\n###### Usage\n\n```sh\n$ nodecliac print --command=\u003ccommand\u003e # Print .acdef for given command.\n```\n\n---\n\n\u003ca name=\"cli-command-registry\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eregistry\u003c/i\u003e\u003c/b\u003e\n\n\u003e Lists packages in [registry](#registry).\n\n- _No arguments_\n\n###### Usage\n\n```sh\n$ nodecliac registry # Print packages in registry.\n```\n\n---\n\n\u003ca name=\"cli-command-add\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eadd\u003c/i\u003e\u003c/b\u003e\n\n\u003e Adds package to registry.\n\n- `--path`: Path to completion package.\n- `--repo`: Repo to install completion package from.\n  - Github: Repo only (`master`): `\u003cusername\u003e/\u003crepo_name\u003e`\n  - Github: Repo branch (default: `master`): `\u003cusername\u003e/\u003crepo_name\u003e\u003c#branch_name\u003e`\n  - Github: Repo sub-directory: `\u003cusername\u003e/\u003crepo_name\u003e/trunk/\u003csub_directory_path\u003e`\n  - Github: Repo branch + sub-directory: `\u003cusername\u003e/\u003crepo_name\u003e\u003c#branch_name\u003e/trunk/\u003csub_directory_path\u003e`\n  - Or GitHub, GitLab, or BitBucket URL to completion package: `\u003crepo_url\u003e`\n    - URL must start with `git@` or `htttp://` and end with `.git`.\n- `--allow-size`: Disables local repo package `10MB` size check, letting for any size.\n  - Meant as a safeguard to prevent accidentally copying large folders.\n- `--allow-structure`: Disables valid base completion package structure checks.\n- `--allow-overwrite`: Disables overwrite warning of same name package in registry.\n- `--force`: Skip all guards/checks (size, structure, overwrite).\n  - `--size`: Size of local repo is no longer checked when copying to registry.\n  - `--structure`: Basic completion package structure checks are disabled.\n  - `--overwrite`: Same name completion package overwriting is allowed.\n\n###### Usage\n\n```sh\n$ nodecliac add # Copies cwd folder (completion package) to registry.\n$ nodecliac add --path ~/Desktop/subl # Installs completion package at specified path.\n\n$ nodecliac add --repo cgabriel5/nodecliac # Install completion package from a GitHub repo.\n# Install completion package from a specific branch (defaults to master branch).\n$ nodecliac add --repo cgabriel5/nodecliac#master\n# Install completion package from a specific directory in a GitHub repo.\n$ nodecliac add --repo cgabriel5/nodecliac/trunk/resources/packages/yarn\n# Install completion package from a specific directory + branch (defaults to master branch).\n$ nodecliac add --repo cgabriel5/nodecliac#dev/trunk/resources/packages/yarn\n\n# Install completion package via GitHub, GitLab, BitBucket URL.\n$ nodecliac add --repo \u003crepo_url\u003e\n```\n\n---\n\n\u003ca name=\"cli-command-remove\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eremove\u003c/i\u003e\u003c/b\u003e\n\n\u003e Removes package(s) from registry.\n\n- Takes n-amount of package names as arguments.\n- `--all`: Removes all packages in registry.\n\n###### Usage\n\n```sh\n$ nodecliac remove # Removes cwd folder (completion package) from registry.\n$ nodecliac remove --all # Removes all packages from registry.\n```\n\n---\n\n\u003ca name=\"cli-command-link\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003elink\u003c/i\u003e\u003c/b\u003e\n\n\u003e Creates soft [symbolic](https://linuxize.com/post/how-to-create-symbolic-links-in-linux-using-the-ln-command/) link of package in registry.\n\n- `--path`: Path to completion package.\n\n###### Usage\n\n```sh\n$ nodecliac link # Symlinks cwd folder (completion package) to registry.\n$ nodecliac link --path ~/Desktop/subl # Symlinks completion package at specified path.\n```\n\n---\n\n\u003ca name=\"cli-command-unlink\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eunlink\u003c/i\u003e\u003c/b\u003e\n\n\u003e Alias to [`remove`](#cli-command-remove) command.\n\n- See [`remove`](#cli-command-remove) command.\n\n###### Usage\n\n```sh\n$ nodecliac unlink # Removes cwd folder (completion package) from registry.\n$ nodecliac unlink --all # Removes all packages from registry.\n```\n\n---\n\n\u003ca name=\"cli-command-enable\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003eenable\u003c/i\u003e\u003c/b\u003e\n\n\u003e Enables completions for package(s).\n\n- Takes n-amount of package names as arguments.\n- `--all`: Enables all packages in registry.\n\n###### Usage\n\n```sh\n$ nodecliac enable # Enables disabled package(s).\n$ nodecliac enable --all # Enables all disabled packages.\n```\n\n---\n\n\u003ca name=\"cli-command-disable\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003edisable\u003c/i\u003e\u003c/b\u003e\n\n\u003e Disables completions for package(s).\n\n- Takes n-amount of package names as arguments.\n- `--all`: Disables all packages in registry.\n\n###### Usage\n\n```sh\n$ nodecliac disable # Disables enabled package(s).\n$ nodecliac disable --all # Disables all enabled packages.\n```\n\n---\n\n\u003ca name=\"cli-command-refresh\"\u003e\u003c/a\u003e\n\n\u003cb\u003e\u003ci\u003erefresh\u003c/i\u003e\u003c/b\u003e\n\n\u003e Fetches and updates the list of nodecliac completion packages.\n\n- _No arguments_\n\n###### Usage\n\n```sh\n$ nodecliac refresh\n```\n\n---\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eCLI quick usage\u003c/summary\u003e\n\n#### Compile `.acmap` files to `.acdef`.\n\n```sh\n$ nodecliac make --source path/to/program.acmap\n```\n\n#### Prettify `.acmap` file\n\n```sh\n# Prettify using 2 spaces per indentation level and print output.\n$ nodecliac format --source path/to/program.acmap --print --indent \"s:2\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eCLI anatomy breakdown\u003c/summary\u003e\n\n\u003cbr\u003e\n\nnodecliac assumes following CLI program [design](http://programmingpractices.blogspot.com/2008/04/anatomy-of-command-line.html) pathway:\n\n- `program-name` → [`subcommands`](https://github.com/mosop/cli/wiki/Defining-Subcommands) → `short-flags`/`long-flags` → `positional-parameters`\n\n```\n$ program [subcommand ...] [-a | -b] [--a-opt \u003cNumber\u003e | --b-opt \u003cString\u003e] [file ...]\n  ^^^^^^^  ^^^^^^^^^^^^^^   ^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   ^^^^^^^^\n     |            \\             \\                      |                   /\n  CLI program's   Program        Program          Program long     Program's (flag-less)\n  command.        subcommands.   short flags.     flags.           positional parameters.\n```\n\n\u003c/details\u003e\n\n\u003ca name=\"syntax\"\u003e\u003c/a\u003e\n\n## Syntax\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003eacmap\u003c/code\u003e (\u003cb\u003ea\u003c/b\u003euto-\u003cb\u003ec\u003c/b\u003eompletion \u003cb\u003emap\u003c/b\u003e) is a simple \u003ca href=\"https://en.wikipedia.org/wiki/Domain-specific_language\" target=\"_blank\"\u003edomain-specific language\u003c/a\u003e which \u003ci\u003emaps\u003c/i\u003e a program's commands to their flags in \u003ccode\u003e.acmap\u003c/code\u003e files.\u003c/summary\u003e\n\n###### Constructs:\n\n- [Comments](#syntax-comments)\n- [Settings](#syntax-settings)\n- [Variables](#syntax-variables)\n- [Command Chains](#syntax-cc)\n- [Flags](#syntax-flags)\n\n\u003ca name=\"syntax-comments\"\u003e\u003c/a\u003e\n\n#### Comments\n\n- Comments begin with a number-sign (\u003ccode\u003e#\u003c/code\u003e) and continue to the end of the line.\n- Whitespace indentation can precede a comment.\n- Trailing comments are allowed.\n- Multi-line comments are _not_ supported.\n\n```acmap\n# This is a comment.\n    # Whitespace can precede comment.\nprogram.command = --flag # A trailing comment.\n```\n\n\u003ca name=\"syntax-settings\"\u003e\u003c/a\u003e\n\n#### Settings\n\n- Settings begin with an at-sign (`@`) followed by the setting name.\n- Setting values are assigned with `=` followed by the setting value.\n- Any amount of whitespace before and after `=` is allowed.\n- Whitespace indentation can precede a setting declaration.\n- **Note**: Settings can be declared _anywhere_ within your `.acmap` file.\n  - However, it's best if declared at the start of file to quickly spot them.\n\n```acmap\n# Available settings.\n@compopt   = \"default\"\n@filedir   = \"\"\n@disable   = false\n@placehold = true\n```\n\n###### Available Settings:\n\n- `@compopt`: [`comp-option`](https://gerardnico.com/lang/bash/edition/complete#o_comp-option) ([`-o`](https://www.thegeekstuff.com/2013/12/bash-completion-complete/)) value to Bash's builtin [`complete`](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html#Programmable-Completion-Builtins) function.\n  - Values: `false` (no value), `true` (default: `false`)\n- `@filedir`: [Pattern](https://unix.stackexchange.com/a/108646) to provide [bash-completion](https://github.com/scop/bash-completion/)'s `_filedir` function.\n  - Values: A string value (i.e. `\"@(acmap)`, `\"-d\"`) (default: `\"\"`)\n    \u003c!-- - Values: To complete directories only provide `\"-d\"`. To complete specific file types provide a pattern like so: `\"@(pdf)\"`. (default: `\"\"`) --\u003e\n    \u003c!-- - `_filedir` resources: [\\[1\\]](https://unix.stackexchange.com/a/463342), [\\[2\\]](https://unix.stackexchange.com/a/463336), [\\[3\\]](https://github.com/scop/bash-completion/blob/master/completions/java), [\\[4\\]](https://stackoverflow.com/a/23999768), [\\[5\\]](https://unix.stackexchange.com/a/190004), [\\[6\\]](https://unix.stackexchange.com/a/198025) --\u003e\n- `@disable`: Disables bash-completion for command.\n  - Values: `false`, `true` (default: `false`)\n- `@placehold`: Placehold long `.acdef` rows to provide faster file lookups.\n  - Values: `false`, `true` (default: `false`)\n  - **Note**: Used only when compiling `.acdef` files.\n\n\u003ca name=\"syntax-variables\"\u003e\u003c/a\u003e\n\n#### Variables\n\n- Variables begin with a dollar-sign (`$`) followed by the variable name.\n- Variable name _must_ start with an underscore (`_`) or a letter (`a-zA-Z`).\n- Variable values are assigned with `=` followed by the variable value.\n- A variable's value must be enclosed with quotes.\n- Any amount of whitespace before and after `=` is allowed.\n- Whitespace indentation can precede a variable declaration.\n- **Note**: Variables can be declared _anywhere_ within your `.acmap`.\n\n```acmap\n$scriptpath = \"~/path/to/script1.sh\"\n$scriptpath=\"~/path/to/script2.sh\"\n$scriptpath    =   \"~/path/to/script3.sh\"\n\n# Note: `$scriptpath` gets declared 3 times.\n# It's final value is: \"~/path/to/script3.sh\"\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eVariable Interpolation\u003c/summary\u003e\n\n#### Variable Interpolation\n\n- Variables are intended to be used inside quoted strings.\n- Interpolation has the following structure:\n  - Start with `${` and close with `}`.\n  - Any amount of space between opening/closing syntax is allowed.\n  - The string between the closing/starting syntax is the variable name.\n\n```acmap\n$mainscript = \"~/.nodecliac/registry/yarn/init.sh\"\n\nyarn.remove = default $(\"${mainscript} remove\")\nyarn.run = default $(\"${mainscript} run\")\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eVariable Builtins\u003c/summary\u003e\n\n#### Variable Builtins\n\n`acmap`s provide the following builtin variables:\n\n- `$OS`: The user's platform: `linux`, `macosx`\n- `$HOME`: The user's home directory.\n- `$COMMAND`: The command being completed.\n- `$PATH`: The command's nodecliac registry path:\n  - For example: `~/.nodecliac/registry/\u003cCOMMAND\u003e`\n\n\u003c/details\u003e\n\n\u003ca name=\"syntax-cc\"\u003e\u003c/a\u003e\n\n#### Command Chains\n\n- Commands/subcommands should be viewed as chains which read from left to right.\n- They start with the CLI program's name, are followed by any commands/subcommands, and are dot (`.`) delimited.\n- If a (sub)command happens to use a dot then simply escape the dot. Non escaped dots will be used as delimiters.\n- Whitespace indentation can precede a command chain.\n\n**Example**: Say the CLI program `program` has two commands `install` and `uninstall`. It's `.acmap` will be:\n\n```acmap\nprogram.install\nprogram.uninstall\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eCommand default documentation\u003c/summary\u003e\n\n#### Command Chain Default\n\nA command chain's `default` `command-string` (a runable shell command string) can be used to dynamically generate auto-completion items. This `command-string` is run when no completion items (commands/flags) are returned. Think of it as a fallback.\n\n- Start by using the keyword `default` followed by a whitespace character.\n- Follow that with the `command-string`:\n  - A command string is denoted with starting `$(` and closing `)`.\n  - The string between the closing/starting syntax is the `command-string`.\n  - **Example**: `default $(\"./path/to/script.sh arg1 arg2\")`\n\n```acmap\nprogram.command = [\n  default $(\"./path/to/script.sh arg1 arg2\")\n]\n```\n\n\u003cdetails\u003e\u003csummary\u003eCommand-string example\u003c/summary\u003e\n\n\u003cbr\u003e\n\nFor example, say we are implementing an `.acmap` file for the dependency manager [yarn](https://yarnpkg.com/en/) and would like to return the names of installed packages when removing a package (i.e.`$ yarn remove...`). Essentially, we want to extract the `package.json`'s `dependency` and `devDependency` entries and supply them to nodecliac. Using a `command-string` one can run a script/shell command to do just that.\n\n```acmap\nyarn.remove = [\n  # The command will run on '$ yarn remove [TAB]'. The script 'script.sh' should contain the\n  # logic needed to parse package.json to return the installed (dev)dependency package names.\n  default $(\"~/.nodecliac/registry/yarn/script.sh\")\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCommand-string escaping\u003c/summary\u003e\n\n\u003chr\u003e\u003c/hr\u003e\n\n#### Varying Levels Of Escaping.\n\n- **Level 0**: Hypothetical `script.sh` with the following contents. _No extra escaping when running a script._\n\n```sh\nfor f in ~/.nodecliac/registry/yarn/hooks/*.*; do\n  [[ \"${f##*/}\" =~ ^(pre-parse)\\.[a-zA-Z]+$ ]] \u0026\u0026 echo \"$f\"\ndone\n```\n\n- **Code Breakdown**\n\n  - The code will loop over the `~/.nodecliac/registry/yarn/hooks` directory.\n  - File names matching the pattern (`^(pre-parse).[a-zA-Z]+$`) will print to console.\n\n- **Level 1**: If `bash` is one's default shell, copy/paste and run this one-liner in a Terminal:\n\n```bash\nfor f in ~/.nodecliac/registry/yarn/hooks/*.*; do [[ \"${f##*/}\" =~ ^(pre-parse)\\.[a-zA-Z]+$ ]] \u0026\u0026 echo \"$f\"; done\n```\n\n- **Level 2**: Now say we want to run the same line of code via `bash -c`. Run the following in a Terminal:\n\n```bash\nbash -c \"for f in ~/.nodecliac/registry/yarn/hooks/*.*; do [[ \\\"\\${f##*/}\\\" =~ ^(pre-parse)\\\\.[a-zA-Z]+$ ]] \u0026\u0026 echo \\\"\\$f\\\"; done;\"\n```\n\n- **Level 3**: How about using `Perl` to run `bash -c` to execute the command?\n\n```bash\nperl -e 'print `bash -c \"for f in ~/.nodecliac/registry/yarn/hooks/*.*; do [[ \\\\\\\"\\\\\\${f##*/}\\\\\\\" =~ ^(pre-parse)\\\\.[a-zA-Z]+\\$ ]] \u0026\u0026 echo \\\"\\\\\\$f\\\"; done;\"`';\n```\n\nAs shown, the more programs involved the more escaping required due to the string being passed from program to program. Escaping can get cumbersome. If so, running the code from a file will be the easiest alternative.\n\n**Example**: Command-string escaping.\n\nNow let's make a `command-string` to print all `.acdef` file names (without extension) in the nodecliac registry:\n\n```bash\n$ s=\"\";for f in ~/.nodecliac/registry/*/*.acdef; do s=\"$s$f\\n\"; done; echo -e \"$s\" | LC_ALL=C perl -ne \"print \\\"\\$1\\n\\\" while /(?! \\/)([^\\/]*)\\.acdef$/g\"\n```\n\nUsing the following `.acmap` contents the `command-string` would be the following:\n\n- **Note**: Ensure the `|` and `\\` characters are escaped.\n\n```acmap\n# The escaped command-string.\n$cmdstr = 's=\"\";for f in ~/.nodecliac/registry/*/*.acdef; do s=\"$s$f\\\\n\"; done; echo -e \"$s\" \\| LC_ALL=C perl -ne \"print \\\"\\$1\\\\n\\\" while /(?! \\\\/)([^\\\\/]*)\\\\.acdef$/g\"'\n\nnodecliac.print = --command=$('${cmdstr}')\n```\n\nCompiling to `.acdef`, an `.acdef` file with the following contents will be generated:\n\n```acdef\n# DON'T EDIT FILE —— GENERATED: Mon Mar 02 2020 14:15:13 (1583187313)\n\n --\n.print --command=|--command=$('s=\"\";for f in ~/.nodecliac/registry/*/*.acdef; do s=\"$s$f\\\\n\"; done; echo -e \"$s\" \\| LC_ALL=C perl -ne \"print \\\"\\$1\\\\n\\\" while /(?! \\\\/)([^\\\\/]*)\\\\.acdef$/g\"')\n```\n\n\u003chr\u003e\u003c/hr\u003e\n\n\u003c/details\u003e\n\n#### Ignoring Options\n\nLetting the completion engine know an option should be ignored (not displayed) is simple. Merely prefix the option with an exclamation-mark (`!`). This is meant to be used when an option has already been used and therefore doesn't need to be shown again as a possible completion item.\n\n**Note**: For more information about `command-string`s take a look at `acmap Syntax \u003e Flags \u003e Flag Variants \u003e Flags (dynamic values)`. The section contains more details for `command-string`s like special character escaping caveats, dynamic/static arguments, and examples with their breakdowns. Keep in mind that the section uses the term `command-flag` due it being used for flags but `command-flag` and `command-string` are effectively the same thing — _just a runable shell command string_. The naming (`command-{string|flag}`) is based on its application (i.e. for command-chains or flags).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eCommand chain grouping\u003c/summary\u003e\n\n#### Command Chain Grouping\n\nCommand chains can be grouped. It is not necessary but doing may help condense acmaps.\n\n- A command group is denoted with starting `{` and closing `}`.\n- The commands are found in between the closing/starting syntax.\n- Commands are comma delimited.\n\nFor example, take the following:\n\n```acmap\nprogram.deploy-keys.add\nprogram.deploy-keys.list\nprogram.deploy-keys.rm\n```\n\nGrouping can reduce it to:\n\n```acmap\nprogram.deploy-keys.{add,list,rm}\n```\n\n\u003c/details\u003e\n\n\u003ca name=\"syntax-flags\"\u003e\u003c/a\u003e\n\n#### Flags\n\nTo define flags we need to extend the [command chain](#command-chains) syntax.\n\n- Flags are wrapped with `= [` and a closing `]`.\n- The `= [` must be on the same line of the command chain.\n- The closing `]` must be on its own line and man have any amount of indentation.\n\nBuilding on the [command chain](#command-chains) section example, say the `install` command has the flags: `destination/d` and `force/f`. Code can be updated to:\n\n```acmap\nprogram.install = [\n  --destination\n  -d\n  --force\n  -f\n]\nprogram.uninstall\n```\n\nHowever, it can be cleaned up a bit by using the flag `alias` syntax:\n\n```acmap\nprogram.install = [\n  --destination::d\n  --force::f\n]\nprogram.uninstall\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eFlag variants\u003c/summary\u003e\n\n###### Types:\n\n- [Input](#flags-variant-input)\n- [Boolean](#flags-variant-boolean)\n- [Multi](#flags-variant-multi)\n- [Oneliner](#flags-variant-oneliner)\n- [Long Form](#flags-variant-long-form)\n- [Dynamic](#flags-variant-dynamic)\n\n###### Keywords:\n\n- [filedir](#flags-variant-filedir)\n- [context](#flags-variant-context)\n- [exclude](#flags-variant-exclude)\n\n\u003ca name=\"flags-variant-input\"\u003e\u003c/a\u003e\n\n#### Flags (input)\n\n- If flag requires user input append `=` to the flag.\n\n```acmap\nprogram.command = [\n  --flag=\n]\n```\n\n\u003ca name=\"flags-variant-boolean\"\u003e\u003c/a\u003e\n\n#### Flags (boolean)\n\n- If flag is a switch (boolean) append a `?` to the flag to let the completion engine know the flag doesn't require value completion.\n\n```acmap\nprogram.command = [\n  --flag?\n]\n```\n\n\u003ca name=\"flags-variant-multi\"\u003e\u003c/a\u003e\n\n#### Flags (multi-flag)\n\n- Sometimes a flag can be supplied multiple times.\n- Let the completion engine know this by using the multi-flag indicator `*`.\n\n```acmap\nprogram.command = [\n  # Allow user to provide multiple file paths.\n  --file=*\n\n  # Hard-coded values.\n  --colors=*(red green yellow)\n]\n```\n\n\u003ca name=\"flags-variant-oneliner\"\u003e\u003c/a\u003e\n\n#### Flags (one liner)\n\n- This method should be used when the flag value list can be kept to a single line.\n- **Note**: Values must be delimited with spaces.\n- **Note**: When a flag has many values a [long form list](#flags-variant-long-form) should be used for clarity's sake.\n\n```acmap\nprogram.command = [\n  # Supply 1, \"2\", false, 4 as hard-coded values.\n  --flag=(1 \"2\" false 4)\n\n  # If multiple values can be supplied to program use the multi-flag indicator '*'.\n  # This allows --flag to be used multiple times until all values have been used.\n  --flag=*(1 \"2\" false 4)\n]\n```\n\n\u003ca name=\"flags-variant-long-form\"\u003e\u003c/a\u003e\n\n#### Flags (long form)\n\n- Flag long form lists are wrapped with starting `=(` and a closing `)`.\n- The `=(` must be on the same line as the flag.\n- The closing `)` must be on its own line and man have any amount of indentation.\n- A flag value option starts with \u003ccode\u003e- \u003c/code\u003e (a hyphen + a space) followed by the value.\n- Any amount of whitespace indentation can precede the flag value option \u003ccode\u003e- \u003c/code\u003e sequence.\n\n```acmap\nprogram.command = [\n  --flag=(\n    - 1\n    - \"2\"\n    - false\n    - 4\n  )\n\n  # Allow flag to be used multiple times.\n  --flag=*(\n    - 1\n    - \"2\"\n    - false\n    - 4\n  )\n]\nprogram.uninstall\n```\n\n\u003ca name=\"flags-variant-dynamic\"\u003e\u003c/a\u003e\n\n#### Flags (dynamic values)\n\nSometimes static values are not enough so a `command-flag` can be used. A `command-flag` is just a runnable shell command.\n\n`command-flag` syntax:\n\n- Begins with starting `$(`, followed by command, and ends with closing `)`.\n- Output: a newline (`\\n`) delimited list is expected.\n  - Each completion item should be on its own line.\n- Example: `$(\"cat ~/colors.text\")`\n- **Note**: Command must be quoted (double or single).\n\n_static_ or _dynamic_ arguments may be provided.\n\n- Example: `$(\"cat ~/colors.text\", \"!red\", $\"cat ~/names.text\")`:\n  - This provides the _static_ `!red` and _dynamic_ `cat ~/names.text` arguments.\n  - `!red` will be argument `0` and the output of `cat ~/names.text` will be argument `1`.\n- **Note**: _dynamic_ arguments must be dollar-sign prefixed (`$`).\n\n**Escaping**: `$` and `|` are used internally so require escaping when used.\n\n- `--flag=$(\"echo \\$0-\\$1\", $\"echo 'john'\", \"doe\")`:\n  - The `$`s in the command are escaped.\n- `--flag=$(\"nodecliac registry \\| grep -oP \\\"(?\u003c=─ )([-a-z]*)\\\"\")`:\n  - The `|` gets escaped here.\n  - **Note**: Inner quotes are also escaped like one would on the command-line.\n\n**Example**: Showcases _dynamic_ and _static_ values.\n\n```acmap\nprogram.command = [\n  # '*' denotes the flag is a multi-flag.\n  --flag=*\n  --flag=(\n    - index.js\n    - ':task:js'\n    - \"some-thing\"\n    # Dynamic values get combined with hard-coded values.\n    - $(\"cat ~/values.text\")\n  )\n\n  # Same as above.\n  --flag=*(\n    - index.js\n    - ':task:js'\n    - \"some-thing\"\n    - $(\"cat ~/values.text\")\n  )\n]\nprogram.uninstall\n```\n\n\u003ca name=\"flags-variant-filedir\"\u003e\u003c/a\u003e\n\n#### Keyword (filedir)\n\nWhen no completion items are found bash-completion's `_filedir` function is used as a fallback. `_filedir` performs file/directory completion. By default it returns both file and directory names. However, this can be controlled to only return directory names or files of certain types.\n\n\u003c!-- [https://www.nebulousresearch.org/other/bashcompletion] --\u003e\n\n- Start by using the keyword `filedir` followed by a whitespace character.\n- Follow that with a string:\n  - To only return directories use `\"-d\"`.\n  - To filter file type extensions provide a [pattern](https://unix.stackexchange.com/a/108646) like `\"@(acmap)\"`.\n  - **Example**: `filedir \"@(acmap)\"`\n\n```acmap\nprogram.command = [\n  filedir \"@(acmap)\"\n]\n```\n\n**Note**: This `filedir` usage is per command chain. If this is not needed, a global `filedir` value can be provided via the `@filedir` setting like so: `@filedir = \"@(acmap)\"`. Both can be used but precedence is as follows:\n\n- If a command uses `filedir` use that.\n- If not, look for `@filedir` setting.\n- If neither are provided all files/directories are returned (_no filtering_).\n\n\u003ca name=\"flags-variant-context\"\u003e\u003c/a\u003e\n\n#### Keyword (context)\n\nThe `context` keyword provides the ability to disable flags and deal with mutual flag exclusivity.\n\n- Start by using the keyword `context` followed by a whitespace character.\n- Follow that with a string:\n  - **Conditional Example**: `context \"!help: #fge0\"`\n  - **Mutual Exclusivity Example**: `context \"{ json | yaml | csv }`\n\n#### Context String (conditional):\n\nConditional context strings have their own grammar: `\"\u003cflag1, flagN\u003e : \u003ccondition1, conditionN\u003e\"`. If each `\u003ccondition\u003e` results in `true` the `\u003cflags\u003e` are enabled/disabled.\n\n##### Flag grammar\n\n- A flag is represented without the hyphens.\n  - Example: For the flag `--help` it would just be `help`.\n- If the flag needs to be disabled, prepend a `!`.\n  - Example: `help` (If conditions are `true` flag will be _enabled_)\n  - Example: `!help` (If conditions are `true` flag will be _disabled_)\n\n##### Condition grammar\n\n- Check against flag/positional arguments:\n  - Format: `# + (f)lag|(a)rgument + operator + number`\n  - Example (flag check): `#fge0`\n  - Example (argument check): `#age0`\n- Operators:\n  - `eq`: Equal to\n  - `ne`: Not equal to\n  - `gt`: Greater than\n  - `ge`: Greater than or equal to\n  - `lt`: Less than\n  - `le`: Less than or equal to\n- Number:\n  - Must be a positive number.\n- Inversion: Tests can be _inverted_ by prepending a `!`.\n\n###### Example 1\n\nDisable `help` and `version` flags when used flag count is greater or equal to 0.\n\n```acmap\nprogram.command = [\n  --help?\n  --version?\n  context \"!help, !version: #fge0\"\n]\n```\n\n###### Example 2\n\nDisable `help` flag when the used flag count is greater or equal to 0 and version flag is used.\n\n```acmap\nprogram.command = [\n  --help?\n  --version?\n  context \"!help: #fge0, version\"\n]\n```\n\n#### Context String (mutual exclusivity):\n\nMutual exclusivity is represented like so: `\"{ flag1 | flagN }\"`. Once a grouped flag is used the other(s) are disabled.\n\n###### Example 1\n\nFor example, say the `--json`, `--csv`, and `--text` flags are allowed but the `--json` flag is used. The remaining flags `--text` and `--csv` won't be shown as completion items.\n\n```acmap\nprogram.command = [\n  --json=,\n  --csv=,\n  --text=(false true)\n  context \"{ json | csv | text }\"\n]\n```\n\n###### Example 2\n\nIn this example, once `--follow` or `--tail` is used the other flag will be disabled.\n\n```acmap\nprogram.command = [\n  --follow=,\n  --tail=(false true)\n  context \"{follow | tail}\"\n]\n```\n\nThis is equivalent to the previous example.\n\n```acmap\nprogram.command = [\n  --follow=,\n  --tail=(false true)\n  context \"!follow: tail\"\n  context \"!tail: follow\"\n]\n```\n\n#### Combine Context Strings\n\nContext strings can be combined but for maintainability it's better to separate them.\n\n###### Example 1: Separate Context Strings\n\n```acmap\nprogram.command = [\n  --help?\n  --version?\n  context \"!help, !version: #fge0\"\n\n  --json=,\n  --csv=,\n  --text=(false true)\n  context \"{ json | csv | text }\"\n\n  --follow=,\n  --tail=(false true)\n  context \"{follow | tail}\"\n\n  --hours=\n  --minutes=\n  --seconds=\n  --service=\n\n  --job-id=\n  --target=\n  context \"{ job-id | target }\"\n]\n```\n\n###### Example 1: Combined Context Strings\n\nContext strings can be combined by delimiting them with `;`.\n\n```acmap\nprogram.command = [\n  --help?\n  --version?\n\n  --json=,\n  --csv=,\n  --text=(false true)\n\n  --follow=,\n  --tail=(false true)\n\n  --hours=\n  --minutes=\n  --seconds=\n  --service=\n\n  --job-id=\n  --target=\n\n  context \"!help, !version: #fge0; { json | csv | text }; { follow | tail }; { job-id | target }\"\n]\n```\n\n**Note**: Context strings are evaluated on every completion cycle. Therefore, using too many may slow down the 'perceived completion feel' as it takes time to evaluate all provided contexts.\n\n\u003ca name=\"flags-variant-exclude\"\u003e\u003c/a\u003e\n\n#### Keyword (exclude)\n\nThe `exclude` keyword is only allowed in a _wildcard_ command block. It serves to easily give all command strings the same (universal/shared) flags. Although this can be done manually, this can help reduce the acmap and make it easier to maintain.\n\nLet's look at an example. All command strings but `program.cache` share the `--help` flag.\n\n```acmap\nprogram = [\n  --help?\n  --version\n]\n\nprogram.make = [\n  --help?\n  --extensions=*(js html css)\n]\n\nprogram.format = [\n  --help?\n  --extensions=*(js html css)\n  --indentation\n]\n\nprogram.cache = [\n  --clear?\n]\n```\n\nNow let's use a wildcard block and exclude the `program.cache` command string.\n\n```acmap\n* = [\n  exclude \"program.cache\"\n  --help?\n]\n\nprogram = [\n  --version\n]\n\nprogram.make = [\n  --extensions=*(js html css)\n]\n\nprogram.format = [\n  --extensions=*(js html css)\n  --indentation\n]\n\nprogram.cache = [\n  --clear?\n]\n```\n\nIf desired it can even be condensed to.\n\n```acmap\n* = --help?|exclude \"program.cache\"\nprogram = --version\nprogram.make,\nprogram.format = --extensions=*(js html css)\nprogram.format = --indentation\nprogram.cache = --clear?\n```\n\n\u003cbr\u003e\n\n\u003c/details\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003eacdef\u003c/code\u003e (\u003cb\u003ea\u003c/b\u003euto-\u003cb\u003ec\u003c/b\u003eompletion \u003cb\u003edef\u003c/b\u003einition) is a subset of \u003ccode\u003eacmap\u003c/code\u003e syntax, is auto-generated, and is used to perform Bash completion lookups.\u003c/summary\u003e\n\n###### Constructs:\n\n- [Header](#syntax-header)\n- [Command/Flags](#syntax-command-flags)\n- [Command Fallbacks](#syntax-command-fallbacks)\n- [Placeholders](#syntax-placeholders)\n\n#### `.acdef` Anatomy\n\nThe following example `.acdef` will be used to explain how to read `.acdef` files.\n\n```acdef\n# DON'T EDIT FILE —— GENERATED: Mon Mar 02 2020 14:15:13 (1583187313)\n\n --cache-folder|--check-files|--cwd|--disable-pnp\n.access --\n.add --audit|--dev|--exact|--ignore-workspace-root-check|--optional|--peer|--tilde\n.autoclean --force|--init\n.bin --\n.cache --\n.upgrade --caret|--exact|--latest|--pattern|--scope|--tilde\n.why --\n.workspace --\n.workspaces --\n.workspaces.info --\n.workspaces.run --\n\n.upgrade default $(\"~/.nodecliac/registry/command/scripts/init.sh upgrade\")\n.why default $(\"command list --depth=0 \\| perl -wln -e \\\"/(?! ─ )([-\\/_.@(?)a-zA-Z0-9]*)(?=\\@)/ and print $\u0026;\\\"\")\n.workspace default $(\"~/.nodecliac/registry/command/scripts/init.sh workspace\")\n.workspaces.run default $(\"~/.nodecliac/registry/command/scripts/init.sh run\")\n```\n\n\u003ca name=\"syntax-header\"\u003e\u003c/a\u003e\n\n#### Header\n\n- The first line is the file's header.\n- It is the only comment in the document.\n- It contains a warning to not modify the file and the file's creation information.\n\n```acdef\n# DON'T EDIT FILE —— GENERATED: Mon Mar 02 2020 14:15:13 (1583187313)\n\n...\n```\n\n\u003ca name=\"syntax-command-flags\"\u003e\u003c/a\u003e\n\n#### Commands/Flags\n\n- The following section contains the command-chains and their respective flags.\n- Each line represents a _row_ which starts with the command chain and is followed by a single space.\n- Whatever comes after the single space are the command's flags.\n  - Flags are delimited by pipe (`|`) characters.\n- Rows that do not have flags will contain two hyphens (`--`) after the single space character.\n\n```acdef\n...\n\n --cache-folder|--check-files|--cwd|--disable-pnp\n.access --\n.add --audit|--dev|--exact|--ignore-workspace-root-check|--optional|--peer|--tilde\n.autoclean --force|--init\n.bin --\n.cache --\n.upgrade --caret|--exact|--latest|--pattern|--scope|--tilde\n.why --\n.workspace --\n.workspaces --\n.workspaces.info --\n.workspaces.run --\n\n...\n```\n\n**Note**: Command chain lines, lines starting with a single space or a dot (`.`) character, have the program's name removed.\nFor example, the line `.workspaces.run --` can be viewed as `command.workspaces.run --`.\n\n\u003ca name=\"syntax-command-fallbacks\"\u003e\u003c/a\u003e\n\n#### Command Fallbacks\n\n- The bottom section of an `.acdef` file will contain any command chain fallbacks.\n\n```acdef\n...\n\n.upgrade default $(\"~/.nodecliac/registry/command/scripts/init.sh upgrade\")\n.why default $(\"command list --depth=0 \\| perl -wln -e \\\"/(?! ─ )([-\\/_.@(?)a-zA-Z0-9]*)(?=\\@)/ and print $\u0026;\\\"\")\n.workspace default $(\"~/.nodecliac/registry/command/scripts/init.sh workspace\")\n.workspaces.run default $(\"~/.nodecliac/registry/command/scripts/init.sh run\")\n```\n\n\u003ca name=\"syntax-placeholders\"\u003e\u003c/a\u003e\n\n#### Placeholders\n\n- Depending how complex an `.acmap` is sometimes placeholders are needed. They are used internally to speed up reading, what would otherwise be large, `.acdef` files.\n- Placeholder syntax:\n  - Begin with `--p#` and are followed by a fixed number of hexadecimal characters.\n  - **Example**: `--p#d2eef1`\n\nThe following example `.acdef` showcase placeholders.\n\n```acdef\n# DON'T EDIT FILE —— GENERATED: Thu Apr 09 2020 10:4:22 (1586451862)\n\n --help|--version\n.buildIndex --p#07d43e\n.c --p#07d43e\n.cc --p#07d43e\n.check --p#07d43e\n.compile --p#07d43e\n.compileToC --p#07d43e\n.compileToCpp --p#07d43e\n.compileToOC --p#07d43e\n.cpp --p#07d43e\n.ctags --p#07d43e\n.doc --p#07d43e\n.doc2 --p#07d43e\n.dump --p#07d43e\n.e --p#07d43e\n.genDepend --p#07d43e\n.js --p#07d43e\n.jsondoc --p#07d43e\n.objc --p#07d43e\n.rst2html --p#07d43e\n.rst2tex --p#07d43e\n```\n\n\u003c/details\u003e\n\n\u003ca name=\"registry\"\u003e\u003c/a\u003e\n\n## Registry\n\nSimply put, the registry (`~/.nodecliac/registry`) is where completion packages are stored. Completion packages are stored in the form: `~/.nodecliac/registry/\u003ccommand\u003e`.\n\n\u003ca name=\"packages\"\u003e\u003c/a\u003e\n\n## Packages\n\nPackage documentation is divided into their own sections.\n\n\u003c!-- Table formatting hack: [https://stackoverflow.com/a/51701842] --\u003e\n\n| \u003cimg width=220/\u003e \u003cbr /\u003e [Create](/docs/packages/creating.md) \u003cimg width=220/\u003e | \u003cimg width=220/\u003e \u003cbr /\u003e [Add / Link](/docs/packages/adding.md) \u003cimg width=220/\u003e | \u003cimg width=220/\u003e \u003cbr /\u003e [Remove / Unlink](/docs/packages/removing.md) \u003cimg width=220/\u003e | \u003cimg width=220/\u003e \u003cbr /\u003e [Enable / Disable](/docs/packages/state.md) \u003cimg width=220/\u003e |\n| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |\n\n\nPre-made completion packages for several programs of varying complexity are [available](https://github.com/cgabriel5/nodecliac/tree/master/resources/packages) for reference.\n\n\u003ca name=\"hooks\"\u003e\u003c/a\u003e\n\n## Hooks\n\nHooks are _just regular executable shell scripts_ that run at specific points along a completion cycle when a completion is attempted. They let one modify internal aspects of nodecliac's completion logic and behavior.\n\n\u003cdetails\u003e\u003csummary\u003eExpand hook section\u003c/summary\u003e\n\n#### Available Hooks\n\n1. `hooks/pre-parse.sh`: Modifies select initialization variables before running [completion script](/src/scripts/ac).\n1. `hooks/post-parse.sh`: Modifies final completions before terminating the completion cycle and printing suggestions.\n\n#### `hooks/` Directory\n\nIn the command's completion package create a `hooks/` directory. All hook scripts will be stored here.\n\n```sh\n\u003ccommand\u003e/\n  ├── \u003ccommand\u003e.acmap\n  ├── \u003ccommand\u003e.acdef\n  ├── .\u003ccommand\u003e.config.acdef\n  └── hooks/\n```\n\n#### Environment Variables\n\nHook scripts are provided parsing information via environment variables.\n\n\u003cdetails\u003e\u003csummary\u003eBash provided variables but exposed by nodecliac\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- `NODECLIAC_COMP_LINE`: Original (unmodified) CLI input.\n- `NODECLIAC_COMP_POINT`: Caret index when \u003ckbd\u003eTab\u003c/kbd\u003e key was pressed.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003enodecliac provided variables\u003c/summary\u003e\n\n\u003cbr\u003e\n\n- `NODECLIAC_MAIN_COMMAND`: The command auto completion is being performed for.\n- `NODECLIAC_COMMAND_CHAIN`: The parsed command chain.\n- `NODECLIAC_COMP_INDEX`: The index where completion is being attempted.\n- `NODECLIAC_LAST`: The last parsed word item.\n  - **Note**: Last word item could be a _partial_ word item.\n    - This happens when the \u003ckbd\u003eTab\u003c/kbd\u003e key gets pressed _within_ a word item. For example, take the following input:`$ program command`. If the\u003ckbd\u003eTab\u003c/kbd\u003e key was pressed like so: \u003ccode\u003e\\$ program comm\u003ckbd\u003eTab\u003c/kbd\u003eand\u003c/code\u003e, the last word item is `comm`. Thus a _partial_ word with a remainder string of `and`. Resulting in finding completions for `comm`.\n- `NODECLIAC_PREV`: The word item preceding the last word item.\n- `NODECLIAC_INPUT`: CLI input from start to caret (\u003ckbd\u003eTab\u003c/kbd\u003e key press) index.\n- `NODECLIAC_INPUT_ORIGINAL`: Original unmodified CLI input.\n- `NODECLIAC_INPUT_REMAINDER`: CLI input from start to caret index.\n- `NODECLIAC_LAST_CHAR`: Character before caret.\n- `NODECLIAC_NEXT_CHAR`: Character after caret.\n  - **Note**: If char is _not_ `''` (empty) then the last word item (`NODECLIAC_LAST`) is a _partial_ word.\n- `NODECLIAC_COMP_LINE_LENGTH`: Original CLI input's length.\n- `NODECLIAC_INPUT_LINE_LENGTH`: CLI input length from string beginning to caret position.\n- `NODECLIAC_ARG_COUNT`: Amount of arguments parsed in `NODECLIAC_INPUT` string.\n- `NODECLIAC_ARG_N`: Parsed arguments can be individually accessed with this variable.\n  - First argument is `NODECLIAC_ARG_0` and will _always_ be the program's command.\n  - Because input is variable all other arguments can be retrieved with a loop.\n    - Use `NODECLIAC_ARG_COUNT` as max loop iteration.\n  - **Example**: Given the CLI input: `$ yarn remove chalk prettier`\n    - Arguments would be:\n      - `NODECLIAC_ARG_0`: `yarn`\n      - `NODECLIAC_ARG_1`: `remove`\n      - `NODECLIAC_ARG_2`: `chalk`\n      - `NODECLIAC_ARG_3`: `prettier`\n- `NODECLIAC_USED_DEFAULT_POSITIONAL_ARGS`: Collected positional arguments.\n\n\u003c/details\u003e\n\n#### Writing Pre Hook Script\n\nTake yarn's [`pre-parse.sh`](/resources/packages/yarn/hooks/pre-parse.sh) script as an example:\n\n```sh\n#!/bin/bash\n\n# Initialization variables:\n#\n# cline    # CLI input.\n# cpoint   # Index of caret position when [TAB] key was pressed.\n# command  # Program for which completions are for.\n# acdef    # The command's .acdef file contents.\n\noutput=\"$(\"$HOME/.nodecliac/registry/$command/hooks/pre-parse.pl\" \"$cline\")\"\n\n# Remaining lines are package.json's script entries.\nmapfile -ts1 lines \u003c \u003c(echo -e \"$output\")\nprintf -v output '%s\\n' \"${lines[@]}\" \u0026\u0026 acdef+=$'\\n'\"$output\"\n```\n\n- The Bash script is [glue code](https://en.wikipedia.org/wiki/Scripting_language#Glue_languages). It runs the Perl script [`pre-parse.pl`](/resources/packages/yarn/hooks/pre-parse.pl) to retrieve the cwd `package.json` `scripts` and determine whether yarn is being used in a workspace.\n- Using the Perl script's output the Bash script overwrites the `cline` variable and appends the `package.json` `scripts` to the `acdef` variable. Adding them as their [own commands](https://yarnpkg.com/en/docs/cli/run#toc-yarn-run).\n- nodecliac uses the new values to determine completions.\n\n#### Writing Post Hook Script\n\nTake m-cli's [`post-parse.sh`](/resources/packages/m-cli/hooks/post-parse.sh) script as an example:\n\n```sh\n#!/bin/bash\n\nfunction completion_logic() {\n  COMP_CWORD=\"$NODECLIAC_COMP_INDEX\"\n  prev=\"$NODECLIAC_PREV\"\n  cmd=\"$NODECLIAC_ARG_1\"\n  sub=\"$NODECLIAC_ARG_2\"\n  case \"$cmd\" in\n    dir)\n      case \"$prev\" in\n        delete) echo -e \"empty\\ndsfiles\"; return ;;\n        dsfiles) echo -e \"on\\noff\"; return ;;\n      esac\n      ;;\n    disk)\n      case \"$sub\" in\n        # _m_disk\n        verify|repair) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"disk\\nvolume\"; return ;;\n        format)\n          case $COMP_CWORD in\n            3) echo -e \"ExFAT\\nJHFS+\\nMS-DOS\\nvolume\" ;;\n            4) [[ \"$NODECLIAC_ARG_3\" == \"volume\" ]] \u0026\u0026 echo -e \"ExFAT\\nJHFS+\\nMS-DOS\" ;;\n          esac\n          return\n        ;;\n        rename) [[ $COMP_CWORD == 3 ]] \u0026\u0026 \\\n        echo -e \"$(grep -oE '(disk[0-9s]+)' \u003c\u003c\u003c \"$(diskutil list)\")\"; return ;;\n\n        # _m_dock\n        autohide) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"YES\\nNO\"; return ;;\n        magnification) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"YES\\nNO\"; return ;;\n        position) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"BOTTOM\\nLEFT\\nRIGHT\"; return ;;\n      esac\n      ;;\n    dock)\n      case \"$sub\" in\n        autohide) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"YES\\nNO\"; return ;;\n        magnification) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"YES\\nNO\"; return ;;\n        position) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"BOTTOM\\nLEFT\\nRIGHT\"; return ;;\n      esac\n      ;;\n    finder) [[ $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"YES\\nNO\"; return ;;\n    screensaver) [[ $sub == \"askforpassword\" \u0026\u0026 $COMP_CWORD == 3 ]] \u0026\u0026 echo -e \"YES\\nNO\"; return ;;\n  esac\n}\ncompletion_logic\n```\n\n- The post hook script is written in Bash but any language may be used. As shown, the script makes use of the provided `NODECLIAC_*` environment variables to determine what completion items to add. Each completion item must be returned on its own line.\n\n\u003c/details\u003e\n\n\u003ca name=\"caching\"\u003e\u003c/a\u003e\n\n## Caching\n\nTo return quicker results completions are cached.\n\n\u003cdetails\u003e\u003csummary\u003eExpand cache section\u003c/summary\u003e\n\n##### Cache Levels:\n\n- `0`: No caching.\n- `1`: Cache all but `command-string` (dynamic) completions. (`default`)\n- `2`: Cache everything.\n\n```sh\n$ nodecliac cache --clear # Clear cache.\n$ nodecliac cache --level 0 # Turn cache off.\n```\n\n\u003c/details\u003e\n\n\u003ca name=\"testing\"\u003e\u003c/a\u003e\n\n## Testing\n\nnodecliac provides a way to test completions for your program.\n\n\u003cdetails\u003e\u003csummary\u003eExpand testing section\u003c/summary\u003e\n\n#### Creating tests:\n\nCreating tests is done directly from the program's acmap via `@test`. Start with `@test =` followed by the test string `\"\u003ccompletion string\u003e ; \u003ctest1 ; testN\u003e\"`.\n\n- Test entire completion output (including meta data):\n  - _Does the output contain_ `format`_?_: `@test = \"program --; *format*`\n  - _Does the output omit_ `format`_?_: `@test = \"program --; !*format*`\n- Test individual completion items:\n  - _Do any completion items contain_ `format`_?_: `@test = \"program --; *:*format*`\n  - _Does the first completion item contain_ `format`_?_: `@test = \"program --; 1:*format*`\n  - _Does the first completion item start with_ `--for`_?_: `@test = \"program --; 1:--for*`\n  - _Does the first completion item end with_ `format`_?_: `@test = \"program --; 1:*format`\n  - _Does the first completion item equal_ `--format`_?_: `@test = \"program --; 1:--format`\n- Test completion items count:\n  - _Is there at least 1 completion item?_: `@test = \"program --; #cgt0`\n  - _Are there 3 completion items?_: `@test = \"program --; #ceq3`\n    - Format: `# + (c)ount + operator + number`\n    - Operators:\n      - `eq`: Equal to\n      - `ne`: Not equal to\n      - `gt`: Greater than\n      - `ge`: Greater than or equal to\n      - `lt`: Less than\n      - `le`: Less than or equal to\n    - Number:\n      - Must be a positive number.\n- Inversion: Any test can be _inverted_ by preceding the test with a `!`.\n\n###### Example 1\n\nTake the following example acmap. It contains a couple commands and their respective flags.\n\n```acmap\nprogram.make = --source\nprogram.format = --source\n\n@test = \"program make --; *source*\"\n@test = \"program format --for; *format*\"\n```\n\n###### Example 2\n\nMultiple tests can be provided to test a single completion string. Simply delimit them with `;`.\n\n```acmap\nprogram.make = --source\nprogram.format = --source\n\n@test = \"program make --; *source* ; #ceq1\"\n@test = \"program format --for; *format* ; #ceq1\"\n```\n\n#### Running tests:\n\nRunning tests is done by running a built in command: `$ nodecliac test \u003ccommand-name\u003e`. As an example, try running nodecliac's tests. With nodecliac installed, enter `nodecliac test nodecliac` into a Terminal and press \u003ckbd\u003eEnter\u003c/kbd\u003e. Note, for tests to run the program's completion package _must_ exist in the [registry](#registry) to be able to run tests. Running `$ nodecliac registry` will list installed completion packages.\n\n\u003c/details\u003e\n\n\u003ca name=\"debugging\"\u003e\u003c/a\u003e\n\n## Debugging\n\nLike with testing completion strings, nodecliac also provides a way to debug completions. This is useful when creating a completion package. To start debugging simply enable it. When enabled pressing the \u003ckbd\u003eTab\u003c/kbd\u003e key will output debugging information instead of providing bash completions.\n\n\u003cdetails\u003e\u003csummary\u003eExpand debugging section\u003c/summary\u003e\n\n#### Enabling debugging:\n\nRun: `$ nodecliac debug --enable`\n\n#### Disabling debugging:\n\nRun: `$ nodecliac debug --disable`\n\n#### Picking Debug Script\n\nnodecliac's auto-completion script is written in `Nim` and `Perl`. The Nim version supports Linux/macOS while Perl is used as a fallback. When both versions are installed it's possible to use one over the other to debug. This is done with the `--script` flag like so:\n\n- Explicitly use Nim script: `$ nodecliac debug --enable --script nim`\n- Explicitly use Perl script: `$ nodecliac debug --enable --script perl`\n\n#### Debug mode\n\nTo get the debug mode: `$ nodecliac debug`\n\n- `0`: Disabled\n- `1`: Enabled\n- `2`: Enabled + use Perl script\n- `3`: Enabled + use Nim script\n\n\u003c/details\u003e\n\n\u003ca name=\"support\"\u003e\u003c/a\u003e\n\n## Support\n\n\u003cdetails\u003e\u003csummary\u003eOS Support\u003c/summary\u003e\n\n\u003c!-- #### OS Support --\u003e\n\n- Made using Node.js `v8.16.0` on a Linux machine running `Ubuntu 16.04.5 LTS`.\n- Tested and working on:\n  - `macOS Mojave (v10.14.4)`.\n  - `Windows 10 - Untested`.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eShell Support\u003c/summary\u003e\n\n\u003c!-- #### Shell Support --\u003e\n\n- nodecliac only works with Bash.\n- Support for other shells (Zsh, Fish, etc.) may be added with increased usage.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eEditor Support\u003c/summary\u003e\n\n\u003c!-- #### Editor Support (Syntax Highlighting) --\u003e\n\n- `.acmap`/`.acdef` [grammar packages](/resources/editors) available for [Sublime Text 3](https://www.sublimetext.com/3), [VSCode](https://code.visualstudio.com/), and [Atom](https://atom.io/) text editors.\n- **Note**: `README.md` files are found next to each package explaining how to install it.\n- Packages are stored under [`resources/editors`](/resources/editors).\n\n\u003c/details\u003e\n\n\u003ca name=\"contributing\"\u003e\u003c/a\u003e\n\n## Contributing\n\nContributions are welcome! Found a bug, feel like documentation is lacking/confusing and needs an update, have performance/feature suggestions or simply found a typo? Let me know! :)\n\nSee how to contribute [here](/CONTRIBUTING.md).\n\n\u003ca name=\"license\"\u003e\u003c/a\u003e\n\n## License\n\nThis project uses the [MIT License](/LICENSE.txt).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgabriel5%2Fnodecliac","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcgabriel5%2Fnodecliac","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgabriel5%2Fnodecliac/lists"}