diff --git a/examples/README.md b/examples/README.md index 8998c7822..f43edfe48 100644 --- a/examples/README.md +++ b/examples/README.md @@ -43,6 +43,7 @@ Each of these examples demonstrates one aspect or feature of bashly. - [key-value-pairs](key-value-pairs#readme) - parsing key=value arguments and flags - [command-examples-on-error](command-examples-on-error#readme) - showing examples on error - [internal-run](internal-run#readme) - calling other commands internally +- [command-line-manipulation](command-line-manipulation#readme) - read or modify the raw command line ## Customization diff --git a/examples/command-line-manipulation/.gitignore b/examples/command-line-manipulation/.gitignore new file mode 100644 index 000000000..8a58e1ae8 --- /dev/null +++ b/examples/command-line-manipulation/.gitignore @@ -0,0 +1 @@ +download \ No newline at end of file diff --git a/examples/command-line-manipulation/README.md b/examples/command-line-manipulation/README.md new file mode 100644 index 000000000..43b9b22b1 --- /dev/null +++ b/examples/command-line-manipulation/README.md @@ -0,0 +1,102 @@ +# Command Line Manipulation + +Demonstrates how to read or override the raw input command line. + +Note that this is *not needed nor recommended* under most circumstances - it +is provided as an edge case utility. + +This example was generated with: + +```bash +$ bashly init --minimal +$ bashly add hooks +# ... now edit src/bashly.yml to match the example ... +# ... now edit src/initialize.sh to match the example ... +# ... now edit src/before.sh to match the example ... +$ bashly generate +``` + + + +----- + +## `bashly.yml` + +````yaml +name: download +help: Sample minimal application without commands +version: 0.1.0 + +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 +```` + +## `src/initialize.sh` + +````bash +echo "==[ Initialize Called ]==" + +# Override the command line completely if the first argument is 'debug' +if [[ "${command_line_args[0]:-""}" = "debug" ]]; then + command_line_args=("modified" "args" "--force") +fi + +```` + +## `src/before.sh` + +````bash +echo "==[ Before Hook Called ]==" + +echo "Read-only copy of the raw input array: ${input[*]}" +inspect_args + +```` + + +## Output + +### `$ ./download ` + +````shell +==[ Initialize Called ]== +missing required argument: SOURCE +usage: download SOURCE [TARGET] [OPTIONS] + + +```` + +### `$ ./download debug` + +````shell +==[ Initialize Called ]== +==[ Before Hook Called ]== +Read-only copy of the raw input array: modified args --force +args: +- ${args[--force]} = 1 +- ${args[source]} = modified +- ${args[target]} = args +# This file is located at 'src/root_command.sh'. +# It contains the implementation for the 'download' command. +# The code you write here will be wrapped by a function named 'download_command()'. +# Feel free to edit this file; your changes will persist when regenerating. +args: +- ${args[--force]} = 1 +- ${args[source]} = modified +- ${args[target]} = args +==[ After Hook Called ]== + + +```` + + + diff --git a/examples/command-line-manipulation/src/after.sh b/examples/command-line-manipulation/src/after.sh new file mode 100644 index 000000000..2440081e3 --- /dev/null +++ b/examples/command-line-manipulation/src/after.sh @@ -0,0 +1,7 @@ +## after hook +## +## Any code here will be placed inside an `after_hook()` function and called +## after running any command. +## +## You can safely delete this file if you do not need it. +echo "==[ After Hook Called ]==" \ No newline at end of file diff --git a/examples/command-line-manipulation/src/bashly.yml b/examples/command-line-manipulation/src/bashly.yml new file mode 100644 index 000000000..e9105768e --- /dev/null +++ b/examples/command-line-manipulation/src/bashly.yml @@ -0,0 +1,15 @@ +name: download +help: Sample minimal application without commands +version: 0.1.0 + +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 diff --git a/examples/command-line-manipulation/src/before.sh b/examples/command-line-manipulation/src/before.sh new file mode 100644 index 000000000..43eab9d35 --- /dev/null +++ b/examples/command-line-manipulation/src/before.sh @@ -0,0 +1,4 @@ +echo "==[ Before Hook Called ]==" + +echo "Read-only copy of the raw input array: ${input[*]}" +inspect_args diff --git a/examples/command-line-manipulation/src/initialize.sh b/examples/command-line-manipulation/src/initialize.sh new file mode 100644 index 000000000..484dc4a60 --- /dev/null +++ b/examples/command-line-manipulation/src/initialize.sh @@ -0,0 +1,6 @@ +echo "==[ Initialize Called ]==" + +# Override the command line completely if the first argument is 'debug' +if [[ "${command_line_args[0]:-""}" = "debug" ]]; then + command_line_args=("modified" "args" "--force") +fi diff --git a/examples/command-line-manipulation/src/root_command.sh b/examples/command-line-manipulation/src/root_command.sh new file mode 100644 index 000000000..28c47a208 --- /dev/null +++ b/examples/command-line-manipulation/src/root_command.sh @@ -0,0 +1,5 @@ +echo "# This file is located at 'src/root_command.sh'." +echo "# It contains the implementation for the 'download' command." +echo "# The code you write here will be wrapped by a function named 'download_command()'." +echo "# Feel free to edit this file; your changes will persist when regenerating." +inspect_args diff --git a/examples/command-line-manipulation/test.sh b/examples/command-line-manipulation/test.sh new file mode 100644 index 000000000..bd87f95b4 --- /dev/null +++ b/examples/command-line-manipulation/test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -x + +bashly generate + +### Try Me ### + +./download +./download debug diff --git a/examples/dependencies-alt/README.md b/examples/dependencies-alt/README.md index b896b37a4..269dfd7c5 100644 --- a/examples/dependencies-alt/README.md +++ b/examples/dependencies-alt/README.md @@ -52,16 +52,6 @@ commands: ### `$ ./cli download` ````shell -# This file is located at 'src/download_command.sh'. -# It contains the implementation for the 'cli download' command. -# The code you write here will be wrapped by a function named 'cli_download_command()'. -# Feel free to edit this file; your changes will persist when regenerating. -args: none - -deps: -- ${deps[git]} = /usr/bin/git -- ${deps[http_client]} = /usr/bin/curl -- ${deps[ruby]} = /home/vagrant/.rbenv/versions/3.4.1/bin/ruby ```` diff --git a/examples/hooks/src/before.sh b/examples/hooks/src/before.sh index b246442c3..7a5210f37 100644 --- a/examples/hooks/src/before.sh +++ b/examples/hooks/src/before.sh @@ -1,8 +1,11 @@ ## before hook ## -## Any code here will be placed inside a `before_hook()` function and called -## before running any command (but after processing its arguments). +## Any code here will be placed inside the `before_hook()` function and called +## before running any command (but after argument processing is complete). +## +## - The processed args are available to you here as `args` and `extra_args` +## - The raw input array is also available in read-only mode as `input` ## ## You can safely delete this file if you do not need it. echo "==[ Before Hook Called ]==" -inspect_args \ No newline at end of file +inspect_args diff --git a/examples/hooks/src/initialize.sh b/examples/hooks/src/initialize.sh index 30b092bd6..ae2356f29 100644 --- a/examples/hooks/src/initialize.sh +++ b/examples/hooks/src/initialize.sh @@ -3,4 +3,8 @@ ## Any code here will be placed inside the `initialize()` function and called ## before running anything else. ## +## The original command line arguments are available in the `command_line_args` +## array. You can modify or override the input before it is processed further, +## though this is usually only needed for advanced use cases. +## ## You can safely delete this file if you do not need it. diff --git a/examples/render-mandoc/README.md b/examples/render-mandoc/README.md index b86614ec0..e466175aa 100644 --- a/examples/render-mandoc/README.md +++ b/examples/render-mandoc/README.md @@ -102,7 +102,7 @@ ISSUE TRACKER AUTHORS Lana Lang. -Version 0.1.0 July 2025 download(1) +Version 0.1.0 August 2025 download(1) ```` diff --git a/examples/stacktrace/README.md b/examples/stacktrace/README.md index 4e54598bb..4746973b6 100644 --- a/examples/stacktrace/README.md +++ b/examples/stacktrace/README.md @@ -117,8 +117,8 @@ Examples: Stack trace: from ./download:15 in `root_command` - from ./download:260 in `run` - from ./download:266 in `main` + from ./download:259 in `run` + from ./download:267 in `main` ```` diff --git a/lib/bashly/libraries/hooks/before.sh b/lib/bashly/libraries/hooks/before.sh index b246442c3..7a5210f37 100644 --- a/lib/bashly/libraries/hooks/before.sh +++ b/lib/bashly/libraries/hooks/before.sh @@ -1,8 +1,11 @@ ## before hook ## -## Any code here will be placed inside a `before_hook()` function and called -## before running any command (but after processing its arguments). +## Any code here will be placed inside the `before_hook()` function and called +## before running any command (but after argument processing is complete). +## +## - The processed args are available to you here as `args` and `extra_args` +## - The raw input array is also available in read-only mode as `input` ## ## You can safely delete this file if you do not need it. echo "==[ Before Hook Called ]==" -inspect_args \ No newline at end of file +inspect_args diff --git a/lib/bashly/libraries/hooks/initialize.sh b/lib/bashly/libraries/hooks/initialize.sh index 30b092bd6..ae2356f29 100644 --- a/lib/bashly/libraries/hooks/initialize.sh +++ b/lib/bashly/libraries/hooks/initialize.sh @@ -3,4 +3,8 @@ ## Any code here will be placed inside the `initialize()` function and called ## before running anything else. ## +## The original command line arguments are available in the `command_line_args` +## array. You can modify or override the input before it is processed further, +## though this is usually only needed for advanced use cases. +## ## You can safely delete this file if you do not need it. diff --git a/lib/bashly/views/command/master_script.gtx b/lib/bashly/views/command/master_script.gtx index bdfdbb784..0b5eccd4a 100644 --- a/lib/bashly/views/command/master_script.gtx +++ b/lib/bashly/views/command/master_script.gtx @@ -15,11 +15,9 @@ > if Settings.enabled? :sourcing > if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then - > {{ Settings.function_name :initialize }} - > {{ Settings.function_name :run }} "$@" + = render(:start).indent 2 > fi else - > {{ Settings.function_name :initialize }} - > {{ Settings.function_name :run }} "$@" + = render :start end > diff --git a/lib/bashly/views/command/start.gtx b/lib/bashly/views/command/start.gtx new file mode 100644 index 000000000..4991ea7b9 --- /dev/null +++ b/lib/bashly/views/command/start.gtx @@ -0,0 +1,5 @@ += view_marker + +> command_line_args=("$@") +> {{ Settings.function_name :initialize }} +> {{ Settings.function_name :run }} "${command_line_args[@]}" diff --git a/spec/approvals/cli/preview/no-args b/spec/approvals/cli/preview/no-args index d42463e5d..e5c8d290e 100644 --- a/spec/approvals/cli/preview/no-args +++ b/spec/approvals/cli/preview/no-args @@ -1,3 +1,3 @@ #!/usr/bin/env bash ... -run "$@" \ No newline at end of file +fi \ No newline at end of file diff --git a/spec/approvals/examples/command-line-manipulation b/spec/approvals/examples/command-line-manipulation new file mode 100644 index 000000000..62b3d960a --- /dev/null +++ b/spec/approvals/examples/command-line-manipulation @@ -0,0 +1,26 @@ ++ bashly generate +creating user files in src +skipped src/root_command.sh (exists) +created ./download +run ./download --help to test your bash script ++ ./download +==[ Initialize Called ]== +missing required argument: SOURCE +usage: download SOURCE [TARGET] [OPTIONS] ++ ./download debug +==[ Initialize Called ]== +==[ Before Hook Called ]== +Read-only copy of the raw input array: modified args --force +args: +- ${args[--force]} = 1 +- ${args[source]} = modified +- ${args[target]} = args +# This file is located at 'src/root_command.sh'. +# It contains the implementation for the 'download' command. +# The code you write here will be wrapped by a function named 'download_command()'. +# Feel free to edit this file; your changes will persist when regenerating. +args: +- ${args[--force]} = 1 +- ${args[source]} = modified +- ${args[target]} = args +==[ After Hook Called ]== diff --git a/spec/approvals/examples/render-mandoc b/spec/approvals/examples/render-mandoc index fca583fc3..f09a7397e 100644 --- a/spec/approvals/examples/render-mandoc +++ b/spec/approvals/examples/render-mandoc @@ -44,4 +44,4 @@ ISSUE TRACKER AUTHORS Lana Lang. -Version 0.1.0 August 2025 download(1) +