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