Show More
@@ -0,0 +1,22 b'' | |||||
|
1 | .. _hg-%(cmdname)s.1: | |||
|
2 | ||||
|
3 | %(cmdtitle)s | |||
|
4 | ||||
|
5 | %(cmdshortdesc)s | |||
|
6 | ||||
|
7 | .. contents:: | |||
|
8 | :backlinks: top | |||
|
9 | :class: htmlonly | |||
|
10 | :depth: 1 | |||
|
11 | ||||
|
12 | Synopsis | |||
|
13 | -------- | |||
|
14 | ||||
|
15 | :: | |||
|
16 | ||||
|
17 | %(cmdsynopsis)s | |||
|
18 | ||||
|
19 | Description | |||
|
20 | ----------- | |||
|
21 | %(cmdlongdesc)s | |||
|
22 |
@@ -0,0 +1,9 b'' | |||||
|
1 | .. _ext-%(extname)s: | |||
|
2 | ||||
|
3 | %(exttitle)s | |||
|
4 | ||||
|
5 | .. contents:: | |||
|
6 | :backlinks: top | |||
|
7 | :class: htmlonly | |||
|
8 | :depth: 2 | |||
|
9 |
@@ -0,0 +1,9 b'' | |||||
|
1 | .. _topic-%(topicname)s: | |||
|
2 | ||||
|
3 | %(topictitle)s | |||
|
4 | ||||
|
5 | .. contents:: | |||
|
6 | :backlinks: top | |||
|
7 | :class: htmlonly | |||
|
8 | :depth: 2 | |||
|
9 |
@@ -40,10 +40,17 b' contrib/merge-lists/target/' | |||||
40 | dist |
|
40 | dist | |
41 | packages |
|
41 | packages | |
42 | doc/common.txt |
|
42 | doc/common.txt | |
|
43 | doc/commandlist.txt | |||
|
44 | doc/extensionlist.txt | |||
|
45 | doc/topiclist.txt | |||
|
46 | doc/*.mk | |||
43 | doc/*.[0-9] |
|
47 | doc/*.[0-9] | |
44 | doc/*.[0-9].txt |
|
48 | doc/*.[0-9].txt | |
45 | doc/*.[0-9].gendoc.txt |
|
49 | doc/*.[0-9].gendoc.txt | |
46 | doc/*.[0-9].{x,ht}ml |
|
50 | doc/*.[0-9].{x,ht}ml | |
|
51 | doc/build | |||
|
52 | doc/html | |||
|
53 | doc/man | |||
47 | MANIFEST |
|
54 | MANIFEST | |
48 | MANIFEST.in |
|
55 | MANIFEST.in | |
49 | patches |
|
56 | patches |
@@ -3,6 +3,7 b' MAN=$(SOURCES:%.txt=%)' | |||||
3 | HTML=$(SOURCES:%.txt=%.html) |
|
3 | HTML=$(SOURCES:%.txt=%.html) | |
4 | GENDOC=gendoc.py ../mercurial/commands.py ../mercurial/help.py \ |
|
4 | GENDOC=gendoc.py ../mercurial/commands.py ../mercurial/help.py \ | |
5 | ../mercurial/helptext/*.txt ../hgext/*.py ../hgext/*/__init__.py |
|
5 | ../mercurial/helptext/*.txt ../hgext/*.py ../hgext/*/__init__.py | |
|
6 | RUNRST=runrst | |||
6 | PREFIX=/usr/local |
|
7 | PREFIX=/usr/local | |
7 | MANDIR=$(PREFIX)/share/man |
|
8 | MANDIR=$(PREFIX)/share/man | |
8 | INSTALL=install -m 644 |
|
9 | INSTALL=install -m 644 | |
@@ -14,10 +15,150 b' PYTHON?=py -3' | |||||
14 | else |
|
15 | else | |
15 | PYTHON?=python3 |
|
16 | PYTHON?=python3 | |
16 | endif |
|
17 | endif | |
|
18 | ||||
17 | RSTARGS= |
|
19 | RSTARGS= | |
|
20 | GENDOCARGS= | |||
|
21 | GENDOCCMD=$(PYTHON) gendoc.py $(GENDOCARGS) | |||
|
22 | ||||
|
23 | # Output directories for individual help pages. | |||
|
24 | MANOUT=man | |||
|
25 | HTMLOUT=html | |||
|
26 | BUILDDIR=build | |||
18 |
|
27 | |||
19 | export HGENCODING=UTF-8 |
|
28 | export HGENCODING=UTF-8 | |
20 |
|
29 | |||
|
30 | .PHONY: all man html install clean knownrefs | |||
|
31 | ||||
|
32 | # Generate a list of hg commands and extensions. | |||
|
33 | commandlist.txt: $(GENDOC) | |||
|
34 | ${GENDOCCMD} commandlist > $@.tmp | |||
|
35 | mv $@.tmp $@ | |||
|
36 | ||||
|
37 | topiclist.txt: $(GENDOC) | |||
|
38 | ${GENDOCCMD} topiclist > $@.tmp | |||
|
39 | mv $@.tmp $@ | |||
|
40 | ||||
|
41 | extensionlist.txt: $(GENDOC) | |||
|
42 | ${GENDOCCMD} extensionlist > $@.tmp | |||
|
43 | mv $@.tmp $@ | |||
|
44 | ||||
|
45 | # Build target for running runrst more easily by hand | |||
|
46 | knownrefs: commandlist.txt topiclist.txt extensionlist.txt | |||
|
47 | ||||
|
48 | BUILDFILES=commandlist.txt topiclist.txt extensionlist.txt | |||
|
49 | ||||
|
50 | # We want to generate a sub-Makefile that can build the RST/man/html doc for | |||
|
51 | # each hg command. Here are templates that we'll use to generate this | |||
|
52 | # sub-Makefile. | |||
|
53 | HGCMDTPL=templates/cmdheader.txt | |||
|
54 | TOPICTPL=templates/topicheader.txt | |||
|
55 | EXTTPL=templates/extheader.txt | |||
|
56 | ||||
|
57 | define RuleAllCommandsTemplate | |||
|
58 | HG_COMMANDS=$(1) | |||
|
59 | all-commands: $$(HG_COMMANDS:%=$$(BUILDDIR)/hg-%.gendoc.txt) | |||
|
60 | endef | |||
|
61 | ||||
|
62 | define RuleAllTopicsTemplate | |||
|
63 | HG_TOPICS=$(1) | |||
|
64 | all-topics: $$(HG_TOPICS:%=$$(BUILDDIR)/%.gendoc.txt) | |||
|
65 | endef | |||
|
66 | ||||
|
67 | define RuleAllExtensionsTemplate | |||
|
68 | HG_EXTENSIONS=$(1) | |||
|
69 | all-extensions: $$(HG_EXTENSIONS:%=$$(BUILDDIR)/%.gendoc.txt) | |||
|
70 | endef | |||
|
71 | ||||
|
72 | define RuleCommandTemplate | |||
|
73 | $$(BUILDDIR)/hg-$C.gendoc.txt: $$(GENDOC) $$(HGCMDTPL) | |||
|
74 | mkdir -p $$(@D) | |||
|
75 | $${GENDOCCMD} cmd-$C > $$@.tmp | |||
|
76 | mv $$@.tmp $$@ | |||
|
77 | endef | |||
|
78 | ||||
|
79 | define RuleTopicTemplate | |||
|
80 | $$(BUILDDIR)/topic-$T.gendoc.txt: $$(GENDOC) $$(TOPICTPL) | |||
|
81 | mkdir -p $$(@D) | |||
|
82 | $${GENDOCCMD} topic-$T > $$@.tmp | |||
|
83 | mv $$@.tmp $$@ | |||
|
84 | endef | |||
|
85 | ||||
|
86 | define RuleExtensionTemplate | |||
|
87 | $$(BUILDDIR)/ext-$E.gendoc.txt: $$(GENDOC) $$(EXTTPL) | |||
|
88 | mkdir -p $$(@D) | |||
|
89 | $${GENDOCCMD} ext-$E > $$@.tmp | |||
|
90 | mv $$@.tmp $$@ | |||
|
91 | endef | |||
|
92 | ||||
|
93 | # Actually generate the sub-Makefile. | |||
|
94 | # The $file function is only supported by GNU Make 4 and above. | |||
|
95 | CommandsTopicsExtensions.mk: commandlist.txt topiclist.txt extensionlist.txt Makefile | |||
|
96 | ifeq (4.0,$(firstword $(sort $(MAKE_VERSION) 4.0))) | |||
|
97 | $(file > $@.tmp,# Generated by Makefile) | |||
|
98 | $(file >> $@.tmp,$(call RuleAllCommandsTemplate,$(file < commandlist.txt))) | |||
|
99 | $(file >> $@.tmp,$(call RuleAllTopicsTemplate,$(file < topiclist.txt))) | |||
|
100 | $(file >> $@.tmp,$(call RuleAllExtensionsTemplate,$(file < extensionlist.txt))) | |||
|
101 | $(foreach C,$(file < commandlist.txt),$(file >> $@.tmp,$(RuleCommandTemplate))) | |||
|
102 | $(foreach T,$(file < topiclist.txt),$(file >> $@.tmp,$(RuleTopicTemplate))) | |||
|
103 | $(foreach E,$(file < extensionlist.txt),$(file >> $@.tmp,$(RuleExtensionTemplate))) | |||
|
104 | mv $@.tmp $@ | |||
|
105 | else | |||
|
106 | @echo "You are running make ${MAKE_VERSION} but you need make 4.0 or above" | |||
|
107 | endif | |||
|
108 | ||||
|
109 | BUILDFILES+=CommandsTopicsExtensions.mk | |||
|
110 | ||||
|
111 | # Include the sub-Makefile that contains rules for generating each individual | |||
|
112 | # command/help-topic/extension help page. This sub-Makefile is created by the | |||
|
113 | # rule above (CommandsTopicsExtensions.mk) which in turn is created from the | |||
|
114 | # plain-text lists of commands/help-topics/extensions. | |||
|
115 | # | |||
|
116 | # Any time the source code changes, these plain-text lists and this | |||
|
117 | # sub-Makefile will get regenerated. Make will then restart itself to take | |||
|
118 | # into account the rules inside the sub-Makefile. | |||
|
119 | # | |||
|
120 | # We want to avoid doing all this work for targets that we know don't need it | |||
|
121 | # however. For example, running `make clean` would only generate these files | |||
|
122 | # in order to delete them immediately. As a result, we don't include the | |||
|
123 | # sub-Makefile (and therefore don't require generating it) if clean is one of | |||
|
124 | # the targets. This might not do what we want when other targets are specified | |||
|
125 | # but it's most likely what we want. | |||
|
126 | ifeq (,$(filter clean,$(MAKECMDGOALS))) | |||
|
127 | -include CommandsTopicsExtensions.mk | |||
|
128 | endif | |||
|
129 | ||||
|
130 | # If the sub-Makefile is available, add all the hg commands, help-topics, and | |||
|
131 | # extensions to the list of things to generate html and man pages for. | |||
|
132 | # | |||
|
133 | # Naming convention: | |||
|
134 | # - commands: hg-foo (html and man) | |||
|
135 | # - help topics: topic-foo (html), hgfoo (man) | |||
|
136 | # - extensions: ext-foo (html), hgext-foo (man) | |||
|
137 | # | |||
|
138 | # Man pages for commands are in section 1 (user commands), topics and | |||
|
139 | # extensions are in section 7 (miscellanea) | |||
|
140 | # | |||
|
141 | # NOTE: topics and extension are temporarily disabled for man pages because | |||
|
142 | # they make docutils' RST converter crash. | |||
|
143 | ifdef HG_COMMANDS | |||
|
144 | HTML+=$(HG_COMMANDS:%=$(HTMLOUT)/hg-%.html) | |||
|
145 | MAN+=$(HG_COMMANDS:%=$(MANOUT)/hg-%.1) | |||
|
146 | endif | |||
|
147 | ||||
|
148 | ifdef HG_TOPICS | |||
|
149 | HTML+=$(HG_TOPICS:%=$(HTMLOUT)/topic-%.html) | |||
|
150 | #MAN+=$(HG_TOPICS:%=$(MANOUT)/hg%.7) | |||
|
151 | endif | |||
|
152 | ||||
|
153 | ifdef HG_EXTENSIONS | |||
|
154 | HTML+=$(HG_EXTENSIONS:%=$(HTMLOUT)/ext-%.html) | |||
|
155 | #MAN+=$(HG_EXTENSIONS:%=$(MANOUT)/hgext-%.7) | |||
|
156 | endif | |||
|
157 | ||||
|
158 | # Also add the HTML index page | |||
|
159 | HTML+=$(HTMLOUT)/index.html | |||
|
160 | ||||
|
161 | ||||
21 | all: man html |
|
162 | all: man html | |
22 |
|
163 | |||
23 | man: $(MAN) |
|
164 | man: $(MAN) | |
@@ -26,17 +167,45 b' html: $(HTML)' | |||||
26 |
|
167 | |||
27 | # This logic is duplicated in setup.py:hgbuilddoc() |
|
168 | # This logic is duplicated in setup.py:hgbuilddoc() | |
28 | common.txt $(SOURCES) $(SOURCES:%.txt=%.gendoc.txt): $(GENDOC) |
|
169 | common.txt $(SOURCES) $(SOURCES:%.txt=%.gendoc.txt): $(GENDOC) | |
29 |
${ |
|
170 | ${GENDOCCMD} "$(basename $@)" > $@.tmp | |
30 | mv $@.tmp $@ |
|
171 | mv $@.tmp $@ | |
31 |
|
172 | |||
32 | %: %.txt %.gendoc.txt common.txt |
|
173 | %: %.txt %.gendoc.txt common.txt $(RUNRST) | |
33 | $(PYTHON) runrst hgmanpage $(RSTARGS) --halt warning \ |
|
174 | $(PYTHON) runrst hgmanpage $(RSTARGS) --halt warning \ | |
34 | --strip-elements-with-class htmlonly $*.txt $* |
|
175 | --strip-elements-with-class htmlonly $*.txt $* | |
35 |
|
176 | |||
36 | %.html: %.txt %.gendoc.txt common.txt |
|
177 | %.html: %.txt %.gendoc.txt common.txt $(RUNRST) | |
37 | $(PYTHON) runrst html $(RSTARGS) --halt warning \ |
|
178 | $(PYTHON) runrst html $(RSTARGS) --halt warning \ | |
38 | --link-stylesheet --stylesheet-path style.css $*.txt $*.html |
|
179 | --link-stylesheet --stylesheet-path style.css $*.txt $*.html | |
39 |
|
180 | |||
|
181 | # Rules for index page and individual command/help-topic/extension pages | |||
|
182 | # Because the naming isn't the same between html and man pages, we need to | |||
|
183 | # break down man pages rules a bit more. | |||
|
184 | $(BUILDDIR)/index.gendoc.txt: $(GENDOC) | |||
|
185 | mkdir -p $(@D) | |||
|
186 | ${GENDOCCMD} index > $@.tmp | |||
|
187 | mv $@.tmp $@ | |||
|
188 | ||||
|
189 | $(MANOUT)/hg-%.1: $(BUILDDIR)/hg-%.gendoc.txt common.txt $(RUNRST) | |||
|
190 | mkdir -p $(@D) | |||
|
191 | $(PYTHON) runrst hgmanpage --hg-individual-pages $(RSTARGS) --halt warning \ | |||
|
192 | --strip-elements-with-class htmlonly $(BUILDDIR)/hg-$*.gendoc.txt $@ | |||
|
193 | ||||
|
194 | $(MANOUT)/hg%.7: $(BUILDDIR)/topic-%.gendoc.txt common.txt $(RUNRST) | |||
|
195 | mkdir -p $(@D) | |||
|
196 | $(PYTHON) runrst hgmanpage --hg-individual-pages $(RSTARGS) --halt warning \ | |||
|
197 | --strip-elements-with-class htmlonly $(BUILDDIR)/topic-$*.gendoc.txt $@ | |||
|
198 | ||||
|
199 | $(MANOUT)/hgext-%.7: $(BUILDDIR)/ext-%.gendoc.txt common.txt $(RUNRST) | |||
|
200 | mkdir -p $(@D) | |||
|
201 | $(PYTHON) runrst hgmanpage --hg-individual-pages $(RSTARGS) --halt warning \ | |||
|
202 | --strip-elements-with-class htmlonly $(BUILDDIR)/ext-$*.gendoc.txt $@ | |||
|
203 | ||||
|
204 | $(HTMLOUT)/%.html: $(BUILDDIR)/%.gendoc.txt common.txt $(RUNRST) | |||
|
205 | mkdir -p $(@D) | |||
|
206 | $(PYTHON) runrst html --hg-individual-pages $(RSTARGS) --halt warning \ | |||
|
207 | --link-stylesheet --stylesheet-path style.css $(BUILDDIR)/$*.gendoc.txt $@ | |||
|
208 | ||||
40 | MANIFEST: man html |
|
209 | MANIFEST: man html | |
41 | # tracked files are already in the main MANIFEST |
|
210 | # tracked files are already in the main MANIFEST | |
42 | $(RM) $@ |
|
211 | $(RM) $@ | |
@@ -51,5 +220,9 b' install: man' | |||||
51 | $(INSTALL) $$i "$(DESTDIR)$(MANDIR)"/$$subdir ; \ |
|
220 | $(INSTALL) $$i "$(DESTDIR)$(MANDIR)"/$$subdir ; \ | |
52 | done |
|
221 | done | |
53 |
|
222 | |||
|
223 | # The clean target explicitly doesn't bother with the sub-Makefile, so we don't | |||
|
224 | # know anything about all the command/topic/extension targets and files. | |||
|
225 | # $(HTML) only has the basic topics, so we need to delete $(HTMLOUT)/*.html and | |||
|
226 | # other similar files "by hand" here. | |||
54 | clean: |
|
227 | clean: | |
55 |
$(RM) $(MAN) $(HTML) common.txt $(SOURCES) $( |
|
228 | $(RM) $(MAN) $(HTML) common.txt $(SOURCES) MANIFEST *.gendoc.txt $(BUILDFILES) $(BUILDDIR)/*.gendoc.* $(HTMLOUT)/*.html |
@@ -178,6 +178,202 b' def showdoc(ui, debugcmds=False):' | |||||
178 | ) |
|
178 | ) | |
179 |
|
179 | |||
180 |
|
180 | |||
|
181 | def showcommandlist(ui, debugcmds=False): | |||
|
182 | """Render a plain text list of all command names | |||
|
183 | ||||
|
184 | Args: | |||
|
185 | ui: the UI object to output to | |||
|
186 | debugcmds: whether to include debug commands | |||
|
187 | """ | |||
|
188 | cmdnames = allcommandnames(table, debugcmds=debugcmds) | |||
|
189 | for mainname in cmdnames.keys(): | |||
|
190 | # Make does not like semicolons in filenames (or what it | |||
|
191 | # considers as filenames). We use command names as targets so | |||
|
192 | # it applies here. For now let's skip commands with semicolons | |||
|
193 | # in them (at this time it only includes the `admin::verify` | |||
|
194 | # advanced command). | |||
|
195 | if b'::' in mainname: | |||
|
196 | continue | |||
|
197 | ui.write(mainname) | |||
|
198 | ui.write(b" ") | |||
|
199 | ||||
|
200 | ||||
|
201 | def showtopiclist(ui): | |||
|
202 | """Render a plain text list of all help topic names | |||
|
203 | ||||
|
204 | Args: | |||
|
205 | ui: the UI object to output to | |||
|
206 | """ | |||
|
207 | for topic in helptable: | |||
|
208 | topicname = topic[0][0] | |||
|
209 | if help.filtertopic(ui, topicname): | |||
|
210 | continue | |||
|
211 | ui.write(topicname) | |||
|
212 | ui.write(b" ") | |||
|
213 | ||||
|
214 | ||||
|
215 | def showextensionlist(ui): | |||
|
216 | """Render a plain text list of all extension names | |||
|
217 | ||||
|
218 | Args: | |||
|
219 | ui: the UI object to output to | |||
|
220 | """ | |||
|
221 | for extensionname in allextensionnames(): | |||
|
222 | ui.write(extensionname) | |||
|
223 | ui.write(b" ") | |||
|
224 | ||||
|
225 | ||||
|
226 | def showhelpindex(ui, debugcmds=False): | |||
|
227 | """Render restructured text for a complete mercurial help index | |||
|
228 | ||||
|
229 | This index will show a list of commands, followed by a list of help topics, | |||
|
230 | and finally a list of extensions. These lists are split in categories and | |||
|
231 | ordered 'nicely' as defined by alphabetical and categeory order. | |||
|
232 | ||||
|
233 | Each entry in this index is a reference to the specific help page of the | |||
|
234 | command, topic, or extension at hand. | |||
|
235 | """ | |||
|
236 | ui.write(minirst.section(_(b"Mercurial Distributed SCM"))) | |||
|
237 | ||||
|
238 | missingdoc = _(b"(no help text available)") | |||
|
239 | ||||
|
240 | cats, h, syns = help._getcategorizedhelpcmds(ui, table, None) | |||
|
241 | ui.write(minirst.subsection(_(b"Commands"))) | |||
|
242 | ||||
|
243 | for cat in help.CATEGORY_ORDER: | |||
|
244 | catfns = sorted(cats.get(cat, [])) | |||
|
245 | if not catfns: | |||
|
246 | continue | |||
|
247 | ||||
|
248 | catname = gettext(help.CATEGORY_NAMES[cat]) | |||
|
249 | ui.write(minirst.subsubsection(catname)) | |||
|
250 | for c in catfns: | |||
|
251 | url = b'hg-%s.html' % c | |||
|
252 | ui.write(b" :`%s <%s>`__: %s" % (c, url, h[c])) | |||
|
253 | syns[c].remove(c) | |||
|
254 | if syns[c]: | |||
|
255 | ui.write(_(b" (aliases: *%s*)") % (b', '.join(syns[c]))) | |||
|
256 | ui.write(b"\n") | |||
|
257 | ui.write(b"\n\n") | |||
|
258 | ||||
|
259 | ui.write(b"\n\n") | |||
|
260 | ||||
|
261 | ui.write(minirst.subsection(_(b"Additional Help Topics"))) | |||
|
262 | topiccats, topicsyns = help._getcategorizedhelptopics(ui, helptable) | |||
|
263 | for cat in help.TOPIC_CATEGORY_ORDER: | |||
|
264 | topics = topiccats.get(cat, []) | |||
|
265 | if not topics: | |||
|
266 | continue | |||
|
267 | ||||
|
268 | catname = gettext(help.TOPIC_CATEGORY_NAMES[cat]) | |||
|
269 | ui.write(minirst.subsubsection(catname)) | |||
|
270 | for t, desc in topics: | |||
|
271 | url = b'topic-%s.html' % t | |||
|
272 | ui.write(b" :`%s <%s>`__: %s" % (t, url, desc)) | |||
|
273 | topicsyns[t].remove(t) | |||
|
274 | if topicsyns[t]: | |||
|
275 | ui.write(_(b" (aliases: *%s*)") % (b', '.join(topicsyns[t]))) | |||
|
276 | ui.write(b"\n") | |||
|
277 | ui.write(b"\n\n") | |||
|
278 | ||||
|
279 | ui.write(b"\n\n") | |||
|
280 | ||||
|
281 | # Add an alphabetical list of extensions, categorized by group. | |||
|
282 | sectionkeywords = [ | |||
|
283 | (b"(ADVANCED)", _(b"(ADVANCED)")), | |||
|
284 | (b"(EXPERIMENTAL)", _(b"(EXPERIMENTAL)")), | |||
|
285 | (b"(DEPRECATED)", _(b"(DEPRECATED)")), | |||
|
286 | ] | |||
|
287 | extensionsections = [ | |||
|
288 | (b"Extensions", []), | |||
|
289 | (b"Advanced Extensions", []), | |||
|
290 | (b"Experimental Extensions", []), | |||
|
291 | (b"Deprecated Extensions", []), | |||
|
292 | ] | |||
|
293 | for extensionname in allextensionnames(): | |||
|
294 | mod = extensions.load(ui, extensionname, None) | |||
|
295 | shortdoc, longdoc = _splitdoc(mod) | |||
|
296 | for i, kwds in enumerate(sectionkeywords): | |||
|
297 | if any([kwd in shortdoc for kwd in kwds]): | |||
|
298 | extensionsections[i + 1][1].append( | |||
|
299 | (extensionname, mod, shortdoc) | |||
|
300 | ) | |||
|
301 | break | |||
|
302 | else: | |||
|
303 | extensionsections[0][1].append((extensionname, mod, shortdoc)) | |||
|
304 | for sectiontitle, extinfos in extensionsections: | |||
|
305 | ui.write(minirst.subsection(_(sectiontitle))) | |||
|
306 | for extinfo in sorted(extinfos, key=lambda ei: ei[0]): | |||
|
307 | extensionname, mod, shortdoc = extinfo | |||
|
308 | url = b'ext-%s.html' % extensionname | |||
|
309 | ui.write( | |||
|
310 | minirst.subsubsection(b'`%s <%s>`__' % (extensionname, url)) | |||
|
311 | ) | |||
|
312 | ui.write(shortdoc) | |||
|
313 | ui.write(b'\n\n') | |||
|
314 | cmdtable = getattr(mod, 'cmdtable', None) | |||
|
315 | if cmdtable: | |||
|
316 | cmdnames = allcommandnames(cmdtable, debugcmds=debugcmds) | |||
|
317 | for f in sorted(cmdnames.keys()): | |||
|
318 | d = get_cmd(cmdnames[f], cmdtable) | |||
|
319 | ui.write(b':%s: ' % d[b'cmd']) | |||
|
320 | ui.write(d[b'desc'][0] or (missingdoc + b"\n")) | |||
|
321 | ui.write(b'\n') | |||
|
322 | ui.write(b'\n') | |||
|
323 | ||||
|
324 | ||||
|
325 | def showcommand(ui, mainname): | |||
|
326 | # Always pass debugcmds=True so that we find whatever command we are told | |||
|
327 | # to display. | |||
|
328 | cmdnames = allcommandnames(table, debugcmds=True) | |||
|
329 | allnames = cmdnames[mainname] | |||
|
330 | d = get_cmd(allnames, table) | |||
|
331 | ||||
|
332 | header = _rendertpl( | |||
|
333 | 'cmdheader.txt', | |||
|
334 | { | |||
|
335 | 'cmdname': mainname, | |||
|
336 | 'cmdtitle': minirst.section(b'hg ' + mainname), | |||
|
337 | 'cmdshortdesc': minirst.subsection(d[b'desc'][0]), | |||
|
338 | 'cmdlongdesc': d[b'desc'][1], | |||
|
339 | 'cmdsynopsis': d[b'synopsis'], | |||
|
340 | }, | |||
|
341 | ) | |||
|
342 | ui.write(header.encode()) | |||
|
343 | ||||
|
344 | _optionsprinter(ui, d, minirst.subsubsection) | |||
|
345 | if d[b'aliases']: | |||
|
346 | ui.write(minirst.subsubsection(_(b"Aliases"))) | |||
|
347 | ui.write(b"::\n\n ") | |||
|
348 | ui.write(b", ".join(d[b'aliases'])) | |||
|
349 | ui.write(b"\n") | |||
|
350 | ||||
|
351 | ||||
|
352 | def _splitdoc(obj): | |||
|
353 | objdoc = pycompat.getdoc(obj) | |||
|
354 | firstnl = objdoc.find(b'\n') | |||
|
355 | if firstnl > 0: | |||
|
356 | shortdoc = objdoc[:firstnl] | |||
|
357 | longdoc = objdoc[firstnl + 1 :] | |||
|
358 | else: | |||
|
359 | shortdoc = objdoc | |||
|
360 | longdoc = '' | |||
|
361 | return shortdoc.lstrip(), longdoc.lstrip() | |||
|
362 | ||||
|
363 | ||||
|
364 | def _rendertpl(tplname, data): | |||
|
365 | tplpath = os.path.join(os.path.dirname(__file__), 'templates', tplname) | |||
|
366 | with open(tplpath, 'r') as f: | |||
|
367 | tpl = f.read() | |||
|
368 | ||||
|
369 | if isinstance(tpl, bytes): | |||
|
370 | tpl = tpl.decode() | |||
|
371 | for k in data: | |||
|
372 | data[k] = data[k].decode() | |||
|
373 | ||||
|
374 | return tpl % data | |||
|
375 | ||||
|
376 | ||||
181 | def gettopicstable(): |
|
377 | def gettopicstable(): | |
182 | extrahelptable = [ |
|
378 | extrahelptable = [ | |
183 | ([b"common"], b'', loaddoc(b'common'), help.TOPIC_CATEGORY_MISC), |
|
379 | ([b"common"], b'', loaddoc(b'common'), help.TOPIC_CATEGORY_MISC), | |
@@ -268,6 +464,41 b' def helpprinter(ui, topics, sectionfunc)' | |||||
268 | ui.write(b"\n") |
|
464 | ui.write(b"\n") | |
269 |
|
465 | |||
270 |
|
466 | |||
|
467 | def showextension(ui, extensionname, debugcmds=False): | |||
|
468 | """Render the help text for an extension | |||
|
469 | ||||
|
470 | Args: | |||
|
471 | ui: the UI object to output to | |||
|
472 | extensionname: the name of the extension to output | |||
|
473 | debugcmds: whether to include the extension's debug commands, if any | |||
|
474 | """ | |||
|
475 | mod = extensions.load(ui, extensionname, None) | |||
|
476 | ||||
|
477 | header = _rendertpl( | |||
|
478 | 'extheader.txt', | |||
|
479 | {'extname': extensionname, 'exttitle': minirst.section(extensionname)}, | |||
|
480 | ) | |||
|
481 | ui.write(header.encode()) | |||
|
482 | ||||
|
483 | shortdoc, longdoc = _splitdoc(mod) | |||
|
484 | if shortdoc: | |||
|
485 | ui.write(b"%s\n\n" % gettext(shortdoc)) | |||
|
486 | if longdoc: | |||
|
487 | ui.write(minirst.subsection(_(b"Description"))) | |||
|
488 | ui.write(b"%s\n\n" % gettext(longdoc)) | |||
|
489 | ||||
|
490 | cmdtable = getattr(mod, 'cmdtable', None) | |||
|
491 | if cmdtable: | |||
|
492 | ui.write(minirst.subsection(_(b'Commands'))) | |||
|
493 | commandprinter( | |||
|
494 | ui, | |||
|
495 | cmdtable, | |||
|
496 | minirst.subsubsection, | |||
|
497 | minirst.subsubsubsection, | |||
|
498 | debugcmds=debugcmds, | |||
|
499 | ) | |||
|
500 | ||||
|
501 | ||||
271 | def commandprinter(ui, cmdtable, sectionfunc, subsectionfunc, debugcmds=False): |
|
502 | def commandprinter(ui, cmdtable, sectionfunc, subsectionfunc, debugcmds=False): | |
272 | """Render restructuredtext describing a list of commands and their |
|
503 | """Render restructuredtext describing a list of commands and their | |
273 | documentations, grouped by command category. |
|
504 | documentations, grouped by command category. | |
@@ -427,7 +658,27 b' if __name__ == "__main__":' | |||||
427 | # ui.debugflag determines if the help module returns debug commands to us. |
|
658 | # ui.debugflag determines if the help module returns debug commands to us. | |
428 | ui.debugflag = debugcmds |
|
659 | ui.debugflag = debugcmds | |
429 |
|
660 | |||
|
661 | # Render the 'all-in-one' giant documentation file | |||
430 | if doc == b'hg.1.gendoc': |
|
662 | if doc == b'hg.1.gendoc': | |
431 | showdoc(ui) |
|
663 | showdoc(ui) | |
|
664 | # Render a command/help-topic/extension name list (for internal use) | |||
|
665 | elif doc == b'commandlist': | |||
|
666 | showcommandlist(ui, debugcmds=debugcmds) | |||
|
667 | elif doc == b'topiclist': | |||
|
668 | showtopiclist(ui) | |||
|
669 | elif doc == b'extensionlist': | |||
|
670 | showextensionlist(ui) | |||
|
671 | # Render the help index/main page | |||
|
672 | elif doc == b'index': | |||
|
673 | showhelpindex(ui, debugcmds=debugcmds) | |||
|
674 | # Render an individual command/help-topic/extension page | |||
|
675 | elif doc.startswith(b'cmd-'): | |||
|
676 | showcommand(ui, doc[4:]) | |||
|
677 | elif doc.startswith(b'topic-'): | |||
|
678 | showtopic(ui, doc[6:], wraptpl=True) | |||
|
679 | elif doc.startswith(b'ext-'): | |||
|
680 | showextension(ui, doc[4:], debugcmds=debugcmds) | |||
|
681 | # Render a help-topic page without any title/footer, for later inclusion | |||
|
682 | # into a hand-written help text file | |||
432 | else: |
|
683 | else: | |
433 | showtopic(ui, doc) |
|
684 | showtopic(ui, doc) |
@@ -13,6 +13,7 b' where WRITER is the name of a Docutils w' | |||||
13 | """ |
|
13 | """ | |
14 |
|
14 | |||
15 |
|
15 | |||
|
16 | import re | |||
16 | import sys |
|
17 | import sys | |
17 |
|
18 | |||
18 | try: |
|
19 | try: | |
@@ -31,13 +32,63 b' except ImportError:' | |||||
31 | ) |
|
32 | ) | |
32 | sys.exit(-1) |
|
33 | sys.exit(-1) | |
33 |
|
34 | |||
|
35 | # Whether we are rendering a help page for a single topic. | |||
|
36 | # If false, we are rendering a monolithic page with all topics together. | |||
|
37 | is_individual_pages_mode = False | |||
|
38 | ||||
|
39 | ||||
|
40 | def make_cmd_ref_uri(cmd): | |||
|
41 | if is_individual_pages_mode: | |||
|
42 | return "hg-%s.html" % cmd | |||
|
43 | else: | |||
|
44 | return "hg.1.html#%s" % cmd | |||
|
45 | ||||
|
46 | ||||
|
47 | known_refs = None | |||
|
48 | ||||
|
49 | ||||
|
50 | def load_known_refs(fname): | |||
|
51 | try: | |||
|
52 | with open(fname, 'r') as fp: | |||
|
53 | text = fp.read() | |||
|
54 | return re.split(r'[ \n]+', text) | |||
|
55 | except OSError: | |||
|
56 | sys.stderr.write( | |||
|
57 | "abort: couldn't find '%', please run documentation generation " | |||
|
58 | "through the Makefile, or run 'make knownrefs'\n" | |||
|
59 | ) | |||
|
60 | sys.exit(-1) | |||
|
61 | ||||
|
62 | ||||
|
63 | def find_known_ref(ref): | |||
|
64 | global known_refs | |||
|
65 | if known_refs is None: | |||
|
66 | cmds = load_known_refs('commandlist.txt') | |||
|
67 | topics = load_known_refs('topiclist.txt') | |||
|
68 | exts = load_known_refs('extensionlist.txt') | |||
|
69 | known_refs = {'hg': cmds, 'topic': topics, 'ext': exts} | |||
|
70 | for reftype, refnames in known_refs.items(): | |||
|
71 | if ref in refnames: | |||
|
72 | return reftype | |||
|
73 | return None | |||
|
74 | ||||
|
75 | ||||
|
76 | def make_any_ref_uri(ref): | |||
|
77 | if is_individual_pages_mode: | |||
|
78 | # Try to find if ref is a command, topic, or extension. If not, | |||
|
79 | # reference the anchor in the main hg.1 help page. | |||
|
80 | reftype = find_known_ref(ref) | |||
|
81 | if reftype: | |||
|
82 | return '%s-%s.html' % (reftype, ref) | |||
|
83 | return "hg.1.html#%s" % ref | |||
|
84 | ||||
34 |
|
85 | |||
35 | def role_hg(name, rawtext, text, lineno, inliner, options=None, content=None): |
|
86 | def role_hg(name, rawtext, text, lineno, inliner, options=None, content=None): | |
36 | text = "hg " + utils.unescape(text) |
|
87 | text = "hg " + utils.unescape(text) | |
37 | linktext = nodes.literal(rawtext, text) |
|
88 | linktext = nodes.literal(rawtext, text) | |
38 | parts = text.split() |
|
89 | parts = text.split() | |
39 | cmd, args = parts[1], parts[2:] |
|
90 | cmd, args = parts[1], parts[2:] | |
40 | refuri = "hg.1.html#%s" % cmd |
|
91 | refuri = make_cmd_ref_uri(cmd) | |
41 | if cmd == 'help' and args: |
|
92 | if cmd == 'help' and args: | |
42 | if args[0] == 'config': |
|
93 | if args[0] == 'config': | |
43 | # :hg:`help config` |
|
94 | # :hg:`help config` | |
@@ -48,9 +99,9 b' def role_hg(name, rawtext, text, lineno,' | |||||
48 | elif len(args) >= 2 and args[0] == '-c': |
|
99 | elif len(args) >= 2 and args[0] == '-c': | |
49 | # :hg:`help -c COMMAND ...` is equivalent to :hg:`COMMAND` |
|
100 | # :hg:`help -c COMMAND ...` is equivalent to :hg:`COMMAND` | |
50 | # (mainly for :hg:`help -c config`) |
|
101 | # (mainly for :hg:`help -c config`) | |
51 |
refuri = |
|
102 | refuri = make_cmd_ref_uri(args[1]) | |
52 | else: |
|
103 | else: | |
53 |
refuri = |
|
104 | refuri = make_any_ref_uri(args[0]) | |
54 | node = nodes.reference(rawtext, '', linktext, refuri=refuri) |
|
105 | node = nodes.reference(rawtext, '', linktext, refuri=refuri) | |
55 | return [node], [] |
|
106 | return [node], [] | |
56 |
|
107 | |||
@@ -65,4 +116,8 b' if __name__ == "__main__":' | |||||
65 | writer = sys.argv[1] |
|
116 | writer = sys.argv[1] | |
66 | del sys.argv[1] |
|
117 | del sys.argv[1] | |
67 |
|
118 | |||
|
119 | if sys.argv[1] == '--hg-individual-pages': | |||
|
120 | is_individual_pages_mode = True | |||
|
121 | del sys.argv[1] | |||
|
122 | ||||
68 | core.publish_cmdline(writer_name=writer) |
|
123 | core.publish_cmdline(writer_name=writer) |
General Comments 0
You need to be logged in to leave comments.
Login now