[m-rev.] for review: Generate better man pages.

Peter Wang novalazy at gmail.com
Mon May 27 14:50:02 AEST 2019


doc/make_manpage:
    Replace the old script with a new version written in awk.

    The new output should be an improvement in these ways:
      - works for tools that use spaces for indentation instead of tabs
      - uses .TP for indenting text instead of monospace text with
        inconsistent leading spaces
      - option names are in bold
      - removes redundant blank lines

doc/Mmakefile:
    Adjust command line to call the new make_manpage script.

profiler/mercury_profile.m:
    Add "Name:" line to --help output for make_manpage to read.

scripts/mtags.in:
    Add "Name:" line to --help output for make_manpage to read.

    Delete initial blank line in help and usage text.

    Delete stray full stop.

scripts/mprof_merge_runs:
scripts/parse_ml_options.sh-subr.in:
    Simplify --help text for make_manpage.
---
 doc/Mmakefile                       |   3 +-
 doc/make_manpage                    | 269 +++++++++++++++++-----------
 profiler/mercury_profile.m          |  13 +-
 scripts/mprof_merge_runs            |  17 +-
 scripts/mtags.in                    |  10 +-
 scripts/parse_ml_options.sh-subr.in |  13 +-
 6 files changed, 193 insertions(+), 132 deletions(-)

diff --git a/doc/Mmakefile b/doc/Mmakefile
index 815e16270..1f347fd32 100644
--- a/doc/Mmakefile
+++ b/doc/Mmakefile
@@ -97,7 +97,8 @@ M_ENV = \
 	MCFLAGS=--no-mercury-stdlib-dir
 
 %.1: ../scripts/% make_manpage
-	$(M_ENV) ./make_manpage $< > $@
+	$(M_ENV) $< --help 2>&1 | \
+		awk -f make_manpage -v date=$(shell date "+%Y-%m-%d") > $@
 
 %.man: %.1
 	nroff -man $< > $@
diff --git a/doc/make_manpage b/doc/make_manpage
index 2b2b85cc4..a67dd610b 100755
--- a/doc/make_manpage
+++ b/doc/make_manpage
@@ -1,117 +1,178 @@
-#!/bin/sh
+#!/usr/bin/awk -f
 #-----------------------------------------------------------------------------#
-# Copyright (C) 1997-1998, 2002, 2006 The University of Melbourne. 
+# Copyright (C) 1997-1998, 2002, 2006 The University of Melbourne.
+# Copyright (C) 2019 The Mercury team.
 # This file may only be copied under the terms of the GNU General
 # Public Licence - see the file COPYING in the Mercury distribution.
 #-----------------------------------------------------------------------------#
 #
 # make_manpage: create Unix man page from help message.
 #
-# Usage: make_manpage <program>
+# Usage: <program> --help | awk -f make_manpage
 #
 # This file takes the output of `<program> --help'
 # and turns it into a Unix-style man page by
 # massaging it a bit and inserting some extra stuff that is
 # the same for all the Mercury man pages.
 
-# Section headings must match /[\/A-Za-z ]*:/.
-# We insert the `.SH' command for them,
-# convert them to uppercase, delete the ":",
-# and replace "USAGE" with "SYNOPSIS".
-
-# Section sub-headings start with spaces.
-# We insert the `.SH' command for them.
-
-# Option headings start with a tab and then a `-'.
-# We put them in bold, and indent them differently.
-
-# Each line of the main text must start with a tab.
-# We change the tab to "\&".
-
-# NOTE: some of the sed expressions below occur on very long lines.
-# This is deliberate, BSD sed has problems handling line continuations in some
-# cases.
-
-program="$1"
-name="`basename $program `"
-
-trap 'rm -f /tmp/make_manpage$$' 1 2 3 13 15
-$program --help 2>&1 \
-	| sed	\
-		-e '/^[\/A-Za-z ]*:[ 	]/s//.SH "&"\
-/'			\
-		-e '/^[\/A-Za-z ]*:/s//.SH "&"\
-/'			\
-		-e '/^ .*/s//.SH "&"\
-/'			\
-		-e '/^	[^-	].*:/s/^	.*$/	.Ve\
-.B\
-.Vb 1\
-\\\& &\
-.Ve\
-.Vb 2/' 					\
-		-e '/^	-/s/^	.*$/	.Ve\
-.B\
-.Vb 1\
-\\\& &\
-.Ve\
-.Vb 2/' 					\
-		-e 's/\\& 	/\\\& /' \
-		-e 's/^		/	\\\&	/g' 	\
-		-e 's/^	//' \
-	| sed	\
-		-e '/^.SH "[\/A-Za-z ]*:[ 	]*"/y/abcdefghijklmnopqrstuvwxyz:/ABCDEFGHIJKLMNOPQRSTUVWXYZ /' \
-		-e 's/^.SH "USAGE[ 	]*"/.SH "SYNOPSIS"/' \
-	> /tmp/make_manpage$$ 
-manpage="`cat /tmp/make_manpage$$`"
-rm -f /tmp/make_manpage$$
-uppername="$name"
-
-if echo "$manpage" | grep '^.SH "ARGUMENTS' > /dev/null; then
-	first_half="`echo \"$manpage\" | sed '/^.SH \"ARGUMENTS *\"/,$d'`"
-	last_half="`echo \"$manpage\" | sed -n '/^.SH \"ARGUMENTS *\"/,$p'`"
-else
-	first_half="`echo \"$manpage\" | sed '/^.SH \"OPTIONS *\"/,$d'`"
-	last_half="`echo \"$manpage\" | sed -n '/^.SH \"OPTIONS *\"/,$p'`"
-fi
-
-cat <<EOF
-.de Vb
-.nf
-.ne \\\$1
-..
-.de Ve
-
-.fi
-..
-.TH $uppername 1 "`date`" "" "Mercury Programmer's Manual"
-.AT 3
-.Vb 2
-$first_half
-.fi
-.SH NOTES
-.I $name
-is one of the development tools
-that are part of the Mercury distribution.
-.PP
-This manual page is limited to a brief summary.
-For further information see the Mercury User's Guide.
-.Vb 2
-$last_half
-.fi
-.SH AUTHORS
-The Mercury team.
-.P
-See <http://www.mercurylang.org/contact/people.html>.
-.SH COPYRIGHT
-This program and its documentation are copyright by the University of Melbourne.
-They may be copied only under the terms of the GNU General Public License \-
-see the file COPYING in the Mercury distribution.
-.SH "SEE ALSO"
-<http://www.mercurylang.org/information/documentation.html>
-.P
-The Mercury User's Guide.
-.P
-The GNU General Public License.
-.ex
-EOF
+# Strip leading whitespace.
+function lstrip(s) {
+    sub(/^[\t ]+/, "", s)
+    return s
+}
+
+# Replace tabs with spaces.
+function replace_tabs(s) {
+    gsub(/\t/, " ", s)
+    return s
+}
+
+# Escape characters (add as required).
+function escape(s) {
+    gsub(/\\/, "\\\\", s)
+    gsub(/-/, "\\-", s)
+    return s
+}
+
+# Add a section adding to global variable `accum'.
+function accum_sh(section) {
+    accum = accum ".SH " escape(toupper(section)) "\n"
+    held_blank = 0
+}
+
+# Add some text into global variable `accum'.
+function accum_text(line) {
+    if (line == "") {
+        held_blank = 1
+        return
+    }
+    if (line ~ /^Copyright \(C\) /) {
+        held_blank = 1
+    }
+    if (held_blank) {
+        accum = accum "\n"
+        held_blank = 0
+    }
+    accum = accum escape(line) "\n"
+}
+
+BEGIN {
+    name = ""       # program name
+    accum = "\n"    # initial newline required for some reason
+    have_notes = 0  # have output the NOTES section
+    held_blank = 0  # preceding blank line deferred
+}
+
+# Single-word section heading with trailing text, e.g.
+#   Name: foo
+#   Usage: foo [options]
+/^[A-Z][a-z]*:[\t ]/ {
+    section = $1
+    sub(/:$/, "", section)
+    if (section == "Name" && !name) {
+        name = $2
+    }
+    if (section == "Usage") {
+        section = "Synopsis"
+    }
+    accum_sh(section)
+
+    text = $0
+    gsub(/^.*:[\t ]/, "", text)
+    accum_text(lstrip(text))
+    next
+}
+
+# Add a NOTES section before ARGUMENTS or OPTIONS.
+!have_notes && /Arguments:|Options:/ {
+    accum_sh("NOTES")
+    accum_text(".I " name)
+    accum_text("is one of the development tools")
+    accum_text("that are part of the Mercury distribution.")
+    accum_text(".PP")
+    accum_text("This manual page is limited to a brief summary.")
+    accum_text("For further information see the Mercury User's Guide.")
+    have_notes = 1
+}
+
+# Section heading without trailing text, e.g.
+#   Options:
+#   Environment variables:
+/^[A-Z][\/A-Za-z ]*:$/ {
+    section = $0
+    sub(/:.*$/, "", section)
+
+    # Stop early for mercury_config at "Configure options".
+    if (name == "mercury_config" && section == "Configure options") {
+        exit
+    }
+
+    accum_sh(section)
+    next
+}
+
+# Options, e.g.
+#   -f, --foo
+#   --foo-bar:
+/^(    |\t)-/ {
+    line = lstrip($0)
+    sub(/:$/, "", line)
+    # Remove tab alignment in mmc --help
+    line = replace_tabs(line)
+    accum = accum ".TP\n"
+    accum = accum ".B " escape(line) "\n"
+    held_blank = 0
+    next
+}
+
+# Special case for mmake targets, e.g.
+#   <module>.depend:
+#   clean:
+name == "mmake" && section == "Targets" && /^\t.*:$/ {
+    line = lstrip($0)
+    sub(/:$/, "", line)
+    accum = accum ".TP\n"
+    accum = accum ".B " escape(line) "\n"
+    held_blank = 0
+    next
+}
+
+# Special case for mprof_merge_runs usage text.
+# (This could be extended to other "verbatim" text.)
+name == "mprof_merge_runs" && section == "Usage" && /^\t\t./ {
+    accum = accum "\n.nf\n"     # no-fill mode
+    accum = accum "\\&\t" escape(lstrip($0)) "\n"
+    accum = accum ".fi\n"       # fill mode
+    held_blank = 0
+    next
+}
+
+# Main text.
+{
+    accum_text(lstrip($0))
+}
+
+END {
+    # The date is passed in by Mmakefile as not all awk implementations support
+    # strftime().
+    if (!date) {
+        date = strftime("%Y-%m-%d")
+    }
+    manual = "Mercury Programmer's Manual"
+    printf ".TH %s 1 \"%s\" \"\" \"%s\"", toupper(name), date, manual
+    # Squeeze verbatim lines.
+    gsub(/\.fi\n\n\.nf\n/, "", accum)
+    printf "%s", accum
+    print ".SH AUTHORS"
+    print "The Mercury team."
+    print ".SH COPYRIGHT"
+    print "This program and its documentation are copyright by"
+    print "the University of Melbourne and the Mercury team."
+    print "They may be copied only under the terms of the"
+    print "GNU General Public License \\-"
+    print "see the file COPYING in the Mercury distribution."
+    print ".SH SEE ALSO"
+    print "The Mercury User's Guide."
+    print ".PP"
+    print "<http://www.mercurylang.org/information/documentation.html>"
+}
diff --git a/profiler/mercury_profile.m b/profiler/mercury_profile.m
index 676b12404..6540acf16 100644
--- a/profiler/mercury_profile.m
+++ b/profiler/mercury_profile.m
@@ -108,12 +108,12 @@ usage(!IO) :-
     io.stderr_stream(StdErr, !IO),
     library.version(Version, Fullarch),
     io.write_strings(StdErr, [
-        "Mercury Profiler, version ", Version, ", on ", Fullarch, ".\n",
+        "mprof - Mercury profiler, version ", Version, ", on ", Fullarch, "\n",
         "Copyright (C) 1995-2012 The University of Melbourne\n",
         "Copyright (C) 2013-2019 The Mercury team\n",
-            "Usage: ", ProgName, " [<options>] [<files>]\n",
-            "Use `", ProgName, " --help' for more information.\n"
-        ], !IO).
+        "Usage: ", ProgName, " [<options>] [<files>]\n",
+        "Use `", ProgName, " --help' for more information.\n"
+    ], !IO).
 
 :- pred long_usage(io::di, io::uo) is det.
 
@@ -121,10 +121,11 @@ long_usage(!IO) :-
     io.progname_base("mprof", ProgName, !IO),
     library.version(Version, Fullarch),
     io.write_strings([
-        "Mercury Profiler, version ", Version, ", on ", Fullarch, ".\n",
+        "Name: mprof - Mercury profiler, version ", Version, ", on ",
+        Fullarch, "\n",
         "Copyright (C) 1995-2012 The University of Melbourne\n",
         "Copyright (C) 2013-2019 The Mercury team\n\n",
-            "Usage: ", ProgName, " [<options>] [<files>]\n",
+        "Usage: ", ProgName, " [<options>] [<files>]\n",
         "\n",
         "Description:\n",
         "\t`mprof' produces execution profiles for Mercury programs.\n",
diff --git a/scripts/mprof_merge_runs b/scripts/mprof_merge_runs
index 8f47e88f2..33c54daa1 100755
--- a/scripts/mprof_merge_runs
+++ b/scripts/mprof_merge_runs
@@ -12,7 +12,7 @@
 # Usage: see below.
 
 Help="\
-Name: mprof_merge_runs - Mercury Profiling utility
+Name: mprof_merge_runs - Mercury profiling utility
 
 Description:
 	mprof_merge_runs merges the profiling data from different
@@ -21,7 +21,7 @@ Description:
 Usage:
 	First, compile with profiling enabled:
 
-		mmc --profiling my_program	
+		mmc --profiling my_program
 
 	Then, collect the profiling data:
 
@@ -36,14 +36,13 @@ Usage:
 
 		mprof -c | more
 
-	Note:
-		If you just want to run your program N times with
-		the same arguments, a simpler way of achieving this
-		is to instead use the \`-r<N>' (\"repeat N times\")
-		option to the Mercury runtime, which you can pass by
-		setting the environment variable MERCURY_OPTIONS, e.g.
+	Note: If you just want to run your program N times with
+	the same arguments, a simpler way of achieving this
+	is to instead use the \`-r<N>' (\"repeat N times\")
+	option to the Mercury runtime, which you can pass by
+	setting the environment variable MERCURY_OPTIONS, e.g.
 
-			env MERCURY_OPTIONS="-r100" ./my_program
+		env MERCURY_OPTIONS=-r100 ./my_program
 
 Options:
 	-h, --help
diff --git a/scripts/mtags.in b/scripts/mtags.in
index 2f4bbe1aa..127ab6e59 100755
--- a/scripts/mtags.in
+++ b/scripts/mtags.in
@@ -6,11 +6,13 @@
 # Public License - see the file COPYING in the Mercury distribution.
 #---------------------------------------------------------------------------#
 
-$usage = "\
-Usage: mtags [<options>] <source files>
+$usage =
+"Usage: mtags [<options>] <source files>
 Use \`mtags --help' for help.";
 
-$help = "\
+$help =
+"Name: mtags - generate tag files for Mercury source code
+
 Usage:
     mtags [<options>] <source files>
 
@@ -73,7 +75,7 @@ Options:
         This option is the default, but is retained for
         backwards compatibility.
 
-    --no-keep-duplicates.
+    --no-keep-duplicates
         If a tag has multiple definitions, ignore all but the
         first.  Also ignores typeclass instance tags.
 
diff --git a/scripts/parse_ml_options.sh-subr.in b/scripts/parse_ml_options.sh-subr.in
index 8c5201dc3..4c8e8d3ca 100644
--- a/scripts/parse_ml_options.sh-subr.in
+++ b/scripts/parse_ml_options.sh-subr.in
@@ -113,14 +113,11 @@ Diagnostics options:
 Dynamic/static linking options:
 	--mercury-libs {shared, static, none}
 		Specify which version of the standard Mercury libraries to
-		link with:
-			--mercury-libs shared
-				Link with the shared libraries (*.so),
-				if possible, otherwise with the static ones.
-			--mercury-libs static
-				Link with the static libraries (*. at LIB_SUFFIX@).
-			--mercury-libs none
-				Don't link in the Mercury standard libraries.
+		link with.
+		\`shared' links with the shared libraries (*.so) if possible,
+		otherwise with the static ones.
+		\`static' links with the static libraries (*.a).
+		\`none' disables linking with the Mercury standard libraries.
 	-shared, --shared
 		Similar to \`--mercury-libs shared', but applies to all
 		libraries, not just the standard Mercury libraries.
-- 
2.21.0



More information about the reviews mailing list