Last active
May 9, 2025 16:09
-
-
Save ernstki/ea2649e5ec34dacd9b1d13a8eae10a54 to your computer and use it in GitHub Desktop.
Render a roff man page from the apple-oss-distributions GitHub org
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
## | |
## Fetch macOS manual pages from the apple-oss-distributions GitHub org | |
## | |
## Author: Kevin Ernst <ernstki -at- mail.uc.edu> | |
## Date: 8 May 2025 | |
## Source: https://gist.github.com/ernstki/ea2649e5ec34dacd9b1d13a8eae10a54 | |
## License: WTFPL | |
## | |
## To do: caching | |
## See also: https://apple.stackexchange.com/questions/239484 | |
## | |
set -euo pipefail | |
TRACE=${TRACE:-}; (( TRACE )) && set -x | |
ME=${BASH_SOURCE##*/} | |
NEEDS=(jq curl groff ps2pdf) | |
GITHUB_API_KEY=${GITHUB_API_KEY:-${MACMAN_API_KEY:?Please set MACMAN_API_KEY in the environment}} | |
CURLARGS=(--fail -H "Authorization: Bearer $GITHUB_API_KEY") | |
GHAPI='https://api.github.com' | |
ORG='apple-oss-distributions' | |
OOPS="$(tput bold)$(tput setaf 1)OOPS!$(tput sgr0)" | |
pdf= | |
list= | |
exact= | |
overwrite= | |
cols=$(tput cols) | |
width=$(( cols > 100 ? 100 : cols )) # restrict to 100 columns | |
leftpad= | |
verbose= | |
section='[0-9]' # any section | |
while (( $# )); do | |
case $1 in | |
-h|--flags|--help|-\?) | |
echo " | |
usage: $ME [-h|--help] | |
$ME [-v|--verbose] [-p|--pdf [-o|--overwrite]] [-w|--width WIDTH] manpage | |
$ME {-l|--list} [-x|--exact] manpage | |
examples: | |
$ $ME grep | |
$ $ME grep --pdf --overwrite | |
$ $ME grep --width=70 | |
$ $ME 5 crontab | |
homepage: | |
https://gist.github.com/ernstki/ea2649e5ec34dacd9b1d13a8eae10a54 | |
" | |
exit | |
;; | |
-v|--verbose) | |
verbose=1 | |
;; | |
-p|--pdf) | |
pdf=1 | |
;; | |
-o|--overwrite) | |
overwrite=1 | |
;; | |
-w*|--width*) | |
if [[ $1 =~ --?w(idth=)?(.+) ]]; then | |
width=${BASH_REMATCH[2]} | |
else | |
shift | |
width=${1:-$width} | |
fi | |
;; | |
-l|--list) | |
list=1 | |
;; | |
-x|--exact) | |
exact=1 | |
;; | |
-*) | |
echo "$OOPS Unknown argument '$1'." >&2; | |
exit 1 | |
;; | |
*) | |
if [[ $1 =~ ^[0-9]$ ]]; then | |
section=$1 | |
else | |
manpage=$1 | |
fi | |
;; | |
esac | |
shift | |
done | |
for util in ${NEEDS[*]}; do | |
if ! type $util &>/dev/null; then | |
if [[ $util =~ pdf && -z $pdf ]]; then continue; fi | |
echo "$OOPS Missing required utility '$util'" >&2 | |
exit 1 | |
fi | |
done | |
if (( !TRACE )); then | |
CURLARGS+=(--silent) | |
fi | |
if (( exact && !list )); then | |
echo "$OOPS The '--exact' option requires '--list'." >&2 | |
exit 1 | |
fi | |
# left margin that's half the difference between terminal size and `width` | |
if (( cols > width )); then | |
leftpad=$(printf " %.0s" $(seq 1 $(( (cols-width)/2 )))) | |
fi | |
# ref: https://docs.github.com/en/rest/search/search#search-code | |
manpages() ( | |
(( verbose )) && set -x | |
curl "${CURLARGS[@]}" "$GHAPI/search/code?q=org:$ORG%20in:path%20$1.[0-9]" | { | |
# TODO: revisit this later, when I'm not being rate-limited | |
if (( exact )); then | |
jq -r ".items[]|select(.name|test(\"$manpage\\\\.$section\"))|.url" | |
else | |
jq -r ".items[]|select(.name|test(\".*$manpage\\\\.$section\"))|.url" | |
fi | |
} | |
) | |
list() { | |
while read -r url; do | |
curl "${CURLARGS[@]}" "$url" | jq -r .html_url | |
done | |
} | |
getraw() { | |
curl "${CURLARGS[@]}" -H 'Accept: application/vnd.github.raw+json' "$1" | |
} | |
if (( list )); then | |
manpages "$manpage" | list | |
exit | |
fi | |
if ! url=$(exact=1 manpages "$manpage" | head -1) || [[ -z $url ]]; then | |
echo "Sorry, no results for '$manpage'." >&2 | |
exit 1 | |
fi | |
getraw "$url" | { | |
if (( pdf )); then | |
if [[ -f $manpage.pdf && -z $overwrite ]]; then | |
echo "File '$manpage.pdf' exists." \ | |
"Pass '-o' / '--overwrite' to overwrite it." >&2 | |
exit 1 | |
fi | |
groff -man -Tps | ps2pdf - $manpage.pdf | |
echo "Wrote '$manpage.pdf'." >&2 | |
else | |
groff -man -Tutf8 -rLL=${width}n \ | |
| sed "s/^/$leftpad/" | less -RX | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Only half-way works, because API-based search seems a bit flaky;
path:
doesn't work,in:path
gives mixed results, and and API-based search doesn't (yet) support regular expressions. So, for example, you should get a man page forkextfind
when youmacman -l find
, but you don't.