Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.9)
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
base64 (0.3.0)
clamp (1.5.2)
colsole (1.0.0)
colsole (1.0.1)
docopt_ng (0.7.1)
domain_name (0.6.20240107)
ffi (1.17.3-x86_64-linux-gnu)
ffi-compiler (1.3.2)
ffi (1.17.4-x86_64-linux-gnu)
ffi-compiler (1.4.2)
ffi (>= 1.15.5)
rake
filewatcher (3.0.1)
Expand All @@ -25,7 +25,7 @@ GEM
http-cookie (~> 1.0)
http-form_data (~> 2.2)
llhttp-ffi (~> 0.5.0)
http-cookie (1.1.0)
http-cookie (1.1.6)
domain_name (~> 0.5)
http-form_data (2.3.0)
httpme (0.2.4)
Expand All @@ -35,7 +35,7 @@ GEM
rack-contrib (~> 2.3)
rackup (~> 2.2)
sinatra (~> 4.2)
io-console (0.8.2)
io-console (0.9.2)
llhttp-ffi (0.5.1)
ffi-compiler (~> 1.0)
rake (~> 13.0)
Expand All @@ -45,31 +45,29 @@ GEM
docopt_ng (~> 0.7.1)
reline (~> 0.6)
module_methods (1.0.0)
mustermann (3.0.4)
ruby2_keywords (~> 0.0.1)
mustermann (3.1.1)
nio4r (2.7.5)
nokogiri (1.19.2-x86_64-linux-gnu)
nokogiri (1.19.4-x86_64-linux-gnu)
racc (~> 1.4)
public_suffix (7.0.5)
puma (7.2.0)
puma (7.2.1)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.2.5)
rack (3.2.7)
rack-contrib (2.5.0)
rack (< 4)
rack-protection (4.2.1)
base64 (>= 0.1.0)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-session (2.1.1)
rack-session (2.1.2)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rackup (2.3.1)
rack (>= 3)
rake (13.3.1)
reline (0.6.3)
rake (13.4.2)
reline (0.7.0)
io-console (~> 0.5)
ruby2_keywords (0.0.5)
sinatra (4.2.1)
logger (>= 1.6.0)
mustermann (~> 3.0)
Expand All @@ -83,7 +81,7 @@ GEM
nokogiri (~> 1.10)
webcache (~> 0.8)
thor (1.5.0)
tilt (2.7.0)
tilt (2.9.0)
webcache (0.9.0)
http (~> 5.0)

Expand Down
2 changes: 1 addition & 1 deletion retype.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ editor:
enabled: false

branding:
label: v1.4.0
label: v2.0.0
logo: assets/logo.svg
logoDark: assets/logo-dark.svg
# logoWidth: 143
Expand Down
234 changes: 148 additions & 86 deletions src/advanced/bash-completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,125 +3,187 @@ icon: dot
order: 60
---

# Bash Completion
# Runtime Completions

Bashly comes with a built-in bash completions generator, provided by the
[completely][completely] gem.
Bashly can generate native runtime completions for your application. The
generated completion script suggests commands, aliases, flags, positional
arguments with `allowed` values, and flag arguments with `allowed` values.

By running `bashly add completions`, you can add this functionality to your
script in one of three ways:
Runtime completions are disabled by default. Bashly provides adapters for Bash
and Zsh.

## Enable runtime completions

==- `bashly add completions`
Creates a function in your `./src/lib` directory that echoes a completion
script. You can then call this function from any command (for example `yourcli
completions`) and your users will be able to install the completions by running
`eval "$(yourcli completions)"`.
Enable the runtime engine and all available shell adapters in your Bashly
settings file:

==- `bashly add completions_script`
Creates a standalone completions script that can be sourced or copied to the
system's bash completions directory.
```yaml settings.yml
completions: full
```

==- `bashly add completions_yaml`
Creates the raw data YAML file. This is intended mainly for development
purposes.
Add a command that users can call to generate the completion script:

===
```yaml bashly.yml
commands:
- name: completions
help: Generate a shell completion script
args:
- name: shell
help: Shell to generate completions for
allowed: [bash, zsh]
default: bash
```

The bash completions generation is **completely automatic**, but you will have
to regenerate the completion function whenever you make changes to your
`bashly.yml` file.
In the command handler, call `send_completions` with the requested shell:

!!!success Tip
By running `bashly generate --upgrade`, your completions function
(generated with `bashly add completions`) will be regenerated.
!!!
```bash src/completions_command.sh
send_completions "${args[shell]}"
```

## Custom argument completions
After regenerating your application, users can load its completion script in
their shell:

In addition to the automatic suggestion of subcommands and flags, you can
instruct bashly to also suggest files, directories, users, git branches and
more.
```bash
# Bash
source <(cli completions bash)

For positional arguments, add `completions` to the argument that should receive
these suggestions:
# Zsh
source <(cli completions zsh)
```

```yaml bashly.yml
commands:
- name: upload
help: Upload a file
args:
- name: source
help: File to upload
required: true
completions:
- <file>
- <directory>
- $(git branch 2> /dev/null)
Replace `cli` with the name or path of your generated application.

[!button variant="primary" icon="code-review" text="Runtime Completions Example"](https://github.com/bashly-framework/bashly/tree/master/examples/completions#readme)

## Configure completion candidates

In addition to the candidates Bashly generates automatically, you can
configure custom completions for positional arguments and flags that have an
`arg`.

The `completions` mapping accepts three optional keys:

- `static`: literal completion candidates.
- `dynamic`: Bash commands that print completion candidates.
- `options`: completion behavior and filesystem candidate sources.

### Static candidates

Use `static` for literal suggestions:

```yaml bashly.yml
args:
- name: environment
help: Environment to deploy to
completions:
static:
- staging
- production
```

The `completions` option is still supported on commands as a fallback for
positional arguments, but it is discouraged for new configurations. Prefer
placing completions directly on the relevant `args` entry.
!!! Note
Use [`allowed`](/configuration/argument/#allowed) when values should be
validated. Use `completions.static` when they should only be suggested.
Values configured with `allowed` are suggested automatically.
!!!

## Custom flag completions
### Dynamic candidates

For flag values, add `completions` to flags that have an `arg`. Similarly to
the `allowed` option for arguments and flags, the allowed list is added to the
suggestions automatically (without the need to use `completions`).
Use `dynamic` to run external commands or Bash functions included in your
generated application:

```yaml bashly.yml
commands:
- name: login
help: Login to SETI
flags:
- long: --user
arg: username
completions:
- <user>
- long: --protocol
arg: protocol
allowed:
- ssh
- telnet
args:
- name: branch
help: Branch to deploy
completions:
dynamic:
- git branch --format='%(refname:short)'
- completion_branches
```

- Anything between `<...>` will be added using the `compgen -A action` flag.
- Anything else will be appended to the `compgen -W` flag.
Each command or function must print one candidate per line to standard output.
A producer that fails contributes no candidates. Its failure and error output
do not fail or pollute the overall completion request.

!!! Note
In case you are using the
[Argument `allowed` option](../configuration/argument.md#allowed) or
the [Flag argument `allowed` option](../configuration/flag.md#allowed),
these will be automatically added to the completions list as well.
Dynamic entries run whenever the user requests a completion. Keep them fast
and side-effect free.
!!!

## Completions in ZSH
### Completion options

If you are using Oh-My-Zsh, bash completions should already be enabled,
otherwise, you should enable completion by adding this to your `~/.zshrc`
(if it is not already there):
Use `options` to add filesystem candidates or change how an inserted
completion behaves:

```bash
# Load completion functions
autoload -Uz +X compinit && compinit
autoload -Uz +X bashcompinit && bashcompinit
```yaml bashly.yml
flags:
- long: --config
arg: file
help: Configuration file
completions:
options: [files]

- long: --directory
arg: path
help: Working directory
completions:
options: [directories]
```

The supported options are:

- `files`: add file and directory candidates.
- `directories`: add directory candidates only.
- `no-space`: do not append a space after inserting a completion.

Filesystem completion is not implicit. Without `files` or `directories`, the
shell uses only candidates returned by Bashly.

Normal spacing is the default. Use `no-space` only when the user should
continue typing immediately after the inserted candidate. Candidate
de-duplication is always enabled and is not configurable.

## Combine completion sources

You can combine `static`, `dynamic`, and `options` on the same argument or
flag:

```yaml bashly.yml
args:
- name: environment
help: Environment to deploy to
completions:
static: [staging, production]
dynamic: [completion_environments]
options: [no-space]
```

After adding this (and restarting your session), you should be able to source
any bash completion script in zsh.
## Test completion candidates

## Additional documentation
The generated application includes an internal `__complete` command. You can
use it to inspect the raw candidates returned for a command line without
loading the completion script:

```bash
cli __complete deploy main st
```

For more information about these custom completions, see the
[documentation for the completely gem][completely-docs].
Each argument after `__complete` represents one word in the command line. Pass
an empty final argument to represent the blank word after a trailing space:

## Example
```bash
cli __complete deploy --config ""
```

[!button variant="primary" icon="code-review" text="Bash Completions Example"](https://github.com/bashly-framework/bashly/tree/master/examples/completions#readme)
Candidate lines are written to standard output, followed by an internal
`:options=` line used by the shell adapters. This makes `__complete`
useful when testing custom `static`, `dynamic`, or filesystem completions.

!!! Note
`__complete` is an internal completion endpoint intended for testing and shell
integration. Users should normally load completions with
`source <(cli completions bash)` or `source <(cli completions zsh)`.
!!!

[completely]: https://github.com/DannyBen/completely
[completely-docs]: https://github.com/DannyBen/completely#suggesting-files-directories-and-other-bash-built-ins
[compgen]: https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
[!button variant="primary" icon="code-review" text="Advanced Completions Example"](https://github.com/bashly-framework/bashly/tree/master/examples/completions-advanced#readme)
20 changes: 17 additions & 3 deletions src/configuration/argument.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,24 @@ Allowed values are also added to generated bash completions automatically.

### completions

[!badge Array of Strings]
[!badge Hash]

Configure additional runtime completions for this argument:

```yaml
completions:
static: [main, develop]
dynamic:
- git branch --format='%(refname:short)'
options: [no-space]
```

- `static` contains literal candidates.
- `dynamic` contains Bash commands or functions that print one candidate per
line.
- `options` accepts `files`, `directories`, and `no-space`.

Specify an array of additional completion suggestions when used in conjunction
with `bashly add completions`.
All three keys are optional and can be combined.

[!ref](/advanced/bash-completion.md)

Expand Down
Loading