#!/bin/bash
# dev/docs/ref - package source reference support
set -e
lib_load 'dev/docs/rst'
######
# Source Line Processing
is_docs_marker() {
is_docs_arg "$1" || is_docs_symbol || is_docs_section "$1"
}
is_docs_section() { [ "$1" = '#####' ]; }
is_docs_symbol() { [ "${1/ - /}" != "$1" ]; }
is_docs_arg() { [ "${1/\$[0-9\@] - /}" != "$1" -o "${1#... - }" != "$1" ]; }
# docs_readline() - Reads a line into the named var ($1)
# $1 - Variable name to receive line of documentation
docs_readline() {
local var=$1
local -n value=$var
while true; do
read $var || return
value=${value##[ \t]}
[ "$value" ] || continue
if [ "${value#\#}" != "$value" ]; then
value=${value#\#}
elif echo "$value" | grep -q '^[a-z0-9_]+() '; then
value="${value%%()*}()"
elif echo "$value" | grep -q '^[a-z0-9_]+='; then
value="\$${value%%=*}"
else
continue
fi
value=${value##[ \t\n]}
break
done
}
docs_gen_lines() {
[ ${#docs_lines[*]} -gt 0 ] || return 0
local IFS=$'\n'
echo "${docs_lines[*]}"
echo
docs_lines=()
}
######
# Package Reference Documentation
package_docs_ref_clean() { run rm -rf "$package_docs_refdir"; }
docs_gen_files() {
local -a files=( "$@" )
[ "$*" ] || docs_file_list files src conf libs
run_mkdir "$package_docs_refdir"
for_each docs_gen_file "${files[@]}"
}
docs_gen_file() {
local file=$1
local base=${name%.in}
local out=$(docs_filename "$package_docs_refdir" "$file" rst)
file_mkdir "$out"
local ext=''
[ "${file/conf\//}" != "$file" ] || ext='.sh'
local in="$package_gendir/${file/src\//bin\/}$ext"
local name=${file#*/}
info "$name: generating documentation..."
if ! docs_gen_file_body "$file" <"$in" >"$out"; then
error "$name: error generating documentation"
fi
}
######
# Source File Processing
docs_gen_file_body() {
local file=$1
local name=${file#*/}
local line
docs_readline line
if [ "!/bin/bash" = "$line" ]; then
# discard shebang line, read next
docs_readline line
else
warn "$name: $line: first line should be a shebang"
fi
docs_gen_file_title "$line"
local docs_cur_state=sec
local -a docs_lines
docs_gen_file_header "$name"
docs_gen_file_deps "$file"
docs_gen_file_sections "$name"
}
docs_gen_file_title() {
local line=$1
local title=${line% - *}
local desc=${line#* - }
rst_title "$name" "$desc"
}
docs_gen_file_header() {
local name=$1
local line
while docs_readline line; do
if ! is_docs_section "$line"; then
docs_lines+=( "$line" )
continue
fi
if [ "${docs_lines[*]}" ]; then
rst_h1 "File Description"
docs_gen_lines
fi
docs_cur_state='sec'
break
done
}
docs_gen_file_deps() {
local file=$1
local dotfile=$(docs_filename "$package_docs_refdir" "$file" deps.svg)
# [ -s "$dotfile" ] || return 0
local name=${file#*/}
local base=${file##*/}
local dot="$base.deps.dot"
local svg="$base.deps.svg"
local pdf="$base.deps.pdf"
local rst="$base.rst"
local raw="$base.raw.html"
cat <<DEPS
.. figure:: $svg
:align: right
:alt: Dependency Graph
:width: 100%
$(rst_literal "$name"): Library Dependencies
DEPS
if [ -s "$dotfile" ]; then
cat <<GRAPH
View the full-size SVG (svg_) or PDF (pdf_) image or
graphviz source (dot_)
.. _svg: $svg
.. _pdf: $pdf
.. _dot: $dot
GRAPH
fi
cat <<RST
View color source code (raw_) for this file
.. _raw: $raw
View reStructuredText (rst_) source code for this page
.. _rst: $rst
RST
}
######
# Sections/Symbols/Arguments
docs_gen_file_sections() {
local name=$1
local docs_cur_section
local docs_cur_symbol
local line
while docs_readline line; do
case "$docs_cur_state" in
(top)
docs_gen_lines
if is_docs_section "$line"; then
docs_cur_section=''
docs_cur_symbol=''
docs_cur_state='sec'
elif is_docs_arg "$line"; then
docs_gen_file_sym_arg "$line"
elif is_docs_symbol "$line"; then
docs_gen_file_sym "$line"
docs_cur_symbol="$line"
elif [ "$docs_cur_section" ]; then
line=$(rst_trim "$line")
docs_lines+=( "$line" )
elif [ "$line" ]; then
warn "ignoring: $line"
fi
;;
(sec)
line=$(rst_trim "$line")
docs_gen_file_section 2 "$line"
docs_cur_section=$line
docs_cur_state='top'
;;
(*)
error "$state: unknown generator state"
;;
esac
done
}
docs_gen_file_section() {
min_args 2 "$@"
local level=$1
local title=$2
local desc=$3
title=$(rst_trim "$title")
rst_header_n $level "$title"
desc=$(rst_trim "$desc")
if [ "$desc" ]; then
rst_reflow "$desc"
echo
fi
}
docs_gen_file_sym() { docs_gen_file_section 3 "${1%% - *}" "${1#* - }"; }
docs_gen_file_sym_arg() {
echo "- **${1%% - *}** ${1#* - }"
echo
}
######
# HTML Documentation
docs_gen_html_files() {
local -a files=( "$@" )
[ "$*" ] || docs_file_list files libs src conf
for_each docs_gen_html_file "${files[@]}"
}
docs_gen_html_file() {
local file=$1
local base=${file%.sh}
local rst=$(docs_filename "$package_docs_refdir" "$base" rst)
local tmp
tmp=$(cmd_tempfile)
{
docs_rst_to_html "$rst"
echo
docs_gen_html_ref_footer
} >"$tmp"
local html=$(docs_filename "$package_docs_refdir" "$base" html)
run mv "$tmp" "$html"
}
Generated on Tue Apr 25 21:20:28 PDT 2017 by mcsh i7 v0.18.0.