Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command.variables as a convenience utility for defining global command variables #563

Merged
merged 3 commits into from
Oct 22, 2024
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
1 change: 1 addition & 0 deletions examples/variables/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cli
113 changes: 113 additions & 0 deletions examples/variables/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Variables Example

Demonstrates how to define variables from the bashly.yml configuration.

This example was generated with:

```bash
$ bashly init
# ... now edit src/bashly.yml to match the example ...
# ... now edit src/download_command.sh to match the example ...
# ... now edit src/compress_command.sh to match the example ...
$ bashly generate
```

<!-- include: src/download_command.sh src/compress_command.sh -->

-----

## `bashly.yml`

````yaml
name: cli
help: Sample application demonstrating the use of variables
version: 0.1.0

# The `build_number` variable will be available globally
variables:
- name: build_number
value: 1337

commands:
- name: download
alias: d
help: Download a profile

args:
- name: profile
required: true
help: Profile to download information from

# These variables will be declared when the `download` command is executed.
# Note the use of an array value.
variables:
- name: output_folder
value: output
- name: download_sources
value:
- youtube
- instagram

- name: compress
alias: c
help: Compress data

# These variables will be declared when the `compress` command is executed.
# Note the use of an associative array value.
variables:
- name: zip_options
value:
pattern: "*.json"
compression_level: fast
````

## `src/download_command.sh`

````bash
echo "build_number: $build_number"
echo "output_folder: $output_folder"
echo "download_sources:"
for value in "${download_sources[@]}"; do
echo "- $value"
done
````

## `src/compress_command.sh`

````bash
echo "build_number: $build_number"
echo "zip_options:"
for key in "${!zip_options[@]}"; do
echo " $key: ${zip_options[$key]}"
done

````


## Output

### `$ ./cli download something`

````shell
build_number: 1337
output_folder: output
download_sources:
- youtube
- instagram


````

### `$ ./cli compress`

````shell
build_number: 1337
zip_options:
compression_level: fast
pattern: *.json


````



40 changes: 40 additions & 0 deletions examples/variables/src/bashly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: cli
help: Sample application demonstrating the use of variables
version: 0.1.0

# The `build_number` variable will be available globally
variables:
- name: build_number
value: 1337

commands:
- name: download
alias: d
help: Download a profile

args:
- name: profile
required: true
help: Profile to download information from

# These variables will be declared when the `download` command is executed.
# Note the use of an array value.
variables:
- name: output_folder
value: output
- name: download_sources
value:
- youtube
- instagram

- name: compress
alias: c
help: Compress data

# These variables will be declared when the `compress` command is executed.
# Note the use of an associative array value.
variables:
- name: zip_options
value:
pattern: "*.json"
compression_level: fast
5 changes: 5 additions & 0 deletions examples/variables/src/compress_command.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
echo "build_number: $build_number"
echo "zip_options:"
for key in "${!zip_options[@]}"; do
echo " $key: ${zip_options[$key]}"
done
6 changes: 6 additions & 0 deletions examples/variables/src/download_command.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
echo "build_number: $build_number"
echo "output_folder: $output_folder"
echo "download_sources:"
for value in "${download_sources[@]}"; do
echo "- $value"
done
10 changes: 10 additions & 0 deletions examples/variables/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

set -x

bashly generate

### Try Me ###

./cli download something
./cli compress
10 changes: 8 additions & 2 deletions lib/bashly/config_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def assert_version(key, value)
def assert_catch_all(key, value)
return unless value

assert [TrueClass, String, Hash].include?(value.class),
assert [TrueClass, FalseClass, String, Hash].include?(value.class),
"#{key} must be a boolean, a string or a hash"

assert_catch_all_hash key, value if value.is_a? Hash
Expand Down Expand Up @@ -77,7 +77,7 @@ def assert_dependency(key, value)
def assert_extensible(key, value)
return unless value

assert [TrueClass, String].include?(value.class),
assert [TrueClass, FalseClass, String].include?(value.class),
"#{key} must be a boolean or a string"
end

Expand Down Expand Up @@ -173,6 +173,11 @@ def assert_env_var(key, value)
refute value['required'] && value['default'], "#{key} cannot have both nub`required` and nub`default`"
end

def assert_var(key, value)
assert_hash key, value, keys: %i[name value]
assert_string "#{key}.name", value['name']
end

def assert_command(key, value)
assert_hash key, value, keys: Script::Command.option_keys

Expand Down Expand Up @@ -207,6 +212,7 @@ def assert_command(key, value)
assert_array "#{key}.completions", value['completions'], of: :string
assert_array "#{key}.filters", value['filters'], of: :string
assert_array "#{key}.environment_variables", value['environment_variables'], of: :env_var
assert_array "#{key}.variables", value['variables'], of: :var

assert_uniq "#{key}.commands", value['commands'], %w[name alias]
assert_uniq "#{key}.flags", value['flags'], 'long'
Expand Down
22 changes: 22 additions & 0 deletions lib/bashly/docs/command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,28 @@ command.private:
help: Send bash completions
private: true

command.variables:
help: Define a list of global bash variables.
url: https://bashly.dannyb.co/configuration/command/#variables
example: |-
variables:
# Simple value
- name: output_folder
value: output

# Array
- name: download_sources
value:
- youtube
- instagram

# Associative array
- name: zip_options
value:
pattern: "*.json"
compression_level: fast


command.version:
help: Specify the version to show when running with `--version`.
url: https://bashly.dannyb.co/configuration/command/#version
Expand Down
2 changes: 1 addition & 1 deletion lib/bashly/script/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def option_keys
default dependencies environment_variables examples
extensible expose filename filters flags
footer function group help name
private version
private variables version
]
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/bashly/views/command/function.gtx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
= view_marker

> {{ function_name }}_command() {
= render(:variables).indent(2) if variables&.any?
= load_user_file(filename).indent 2
> }
>
1 change: 1 addition & 0 deletions lib/bashly/views/command/run.gtx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
if has_unique_args_or_flags?
> declare -A unique_lookup=()
end
= render(:variables).indent(2) if variables&.any?
> normalize_input "$@"
> parse_requirements "${input[@]}"
if user_file_exist?('before')
Expand Down
30 changes: 30 additions & 0 deletions lib/bashly/views/command/variables.gtx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
= view_marker

variables.each do |var|
case var['value']
when Array
if var['value'].empty?
> declare -a {{ var['name'] }}=()
else
> declare -a {{ var['name'] }}=(
var['value'].each do |v|
> "{{ v }}"
end
> )
end
when Hash
if var['value'].empty?
> declare -A {{ var['name'] }}=()
else
> declare -A {{ var['name'] }}=(
var['value'].each do |k, v|
> ["{{ k }}"]="{{ v }}"
end
> )
end
when String, NilClass
> {{ var['name'] }}="{{ var['value'] }}"
else
> {{ var['name'] }}={{ var['value'] }}
end
end
23 changes: 23 additions & 0 deletions spec/approvals/cli/doc/full
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,29 @@ command.private

See https://bashly.dannyb.co/configuration/command/#private

command.variables

Define a list of global bash variables.

variables:
# Simple value
- name: output_folder
value: output

# Array
- name: download_sources
value:
- youtube
- instagram

# Associative array
- name: zip_options
value:
pattern: "*.json"
compression_level: fast

See https://bashly.dannyb.co/configuration/command/#variables

command.version

Specify the version to show when running with --version.
Expand Down
1 change: 1 addition & 0 deletions spec/approvals/cli/doc/index
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ command.group
command.help
command.name
command.private
command.variables
command.version
environment_variable
environment_variable.default
Expand Down
17 changes: 17 additions & 0 deletions spec/approvals/examples/variables
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
+ bashly generate
creating user files in src
skipped src/download_command.sh (exists)
skipped src/compress_command.sh (exists)
created ./cli
run ./cli --help to test your bash script
+ ./cli download something
build_number: 1337
output_folder: output
download_sources:
- youtube
- instagram
+ ./cli compress
build_number: 1337
zip_options:
compression_level: fast
pattern: *.json
Loading