Mercurial > public > mercurial-scm > hg
comparison mercurial/help.py @ 40291:170926caf44c
help: adding support for command categories
Differential Revision: https://phab.mercurial-scm.org/D5065
author | rdamazio@google.com |
---|---|
date | Sat, 13 Oct 2018 05:03:50 -0700 |
parents | 8cf459d8b111 |
children | 9c6473d2038b |
comparison
equal
deleted
inserted
replaced
40290:091f9b8a1051 | 40291:170926caf44c |
---|---|
23 fancyopts, | 23 fancyopts, |
24 filemerge, | 24 filemerge, |
25 fileset, | 25 fileset, |
26 minirst, | 26 minirst, |
27 pycompat, | 27 pycompat, |
28 registrar, | |
28 revset, | 29 revset, |
29 templatefilters, | 30 templatefilters, |
30 templatefuncs, | 31 templatefuncs, |
31 templatekw, | 32 templatekw, |
32 util, | 33 util, |
43 _("(ADVANCED)"), | 44 _("(ADVANCED)"), |
44 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently | 45 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently |
45 _("(DEPRECATED)"), | 46 _("(DEPRECATED)"), |
46 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently | 47 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently |
47 _("(EXPERIMENTAL)"), | 48 _("(EXPERIMENTAL)"), |
49 } | |
50 | |
51 # The order in which command categories will be displayed. | |
52 # Extensions with custom categories should insert them into this list | |
53 # after/before the appropriate item, rather than replacing the list or | |
54 # assuming absolute positions. | |
55 CATEGORY_ORDER = [ | |
56 registrar.command.CATEGORY_NONE, | |
57 ] | |
58 | |
59 # Human-readable category names. These are translated. | |
60 # Extensions with custom categories should add their names here. | |
61 CATEGORY_NAMES = { | |
62 registrar.command.CATEGORY_NONE: 'Uncategorized commands', | |
48 } | 63 } |
49 | 64 |
50 def listexts(header, exts, indent=1, showdeprecated=False): | 65 def listexts(header, exts, indent=1, showdeprecated=False): |
51 '''return a text listing of the given extensions''' | 66 '''return a text listing of the given extensions''' |
52 rst = [] | 67 rst = [] |
417 rst.append(_('\n(some details hidden, use --verbose ' | 432 rst.append(_('\n(some details hidden, use --verbose ' |
418 'to show complete help)')) | 433 'to show complete help)')) |
419 | 434 |
420 return rst | 435 return rst |
421 | 436 |
422 | |
423 def helplist(select=None, **opts): | 437 def helplist(select=None, **opts): |
424 # list of commands | 438 # Category -> list of commands |
425 if name == "shortlist": | 439 cats = {} |
426 header = _('basic commands:\n\n') | 440 # Command -> short description |
427 elif name == "debug": | |
428 header = _('debug commands (internal and unsupported):\n\n') | |
429 else: | |
430 header = _('list of commands:\n\n') | |
431 | |
432 h = {} | 441 h = {} |
433 cmds = {} | 442 # Command -> string showing synonyms |
443 syns = {} | |
434 for c, e in commands.table.iteritems(): | 444 for c, e in commands.table.iteritems(): |
435 fs = cmdutil.parsealiases(c) | 445 fs = cmdutil.parsealiases(c) |
436 f = fs[0] | 446 f = fs[0] |
447 syns[f] = ', '.join(fs) | |
448 func = e[0] | |
437 p = '' | 449 p = '' |
438 if c.startswith("^"): | 450 if c.startswith("^"): |
439 p = '^' | 451 p = '^' |
440 if select and not select(p + f): | 452 if select and not select(p + f): |
441 continue | 453 continue |
442 if (not select and name != 'shortlist' and | 454 if (not select and name != 'shortlist' and |
443 e[0].__module__ != commands.__name__): | 455 func.__module__ != commands.__name__): |
444 continue | 456 continue |
445 if name == "shortlist" and not p: | 457 if name == "shortlist" and not p: |
446 continue | 458 continue |
447 doc = pycompat.getdoc(e[0]) | 459 doc = pycompat.getdoc(func) |
448 if filtercmd(ui, f, name, doc): | 460 if filtercmd(ui, f, name, doc): |
449 continue | 461 continue |
450 doc = gettext(doc) | 462 doc = gettext(doc) |
451 if not doc: | 463 if not doc: |
452 doc = _("(no help text available)") | 464 doc = _("(no help text available)") |
453 h[f] = doc.splitlines()[0].rstrip() | 465 h[f] = doc.splitlines()[0].rstrip() |
454 cmds[f] = '|'.join(fs) | 466 |
467 cat = getattr(func, 'helpcategory', None) or ( | |
468 registrar.command.CATEGORY_NONE) | |
469 cats.setdefault(cat, []).append(f) | |
455 | 470 |
456 rst = [] | 471 rst = [] |
457 if not h: | 472 if not h: |
458 if not ui.quiet: | 473 if not ui.quiet: |
459 rst.append(_('no commands defined\n')) | 474 rst.append(_('no commands defined\n')) |
460 return rst | 475 return rst |
461 | 476 |
477 # Output top header. | |
462 if not ui.quiet: | 478 if not ui.quiet: |
463 rst.append(header) | 479 if name == "shortlist": |
464 fns = sorted(h) | 480 rst.append(_('basic commands:\n\n')) |
465 for f in fns: | 481 elif name == "debug": |
466 if ui.verbose: | 482 rst.append(_('debug commands (internal and unsupported):\n\n')) |
467 commacmds = cmds[f].replace("|",", ") | |
468 rst.append(" :%s: %s\n" % (commacmds, h[f])) | |
469 else: | 483 else: |
470 rst.append(' :%s: %s\n' % (f, h[f])) | 484 rst.append(_('list of commands:\n')) |
485 | |
486 def appendcmds(cmds): | |
487 cmds = sorted(cmds) | |
488 for c in cmds: | |
489 if ui.verbose: | |
490 rst.append(" :%s: %s\n" % (syns[c], h[c])) | |
491 else: | |
492 rst.append(' :%s: %s\n' % (c, h[c])) | |
493 | |
494 if name in ('shortlist', 'debug'): | |
495 # List without categories. | |
496 appendcmds(h) | |
497 else: | |
498 # Check that all categories have an order. | |
499 missing_order = set(cats.keys()) - set(CATEGORY_ORDER) | |
500 if missing_order: | |
501 ui.develwarn('help categories missing from CATEGORY_ORDER: %s' % | |
502 missing_order) | |
503 | |
504 # List per category. | |
505 for cat in CATEGORY_ORDER: | |
506 catfns = cats.get(cat, []) | |
507 if catfns: | |
508 if len(cats) > 1: | |
509 catname = gettext(CATEGORY_NAMES[cat]) | |
510 rst.append("\n%s:\n" % catname) | |
511 rst.append("\n") | |
512 appendcmds(catfns) | |
471 | 513 |
472 ex = opts.get | 514 ex = opts.get |
473 anyopts = (ex(r'keyword') or not (ex(r'command') or ex(r'extension'))) | 515 anyopts = (ex(r'keyword') or not (ex(r'command') or ex(r'extension'))) |
474 if not name and anyopts: | 516 if not name and anyopts: |
475 exts = listexts(_('enabled extensions:'), extensions.enabled()) | 517 exts = listexts(_('enabled extensions:'), extensions.enabled()) |
497 rst.append(_("\n(use 'hg help' for the full list of commands " | 539 rst.append(_("\n(use 'hg help' for the full list of commands " |
498 "or 'hg -v' for details)\n")) | 540 "or 'hg -v' for details)\n")) |
499 elif name and not full: | 541 elif name and not full: |
500 rst.append(_("\n(use 'hg help %s' to show the full help " | 542 rst.append(_("\n(use 'hg help %s' to show the full help " |
501 "text)\n") % name) | 543 "text)\n") % name) |
502 elif name and cmds and name in cmds.keys(): | 544 elif name and syns and name in syns.keys(): |
503 rst.append(_("\n(use 'hg help -v -e %s' to show built-in " | 545 rst.append(_("\n(use 'hg help -v -e %s' to show built-in " |
504 "aliases and global options)\n") % name) | 546 "aliases and global options)\n") % name) |
505 else: | 547 else: |
506 rst.append(_("\n(use 'hg help -v%s' to show built-in aliases " | 548 rst.append(_("\n(use 'hg help -v%s' to show built-in aliases " |
507 "and global options)\n") | 549 "and global options)\n") |