chiark / gitweb /
_make-more-docs
authorBen Hutchings <ben@decadent.org.uk>
Tue, 17 Jan 2017 23:57:33 +0000 (23:57 +0000)
committerBen Hutchings <ben@decadent.org.uk>
Tue, 17 Jan 2017 23:57:33 +0000 (23:57 +0000)
Halibut already supports these formats but since the documentation is
all combined we need to do a bit more work to extract the right
information for each game's manual page.

Gbp-Pq: Name 201_make-more-docs.diff

Makefile.doc
mkmanpages.pl [new file with mode: 0644]

index 53e955732a91bed8c970e4489829bf11b13068bd..00436a56ab6b3f4ef60ecee7a233182541e2d8a3 100644 (file)
@@ -14,12 +14,20 @@ puzzles.hhp: puzzles.but chm.but
        halibut --html puzzles.but chm.but
 
 TRANSLATIONS := $(patsubst po/%.po,%,$(wildcard po/*.po))
+LANGUAGES := en $(TRANSLATIONS)
 
 update-po:
 # Please tell me there is an easier way to preserve the POT file header.
        test -f po/puzzles-doc.pot
        po4a-gettextize -f halibut -m puzzles.but --package-name puzzles \
                -p po/puzzles-doc.tmp1.pot
+       awk -F: '{ print ""; \
+                  print "#: " $$1 ".R"; \
+                  print "msgid \"" $$4 "\""; \
+                  print "msgstr \"\""; }' \
+               < gamedesc.txt >> po/puzzles-doc.tmp1.pot
+       xgettext -j -cTranslator: --package-name puzzles \
+               -o po/puzzles-doc.tmp1.pot mkmanpages.pl
        sed -i '1,/^#$$/d' po/puzzles-doc.tmp1.pot
        cat po/puzzles-doc.pot.head po/puzzles-doc.tmp1.pot \
                > po/puzzles-doc.tmp2.pot
@@ -44,6 +52,38 @@ doc/puzzles.txt.%: doc/preprocessed.but.%
        halibut --text=$@ --input-charset=UTF-8 $<
 all: $(addprefix doc/puzzles.txt.,$(TRANSLATIONS))
 
+doc/man-en-stamp: preprocessed.but
+       mkdir -p doc
+       rm -rf doc/man-en
+       mkdir doc/man-en
+       perl mkmanpages.pl en
+       touch $@
+doc/man-%-stamp: doc/preprocessed.but.%
+       mkdir -p doc
+       rm -rf doc/man-$*
+       mkdir doc/man-$*
+       perl mkmanpages.pl $*
+       touch $@
+man: $(patsubst %,doc/man-%-stamp,$(LANGUAGES))
+
+doc/html-en-stamp: preprocessed.but
+       mkdir -p doc
+       rm -rf doc/html-en
+       mkdir doc/html-en
+       cd doc/html-en && halibut --html ../../preprocessed.but
+       touch $@
+doc/html-%-stamp: doc/preprocessed.but.%
+       mkdir -p doc
+       rm -rf doc/html-$*
+       mkdir doc/html-$*
+       cd doc/html-$* && halibut --html --input-charset=UTF-8 ../preprocessed.but.$*
+       touch $@
+html: $(patsubst %,doc/html-%-stamp,$(LANGUAGES))
+
+.PHONY: man html
+all: man html
+
 clean:
        rm -f puzzles.hlp puzzles.txt preprocessed.but HACKING *.html *.hh[pck]
+       rm -f puzzles.cnt
        rm -rf doc
diff --git a/mkmanpages.pl b/mkmanpages.pl
new file mode 100644 (file)
index 0000000..0b56d4c
--- /dev/null
@@ -0,0 +1,157 @@
+#!/usr/bin/perl -w
+
+# Generate manual pages for sgt-puzzles by running extracts of puzzles.but
+# through halibut.
+
+use strict;
+use File::Temp;
+use IO::File;
+use Locale::PO;
+use POSIX ();
+
+my $package = 'sgt-puzzles';
+my $language = $ARGV[0] or die 'mkmanpages.pl: no language specified';
+
+# Fake up gettext without compilation or locales
+my $po_map = Locale::PO->load_file_ashash("po/$language.po");
+sub gettext {
+    my $msgid = shift;
+    my $po = $po_map->{Locale::PO->quote($msgid)};
+    return $po ? Locale::PO->dequote($po->msgstr()) : $msgid;
+}
+
+# Header information
+my $package_roff = $package;
+$package_roff =~ s/-/\\-/g;
+my $date;
+# Translator: conventional name for manual section 6
+my $section = gettext('Games');
+my $section_no = "6";
+my $man_dir = "doc/man-$language";
+
+my %commands;
+my %short_descs;
+my $gamedesc = new IO::File('gamedesc.txt', 'r');
+while (<$gamedesc>) {
+    (my $name, undef, undef, my $desc) = split /:/;
+    $commands{$name} = $ENV{BINPREFIX} . $name;
+    $short_descs{$name} = $desc;
+}
+close $gamedesc;
+
+# We should be able to look these up with strftime('%A') but that
+# requires the relevant locale to be installed on the build host
+my @MONTHS = (gettext('January'), gettext('February'), gettext('March'),
+             gettext('April'),   gettext('May'),      gettext('June'),
+             gettext('July'),    gettext('August'),   gettext('September'),
+             gettext('October'), gettext('November'), gettext('December'));
+
+# Chapter name, initialised to dummy value to capture header
+my $name = '__HEADER__';
+
+# Contents of each chapter/appendix
+my %contents;
+
+# Gather chapters from the original documentation
+my $source_name =
+    $language eq 'en' ? 'preprocessed.but' : "doc/preprocessed.but.$language";
+my $source = new IO::File($source_name, 'r') or die "$source_name: $!";
+while (<$source>) {
+    # Look for chapter/appendix heading
+    if (/^\\[AC]{([^}]+)}\s*/) {
+       $name = $1;
+       # The odd one out - chapter name doesn't match command name
+       if ($name eq 'rectangles') {
+           $name = 'rect';
+       }
+    }
+    # Look for version ID with date
+    if (/^\\versionid .* (\d{4})(\d{2})\d{2}\./) {
+       $date = "${MONTHS[$2-1]} $1";
+    }
+    $contents{$name} .= $_;
+}
+close $source;
+
+# Remove all normal text from the header
+$contents{__HEADER__} =~ s/^(?!\\(?:cfg|define|title){).*$//gm;
+
+# Remove introduction from "common features" chapter
+$contents{common} =~ s/^.*?(?=\\H\{)//s;
+
+for my $short_name (keys %commands) {
+    my $command = $commands{$short_name};
+    print "Generating $command.6\n";
+
+    my $text_name = $language eq 'en' ? 'puzzles.txt' : "puzzles.txt.$language";
+    my $contents =
+      "\\cfg{man-mindepth}{1}\n" # don't show original chapter headings
+      . "\\cfg{man-identity}{".uc($command)."}{$section_no}{$date}{$command ($package_roff)}{$section}\n\n"
+      . "\\cfg{man-charset}{UTF-8}\n" # output encoding
+      . $contents{__HEADER__}
+      . "\\C{man-$command} $command\n\n" # dummy chapter
+      . "\\H{man-$command-name} " . gettext('NAME') . "\n\n"
+      . "\\c{$command} \\- $short_descs{$short_name}\n\n"
+      . "\\H{man-$command-synopsis} " . gettext('SYNOPSIS') . "\n\n"
+      # Translator: abbreviation for 'number'
+      . "\\cw{$command} [\\cw{--generate }\\e{" . gettext('n') . "}]\n"
+      # Translator: abbreviation for 'width'
+      . "[\\cw{--print }\\e{" . gettext('w') . "}\\cw{x}\\e{"
+      # Translator: abbreviation for 'height'
+      . gettext('h') . "} [\\cw{--with-solutions}]\n"
+      . "[\\cw{--scale }\\e{" . gettext('n') . "}] [\\cw{--colour}]]\n"
+      . "[\\e{" . gettext('game-parameters') . "}|\\e{" . gettext('game-ID')
+      . "}|\\e{" . gettext('random-seed') . "}]\n\n"
+      . "\\cw{$command --version}\n\n"
+      . "\\H{man-$command-desc} " . gettext('DESCRIPTION') . "\n\n"
+      . $contents{$short_name}
+      . $contents{common}
+      . "\\H{man-$command-see-also} " . gettext('SEE ALSO') . "\n\n"
+      # Translator: "Full documentation in <filename>."
+      . sprintf(gettext("Full documentation in %s."),
+               "/usr/share/doc/$package/$text_name.gz")
+      . "\n";
+
+    # Kluge cross-references
+    sub replace_ref {
+       my ($above, $target, $below) = @_;
+       # If the target is an earlier or later section in the current page, say
+       # it's above or below.
+       if ($above =~ m/\\(?:[CHA]|S\d*){$target}/) {
+           # Translator: earlier in the manual page
+           gettext('above');
+       } elsif ($below =~ m/\\(?:[CHA]|S\d*){$target}/) {
+           # Translator: later in the manual page
+           gettext('below');
+       }
+       # Else if the target is a bibliographic entry, include the entry directly.
+       elsif ($below =~ m/\\B\{$target\}\s*(.*?)\s*(?:\\(?:[BCHA]|S\d*|$))/s) {
+           "($1)";
+       }
+       # Else if it appears to refer to another game, convert to a customary
+       # cross-manual-page reference.
+       elsif ($target =~ /(\w+)/ && exists $commands{$1}) {
+           "\\e{$commands{$1}}($section_no)";
+       }
+       # Otherwise (and this shouldn't happen), show the reference target.
+       else {
+           print STDERR "Failed to resolve reference to $target\n";
+           $target;
+       }
+    }
+    $contents =~ s/(?:\bin\s+)?\\[kK]{([^}]+)}/replace_ref($`, $1, $')/eg;
+
+    # Run through halibut.  It does not default to using stdin or stdout,
+    # and /dev/std{in,out} apparently don't exist on some systems, so we
+    # can't reliably do this with a pipeline.
+    my ($temp_but, $temp_but_name) = mkstemp "/tmp/sgt-puzzles-but-XXXXXX"
+      or die "$!";
+    my $man_name = "$command.$section_no";
+    print $temp_but $contents or die "$!";
+    close $temp_but;
+    system "halibut --man=$man_dir/$man_name --input-charset=UTF-8 $temp_but_name";
+    unlink $temp_but_name;
+    -s "$man_dir/$man_name" or die "halibut produced an empty $man_name";
+}
+
+exit;