Files
Björn RundenandClaude Opus 5.5 7f6b8ebe07 Basis aus 2nd-brain für LPIC-Prüfungsvorbereitung übernommen
Regeln, Standards, Kontextstruktur und Werkzeuge übernommen; 2nd-brain-
Inhalte (Stacks, Ansible-Inventar, Architektur, Knowledge) entfernt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:56:53 +01:00

105 lines
4.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
#-------------------------------------------------------------------------------
## @file bashdoc.sh
## @brief Erzeugt Markdown-Doku aus den '##'-Kommentaren von Bash-Scripts
## (Präambel + Funktionsköpfe, angelehnt an javadoc)
## @author <AUTOR – aus ai/context/responsible.md>
## @owner <VERANTWORTLICH – aus ai/context/responsible.md>
## @assist KI-unterstützt (Claude), geprüft von <AUTOR>
## @version 1.0.0 (07.10.2026)
##
## @usage bashdoc.sh [Optionen] <script.sh> [...]
## Ausgabe auf stdout oder mit -o in eine Datei
## @options
## @OPTIONS@
## @exit 0 = ok · 1 = Fehler · 2 = Aufruffehler
#-------------------------------------------------------------------------------
set -Eeuo pipefail
SCRIPT_PATH="$(readlink -f -- "${BASH_SOURCE[0]}")"
SCRIPT_DIR="${SCRIPT_PATH%/*}"
SCRIPT_NAME="${SCRIPT_PATH##*/}"
# shellcheck source=_functions.sh
source "${SCRIPT_DIR}/_functions.sh" || { echo "FEHLER: ${SCRIPT_DIR}/_functions.sh fehlt" >&2; exit 1; }
B_OPTS+=(
"o|output|value:DATEI||Markdown in DATEI schreiben (relativ = zum Aufrufverzeichnis)"
"p|private|flag|0|auch interne Funktionen (_name) dokumentieren"
)
b_init "$@"
set -- "${ARGS[@]}"
## @brief Wandelt ein Script in Markdown um
## @param $1 Script-Datei
## @return 0 ok, 1 Datei nicht lesbar; Markdown auf stdout
doc_file() {
local file="$1"
[[ -r "$file" ]] || { berror "Nicht lesbar: $file"; return 1; }
awk -v fname="${file##*/}" -v private="$OPTION_PRIVATE" '
function flush_block(name, i, l, tag) {
if (!private && name ~ /^_/) { n = 0; return }
printf "\n### `%s()`\n\n", name
for (i = 1; i <= n; i++) {
l = blk[i]
if (l ~ /^@brief/) { sub(/^@brief[ \t]*/, "", l); print l; last = "brief" }
else if (l ~ /^@param/) { sub(/^@param[ \t]*/, "", l); print "- **Param** " l; last = "param" }
else if (l ~ /^@return/) { sub(/^@return[ \t]*/, "", l); print "- **Return** " l; last = "return" }
else if (l ~ /^@/) { tag = l; sub(/[ \t].*/, "", tag); sub(/^@[a-z]+[ \t]*/, "", l); print "- **" substr(tag, 2) "** " l }
else if (l != "") { print (last == "brief" ? l : " " l) }
}
n = 0
}
function print_opts( i, f, left) {
print " -h -d -q -n -l Standardoptionen (Hilfe, Debug, still, Trockenlauf, Logdatei)"
for (i = 1; i <= nopt; i++) {
split(opt[i], f, "|"); sub(/:.*/, "", f[3])
left = (f[1] != "" ? "-" f[1] " | " : "") "--" f[2]
if (opt_meta[i] != "") left = left " " opt_meta[i]
printf " %-26s %s%s\n", left, f[5], (f[3] == "value" && f[4] != "" ? " (Default: " f[4] ")" : "")
}
}
# 1. Durchlauf: Script-Optionen aus B_OPTS+=( "…" ) sammeln
FNR == NR {
if ($0 ~ /^[ \t]*B_OPTS\+=\(/) inopts = 1
if (inopts) {
l = $0
while (match(l, /"[^"]*"/)) {
o = substr(l, RSTART + 1, RLENGTH - 2); l = substr(l, RSTART + RLENGTH)
opt[++nopt] = o; split(o, f, "|"); opt_meta[nopt] = (f[3] ~ /:/ ? substr(f[3], index(f[3], ":") + 1) : (f[3] == "value" ? "WERT" : ""))
}
if ($0 ~ /\)[ \t]*$/) inopts = 0
}
next
}
# 2. Durchlauf: Präambel + Funktionsköpfe
/^#-{10,}/ { part++; if (part == 1) printf "## %s\n\n```text\n", fname; if (part == 2) print "```"; next }
part == 1 && /^##/ { l = $0; sub(/^## ?/, "", l); if (l !~ /@OPTIONS@/) print l; else print_opts(); next }
part >= 2 && /^[ \t]*##/ { l = $0; sub(/^[ \t]*## ?/, "", l); blk[++n] = l; next }
part >= 2 && n > 0 && /^[ \t]*(function[ \t]+)?[A-Za-z_][A-Za-z0-9_]*[ \t]*\(\)/ {
name = $0; sub(/^[ \t]*(function[ \t]+)?/, "", name); sub(/[ \t]*\(.*/, "", name)
flush_block(name); next
}
part >= 2 && n > 0 && !/^[ \t]*#/ { n = 0 }
' "$file" "$file"
}
## @brief Hauptablauf
## @param $@ Script-Dateien
## @return 0 ok, 1 Fehler
main() {
(( $# )) || bdie "Mindestens ein Script angeben" 2
local f out="" rc=0
[[ -n "$OPTION_OUTPUT" ]] && out="$(b_abspath "$OPTION_OUTPUT" "$B_CALL_DIR")"
{
printf '# Script-Doku\n\n> Erzeugt mit `bin/bashdoc.sh` am %(%d.%m.%Y)T – Quelle sind die `##`-Kommentare.\n\n' -1
for f in "$@"; do
doc_file "$(b_abspath "$f" "$B_CALL_DIR")" || rc=1
printf '\n'
done
} > "${out:-/dev/stdout}"
[[ -n "$out" ]] && becho "Doku geschrieben: $out"
return "$rc"
}
main "$@"