mirror of
https://github.com/notwa/rc
synced 2024-11-13 20:39:04 -08:00
179 lines
5.6 KiB
Bash
Executable file
179 lines
5.6 KiB
Bash
Executable file
#!/usr/bin/env dash
|
|
# FAKE_COMPAT
|
|
|
|
# NOTE: a lot of boilerplate code is pulled from the pure sh bible:
|
|
# https://github.com/dylanaraps/pure-sh-bible
|
|
|
|
document2() {
|
|
local c=0 # line count
|
|
local d="#""#""#" # marker/delimiter, written this way to avoid self-matching
|
|
# NOTE: since the marker corresponds to a <h3> in markdown, it's used there too.
|
|
local e="${f#sh/}" # function name to expect
|
|
local f="$1" # file
|
|
local o=1 # when one, previous line was a one-liner (@- token).
|
|
[ "$f" != "$e" ] || e="" # only expect function names for stuff in sh/
|
|
while IFS= read -r line; do
|
|
: $((c+=1)) $((o+=1))
|
|
# we only care about lines with our docstring marker in them:
|
|
case "$line" in *"$d"*) :;; *) continue;; esac
|
|
|
|
# split by the marker:
|
|
local code="${line%%$d*}" docs="${line#*$d}"
|
|
code="${code#${code%%[! ]*}}" # ltrim
|
|
docs="${docs# }" # ltrim a single space
|
|
|
|
local s=' ' n='' # using a space to signify unset
|
|
|
|
case "$docs" in
|
|
@-*)
|
|
s="$code"
|
|
n="${s%%[!a-zA-Z0-9_-]*}" # substr first word (might not be one)
|
|
while [ -z "$n" ] || [ "$n" = function ] || [ "$n" = alias ]; do
|
|
[ -n "$s" ] || break
|
|
s="${s#${s%%[!a-zA-Z0-9_-]*}}" # lstrip to end of word
|
|
s="${s#*[!a-zA-Z0-9_-]}" # lstrip to next word
|
|
n="${s%%[!a-zA-Z0-9_-]*}" # substr that word
|
|
done
|
|
s="${docs#@-}" # substr the stuff after the hyphen
|
|
s="${s#${s%%[! ]*}}" # ltrim
|
|
|
|
[ -z "$s" ] || o=0
|
|
;;
|
|
|
|
@*-*)
|
|
# split by the hyphen:
|
|
n="${docs%%-*}"
|
|
s="${docs#*-}"
|
|
|
|
n="${n#@}" # substr the stuff after the at
|
|
n="${n#${n%%[! ]*}}" # ltrim
|
|
n="${n%${n##*[! ]}}" # rtrim
|
|
|
|
s="${s#${s%%[! ]*}}" # ltrim
|
|
|
|
[ -z "$s" ] || o=0
|
|
;;
|
|
|
|
@*)
|
|
n="${docs#@}" # substr the stuff after the at
|
|
n="${n#${n%%[! ]*}}" # ltrim
|
|
;;
|
|
|
|
*)
|
|
s="$docs" # leave whitespace intact
|
|
;;
|
|
esac
|
|
|
|
if [ -n "$n" ]; then
|
|
local url=
|
|
# different subdirs need to be handled differently:
|
|
[ "$f" != "${f#sh/}" ] && url="/sh/${f#sh/}#L$c" || url="/home/${f#.}#L$c"
|
|
if [ "$n" = "$e" ]; then
|
|
# function name matches the filename.
|
|
printf '\n%s [%s](%s)\n\n' "$d" "$n" "$url" || return 5
|
|
else
|
|
# this file contains some other function, so include the filename.
|
|
printf '\n%s [%s](%s)\n\n' "$d" "$n (${f#.})" "$url" || return 5
|
|
#printf '\n%s %s\n\n* defined in [%s](%s)\n\n' "%d" "$n" "$f" "$url" || return 5
|
|
fi
|
|
fi
|
|
|
|
if [ "$s" != ' ' ]; then # don't bother unless it was set to something
|
|
if [ -z "$n" ] || [ -n "$s" ]; then # might only be a name, check that
|
|
# just pass the remaining comment through:
|
|
if [ $o = 1 ]; then
|
|
# ensure one-liners are their in their own paragraph.
|
|
printf '\n' || return 5
|
|
fi
|
|
printf '%s\n' "$s" || return 5
|
|
fi
|
|
fi
|
|
done < "$f" || return 4
|
|
}
|
|
|
|
document1() {
|
|
# NOTE: in the future, it'd be nice to support arbitary files through arguments.
|
|
|
|
local in_='rc/README.md'
|
|
local out='rc/README.md~'
|
|
if [ $# -eq 0 ]; then
|
|
cd || return 2
|
|
[ -d rc ] || return 3 # sanity check
|
|
elif [ $# -eq 1 ]; then
|
|
in_='README.md'
|
|
out='README.md~'
|
|
cd "$1" || return 2
|
|
else
|
|
return 1
|
|
fi
|
|
|
|
# sanity check:
|
|
[ -d sh ] && [ -f .zshrc ] && [ -f .shrc ] && [ -f .bashrc ] || return 3
|
|
|
|
# create new output file (with a tilde as not to overwrite just yet):
|
|
: > "$out" || return 4
|
|
|
|
local line=
|
|
|
|
if [ -f "$in_" ]; then
|
|
# copy existing lines up to (and including) the "DOCUMENT" marker:
|
|
while IFS= read -r line; do
|
|
printf '%s\n' "$line" >> "$out" || return 5
|
|
case "$line" in *DOCUMENT*) break;; esac
|
|
done < "$in_" || return 4
|
|
fi
|
|
|
|
# first section:
|
|
printf '\n## %s\n' 'shell functions' >> "$out" || return 5
|
|
local f=
|
|
for f in sh/*; do
|
|
[ -e "$f" ] || continue # make sure glob went through
|
|
|
|
local fn="${f##*/}"
|
|
# ignore some stuff:
|
|
[ "$fn" = "${fn#_}" ] || continue # completion files
|
|
[ "$fn" = "${fn%.bak}" ] || continue # backup files
|
|
|
|
document2 "$f" >> "$out" || return
|
|
done
|
|
|
|
# second section:
|
|
printf '\n## %s\n' 'miscellaneous' >> "$out" || return 5
|
|
document2 .zshrc >> "$out" || return
|
|
document2 .bashrc >> "$out" || return
|
|
document2 .shrc >> "$out" || return
|
|
}
|
|
|
|
document() { ### @-
|
|
### generate a markdown file out of docstrings in shell scripts.
|
|
###
|
|
### **TODO:** describe. i have a rough outline written in my scrap file.
|
|
|
|
document1 "$@"
|
|
local ret=$?
|
|
|
|
case $ret in
|
|
0)
|
|
return 0;;
|
|
1)
|
|
printf '%s\n' "$0: too many arguments" >&2
|
|
return 1;;
|
|
2)
|
|
printf '%s\n' "$0: failed to change directory" >&2
|
|
return 1;;
|
|
3)
|
|
printf '%s\n' "$0: essential files are missing" >&2
|
|
return 1;;
|
|
4)
|
|
printf '%s\n' "$0: failed to open file" >&2
|
|
return 1;;
|
|
5)
|
|
printf '%s\n' "$0: failed to read line" >&2
|
|
return 1;;
|
|
*)
|
|
printf '%s\n' "$0: unknown error occurred" >&2
|
|
return 1;;
|
|
esac
|
|
}
|
|
|
|
[ -n "${preload+-}" ] || document "$@"
|