|
|
e0018b |
From 706a418798633ccb550b114eca7cc11038ab2695 Mon Sep 17 00:00:00 2001
|
|
|
e0018b |
From: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
e0018b |
Date: Tue, 14 Dec 2021 19:01:02 -0700
|
|
|
e0018b |
Subject: [PATCH 048/217] scripts: Add a man page template generator
|
|
|
e0018b |
|
|
|
e0018b |
Add a script to generate man page templates for the utils and libraries
|
|
|
e0018b |
under ndctl - including cxl, libcxl, ndctl, and daxctl.
|
|
|
e0018b |
|
|
|
e0018b |
The script can control certain include options depending on the options
|
|
|
e0018b |
supplied, and either dump the templates to stdout, or write the actual
|
|
|
e0018b |
files in their eventual directories, and open up an editor to further
|
|
|
e0018b |
edit them (unless --no-edit is used).
|
|
|
e0018b |
|
|
|
e0018b |
Link: https://lore.kernel.org/r/20211215020102.97880-1-vishal.l.verma@intel.com
|
|
|
e0018b |
Cc: Dan Williams <dan.j.williams@intel.com>
|
|
|
e0018b |
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
e0018b |
---
|
|
|
e0018b |
scripts/docsurgeon | 339 +++++++++++++++++++++++++
|
|
|
e0018b |
scripts/docsurgeon_parser_generator.m4 | 23 ++
|
|
|
e0018b |
2 files changed, 362 insertions(+)
|
|
|
e0018b |
create mode 100755 scripts/docsurgeon
|
|
|
e0018b |
create mode 100644 scripts/docsurgeon_parser_generator.m4
|
|
|
e0018b |
|
|
|
e0018b |
diff --git a/scripts/docsurgeon b/scripts/docsurgeon
|
|
|
e0018b |
new file mode 100755
|
|
|
e0018b |
index 0000000..ca0ad78
|
|
|
e0018b |
--- /dev/null
|
|
|
e0018b |
+++ b/scripts/docsurgeon
|
|
|
e0018b |
@@ -0,0 +1,339 @@
|
|
|
e0018b |
+#!/bin/bash -eE
|
|
|
e0018b |
+
|
|
|
e0018b |
+this_script="docsurgeon"
|
|
|
e0018b |
+script_dir="$(cd "$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")" && pwd)"
|
|
|
e0018b |
+env_file="${script_dir}/.env"
|
|
|
e0018b |
+if [ -e "$env_file" ]; then
|
|
|
e0018b |
+ # shellcheck source=.env
|
|
|
e0018b |
+ . "$env_file"
|
|
|
e0018b |
+fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+sources_file="${script_dir}/.sources"
|
|
|
e0018b |
+
|
|
|
e0018b |
+parser_generator="${script_dir}/${this_script}_parser_generator.m4"
|
|
|
e0018b |
+parser_lib="${script_dir}/${this_script}_parser.sh"
|
|
|
e0018b |
+if [ ! -e "$parser_lib" ] || [ "$parser_generator" -nt "$parser_lib" ]; then
|
|
|
e0018b |
+ if command -V argbash > /dev/null; then
|
|
|
e0018b |
+ argbash --strip user-content "$parser_generator" -o "$parser_lib"
|
|
|
e0018b |
+ else
|
|
|
e0018b |
+ echo "error: please install argbash" >&2
|
|
|
e0018b |
+ exit 1
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+if [[ $1 != "bin" ]]; then
|
|
|
e0018b |
+ # shellcheck source=docsurgeon_parser.sh
|
|
|
e0018b |
+ . "${script_dir}/${this_script}_parser.sh" || { echo "Couldn't find $parser_lib" >&2; exit 1; }
|
|
|
e0018b |
+fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+# some script defaults - override using '.env'
|
|
|
e0018b |
+docbase="Documentation"
|
|
|
e0018b |
+copyright_cli="// SPDX-License-Identifier: GPL-2.0"
|
|
|
e0018b |
+copyright_footer_cli="include::../copyright.txt[]"
|
|
|
e0018b |
+copyright_lib="// SPDX-License-Identifier: LGPL-2.0"
|
|
|
e0018b |
+copyright_footer_lib="include::../../copyright.txt[]"
|
|
|
e0018b |
+
|
|
|
e0018b |
+# List of files we're creating, to be edited/renamed later
|
|
|
e0018b |
+# This starts out blank, and is filled in as we go by gen_*() functions
|
|
|
e0018b |
+declare -a outfiles
|
|
|
e0018b |
+
|
|
|
e0018b |
+cleanup()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ if [ ${#outfiles[@]} -gt 0 ]; then
|
|
|
e0018b |
+ rm -f "${outfiles[@]}"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ set +x
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+trap cleanup EXIT
|
|
|
e0018b |
+
|
|
|
e0018b |
+auto_detect_params()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ fs=""
|
|
|
e0018b |
+ module=""
|
|
|
e0018b |
+ section=""
|
|
|
e0018b |
+
|
|
|
e0018b |
+ # if module and section were explicitly specified, respect them
|
|
|
e0018b |
+ if [[ $_arg_module ]] && [[ $_arg_section ]]; then
|
|
|
e0018b |
+ return
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+ # check if names are self-consistent, and determine 'fs'
|
|
|
e0018b |
+ for name in ${_arg_name[@]}; do
|
|
|
e0018b |
+ if [[ ! $fs ]]; then
|
|
|
e0018b |
+ if [[ $name == *-* ]]; then
|
|
|
e0018b |
+ fs="-"
|
|
|
e0018b |
+ elif [[ $name == *_* ]]; then
|
|
|
e0018b |
+ fs="_"
|
|
|
e0018b |
+ else
|
|
|
e0018b |
+ # can't autodetect section
|
|
|
e0018b |
+ return
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ if [[ $fs == "-" ]] && [[ $name == *_* ]]; then
|
|
|
e0018b |
+ die "can't auto-detect params with mixed-style names"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ if [[ $fs == "_" ]] && [[ $name == *-* ]]; then
|
|
|
e0018b |
+ die "can't auto-detect params with mixed-style names"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ done
|
|
|
e0018b |
+
|
|
|
e0018b |
+ # try to detect module name
|
|
|
e0018b |
+ for name in ${_arg_name[@]}; do
|
|
|
e0018b |
+ str=${name%%$fs*}
|
|
|
e0018b |
+ if [[ $module ]]; then
|
|
|
e0018b |
+ if [[ $str != $module ]]; then
|
|
|
e0018b |
+ die "Can't autodetect module because of mixed names ($str and $module)"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ else
|
|
|
e0018b |
+ module="$str"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ done
|
|
|
e0018b |
+
|
|
|
e0018b |
+ # try to detect section number
|
|
|
e0018b |
+ case "$fs" in
|
|
|
e0018b |
+ -)
|
|
|
e0018b |
+ section=1
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ _)
|
|
|
e0018b |
+ section=3
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ *)
|
|
|
e0018b |
+ die "Unknown fs, can't autodetect section number"
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ esac
|
|
|
e0018b |
+
|
|
|
e0018b |
+ if [[ $module ]]; then
|
|
|
e0018b |
+ _arg_module="$module"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ if [[ $section ]]; then
|
|
|
e0018b |
+ _arg_section="$section"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+process_options_logic()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ if [[ $_arg_debug == "on" ]]; then
|
|
|
e0018b |
+ set -x
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+ auto_detect_params
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_underline()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+ char="$2"
|
|
|
e0018b |
+ num="${#name}"
|
|
|
e0018b |
+
|
|
|
e0018b |
+ printf -v tmpstring "%-${num}s" " "
|
|
|
e0018b |
+ echo "${tmpstring// /$char}"
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_header()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ printf "\n%s\n%s\n" "$1" "$(gen_underline "$1" "=")"
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ printf "\n%s\n%s\n" "$1" "$(gen_underline "$1" "-")"
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_name()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+
|
|
|
e0018b |
+ gen_section "NAME"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ $name -
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_synopsis_1()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+
|
|
|
e0018b |
+ gen_section "SYNOPSIS"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ [verse]
|
|
|
e0018b |
+ '$_arg_module ${name#*-} [<options>]'
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_synopsis_3()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+
|
|
|
e0018b |
+ gen_section "SYNOPSIS"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ [verse]
|
|
|
e0018b |
+ ----
|
|
|
e0018b |
+ #include <$_arg_module/lib$_arg_module.h>
|
|
|
e0018b |
+
|
|
|
e0018b |
+ <type> $name();
|
|
|
e0018b |
+ ----
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_example_1()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+
|
|
|
e0018b |
+ gen_section "EXAMPLE"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ ----
|
|
|
e0018b |
+ # $_arg_module ${name#*-}
|
|
|
e0018b |
+ ----
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_example_3()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+
|
|
|
e0018b |
+ gen_section "EXAMPLE"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ See example usage in test/lib$_arg_module.c
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_options_1()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ gen_section "OPTIONS"
|
|
|
e0018b |
+cat << EOF
|
|
|
e0018b |
+-o::
|
|
|
e0018b |
+--option::
|
|
|
e0018b |
+ Description
|
|
|
e0018b |
+EOF
|
|
|
e0018b |
+
|
|
|
e0018b |
+ if [[ $_arg_human_option == "on" ]]; then
|
|
|
e0018b |
+ printf "\n%s\n" "include::human-option.txt[]"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+ if [[ $_arg_verbose_option == "on" ]]; then
|
|
|
e0018b |
+ printf "\n%s\n" "include::verbose-option.txt[]"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_seealso_1()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ gen_section "SEE ALSO"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ link$_arg_module:$_arg_module-list[$_arg_section],
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_section_seealso_3()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ gen_section "SEE ALSO"
|
|
|
e0018b |
+ cat <<- EOF
|
|
|
e0018b |
+ linklib$_arg_module:${_arg_module}_other_API[$_arg_section],
|
|
|
e0018b |
+ EOF
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_cli()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+ path="$docbase/$_arg_module"
|
|
|
e0018b |
+ if [ ! -d "$path" ]; then
|
|
|
e0018b |
+ die "Not found: $path"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+ tmp="$(mktemp -p "$path" "$name.txt.XXXX")"
|
|
|
e0018b |
+ outfiles+=("$tmp")
|
|
|
e0018b |
+
|
|
|
e0018b |
+ # Start template generation
|
|
|
e0018b |
+ printf "%s\n" "$copyright_cli" > "$tmp"
|
|
|
e0018b |
+ gen_header "$name" >> "$tmp"
|
|
|
e0018b |
+ gen_section_name "$name" >> "$tmp"
|
|
|
e0018b |
+ gen_section_synopsis_1 "$name" >> "$tmp"
|
|
|
e0018b |
+ gen_section "DESCRIPTION" >> "$tmp"
|
|
|
e0018b |
+ gen_section_example_1 "$name" >> "$tmp"
|
|
|
e0018b |
+ gen_section_options_1 >> "$tmp"
|
|
|
e0018b |
+ printf "\n%s\n" "$copyright_footer_cli" >> "$tmp"
|
|
|
e0018b |
+ gen_section_seealso_1 >> "$tmp"
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_lib()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+ path="$docbase/$_arg_module/lib"
|
|
|
e0018b |
+ if [ ! -d "$path" ]; then
|
|
|
e0018b |
+ die "Not found: $path"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+ tmp="$(mktemp -p "$path" "$name.txt.XXXX")"
|
|
|
e0018b |
+ outfiles+=("$tmp")
|
|
|
e0018b |
+
|
|
|
e0018b |
+ # Start template generation
|
|
|
e0018b |
+ printf "%s\n" "$copyright_lib" > "$tmp"
|
|
|
e0018b |
+ gen_header "$name($_arg_section)" >> "$tmp"
|
|
|
e0018b |
+ gen_section_name "$name" >> "$tmp"
|
|
|
e0018b |
+ gen_section_synopsis_3 "$name" >> "$tmp"
|
|
|
e0018b |
+ gen_section "DESCRIPTION" >> "$tmp"
|
|
|
e0018b |
+ gen_section "RETURN VALUE" >> "$tmp"
|
|
|
e0018b |
+ gen_section_example_3 "$name" >> "$tmp"
|
|
|
e0018b |
+ printf "\n%s\n" "$copyright_footer_lib" >> "$tmp"
|
|
|
e0018b |
+ gen_section_seealso_3 >> "$tmp"
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_man()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ name="$1"
|
|
|
e0018b |
+ case "$_arg_section" in
|
|
|
e0018b |
+ 1)
|
|
|
e0018b |
+ gen_cli "$name"
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ 3)
|
|
|
e0018b |
+ gen_lib "$name"
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ *)
|
|
|
e0018b |
+ die "Unknown section: $_arg_section"
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ esac
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+gen_include()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ echo "in gen_include"
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+main()
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ process_options_logic
|
|
|
e0018b |
+
|
|
|
e0018b |
+ cmd="$_arg_command"
|
|
|
e0018b |
+ case "$cmd" in
|
|
|
e0018b |
+ gen-man)
|
|
|
e0018b |
+ for name in ${_arg_name[@]}; do
|
|
|
e0018b |
+ gen_man "$name"
|
|
|
e0018b |
+ done
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ gen-include)
|
|
|
e0018b |
+ for name in ${_arg_name[@]}; do
|
|
|
e0018b |
+ gen_include
|
|
|
e0018b |
+ done
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ *)
|
|
|
e0018b |
+ die "Unknown command: $cmd"
|
|
|
e0018b |
+ ;;
|
|
|
e0018b |
+ esac
|
|
|
e0018b |
+
|
|
|
e0018b |
+ if [[ $_arg_dump == "on" ]]; then
|
|
|
e0018b |
+ for file in ${outfiles[@]}; do
|
|
|
e0018b |
+ echo "${file##*/}"
|
|
|
e0018b |
+ cat "$file"
|
|
|
e0018b |
+ rm "$file"
|
|
|
e0018b |
+ done
|
|
|
e0018b |
+ elif [ ${#outfiles[@]} -gt 0 ]; then
|
|
|
e0018b |
+ if [[ $_arg_edit = "on" ]]; then
|
|
|
e0018b |
+ vim -p "${outfiles[@]}"
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+
|
|
|
e0018b |
+ for file in ${outfiles[@]}; do
|
|
|
e0018b |
+ mv "$file" "${file%.*}"
|
|
|
e0018b |
+ done
|
|
|
e0018b |
+ fi
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+main "$@"
|
|
|
e0018b |
diff --git a/scripts/docsurgeon_parser_generator.m4 b/scripts/docsurgeon_parser_generator.m4
|
|
|
e0018b |
new file mode 100644
|
|
|
e0018b |
index 0000000..9283c7c
|
|
|
e0018b |
--- /dev/null
|
|
|
e0018b |
+++ b/scripts/docsurgeon_parser_generator.m4
|
|
|
e0018b |
@@ -0,0 +1,23 @@
|
|
|
e0018b |
+#!/bin/bash
|
|
|
e0018b |
+
|
|
|
e0018b |
+# m4_ignore(
|
|
|
e0018b |
+echo "This is just a parsing library template, not the library - pass this file to 'argbash' to fix this." >&2
|
|
|
e0018b |
+exit 11 #)Created by argbash-init v2.9.0
|
|
|
e0018b |
+# Rearrange the order of options below according to what you would like to see in the help message.
|
|
|
e0018b |
+# ARG_OPTIONAL_REPEATED([name], [n], [Command or function name to generate a template for.\n Can be repeated for multiple names. ], [])
|
|
|
e0018b |
+# ARG_OPTIONAL_BOOLEAN([edit], [e], [Edit template files after creation], [on])
|
|
|
e0018b |
+# ARG_OPTIONAL_BOOLEAN([debug], [], [Debug script problems (enables set -x)], )
|
|
|
e0018b |
+# ARG_OPTIONAL_BOOLEAN([dump], [], [Write generated file to stdout instead of a file], )
|
|
|
e0018b |
+# ARG_OPTIONAL_SINGLE([module], [m], [Module (Docs subdir) in which to create the template], [])
|
|
|
e0018b |
+# ARG_OPTIONAL_SINGLE([section], [s], [man section for which to create the template], [])
|
|
|
e0018b |
+# ARG_OPTIONAL_BOOLEAN([human-option], [u], [Include the human option in 'OPTIONS'], )
|
|
|
e0018b |
+# ARG_OPTIONAL_BOOLEAN([verbose-option], [V], [Include the verbose option in 'OPTIONS'], )
|
|
|
e0018b |
+# ARG_POSITIONAL_DOUBLEDASH()
|
|
|
e0018b |
+# ARG_POSITIONAL_SINGLE([command], [Operation to perform:\n gen-man\n gen-include], [])
|
|
|
e0018b |
+# ARGBASH_SET_DELIM([ =])
|
|
|
e0018b |
+# ARG_OPTION_STACKING([getopt])
|
|
|
e0018b |
+# ARG_RESTRICT_VALUES([no-local-options])
|
|
|
e0018b |
+# ARG_DEFAULTS_POS
|
|
|
e0018b |
+# ARG_HELP([Tool to aid in creating and managing man page templates])
|
|
|
e0018b |
+# ARG_VERSION([echo "docsurgeon 0.1"])
|
|
|
e0018b |
+# ARGBASH_GO
|
|
|
e0018b |
--
|
|
|
e0018b |
2.27.0
|
|
|
e0018b |
|