Package: sgt-puzzles / 20170606.272beef-1

201_make-more-docs.diff Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
Author: Ben Hutchings <ben@decadent.org.uk>
Description: Add rules and script to build manual pages and HTML

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.

--- a/Makefile.doc
+++ b/Makefile.doc
@@ -14,12 +14,20 @@ HACKING: devel.but
 	halibut --text=HACKING devel.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
--- /dev/null
+++ b/mkmanpages.pl
@@ -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;