2 # Copyright © 2014 Géraud Meyer <graud@gmx.com>
4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License version 2 as published by the
6 # Free Software Foundation.
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 # You should have received a copy of the GNU General Public License along with
14 # this program. If not, see <http://www.gnu.org/licenses/>.
16 PROGRAM_NAME
="helpm4sh"
20 # helpm4sh - extract embedded HelpMessage/POD from sh scripts
22 # helpm4sh [--] <format>[-] [<file>]
28 -V|
--version) echo "$PROGRAM_NAME version $PROGRAM_VERSION"; exit ;;
29 --?
*) echo >&2 "$PROGRAM_NAME: error: invalid option"; exit 255 ;;
35 then echo >&2 "$PROGRAM_NAME: error: missing format argument"; exit 255
39 then echo >&2 "$PROGRAM_NAME: error: too many arguments"; exit 255
41 if [ $# -gt 0 ] && expr "$1" : '[a-zA-Z_][a-zA-Z_0-9]*=' >/dev
/null
45 awk -v PROGRAM_NAME
="$PROGRAM_NAME" -v FORMAT
="$FORMAT" '
47 if (sub(/-$/,"", FORMAT))
51 if (tolower(FORMAT) ~ /^help(m|message)$|^hm$/) {
52 FORMAT = "HelpMessage"
53 start = "_*(HelpM|helpm|HELPM)(essage)*"
55 else if (tolower(FORMAT) ~ /^pod$/) {
60 print PROGRAM_NAME ": error: unknown format", FORMAT > "/dev/fd/2"
63 block = 0; dynamic = 0
66 $0 ~ "<< *\"" start "\"$" && block <= 0 {
68 end = $0; sub(/^.*<< *"/,"^",end); sub(/"$/,"",end)
69 if (/^[ \t]*#/) com = 1; else com = 0
70 if (com) sub(/^\^/,"^[ \t]*#",end)
74 sub("<< *\"" start "\"$","</dev/null")
79 $0 ~ end && block > 0 {
85 if (com) sub(/^[ \t]*#/,"")
88 # outside of any block
90 if ($0 ~ "<< *" start " *$") dynamic++
94 print PROGRAM_NAME ":", (block < 0 ? -block : block), \
95 "blocks of " FORMAT " extracted" > "/dev/fd/2"
97 print PROGRAM_NAME ": warning:", dynamic " dynamic blocks detected"
100 if (block == 0) exit 1
105 # helpm4sh extracts constant help messages from the given <file>, or from
106 # standard input if <file> is a dash or is not given. If <format> is
107 # *helpm*, embedded HelpMessage blocks are extracted. The blocks can be
108 # either here documents starting by a line matching the regular expression
109 # C< << *"_*(HELPM|HelpM|helpm)(essage)?"$>, or be similar here documents in
112 # If <format> is *pod*, then here documents (or here documents in comments)
113 # delimited by "=cut" are extracted.
115 # If a dash is appended to <format>, then the here documents are stripped.
117 # If no blocks are found or if "dynamic" blocks (whose delimiter is unquoted)
118 # are detected, the return status is non zero.
120 # This manual page can be extracted from the script itself:
121 # $ helpm4sh helpm $(where helpm4sh) | helpm2man - HELPM4SH.1
123 # helpm4sh was written by G.raud Meyer.
125 # helpmessage(5), perlpod(1)