From 119279f749a7350f938902102a0e94bc1bc81e09 Mon Sep 17 00:00:00 2001 From: rwxrob Date: Mon, 23 Aug 2021 22:10:27 -0400 Subject: [PATCH] Add `config` support and cleanup `readme` --- README.md | 97 ++++++++++++++++++++++++--------- cmd | 160 ++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 196 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 15ebd50..e70a105 100644 --- a/README.md +++ b/README.md @@ -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 Released under Apache-2.0 License Please mention -## Commands - -### The `bar` Command - -Bars. - -### The `foo` Command - -Foos. - -### Display Help Information +## The `bar` Command ``` -help [] +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* diff --git a/cmd b/cmd index ef0c64d..c42db75 100755 --- a/cmd +++ b/cmd @@ -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 Released under Apache-2.0 License -Please mention +Please mention ' -' - -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 [] +'"$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,50 +159,97 @@ 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 GitHub Flavored Markdown suitable for use as a `README.md` file on -GitHub or similar hosting service. ' +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