mirror of
https://github.com/eth-p/bat-extras.git
synced 2025-01-07 21:58:51 +01:00
build: Add experimental support for generating manpages
This commit is contained in:
parent
85c4cfbfe8
commit
9f6e5c0164
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@
|
|||||||
/.circleci/.config.yml
|
/.circleci/.config.yml
|
||||||
.download
|
.download
|
||||||
bin
|
bin
|
||||||
|
man
|
||||||
|
@ -86,6 +86,14 @@ If you only want to install a single script, you can run the build process and c
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Manuals:** (EXPERIMENTAL)
|
||||||
|
|
||||||
|
You can specify `--manuals` to have the build script generate a `man` page for each of the markdown documentation files.
|
||||||
|
This is an experimental feature that uses a non-compliant Markdown "parser" written in Bash, and there is no guarantee
|
||||||
|
as for the quality of the generated manual pages.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Alternate Executable:**
|
**Alternate Executable:**
|
||||||
|
|
||||||
Depending on the distribution, bat may have been renamed to avoid package conflicts.
|
Depending on the distribution, bat may have been renamed to avoid package conflicts.
|
||||||
|
28
build.sh
28
build.sh
@ -8,6 +8,8 @@
|
|||||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
BIN="$HERE/bin"
|
BIN="$HERE/bin"
|
||||||
SRC="$HERE/src"
|
SRC="$HERE/src"
|
||||||
|
MAN="$HERE/man"
|
||||||
|
MAN_SRC="$HERE/doc"
|
||||||
LIB="$HERE/lib"
|
LIB="$HERE/lib"
|
||||||
source "${LIB}/print.sh"
|
source "${LIB}/print.sh"
|
||||||
source "${LIB}/opt.sh"
|
source "${LIB}/opt.sh"
|
||||||
@ -363,6 +365,7 @@ OPT_INSTALL=false
|
|||||||
OPT_COMPRESS=false
|
OPT_COMPRESS=false
|
||||||
OPT_VERIFY=true
|
OPT_VERIFY=true
|
||||||
OPT_BANNER=true
|
OPT_BANNER=true
|
||||||
|
OPT_MANUALS=false
|
||||||
OPT_MINIFY="lib"
|
OPT_MINIFY="lib"
|
||||||
OPT_PREFIX="/usr/local"
|
OPT_PREFIX="/usr/local"
|
||||||
OPT_BAT="$(basename "$EXECUTABLE_BAT")"
|
OPT_BAT="$(basename "$EXECUTABLE_BAT")"
|
||||||
@ -375,6 +378,7 @@ while shiftopt; do
|
|||||||
case "$OPT" in
|
case "$OPT" in
|
||||||
--install) OPT_INSTALL=true ;;
|
--install) OPT_INSTALL=true ;;
|
||||||
--compress) OPT_COMPRESS=true ;;
|
--compress) OPT_COMPRESS=true ;;
|
||||||
|
--manuals) OPT_MANUALS=true ;;
|
||||||
--no-verify) OPT_VERIFY=false ;;
|
--no-verify) OPT_VERIFY=false ;;
|
||||||
--no-banner) OPT_BANNER=false ;;
|
--no-banner) OPT_BANNER=false ;;
|
||||||
--prefix) shiftval; OPT_PREFIX="$OPT_VAL" ;;
|
--prefix) shiftval; OPT_PREFIX="$OPT_VAL" ;;
|
||||||
@ -427,6 +431,30 @@ for file in "$SRC"/*.sh; do
|
|||||||
SOURCES+=("$file")
|
SOURCES+=("$file")
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Build manuals.
|
||||||
|
|
||||||
|
if "$OPT_MANUALS"; then
|
||||||
|
source "${HERE}/mdroff.sh"
|
||||||
|
if ! [[ -d "$MAN" ]]; then
|
||||||
|
mkdir -p "$MAN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printc_msg "%{YELLOW}Building manuals...%{CLEAR}\n"
|
||||||
|
for source in "${SOURCES[@]}"; do
|
||||||
|
name="$(basename "$source" .sh)"
|
||||||
|
doc="${MAN_SRC}/${name}.md"
|
||||||
|
docout="${MAN}/${name}.1"
|
||||||
|
if ! [[ -f "$doc" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
printc_msg " %{YELLOW} %{MAGENTA}%s%{CLEAR}\n" "$(basename "$docout")"
|
||||||
|
(mdroff < "$doc" > "${MAN}/${name}.1")
|
||||||
|
done
|
||||||
|
printc_msg "\n"
|
||||||
|
fi
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Build files.
|
# Build files.
|
||||||
|
|
||||||
|
278
mdroff.sh
Executable file
278
mdroff.sh
Executable file
@ -0,0 +1,278 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# bat-extras | Copyright (C) 2020 eth-p | MIT License
|
||||||
|
#
|
||||||
|
# Repository: https://github.com/eth-p/bat-extras
|
||||||
|
# Issues: https://github.com/eth-p/bat-extras/issues
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
printf_msg() {
|
||||||
|
printf "$@" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
printf_err() {
|
||||||
|
printf "$@" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# MDroff:
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mdroff:emit:h1() {
|
||||||
|
printf '.TH "%s" 1\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:h2() {
|
||||||
|
printf '.SH "%s"\n' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:h3() {
|
||||||
|
echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:h4() {
|
||||||
|
echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:h5() {
|
||||||
|
echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:line() {
|
||||||
|
if "$MDROFF_PARAGRAPH"; then
|
||||||
|
MDROFF_PARAGRAPH=false
|
||||||
|
printf ".P\n%s\n" "$1"
|
||||||
|
else
|
||||||
|
printf ".br\n%s\n" "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:attr() {
|
||||||
|
printf '\\fR'
|
||||||
|
|
||||||
|
if "$MDROFF_ATTR_STRONG"; then
|
||||||
|
printf '\\fB'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$MDROFF_ATTR_EMPHASIS"; then
|
||||||
|
printf '\\fI'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:link() {
|
||||||
|
printf "%s" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:table_heading() {
|
||||||
|
printf '.P\n\\fB'
|
||||||
|
printf '%s ' "$@"
|
||||||
|
printf '\\fR\n'
|
||||||
|
|
||||||
|
# Emit separator.
|
||||||
|
printf '.br\n'
|
||||||
|
local cell
|
||||||
|
for cell in "$@"; do
|
||||||
|
printf "%$(wc -c <<< "$cell")s" '' | tr ' ' '-'
|
||||||
|
printf " "
|
||||||
|
done
|
||||||
|
printf "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit:table_row() {
|
||||||
|
printf '.br\n'
|
||||||
|
printf '%s ' "$@"
|
||||||
|
printf '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit() {
|
||||||
|
local type="$1"
|
||||||
|
local data="$2"
|
||||||
|
|
||||||
|
if type "mdroff:rewrite:${type}" &>/dev/null; then
|
||||||
|
data="$("mdroff:rewrite:${type}" "${@:2}")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if type "mdroff:emit_hook:${type}" &>/dev/null; then
|
||||||
|
"mdroff:emit_hook:${type}" "$data" "${@:3}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
"mdroff:emit:${type}" "$data" "${@:3}"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:parseln() {
|
||||||
|
MDROFF_ATTR_STRONG=false
|
||||||
|
MDROFF_ATTR_EMPHASIS=false
|
||||||
|
|
||||||
|
local buffer="$1"
|
||||||
|
local before
|
||||||
|
local found
|
||||||
|
local pos
|
||||||
|
|
||||||
|
while [[ "${#buffer}" -gt 0 ]]; do
|
||||||
|
[[ "$buffer" =~ \*{1,3}|\[([^\]]+)\]\(([^\)]+)\) ]] || {
|
||||||
|
printf "%s\n" "$buffer"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
found="${BASH_REMATCH[0]}"
|
||||||
|
pos="$(awk -v search="$found" '{print index($0,search) - 1}' <<< "$buffer")"
|
||||||
|
|
||||||
|
before="${buffer:0:$pos}"
|
||||||
|
buffer="${buffer:$(($pos + ${#found}))}"
|
||||||
|
|
||||||
|
printf "%s" "$before"
|
||||||
|
case "$found" in
|
||||||
|
'***')
|
||||||
|
if "$MDROFF_ATTR_STRONG" && "$MDROFF_ATTR_EMPHASIS"; then
|
||||||
|
MDROFF_ATTR_STRONG=false
|
||||||
|
MDROFF_ATTR_EMPHASIS=false
|
||||||
|
else
|
||||||
|
MDROFF_ATTR_STRONG=true
|
||||||
|
MDROFF_ATTR_EMPHASIS=true
|
||||||
|
fi
|
||||||
|
mdroff:emit attr
|
||||||
|
;;
|
||||||
|
|
||||||
|
'**')
|
||||||
|
if "$MDROFF_ATTR_STRONG"; then
|
||||||
|
MDROFF_ATTR_STRONG=false
|
||||||
|
else
|
||||||
|
MDROFF_ATTR_STRONG=true
|
||||||
|
fi
|
||||||
|
mdroff:emit attr
|
||||||
|
;;
|
||||||
|
|
||||||
|
'*')
|
||||||
|
if "$MDROFF_ATTR_EMPHASIS"; then
|
||||||
|
MDROFF_ATTR_EMPHASIS=false
|
||||||
|
else
|
||||||
|
MDROFF_ATTR_EMPHASIS=true
|
||||||
|
fi
|
||||||
|
mdroff:emit attr
|
||||||
|
;;
|
||||||
|
|
||||||
|
'['*)
|
||||||
|
mdroff:emit link "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff() {
|
||||||
|
MDROFF_HEADING_LEVEL=0
|
||||||
|
MDROFF_HEADING=''
|
||||||
|
MDROFF_ATTR_STRONG=false
|
||||||
|
MDROFF_ATTR_EMPHASIS=false
|
||||||
|
MDROFF_IN_TABLE=false
|
||||||
|
MDROFF_PARAGRAPH=false
|
||||||
|
|
||||||
|
local line
|
||||||
|
local empty=0
|
||||||
|
local empty_continue=0
|
||||||
|
while IFS='' read -r line; do
|
||||||
|
line="$(mdroff:parseln "$line")"
|
||||||
|
|
||||||
|
# Empty
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*$ ]]; then
|
||||||
|
((empty_continue++)) || true
|
||||||
|
MDROFF_PARAGRAPH=true
|
||||||
|
MDROFF_IN_TABLE=false
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
empty="$empty_continue"
|
||||||
|
empty_continue=0
|
||||||
|
|
||||||
|
# Headings
|
||||||
|
if [[ "$line" =~ ^(#{1,})[[:space:]]{1,}(.*)$ ]]; then
|
||||||
|
local level="${#BASH_REMATCH[1]}"
|
||||||
|
local text="${BASH_REMATCH[2]}"
|
||||||
|
|
||||||
|
MDROFF_HEADING_LEVEL="$level"
|
||||||
|
MDROFF_HEADING="$text"
|
||||||
|
|
||||||
|
mdroff:emit "h${level}" "$text"
|
||||||
|
MDROFF_PARAGRAPH=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tables (Partially Supported)
|
||||||
|
if [[ "$line" =~ ^[[:space:]]*\| ]]; then
|
||||||
|
local cells=()
|
||||||
|
line="$(sed 's/^[[:space:]]*|//; s/|[[:space:]]*$//' <<< "$line")"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2206
|
||||||
|
IFS='|' cells=($line)
|
||||||
|
|
||||||
|
if [[ "${cells[0]}" =~ ^[[:space:]]*-+[[:space:]]*$ ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! "$MDROFF_IN_TABLE"; then
|
||||||
|
MDROFF_IN_TABLE=true
|
||||||
|
mdroff:emit table_heading "${cells[@]}"
|
||||||
|
else
|
||||||
|
mdroff:emit table_row "${cells[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MDROFF_PARAGRAPH=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
mdroff:emit line "$line"
|
||||||
|
done < <(sed 's/<br *\/?>//')
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# bat-extras:
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mdroff:rewrite:h1() {
|
||||||
|
emitted_name=false
|
||||||
|
emitted_description=false
|
||||||
|
sed 's/^bat-extras: //' <<< "$1" | tr '[[:lower:]]' '[[:upper:]]'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mdroff:emit_hook:h2() {
|
||||||
|
case "$MDROFF_HEADING" in
|
||||||
|
"Installation") return ;;
|
||||||
|
"Issues?") return ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mdroff:emit:h2 "$(tr '[[:lower:]]' '[[:upper:]]' <<< "$1")"
|
||||||
|
}
|
||||||
|
|
||||||
|
mdroff:emit_hook:line() {
|
||||||
|
if [[ "$MDROFF_HEADING_LEVEL" = "1" ]] && [[ "$emitted_name" != true ]]; then
|
||||||
|
emitted_name=true
|
||||||
|
printf ".SH NAME\n%s - %s\n" "$(sed 's/^bat-extras: //' <<< "$MDROFF_HEADING" | tr '[[:upper:]]' '[[:lower:]]')" "$1"
|
||||||
|
printf ".SH DESCRIPTION\n"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$MDROFF_HEADING" in
|
||||||
|
"Installation") return ;;
|
||||||
|
"Issues?") return ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
mdroff:emit:line "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Main:
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [[ "${#BASH_SOURCE[@]}" -eq 1 ]]; then
|
||||||
|
case "$1" in
|
||||||
|
"") mdroff ;;
|
||||||
|
*) {
|
||||||
|
if ! [ -f "$1" ]; then
|
||||||
|
printf_err "%s: cannot find or read file %s\n" "$0" "$1"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
mdroff < "$1"
|
||||||
|
} ;;
|
||||||
|
esac
|
||||||
|
fi
|
Loading…
Reference in New Issue
Block a user