Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
LC_ALL: en_US.UTF-8 # consistent sort order

strategy:
matrix: { ruby: ['2.4', '2.5', '2.6', '2.7', '3.0'] }
matrix: { ruby: ['2.7', '3.0'] }

steps:
- name: Checkout code
Expand Down
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Create beautiful bash scripts from simple YAML configuration
- [Flag options](#flag-options)
- [Environment Variable options](#environment-variable-options)
- [Extensible Scripts](#extensible-scripts)
- [Bash Completions](#bash-completions)
- [Real World Examples](#real-world-examples)
- [Contributing / Support](#contributing--support)

Expand Down Expand Up @@ -75,13 +76,15 @@ Bahsly is responsible for:
- Optional or required **option flags** (with or without flag arguments).
- **Commands** (and subcommands).
- Standard flags (like **--help** and **--version**).
- Preventing your script from running unless the command line is valid.
- Providing you with a place to input your code for each of the functions
your tool performs, and merging it back to the final script.
- Providing you with additional (optional) framework-style, standard
library functions:
- **Color output**.
- **Config file management** (INI format).
- **YAML parsing**.
- **Bash completions**.
- and more.


Expand Down Expand Up @@ -198,6 +201,7 @@ command and subcommands (under the `commands` definition).
`commands` | Specify the array of [commands](#command-options). Each command will have its own args and flags. Note: if `commands` is provided, you cannot specify flags or args at the same level.
`args` | Specify the array of [positional arguments](#argument-options) this script needs.
`flags` | Specify the array of option [flags](#flag-options) this script needs.
`completions` | Specify an array of additional completion suggestions when used in conjunction with `bashly add comp`. See [Bash Completions](#bash-completions).
`catch_all` | Specify that this command should allow for additional arbitrary arguments or flags. It can be set in one of three ways:<br>- Set to `true` to just enable it.<br>- Set to a string, to use this string in the usage help text.<br>- Set to a hash containing `label` and `help` keys, to show a detailed help for it when running with `--help`.
`dependencies` | Specify an array of any required external dependencies (commands). The script execution will be halted with a friendly error unless all dependency commands exist.
`group` | In case you have many commands, use this option to specify a caption to display before this command. This option is purely for display purposes, and needs to be specified only for the first command in each group.
Expand Down Expand Up @@ -326,6 +330,71 @@ The generated script will execute `git status`.
See the [extensible-delegate example](examples/extensible-delegate).


## Bash Completions

Bashly comes with built-in bash completions generator, provided by the
[completely][completely] gem.

By running any of the `bashly add comp` commands, you can add this
functionality to your script in one of three ways:

- `bashly add comp function` - 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)"`.
- `bashly add comp script` - creates a standalone completion script that can be
sourced or copies to the system's bash completions directory.
- `bashly add comp yaml` - creates the "raw data" YAML file. This is intended
mainly for development purposes.

The bash completions generation is completely automatic, and you will have to
rerun the `bashly add comp *` command whenever you change your `bashly.yml`
script.

In addition to suggesting subcommands and flags, you can instruct bashly to
also suggest files, directories, users and more. To do this, add another option
in your `bashly.yml` on the command you wish to alter:

```yaml
# bashly.yml
commands:
- name: upload
help: Upload a file
completions: [directory, user]

```

Valid completion additions are:

| Keyword | Meaning
|-------------|---------------------
| `alias` | Alias names
| `arrayvar` | Array variable names
| `binding` | Readline key binding names
| `builtin` | Names of shell builtin commands
| `command` | Command names
| `directory` | Directory names
| `disabled` | Names of disabled shell builtins
| `enabled` | Names of enabled shell builtins
| `export` | Names of exported shell variables
| `file` | File names
| `function` | Names of shell functions
| `group` | Group names
| `helptopic` | Help topics as accepted by the help builtin
| `hostname` | Hostnames, as taken from the file specified by the HOSTFILE shell variable
| `job` | Job names
| `keyword` | Shell reserved words
| `running` | Names of running jobs
| `service` | Service names
| `signal` | Signal names
| `stopped` | Names of stopped jobs
| `user` | User names
| `variable` | Names of all shell variables

Note that these are taken from the [Programmable Completion Builtin][compgen],
and will simply be added using the `compgen -A action` command.


## Real World Examples

- [Rush][rush] - a Personal Package Manager
Expand All @@ -344,3 +413,5 @@ to contribute, feel free to [open an issue][issues].
[rush]: https://github.com/DannyBen/rush-cli
[alf]: https://github.com/DannyBen/alf
[git-changelog]: https://github.com/DannyBen/git-changelog
[completely]: https://github.com/DannyBen/completely
[compgen]: https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
3 changes: 2 additions & 1 deletion bashly.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ Gem::Specification.new do |s|
s.executables = ['bashly']
s.homepage = 'https://github.com/dannyben/bashly'
s.license = 'MIT'
s.required_ruby_version = ">= 2.3.0"
s.required_ruby_version = ">= 2.7.0"

s.add_runtime_dependency 'colsole', '~> 0.6'
s.add_runtime_dependency 'completely', '~> 0.1', '>= 0.1.2'
s.add_runtime_dependency 'mister_bin', '~> 0.7'
s.add_runtime_dependency 'requires', '~> 0.1'
end
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ Each of these examples demonstrates one aspect or feature of bashly.
- [config-ini](config-ini#readme) - using the config (INI) functions
- [colors](colors#readme) - using the color print feature
- [yaml](yaml#readme) - using the YAML reading functions
- [completions](completions#readme) - adding bash completion functionality
164 changes: 164 additions & 0 deletions examples/completions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Bash Completions Example

Demonstrates how to build a script that supports bash completions.

This example was generated with:

$ bashly init
$ bashly add comp function
$ bashly generate

-----

## `bashly.yml`

```yaml
name: cli
help: Sample application with bash completions
version: 0.1.0

commands:
- name: completions
help: |-
Generate bash completions
Usage: eval "\$(cli completions)"

- name: download
short: d
help: Download a file
completions: [file]

args:
- name: source
required: true
help: URL to download from
- name: target
help: "Target filename (default: same as source)"

flags:
- long: --force
short: -f
help: Overwrite existing files

examples:
- cli download example.com
- cli download example.com ./output -f

environment_variables:
- name: default_target_location
help: Set the default location to download to

- name: upload
short: u
help: Upload a file
completions: [directory, user]
args:
- name: source
required: true
help: File to upload

flags:
- long: --user
short: -u
arg: user
help: Username to use for logging in
required: true
- long: --password
short: -p
arg: password
help: Password to use for logging in
```

## Generated script output

### `$ ./cli`

```shell
cli - Sample application with bash completions

Usage:
cli [command]
cli [command] --help | -h
cli --version | -v

Commands:
completions Generate bash completions
download Download a file
upload Upload a file



```

### `$ ./cli -h`

```shell
cli - Sample application with bash completions

Usage:
cli [command]
cli [command] --help | -h
cli --version | -v

Commands:
completions Generate bash completions
download Download a file
upload Upload a file

Options:
--help, -h
Show this help

--version, -v
Show version number



```

### `$ ./cli completions -h`

```shell
cli completions

Generate bash completions
Usage: eval "$(cli completions)"

Usage:
cli completions
cli completions --help | -h

Options:
--help, -h
Show this help



```

### `$ ./cli completions`

```shell
#!/usr/bin/env bash

# This bash completions script was generated by
# completely (https://github.com/dannyben/completely)
# Modifying it manually is not recommended
_cli_completions() {
local cur=${COMP_WORDS[COMP_CWORD]}

case "$COMP_LINE" in
'cli completions'*) COMPREPLY=($(compgen -W "--help -h" -- "$cur")) ;;
'cli download'*) COMPREPLY=($(compgen -A file -W "--force --help -f -h" -- "$cur")) ;;
'cli upload'*) COMPREPLY=($(compgen -A directory -A user -W "--help --password --user -h -p -u" -- "$cur")) ;;
'cli'*) COMPREPLY=($(compgen -W "--help --version -h -v completions download upload" -- "$cur")) ;;
esac
}

complete -F _cli_completions cli


```



Loading