Add `config` support and cleanup `readme`

This commit is contained in:
rwxrob 2021-08-23 22:10:27 -04:00
parent d022b32e71
commit 119279f749
No known key found for this signature in database
GPG Key ID: 1CCACEDD2F65578E
2 changed files with 196 additions and 61 deletions

View File

@ -9,7 +9,7 @@ create a new Bash command with a command something like this:
gh repo create rwxrob/mycmd -p rwxrob/template-bash-command
```
This `command` inside can then be renamed and finished.
This `cmd` inside can then be renamed and finished.
Obviously, not all of this is needed for many Bash scripts, but anything
with more than two subcommands will benefit from the builtin tab
@ -32,6 +32,7 @@ Required:
Optional:
* `pandoc` - for rich help docs
* `jq` - for `json` and anything that uses it
## Justification
@ -48,7 +49,7 @@ more powerful, safer, flexible, and performant than POSIX shell or Zsh.
* Write GitHub Flavored Markdown only
* Use present tense ("outputs" over "will output")
* Prefer "output" and "display" over ~~print~~
* Prefer term "output" and "display" over ~~print~~
* Follow the [naming conventions](#naming-conventions)
* Use the official bash path: `#!/bin/bash`
* Use of `#!/usr/bin/bash` is outdated
@ -65,53 +66,99 @@ Copyright 2021 Rob Muhlestein <rob@rwx.gg>
Released under Apache-2.0 License
Please mention <https://rwxrob.tv>
## Commands
### The `bar` Command
Bars.
### The `foo` Command
Foos.
### Display Help Information
## The `bar` Command
```
help [<command>]
cmd bar
```
Bar the things.
## The `config` Command
```
cmd config
cmd config KEY
cmd config KEY VALUE
```
The `config` command is for reading, writing, and displaying standard
open desktop configurations properties.
### Arguments
With no arguments outputs all the currently cached configuration
settings.
With a single KEY argument fetches the value for that key and outputs
it.
With more than one argument the remaining arguments after the KEY will
be combined into the VALUE and written to the `config` file in the
standard configuration home location (Search for `XDG_CONFIG_HOME` for
more information).
### Configuration `config` File Format
The file (which is always named `config`) uses the simplest possible
format to facilitate standard UNIX parsing and filtering with any number
of existing tools (and no `jq` dependency).
* One KEY=VALUE per line
* KEYs may be anything but the equal sign (`=`)
* VALUEs may be anything but line returns must be escaped
Note that this is *not* the same as Java properties and other similar
format. It is designed for ultimate simplicity, efficiency, and
portability.
## The `foo` Command
Foos things.
## The `help` Command
```
cmd help [COMMAND]
```
Displays specific help information. If no argument is passed displays
general help information (main). Otherwise, the documentation for the
specific argument keyword is displayed, which usually corresponds to
a command name (but not necessarily). All documentation is written in
a COMMAND name (but not necessarily). All documentation is written in
GitHub Flavored Markdown and will displayed as a web page if `pandoc`
and `$HELP_BROWSER` are detected, otherwise, just the Markdown is sent
to `$PAGER` (default: more).
Also see `readme` and `usage` commands.
### The `json` Command
Converts input into JSON string using `jq` containing only escaped
(`
`) line returns.
### Generate `README.md` File
## Convert to JSON String
```
command readme > README.md
cmd json STRING
cmd json <<< STRING
cmd json < FILE
cmd json < <(COMMAND)
```
Converts input into JSON string using `jq` (if found) containing only
escaped (`\n`) line returns.
## Generate `README.md` File
```
cmd readme > README.md
```
The `readme` command will output the embedded help documentation in raw
GitHub Flavored Markdown suitable for use as a `README.md` file on
GitHub or similar hosting service.
### The `usage` Command
## The `usage` Command
Displays a summary of usage.
----
*Autogenerated Sun Aug 15 04:56:38 PM EDT 2021*
*Autogenerated Mon Aug 23 10:09:44 PM EDT 2021*

158
cmd
View File

@ -8,12 +8,13 @@ set -e
: "${PAGER:=more}"
: "${EDITOR:=vi}"
: "${HELP_BROWSER:=}"
: "${EXE:="${0##*/}"}"
: "${XDG_CONFIG_HOME:="$HOME/.config"}"
EXE="${0##*/}"
declare -A HELP
declare -A CONFIG
declare -A help # associative arrays *require* declaration
help[main]='
HELP[main]='
# Bash Template Command
*This `README.md` is autogenerated.*
@ -25,7 +26,7 @@ create a new Bash command with a command something like this:
gh repo create rwxrob/mycmd -p rwxrob/template-bash-command
```
This `command` inside can then be renamed and finished.
This `cmd` inside can then be renamed and finished.
Obviously, not all of this is needed for many Bash scripts, but anything
with more than two subcommands will benefit from the builtin tab
@ -48,6 +49,7 @@ Required:
Optional:
* `pandoc` - for rich help docs
* `jq` - for `json` and anything that uses it
## Justification
@ -64,7 +66,7 @@ more powerful, safer, flexible, and performant than POSIX shell or Zsh.
* Write GitHub Flavored Markdown only
* Use present tense ("outputs" over "will output")
* Prefer "output" and "display" over ~~print~~
* Prefer term "output" and "display" over ~~print~~
* Follow the [naming conventions](#naming-conventions)
* Use the official bash path: `#!/bin/bash`
* Use of `#!/usr/bin/bash` is outdated
@ -79,31 +81,42 @@ more powerful, safer, flexible, and performant than POSIX shell or Zsh.
Copyright 2021 Rob Muhlestein <rob@rwx.gg>
Released under Apache-2.0 License
Please mention <https://rwxrob.tv>
Please mention <https://rwxrob.tv>'
'
help[foo]='Foos.'
HELP[foo]='Foos things.'
command_foo() {
_filter "$@" && return $?
echo "would foo: $*"
}
help[bar]='Bars.'
HELP[bar]='
```
'"$EXE"' bar
```
Bar the things.'
command_bar() {
_buffer "$@" && return $?
echo "would bar: $*"
}
help[json]='
Converts input into JSON string using `jq` containing only escaped
(`\n`) line returns.'
HELP[json]='
## Convert to JSON String
command_json() {
_jsonstr "$@"
}
```
'"$EXE"' json STRING
'"$EXE"' json <<< STRING
'"$EXE"' json < FILE
'"$EXE"' json < <(COMMAND)
```
Converts input into JSON string using `jq` (if found) containing only
escaped (`\\n`) line returns.'
command_json() { _jsonstr "$@"; }
command__hidden() {
_filter "$@" && return $?
@ -113,7 +126,7 @@ command__hidden() {
# ------------------ builtin commands and functions ------------------
# (https://github.com/rwxrob/template-bash-command)
help[usage]='Displays a summary of usage.'
HELP[usage]='Displays a summary of usage.'
command_usage() {
local -a cmds
@ -125,17 +138,16 @@ command_usage() {
printf "usage: %s (%s)\n" "$EXE" "${cmds[*]}"
}
help[help]='
# Display Help Information
HELP[help]='
```
help [<command>]
'"$EXE"' help [COMMAND]
```
Displays specific help information. If no argument is passed displays
general help information (main). Otherwise, the documentation for the
specific argument keyword is displayed, which usually corresponds to
a command name (but not necessarily). All documentation is written in
a COMMAND name (but not necessarily). All documentation is written in
GitHub Flavored Markdown and will displayed as a web page if `pandoc`
and `$HELP_BROWSER` are detected, otherwise, just the Markdown is sent
to `$PAGER` (default: more).
@ -147,33 +159,33 @@ command_help() {
local name="${1:-main}" title body
title=$(_help_title "$name") || true
if [[ -z "$title" ]]; then
body="${help[$name]}"
body="${HELP[$name]}"
title="$EXE $name"
[[ $name = main ]] && title="$EXE"
else
body="${help[$name]}"
body="${HELP[$name]}"
body=${body#*$title}
fi
local file="/tmp/help-$EXE-$name.html"
if _have pandoc ; then
if _have "$HELP_BROWSER" && [[ -t 1 ]] ;then
pandoc -s --metadata title="$title" \
pandoc -f gfm -s --metadata title="$title" \
-o "$file" <<< "$body"
[[ -z "$2" ]] && cd /tmp && exec "$HELP_BROWSER" "$file"
return 0
fi
pandoc -s --metadata title="$title" \
pandoc -f gfm -s --metadata title="$title" \
-t plain <<< "$body" | "$PAGER"
return 0
fi
echo -e "$title\n\n$body" | "$PAGER"
}
help[readme]='
# Generate `README.md` File
HELP[readme]='
## Generate `README.md` File
```
command readme > README.md
'"$EXE"' readme > README.md
```
The `readme` command will output the embedded help documentation in raw
@ -181,16 +193,63 @@ GitHub Flavored Markdown suitable for use as a `README.md` file on
GitHub or similar hosting service.'
command_readme() {
_trim "${help[main]}"
_trim "${HELP[main]}"
echo
while IFS= read -r name; do
[[ $name = main ]] && continue
body=$(_trim "${help[$name]}")
[[ $body =~ ^\# ]] || body="# The \`$name\` Command\n\n$body"
printf "##%s\n\n" "$body"
done < <(printf "%s\n" "${!help[@]}" | LC_COLLATE=C sort)
body=$(_trim "${HELP[$name]}")
[[ $body =~ ^\# ]] || body="## The \`$name\` Command"$'\n\n'$body
printf "%s\n\n" "$body"
done < <(printf "%s\n" "${!HELP[@]}" | LC_COLLATE=C sort)
echo -e "----\n\n*Autogenerated $(date)*\n"
}
HELP[config]='
```
'"$EXE"' config
'"$EXE"' config KEY
'"$EXE"' config KEY VALUE
```
The `config` command is for reading, writing, and displaying standard
open desktop configurations properties.
### Arguments
With no arguments outputs all the currently cached configuration
settings.
With a single KEY argument fetches the value for that key and outputs
it.
With more than one argument the remaining arguments after the KEY will
be combined into the VALUE and written to the `config` file in the
standard configuration home location (Search for `XDG_CONFIG_HOME` for
more information).
### Configuration `config` File Format
The file (which is always named `config`) uses the simplest possible
format to facilitate standard UNIX parsing and filtering with any number
of existing tools (and no `jq` dependency).
* One KEY=VALUE per line
* KEYs may be anything but the equal sign (`=`)
* VALUEs may be anything but line returns must be escaped
Note that this is *not* the same as Java properties and other similar
format. It is designed for ultimate simplicity, efficiency, and
portability.'
command_config() {
case $# in
0) _dump_config ;;
1) printf "${CONFIG[$1]}" ;;
*) _set_config "$@" ;;
esac
}
_help_title() {
_filter "$@" && return $?;
local name="$1"
@ -198,7 +257,34 @@ _help_title() {
[[ $line =~ ^[:space]*$ ]] && continue
[[ $line =~ ^#\ (.+) ]] && echo "${BASH_REMATCH[1]}" && return 0
return 1
done <<< "${help[$name]}"
done <<< "${HELP[$name]}"
}
_set_config() {
local key="$1"; shift; local val="$*"
val="${val//$'\n'/\\n}"
CONFIG["$key"]="$val"
_write_config
}
_read_config() {
local path="$XDG_CONFIG_HOME/$EXE/config"
while IFS= read -r line; do
[[ $line =~ ^([^=]+)=(.+)$ ]] || continue
CONFIG["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}"
done < "$path"
}
_write_config() {
local path="$XDG_CONFIG_HOME/$EXE/config"
mkdir -p "${path%/config}"
_dump_config > "$path"
}
_dump_config() {
paste -d=\
<(printf "%s\n" "${!CONFIG[@]}") \
<(printf "%s\n" "${CONFIG[@]}")
}
_trim() {
@ -250,6 +336,8 @@ for c in "${COMMANDS[@]}"; do
fi
done
_read_config
if [[ -n "$1" ]]; then
declare cmd="$1"; shift
for c in "${COMMANDS[@]}"; do