https://github.com/carlinigraphy/awkdoc
Shell documentation generation from comment annotations.
https://github.com/carlinigraphy/awkdoc
awk bash documentation documentation-generation documentation-generator documentation-tool shell
Last synced: 6 months ago
JSON representation
Shell documentation generation from comment annotations.
- Host: GitHub
- URL: https://github.com/carlinigraphy/awkdoc
- Owner: carlinigraphy
- License: mit
- Created: 2022-11-11T01:15:20.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-05-19T07:10:51.000Z (about 2 years ago)
- Last Synced: 2025-03-18T16:39:57.104Z (over 1 year ago)
- Topics: awk, bash, documentation, documentation-generation, documentation-generator, documentation-tool, shell
- Language: Awk
- Homepage:
- Size: 154 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.adoc
- License: LICENSE
Awesome Lists containing this project
README
= AWKDoc
:toc: preamble
:toclevels: 3
:source-highlighter: pygments
:pygments-style: algol_nu
:pygments-linenums-mode: table
Generates markdown documentation from comment annotations in [ba]sh source files.
== Usage
Write bash, add comments with <>.
Run `awkdoc` to turn annotations -> markdown documentation.
=== Brief example
.input.sh
```bash
#!/usr/bin/env bash
#---------------------------------------------------------
# @section Arithmetic functions
# @description Some useless functions that complicate
# addition and subtraction in bash.
#---------------------------------------------------------
# @type
declare -i RESULT=
# @description
# Adds a number to the global RESULT.
#
# @set RESULT
# @arg $1 :int Number to add to the $RESULT
function add {
(( RESULT = RESULT + $1 ))
}
# @description
# Subtracts a number from the global RESULT.
#
# @set RESULT
# @arg $1 :int Number to subtract from the $RESULT
function sub {
(( RESULT = RESULT - $1 ))
}
```
out.md
```markdown
# Contents.
- [Arithmetic functions](#arithmetic-functions)
- [`add`](#add)
- [`sub`](#sub)
# Types.
|type|line|file|
|:---|:---|:---|
|`RESULT`|`9`|*input.sh*|
# Functions.
## Arithmetic functions
Some useless functions that complicate
addition and subtraction in bash.
### add()
(*ln. 17, in input.sh*)
Adds a number to the global RESULT.
#### args
|name|type|desc|
|:---|:---|:---|
|`$1`|`:int`|Number to add to the $RESULT|
### sub()
(*ln. 27, in input.sh*)
Subtracts a number from the global RESULT.
#### args
|name|type|desc|
|:---|:---|:---|
|`$1`|`:int`|Number to subtract from the $RESULT|
:: *generated by @carlinigraphy/awkdoc* ::
```
=== Generate documentation
Run `awkdoc`.
```bash
./awkdoc *.sh > out.md
```
(Optionally) use https://github.com/jgm/pandoc[`pandoc`] to convert to .html
```bash
pandoc -s out.md -o out.html --metadata title="documentation"
```
*Note:* `awkdoc` does not include markdown metadata to be more generally applicable.
The `--metadata` flag can fill some gaps.
=== Environment variables
Some behavior can be modified by environment variables.
[cols="1, 1, 3"]
|===
| Variable | Acceptable values | Description
| `AWKDOC_NO_COLOR`
| `["", "yes"]`
| Any non-empty value will disable color in error output
| `AWKDOC_LOG_LEVEL`
| `[-1, 0, 1, 2]`
| Higher number, more verbose. `-1` disables error reporting entirely
|===
== Features
Things that make `awkdoc` nifty.
> *NOTE:* Instead of random examples, all the snippets below come from https://github.com/carlinigraphy/conflang[@carlinigraphy/conflang].
Helps me to understand when looking at real life use cases.
=== Error synchronization
Won't fail on the first error encountered.
Collects all possible errors & info messages before printing output.
=== Error messaging
Includes the source file name, line number, _and original line itself_ in error output.
Easier to see where problems occurred.
.Example
```
==> INFO: Unknown @-flag: asd
in test/testfile.sh
ln. 6: # @asd
==> ERROR: Missing section title
in test/testfile.sh
ln. 26: # @section
```
=== Multiline descriptions
<> text is dedented to the level of the first line, allowing for more flexible comment styles.
=== Variables set/used
Generates a list of variables specified by <> or <>, with sub-items for the function that set them.
Useful when debugging, or reasoning about the whole program.
.Example
```markdown
# Variables referenced.
- `LOCATION`
- [`token:new`](#tokennew)
- `CURSOR`
- [`location:cursor`](#locationcursor)
- [`lexer:advance`](#lexeradvance)
- `TOKEN`
- [`parser:declaration`](#parserdeclaration)
- [`parser:typedef`](#parsertypedef)
- [`parser:type`](#parsertype)
# Variables set.
- `LOCATION`
- [`location:cursor`](#locationcursor)
- `CHAR`
- [`lexer:advance`](#lexeradvance)
- `TOKENS[]`
- [`token:new`](#tokennew)
- `NODE`
- [`parser:declaration`](#parserdeclaration)
- [`parser:program`](#parserprogram)
- [`parser:typedef`](#parsertypedef)
```
== Flags
Annotation flags must occur...
. attached to a function declaration (`@arg`, `@set`, `@env`, `@internal`)
. attached to a variable declaration (`@type`)
. attached to a function/section annotation (`@description`)
. anywhere (`@section`)
=== arg
Specifies an argument, with optional type and one-line description.
Types are indicated by a `:` prefix.
An anchor to the `Types` heading is created when the parameter type matches a <>.
.Example
```bash
# @description
# Copies the properties from $1's location node to $2's. If no properties are
# specified, copies all of them. May only operate on TOKENs and NODEs.
#
# @arg $1 :NODE Source location-containing node
# @arg $2 :NODE Destination location-containing node
function location:copy {
```
.Output
```markdown
### location:copy()
(*ln. 8, in input.sh*)
Copies the properties from $1's location node to $2's. If no properties are
specified, copies all of them. May only operate on TOKENs and NODEs.
#### args
|name|type|desc|
|:---|:---|:---|
|`$1`|`NODE`|Source location-containing node|
|`$2`|`NODE`|Destination location-containing node|
```
=== env
Indicates the function references an environment/global variable.
.Example
```bash
# @description
# Convenience function to create a location at the current cursor's position.
# Cleans up otherwise messy and repetitive code in the lexer.
#
# @set LOCATION
# @env FILE_IDX
# @env CURSOR
#
# @noargs
function location:cursor {
```
.Output
```markdown
# Variables referenced.
- `CURSOR`
- [`location:cursor`](#locationcursor)
- `FILE_IDX`
- [`location:cursor`](#locationcursor)
# Functions.
### location:cursor()
(*ln. 11, in input.sh*)
Convenience function to create a location at the current cursor's position.
Cleans up otherwise messy and repetitive code in the lexer.
#### uses
- `FILE_IDX`
- `CURSOR`
```
=== set
Indicates the function sets a global variable.
.Example
```bash
# @description
# Throws error on circular imports, resolves relative paths to fully qualified
# path.
#
# @set FILES[]
# @set FILE_IDX
# @arg $1 :str Relative or absolute path to config file
# @arg $2 :LOCATION [Optional] For error reporting import statements
function utils:add_file {
```
.Output
```markdown
# Variables set.
- `FILE_IDX`
- [`utils:add_file`](#utilsadd_file)
- `FILES[]`
- [`utils:add_file`](#utilsadd_file)
# Functions.
### utils:add_file()
(*ln. 10, in input.sh*)
Throws error on circular imports, resolves relative paths to fully qualified
path.
#### args
|name|type|desc|
|:---|:---|:---|
|`$1`|`str`|Relative or absolute path to config file|
|`$2`|`LOCATION`|[Optional] For error reporting import statements|
#### set
- `FILES[]`
- `FILE_IDX`
```
=== see
Creates an anchor to another declared function.
.Example
```bash
# @description
# Identifies and calls `utils:parse` on all import statements.
#
# @see utils:parse
# @arg $1 :NODE Root AST node for a file
function imports:parse {
```
.Output
```markdown
### imports:parse()
(*ln. 7, in input.sh*)
Identifies and calls `utils:parse` on all import statements.
#### args
|name|type|desc|
|:---|:---|:---|
|`$1`|`NODE`|Root AST node for a file|
#### see
- [`utils:parse`](#utilsparse)
```
=== internal
Ignores this function definition in generated output.
Useful for library functions you still wish to document.
.Example
```bash
# @internal
# @description
# Holdover until I wire up synchronization function. Called by parser:advance()
# to advance current global Token and nameref pointers.
#
# @see parser:advance
#
# @env TOKENS
# @env IDX
# @set TOKEN
# @set TOKEN_r
# @noargs
function parser:_advance {
```
=== description
May be attached to either a function definition or a sections's annotations to
provide more information.
Descriptions may be multiline, and text is dedented to the position of the first
text-containing line after the `@description` flag.
See plenty of examples above.
=== section
Creates a higher level heading in the TOC, and the markdown body.
Useful for indicating the following functions are all related.
.Example
```bash
#===============================================================================
# @section Utils
# @description
# All of the utilities that tie together functionality from the lexer, parser,
# and compiler. Allows re-entering the parser for each included file, and
# concatenating (not literally, but in spirit) imported files.
#-------------------------------------------------------------------------------
```
.Output
```markdown
# Contents.
- [Utils](#utils)
# Functions.
## Utils
All of the utilities that tie together functionality from the lexer, parser,
and compiler. Allows re-entering the parser for each included file, and
concatenating (not literally, but in spirit) imported files.
```
The same dedentation rules apply as in the <>.
=== type
Indicates the following variable declaration is a "type".
Adds to a list in generated output, with reference to its line number.
Useful if later annotating a function's <>.
.Example
```bash
# @type
declare -g LOCATION=
# @description
# Throws error on circular imports, resolves relative paths to fully qualified
# path.
#
# @set FILES[]
# @set FILE_IDX
# @arg $1 :str Relative or absolute path to config file
# @arg $2 :LOCATION [Optional] For error reporting import statements
function utils:add_file {
```
.Output
```markdown
# Types.
|type|line|file|
|:---|:---|:---|
|`LOCATION`|`2`|*input.sh*|
# Functions.
### utils:add_file()
(*ln. 13, in input.sh*)
Throws error on circular imports, resolves relative paths to fully qualified
path.
#### args
|name|type|desc|
|:---|:---|:---|
|`$1`|`str`|Relative or absolute path to config file|
|`$2`|[`LOCATION`](#types)|[Optional] For error reporting import statements|
#### set
- `FILES[]`
- `FILE_IDX`
```
== Known limitations
=== Annotation placement
Comments with annotations must occur directly before function definitions.
They may not be placed inside the function's body, or after it.
.This works.
```bash
# @arg $1 Adds one to this number
function add_one { echo $(( $1 + 1 )) ;}
```
.These do not.
```bash
# @arg $1 Adds two to this number
function add_two { echo $(( $1 + 2 )) ;}
function add_three {
# @arg $1 Adds three to this number
echo $(( $1 + 3 ))
}
```
=== Markdown anchors
It is currently possible to have an ambiguous anchor reference.
I don't know how to make markdown anchors more specific.
=== Links to typedefs
Source files are parsed linearly.
If there is a defined <> for a function's <> type, an anchor is created.
If the typedef is declared *after* the function, there is no link.
There is no backtracking.
.Example
No link will be created for the function's 1st parameter type, as it's declared
after the function itself.
```bash
# @arg $1 :IP_ADDRESS
function ping_ip_addr { :; }
# @type
declare -g IP_ADDRESS
```
One will need to change the structure of their .sh files, or the order the files
are sourced, so type declarations always precede their use.
Or don't, and some links may not exist.
It's not a big deal.
== Recognition
Obvious inspiration, and some outright function theft, from https://github.com/reconquest/shdoc[`shdoc`].
I wanted to improve on a few edge cases, largely surrounding handling leading whitespace.
Use `shdoc`, it is better and more robust than `awkdoc`.