##// END OF EJS Templates
help: convert flag default to bytes portably...
Augie Fackler -
r32619:d110fb58 default
parent child Browse files
Show More
@@ -1,668 +1,672
1 1 # help.py - help data for mercurial
2 2 #
3 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import itertools
11 11 import os
12 12 import textwrap
13 13
14 14 from .i18n import (
15 15 _,
16 16 gettext,
17 17 )
18 18 from . import (
19 19 cmdutil,
20 20 encoding,
21 21 error,
22 22 extensions,
23 23 filemerge,
24 24 fileset,
25 25 minirst,
26 26 pycompat,
27 27 revset,
28 28 templatefilters,
29 29 templatekw,
30 30 templater,
31 31 util,
32 32 )
33 33 from .hgweb import (
34 34 webcommands,
35 35 )
36 36
37 37 _exclkeywords = {
38 38 "(ADVANCED)",
39 39 "(DEPRECATED)",
40 40 "(EXPERIMENTAL)",
41 41 # i18n: "(ADVANCED)" is a keyword, must be translated consistently
42 42 _("(ADVANCED)"),
43 43 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
44 44 _("(DEPRECATED)"),
45 45 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
46 46 _("(EXPERIMENTAL)"),
47 47 }
48 48
49 49 def listexts(header, exts, indent=1, showdeprecated=False):
50 50 '''return a text listing of the given extensions'''
51 51 rst = []
52 52 if exts:
53 53 for name, desc in sorted(exts.iteritems()):
54 54 if not showdeprecated and any(w in desc for w in _exclkeywords):
55 55 continue
56 56 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
57 57 if rst:
58 58 rst.insert(0, '\n%s\n\n' % header)
59 59 return rst
60 60
61 61 def extshelp(ui):
62 62 rst = loaddoc('extensions')(ui).splitlines(True)
63 63 rst.extend(listexts(
64 64 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
65 65 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
66 66 doc = ''.join(rst)
67 67 return doc
68 68
69 69 def optrst(header, options, verbose):
70 70 data = []
71 71 multioccur = False
72 72 for option in options:
73 73 if len(option) == 5:
74 74 shortopt, longopt, default, desc, optlabel = option
75 75 else:
76 76 shortopt, longopt, default, desc = option
77 77 optlabel = _("VALUE") # default label
78 78
79 79 if not verbose and any(w in desc for w in _exclkeywords):
80 80 continue
81 81
82 82 so = ''
83 83 if shortopt:
84 84 so = '-' + shortopt
85 85 lo = '--' + longopt
86 86 if default:
87 desc += _(" (default: %s)") % default
87 # default is of unknown type, and in Python 2 we abused
88 # the %s-shows-repr property to handle integers etc. To
89 # match that behavior on Python 3, we do str(default) and
90 # then convert it to bytes.
91 desc += _(" (default: %s)") % pycompat.bytestr(default)
88 92
89 93 if isinstance(default, list):
90 94 lo += " %s [+]" % optlabel
91 95 multioccur = True
92 96 elif (default is not None) and not isinstance(default, bool):
93 97 lo += " %s" % optlabel
94 98
95 99 data.append((so, lo, desc))
96 100
97 101 if multioccur:
98 102 header += (_(" ([+] can be repeated)"))
99 103
100 104 rst = ['\n%s:\n\n' % header]
101 105 rst.extend(minirst.maketable(data, 1))
102 106
103 107 return ''.join(rst)
104 108
105 109 def indicateomitted(rst, omitted, notomitted=None):
106 110 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
107 111 if notomitted:
108 112 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
109 113
110 114 def filtercmd(ui, cmd, kw, doc):
111 115 if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
112 116 return True
113 117 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
114 118 return True
115 119 return False
116 120
117 121 def topicmatch(ui, commands, kw):
118 122 """Return help topics matching kw.
119 123
120 124 Returns {'section': [(name, summary), ...], ...} where section is
121 125 one of topics, commands, extensions, or extensioncommands.
122 126 """
123 127 kw = encoding.lower(kw)
124 128 def lowercontains(container):
125 129 return kw in encoding.lower(container) # translated in helptable
126 130 results = {'topics': [],
127 131 'commands': [],
128 132 'extensions': [],
129 133 'extensioncommands': [],
130 134 }
131 135 for names, header, doc in helptable:
132 136 # Old extensions may use a str as doc.
133 137 if (sum(map(lowercontains, names))
134 138 or lowercontains(header)
135 139 or (callable(doc) and lowercontains(doc(ui)))):
136 140 results['topics'].append((names[0], header))
137 141 for cmd, entry in commands.table.iteritems():
138 142 if len(entry) == 3:
139 143 summary = entry[2]
140 144 else:
141 145 summary = ''
142 146 # translate docs *before* searching there
143 147 docs = _(pycompat.getdoc(entry[0])) or ''
144 148 if kw in cmd or lowercontains(summary) or lowercontains(docs):
145 149 doclines = docs.splitlines()
146 150 if doclines:
147 151 summary = doclines[0]
148 152 cmdname = cmd.partition('|')[0].lstrip('^')
149 153 if filtercmd(ui, cmdname, kw, docs):
150 154 continue
151 155 results['commands'].append((cmdname, summary))
152 156 for name, docs in itertools.chain(
153 157 extensions.enabled(False).iteritems(),
154 158 extensions.disabled().iteritems()):
155 159 if not docs:
156 160 continue
157 161 mod = extensions.load(ui, name, '')
158 162 name = name.rpartition('.')[-1]
159 163 if lowercontains(name) or lowercontains(docs):
160 164 # extension docs are already translated
161 165 results['extensions'].append((name, docs.splitlines()[0]))
162 166 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
163 167 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
164 168 cmdname = cmd.partition('|')[0].lstrip('^')
165 169 cmddoc = pycompat.getdoc(entry[0])
166 170 if cmddoc:
167 171 cmddoc = gettext(cmddoc).splitlines()[0]
168 172 else:
169 173 cmddoc = _('(no help text available)')
170 174 if filtercmd(ui, cmdname, kw, cmddoc):
171 175 continue
172 176 results['extensioncommands'].append((cmdname, cmddoc))
173 177 return results
174 178
175 179 def loaddoc(topic, subdir=None):
176 180 """Return a delayed loader for help/topic.txt."""
177 181
178 182 def loader(ui):
179 183 docdir = os.path.join(util.datapath, 'help')
180 184 if subdir:
181 185 docdir = os.path.join(docdir, subdir)
182 186 path = os.path.join(docdir, topic + ".txt")
183 187 doc = gettext(util.readfile(path))
184 188 for rewriter in helphooks.get(topic, []):
185 189 doc = rewriter(ui, topic, doc)
186 190 return doc
187 191
188 192 return loader
189 193
190 194 internalstable = sorted([
191 195 (['bundles'], _('Bundles'),
192 196 loaddoc('bundles', subdir='internals')),
193 197 (['censor'], _('Censor'),
194 198 loaddoc('censor', subdir='internals')),
195 199 (['changegroups'], _('Changegroups'),
196 200 loaddoc('changegroups', subdir='internals')),
197 201 (['requirements'], _('Repository Requirements'),
198 202 loaddoc('requirements', subdir='internals')),
199 203 (['revlogs'], _('Revision Logs'),
200 204 loaddoc('revlogs', subdir='internals')),
201 205 (['wireprotocol'], _('Wire Protocol'),
202 206 loaddoc('wireprotocol', subdir='internals')),
203 207 ])
204 208
205 209 def internalshelp(ui):
206 210 """Generate the index for the "internals" topic."""
207 211 lines = ['To access a subtopic, use "hg help internals.{subtopic-name}"\n',
208 212 '\n']
209 213 for names, header, doc in internalstable:
210 214 lines.append(' :%s: %s\n' % (names[0], header))
211 215
212 216 return ''.join(lines)
213 217
214 218 helptable = sorted([
215 219 (['bundlespec'], _("Bundle File Formats"), loaddoc('bundlespec')),
216 220 (['color'], _("Colorizing Outputs"), loaddoc('color')),
217 221 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
218 222 (["dates"], _("Date Formats"), loaddoc('dates')),
219 223 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
220 224 (['environment', 'env'], _('Environment Variables'),
221 225 loaddoc('environment')),
222 226 (['revisions', 'revs', 'revsets', 'revset', 'multirevs', 'mrevs'],
223 227 _('Specifying Revisions'), loaddoc('revisions')),
224 228 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
225 229 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
226 230 (['merge-tools', 'mergetools', 'mergetool'], _('Merge Tools'),
227 231 loaddoc('merge-tools')),
228 232 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
229 233 loaddoc('templates')),
230 234 (['urls'], _('URL Paths'), loaddoc('urls')),
231 235 (["extensions"], _("Using Additional Features"), extshelp),
232 236 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
233 237 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
234 238 (["glossary"], _("Glossary"), loaddoc('glossary')),
235 239 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
236 240 loaddoc('hgignore')),
237 241 (["phases"], _("Working with Phases"), loaddoc('phases')),
238 242 (['scripting'], _('Using Mercurial from scripts and automation'),
239 243 loaddoc('scripting')),
240 244 (['internals'], _("Technical implementation topics"),
241 245 internalshelp),
242 246 (['pager'], _("Pager Support"), loaddoc('pager')),
243 247 ])
244 248
245 249 # Maps topics with sub-topics to a list of their sub-topics.
246 250 subtopics = {
247 251 'internals': internalstable,
248 252 }
249 253
250 254 # Map topics to lists of callable taking the current topic help and
251 255 # returning the updated version
252 256 helphooks = {}
253 257
254 258 def addtopichook(topic, rewriter):
255 259 helphooks.setdefault(topic, []).append(rewriter)
256 260
257 261 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
258 262 """Extract docstring from the items key to function mapping, build a
259 263 single documentation block and use it to overwrite the marker in doc.
260 264 """
261 265 entries = []
262 266 for name in sorted(items):
263 267 text = (pycompat.getdoc(items[name]) or '').rstrip()
264 268 if (not text
265 269 or not ui.verbose and any(w in text for w in _exclkeywords)):
266 270 continue
267 271 text = gettext(text)
268 272 if dedent:
269 273 # Abuse latin1 to use textwrap.dedent() on bytes.
270 274 text = textwrap.dedent(text.decode('latin1')).encode('latin1')
271 275 lines = text.splitlines()
272 276 doclines = [(lines[0])]
273 277 for l in lines[1:]:
274 278 # Stop once we find some Python doctest
275 279 if l.strip().startswith('>>>'):
276 280 break
277 281 if dedent:
278 282 doclines.append(l.rstrip())
279 283 else:
280 284 doclines.append(' ' + l.strip())
281 285 entries.append('\n'.join(doclines))
282 286 entries = '\n\n'.join(entries)
283 287 return doc.replace(marker, entries)
284 288
285 289 def addtopicsymbols(topic, marker, symbols, dedent=False):
286 290 def add(ui, topic, doc):
287 291 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
288 292 addtopichook(topic, add)
289 293
290 294 addtopicsymbols('bundlespec', '.. bundlecompressionmarker',
291 295 util.bundlecompressiontopics())
292 296 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
293 297 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
294 298 filemerge.internalsdoc)
295 299 addtopicsymbols('revisions', '.. predicatesmarker', revset.symbols)
296 300 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
297 301 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
298 302 addtopicsymbols('templates', '.. functionsmarker', templater.funcs)
299 303 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
300 304 dedent=True)
301 305
302 306 def help_(ui, commands, name, unknowncmd=False, full=True, subtopic=None,
303 307 **opts):
304 308 '''
305 309 Generate the help for 'name' as unformatted restructured text. If
306 310 'name' is None, describe the commands available.
307 311 '''
308 312
309 313 opts = pycompat.byteskwargs(opts)
310 314
311 315 def helpcmd(name, subtopic=None):
312 316 try:
313 317 aliases, entry = cmdutil.findcmd(name, commands.table,
314 318 strict=unknowncmd)
315 319 except error.AmbiguousCommand as inst:
316 320 # py3k fix: except vars can't be used outside the scope of the
317 321 # except block, nor can be used inside a lambda. python issue4617
318 322 prefix = inst.args[0]
319 323 select = lambda c: c.lstrip('^').startswith(prefix)
320 324 rst = helplist(select)
321 325 return rst
322 326
323 327 rst = []
324 328
325 329 # check if it's an invalid alias and display its error if it is
326 330 if getattr(entry[0], 'badalias', None):
327 331 rst.append(entry[0].badalias + '\n')
328 332 if entry[0].unknowncmd:
329 333 try:
330 334 rst.extend(helpextcmd(entry[0].cmdname))
331 335 except error.UnknownCommand:
332 336 pass
333 337 return rst
334 338
335 339 # synopsis
336 340 if len(entry) > 2:
337 341 if entry[2].startswith('hg'):
338 342 rst.append("%s\n" % entry[2])
339 343 else:
340 344 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
341 345 else:
342 346 rst.append('hg %s\n' % aliases[0])
343 347 # aliases
344 348 if full and not ui.quiet and len(aliases) > 1:
345 349 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
346 350 rst.append('\n')
347 351
348 352 # description
349 353 doc = gettext(pycompat.getdoc(entry[0]))
350 354 if not doc:
351 355 doc = _("(no help text available)")
352 356 if util.safehasattr(entry[0], 'definition'): # aliased command
353 357 source = entry[0].source
354 358 if entry[0].definition.startswith('!'): # shell alias
355 359 doc = (_('shell alias for::\n\n %s\n\ndefined by: %s\n') %
356 360 (entry[0].definition[1:], source))
357 361 else:
358 362 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
359 363 (entry[0].definition, doc, source))
360 364 doc = doc.splitlines(True)
361 365 if ui.quiet or not full:
362 366 rst.append(doc[0])
363 367 else:
364 368 rst.extend(doc)
365 369 rst.append('\n')
366 370
367 371 # check if this command shadows a non-trivial (multi-line)
368 372 # extension help text
369 373 try:
370 374 mod = extensions.find(name)
371 375 doc = gettext(pycompat.getdoc(mod)) or ''
372 376 if '\n' in doc.strip():
373 377 msg = _("(use 'hg help -e %s' to show help for "
374 378 "the %s extension)") % (name, name)
375 379 rst.append('\n%s\n' % msg)
376 380 except KeyError:
377 381 pass
378 382
379 383 # options
380 384 if not ui.quiet and entry[1]:
381 385 rst.append(optrst(_("options"), entry[1], ui.verbose))
382 386
383 387 if ui.verbose:
384 388 rst.append(optrst(_("global options"),
385 389 commands.globalopts, ui.verbose))
386 390
387 391 if not ui.verbose:
388 392 if not full:
389 393 rst.append(_("\n(use 'hg %s -h' to show more help)\n")
390 394 % name)
391 395 elif not ui.quiet:
392 396 rst.append(_('\n(some details hidden, use --verbose '
393 397 'to show complete help)'))
394 398
395 399 return rst
396 400
397 401
398 402 def helplist(select=None, **opts):
399 403 # list of commands
400 404 if name == "shortlist":
401 405 header = _('basic commands:\n\n')
402 406 elif name == "debug":
403 407 header = _('debug commands (internal and unsupported):\n\n')
404 408 else:
405 409 header = _('list of commands:\n\n')
406 410
407 411 h = {}
408 412 cmds = {}
409 413 for c, e in commands.table.iteritems():
410 414 f = c.partition("|")[0]
411 415 if select and not select(f):
412 416 continue
413 417 if (not select and name != 'shortlist' and
414 418 e[0].__module__ != commands.__name__):
415 419 continue
416 420 if name == "shortlist" and not f.startswith("^"):
417 421 continue
418 422 f = f.lstrip("^")
419 423 doc = pycompat.getdoc(e[0])
420 424 if filtercmd(ui, f, name, doc):
421 425 continue
422 426 doc = gettext(doc)
423 427 if not doc:
424 428 doc = _("(no help text available)")
425 429 h[f] = doc.splitlines()[0].rstrip()
426 430 cmds[f] = c.lstrip("^")
427 431
428 432 rst = []
429 433 if not h:
430 434 if not ui.quiet:
431 435 rst.append(_('no commands defined\n'))
432 436 return rst
433 437
434 438 if not ui.quiet:
435 439 rst.append(header)
436 440 fns = sorted(h)
437 441 for f in fns:
438 442 if ui.verbose:
439 443 commacmds = cmds[f].replace("|",", ")
440 444 rst.append(" :%s: %s\n" % (commacmds, h[f]))
441 445 else:
442 446 rst.append(' :%s: %s\n' % (f, h[f]))
443 447
444 448 ex = opts.get
445 449 anyopts = (ex('keyword') or not (ex('command') or ex('extension')))
446 450 if not name and anyopts:
447 451 exts = listexts(_('enabled extensions:'), extensions.enabled())
448 452 if exts:
449 453 rst.append('\n')
450 454 rst.extend(exts)
451 455
452 456 rst.append(_("\nadditional help topics:\n\n"))
453 457 topics = []
454 458 for names, header, doc in helptable:
455 459 topics.append((names[0], header))
456 460 for t, desc in topics:
457 461 rst.append(" :%s: %s\n" % (t, desc))
458 462
459 463 if ui.quiet:
460 464 pass
461 465 elif ui.verbose:
462 466 rst.append('\n%s\n' % optrst(_("global options"),
463 467 commands.globalopts, ui.verbose))
464 468 if name == 'shortlist':
465 469 rst.append(_("\n(use 'hg help' for the full list "
466 470 "of commands)\n"))
467 471 else:
468 472 if name == 'shortlist':
469 473 rst.append(_("\n(use 'hg help' for the full list of commands "
470 474 "or 'hg -v' for details)\n"))
471 475 elif name and not full:
472 476 rst.append(_("\n(use 'hg help %s' to show the full help "
473 477 "text)\n") % name)
474 478 elif name and cmds and name in cmds.keys():
475 479 rst.append(_("\n(use 'hg help -v -e %s' to show built-in "
476 480 "aliases and global options)\n") % name)
477 481 else:
478 482 rst.append(_("\n(use 'hg help -v%s' to show built-in aliases "
479 483 "and global options)\n")
480 484 % (name and " " + name or ""))
481 485 return rst
482 486
483 487 def helptopic(name, subtopic=None):
484 488 # Look for sub-topic entry first.
485 489 header, doc = None, None
486 490 if subtopic and name in subtopics:
487 491 for names, header, doc in subtopics[name]:
488 492 if subtopic in names:
489 493 break
490 494
491 495 if not header:
492 496 for names, header, doc in helptable:
493 497 if name in names:
494 498 break
495 499 else:
496 500 raise error.UnknownCommand(name)
497 501
498 502 rst = [minirst.section(header)]
499 503
500 504 # description
501 505 if not doc:
502 506 rst.append(" %s\n" % _("(no help text available)"))
503 507 if callable(doc):
504 508 rst += [" %s\n" % l for l in doc(ui).splitlines()]
505 509
506 510 if not ui.verbose:
507 511 omitted = _('(some details hidden, use --verbose'
508 512 ' to show complete help)')
509 513 indicateomitted(rst, omitted)
510 514
511 515 try:
512 516 cmdutil.findcmd(name, commands.table)
513 517 rst.append(_("\nuse 'hg help -c %s' to see help for "
514 518 "the %s command\n") % (name, name))
515 519 except error.UnknownCommand:
516 520 pass
517 521 return rst
518 522
519 523 def helpext(name, subtopic=None):
520 524 try:
521 525 mod = extensions.find(name)
522 526 doc = gettext(pycompat.getdoc(mod)) or _('no help text available')
523 527 except KeyError:
524 528 mod = None
525 529 doc = extensions.disabledext(name)
526 530 if not doc:
527 531 raise error.UnknownCommand(name)
528 532
529 533 if '\n' not in doc:
530 534 head, tail = doc, ""
531 535 else:
532 536 head, tail = doc.split('\n', 1)
533 537 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
534 538 if tail:
535 539 rst.extend(tail.splitlines(True))
536 540 rst.append('\n')
537 541
538 542 if not ui.verbose:
539 543 omitted = _('(some details hidden, use --verbose'
540 544 ' to show complete help)')
541 545 indicateomitted(rst, omitted)
542 546
543 547 if mod:
544 548 try:
545 549 ct = mod.cmdtable
546 550 except AttributeError:
547 551 ct = {}
548 552 modcmds = set([c.partition('|')[0] for c in ct])
549 553 rst.extend(helplist(modcmds.__contains__))
550 554 else:
551 555 rst.append(_("(use 'hg help extensions' for information on enabling"
552 556 " extensions)\n"))
553 557 return rst
554 558
555 559 def helpextcmd(name, subtopic=None):
556 560 cmd, ext, mod = extensions.disabledcmd(ui, name,
557 561 ui.configbool('ui', 'strict'))
558 562 doc = gettext(pycompat.getdoc(mod)).splitlines()[0]
559 563
560 564 rst = listexts(_("'%s' is provided by the following "
561 565 "extension:") % cmd, {ext: doc}, indent=4,
562 566 showdeprecated=True)
563 567 rst.append('\n')
564 568 rst.append(_("(use 'hg help extensions' for information on enabling "
565 569 "extensions)\n"))
566 570 return rst
567 571
568 572
569 573 rst = []
570 574 kw = opts.get('keyword')
571 575 if kw or name is None and any(opts[o] for o in opts):
572 576 matches = topicmatch(ui, commands, name or '')
573 577 helpareas = []
574 578 if opts.get('extension'):
575 579 helpareas += [('extensions', _('Extensions'))]
576 580 if opts.get('command'):
577 581 helpareas += [('commands', _('Commands'))]
578 582 if not helpareas:
579 583 helpareas = [('topics', _('Topics')),
580 584 ('commands', _('Commands')),
581 585 ('extensions', _('Extensions')),
582 586 ('extensioncommands', _('Extension Commands'))]
583 587 for t, title in helpareas:
584 588 if matches[t]:
585 589 rst.append('%s:\n\n' % title)
586 590 rst.extend(minirst.maketable(sorted(matches[t]), 1))
587 591 rst.append('\n')
588 592 if not rst:
589 593 msg = _('no matches')
590 594 hint = _("try 'hg help' for a list of topics")
591 595 raise error.Abort(msg, hint=hint)
592 596 elif name and name != 'shortlist':
593 597 queries = []
594 598 if unknowncmd:
595 599 queries += [helpextcmd]
596 600 if opts.get('extension'):
597 601 queries += [helpext]
598 602 if opts.get('command'):
599 603 queries += [helpcmd]
600 604 if not queries:
601 605 queries = (helptopic, helpcmd, helpext, helpextcmd)
602 606 for f in queries:
603 607 try:
604 608 rst = f(name, subtopic)
605 609 break
606 610 except error.UnknownCommand:
607 611 pass
608 612 else:
609 613 if unknowncmd:
610 614 raise error.UnknownCommand(name)
611 615 else:
612 616 msg = _('no such help topic: %s') % name
613 617 hint = _("try 'hg help --keyword %s'") % name
614 618 raise error.Abort(msg, hint=hint)
615 619 else:
616 620 # program name
617 621 if not ui.quiet:
618 622 rst = [_("Mercurial Distributed SCM\n"), '\n']
619 623 rst.extend(helplist(None, **pycompat.strkwargs(opts)))
620 624
621 625 return ''.join(rst)
622 626
623 627 def formattedhelp(ui, commands, name, keep=None, unknowncmd=False, full=True,
624 628 **opts):
625 629 """get help for a given topic (as a dotted name) as rendered rst
626 630
627 631 Either returns the rendered help text or raises an exception.
628 632 """
629 633 if keep is None:
630 634 keep = []
631 635 else:
632 636 keep = list(keep) # make a copy so we can mutate this later
633 637 fullname = name
634 638 section = None
635 639 subtopic = None
636 640 if name and '.' in name:
637 641 name, remaining = name.split('.', 1)
638 642 remaining = encoding.lower(remaining)
639 643 if '.' in remaining:
640 644 subtopic, section = remaining.split('.', 1)
641 645 else:
642 646 if name in subtopics:
643 647 subtopic = remaining
644 648 else:
645 649 section = remaining
646 650 textwidth = ui.configint('ui', 'textwidth', 78)
647 651 termwidth = ui.termwidth() - 2
648 652 if textwidth <= 0 or termwidth < textwidth:
649 653 textwidth = termwidth
650 654 text = help_(ui, commands, name,
651 655 subtopic=subtopic, unknowncmd=unknowncmd, full=full, **opts)
652 656
653 657 formatted, pruned = minirst.format(text, textwidth, keep=keep,
654 658 section=section)
655 659
656 660 # We could have been given a weird ".foo" section without a name
657 661 # to look for, or we could have simply failed to found "foo.bar"
658 662 # because bar isn't a section of foo
659 663 if section and not (formatted and name):
660 664 raise error.Abort(_("help section not found: %s") % fullname)
661 665
662 666 if 'verbose' in pruned:
663 667 keep.append('omitted')
664 668 else:
665 669 keep.append('notomitted')
666 670 formatted, pruned = minirst.format(text, textwidth, keep=keep,
667 671 section=section)
668 672 return formatted
General Comments 0
You need to be logged in to leave comments. Login now