From 82915b56c36645bf853e65d62607a0a54ed92be1 Mon Sep 17 00:00:00 2001 From: Jeremy Brubaker Date: Thu, 10 Oct 2024 14:40:08 -0400 Subject: [PATCH 1/2] Add @requires --- README.md | 30 ++++++++++++++ examples/readme-example.md | 11 ++++++ examples/readme-example.sh | 7 +++- shdoc | 10 ++++- tests/testcases/@requires.test.sh | 66 +++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 tests/testcases/@requires.test.sh diff --git a/README.md b/README.md index 5052e42..b2a815d 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ _Output_: [examples/readme-example.md](examples/readme-example.md)

# * b # * c # * etc +# @requires foo +# @requires bar # @description My super function. # Not thread-safe. @@ -55,6 +57,9 @@ _Output_: [examples/readme-example.md](examples/readme-example.md)

# @example # echo "test: $(say-hello World)" # +# @requires Some very specific requirements +# that continue on the next line (indent by a +# single space to continue) # # @option -h | --help Display help. # @option -v | --value= Set a value. @@ -69,6 +74,9 @@ _Output_: [examples/readme-example.md](examples/readme-example.md)

# @exitcode 0 If successful. # @exitcode 1 If an empty string passed. # +# @requires foo +# @requires bar +# # @see validate() # @see [shdoc](https://github.com/reconquest/shdoc). say-hello() { @@ -399,6 +407,28 @@ say-hello-world() { ... } ``` +### `@requires` + +Indicates requirements needed by the file or the given function + +**Example** + +```bash +# @name My script +# @requires foo +# @requires A long description of the requirements +# (indent by one space to continue) +``` + +**Example** + +```bash +# @requires ubuntu>20 +# @requires curl(1) +say-hello-world() { + ... +} +``` ### `@stdin` diff --git a/examples/readme-example.md b/examples/readme-example.md index 742663a..b4c8d33 100644 --- a/examples/readme-example.md +++ b/examples/readme-example.md @@ -10,6 +10,11 @@ The project solves lots of problems: * c * etc +## Requires + +* foo +* bar + ## Index * [say-hello](#say-hello) @@ -62,6 +67,12 @@ echo "test: $(say-hello World)" * [validate()](#validate) * [shdoc](https://github.com/reconquest/shdoc). +### Requires + +* Some very specific requirements + that continue on the next line (indent by a + single space to continue) + ## Sub-section Some grouped functions. diff --git a/examples/readme-example.sh b/examples/readme-example.sh index b064167..687bec3 100644 --- a/examples/readme-example.sh +++ b/examples/readme-example.sh @@ -7,6 +7,8 @@ # * b # * c # * etc +# @requires foo +# @requires bar # @description My super function. # Not thread-safe. @@ -14,6 +16,9 @@ # @example # echo "test: $(say-hello World)" # +# @requires Some very specific requirements +# that continue on the next line (indent by a +# single space to continue) # # @option -h | --help Display help. # @option -v | --value= Set a value. @@ -54,4 +59,4 @@ deeper-level() { echo; } # @endsection # @description Back up again -up-again() { echo; } \ No newline at end of file +up-again() { echo; } diff --git a/shdoc b/shdoc index 762e63d..e1008ff 100755 --- a/shdoc +++ b/shdoc @@ -654,6 +654,11 @@ function render_docblock(func_name, description, docblock, nesting) { push(lines, "") } + if (docblock_allows("requires") && "requires" in docblock) { + render_docblock_list(docblock, "requires", "Requires", nesting_one) + } + + result = join(lines) return result } @@ -912,9 +917,9 @@ multiple_line_docblock_name { } } -# Process similarly @stdin, @stdout and @stderr entries. +# Process similarly @stdin, @stdout, @stderr and @requires entries. # Allow for multiple lines entries. -match($0, /^([[:blank:]]*#[[:blank:]]+)@(stdin|stdout|stderr)[[:blank:]]+(.*[^[:blank:]])[[:blank:]]*$/, contents) { +match($0, /^([[:blank:]]*#[[:blank:]]+)@(stdin|stdout|stderr|requires)[[:blank:]]+(.*[^[:blank:]])[[:blank:]]*$/, contents) { # Fetch matched values. indentation = contents[1] docblock_name = contents[2] @@ -980,6 +985,7 @@ match($0, /^([[:blank:]]*#[[:blank:]]+)@(stdin|stdout|stderr)[[:blank:]]+(.*[^[: docblock_filter["example"] = 1 docblock_filter["see"] = 1 docblock_filter["set"] = 1 + docblock_filter["requires"] = 1 file_annoblock = render_docblock("", "", docblock, 1) delete docblock_filter } diff --git a/tests/testcases/@requires.test.sh b/tests/testcases/@requires.test.sh new file mode 100644 index 0000000..110c60e --- /dev/null +++ b/tests/testcases/@requires.test.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# @file test/testcases/@requires.test.sh +# @author Jeremy Brubaker +# @brief Test cases for @requires keyword. +# @requires foo +# @description +# Test these @requires comportements: +# - file-level @requires +# - simple one line message. +# - one line message with indentation and trailing spaces. +# - indented two lines message. +# - three lines message with trailing spaces. +# - appears between @stdin and @stderr sections. + +tests:put input < Date: Mon, 23 Mar 2026 08:58:25 -0400 Subject: [PATCH 2/2] Move @see to the end --- shdoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shdoc b/shdoc index e1008ff..569b9dd 100755 --- a/shdoc +++ b/shdoc @@ -643,6 +643,10 @@ function render_docblock(func_name, description, docblock, nesting) { render_docblock_list(docblock, "stderr", "Output on stderr", nesting_one) } + if (docblock_allows("requires") && "requires" in docblock) { + render_docblock_list(docblock, "requires", "Requires", nesting_one) + } + if (docblock_allows("see") && "see" in docblock) { push(lines, render(nesting_one, "See also")) for (i in docblock["see"]) { @@ -654,10 +658,6 @@ function render_docblock(func_name, description, docblock, nesting) { push(lines, "") } - if (docblock_allows("requires") && "requires" in docblock) { - render_docblock_list(docblock, "requires", "Requires", nesting_one) - } - result = join(lines) return result