Show More
@@ -10,6 +10,18 b' import itertools' | |||
|
10 | 10 | import re |
|
11 | 11 | import textwrap |
|
12 | 12 | |
|
13 | from typing import ( | |
|
14 | Callable, | |
|
15 | Dict, | |
|
16 | Iterable, | |
|
17 | List, | |
|
18 | Optional, | |
|
19 | Set, | |
|
20 | Tuple, | |
|
21 | Union, | |
|
22 | cast, | |
|
23 | ) | |
|
24 | ||
|
13 | 25 | from .i18n import ( |
|
14 | 26 | _, |
|
15 | 27 | gettext, |
@@ -40,7 +52,16 b' from .utils import (' | |||
|
40 | 52 | stringutil, |
|
41 | 53 | ) |
|
42 | 54 | |
|
43 | _exclkeywords = { | |
|
55 | _DocLoader = Callable[[uimod.ui], bytes] | |
|
56 | # Old extensions may not register with a category | |
|
57 | _HelpEntry = Union["_HelpEntryNoCategory", "_HelpEntryWithCategory"] | |
|
58 | _HelpEntryNoCategory = Tuple[List[bytes], bytes, _DocLoader] | |
|
59 | _HelpEntryWithCategory = Tuple[List[bytes], bytes, _DocLoader, bytes] | |
|
60 | _SelectFn = Callable[[object], bool] | |
|
61 | _SynonymTable = Dict[bytes, List[bytes]] | |
|
62 | _TopicHook = Callable[[uimod.ui, bytes, bytes], bytes] | |
|
63 | ||
|
64 | _exclkeywords: Set[bytes] = { | |
|
44 | 65 | b"(ADVANCED)", |
|
45 | 66 | b"(DEPRECATED)", |
|
46 | 67 | b"(EXPERIMENTAL)", |
@@ -56,7 +77,7 b' from .utils import (' | |||
|
56 | 77 | # Extensions with custom categories should insert them into this list |
|
57 | 78 | # after/before the appropriate item, rather than replacing the list or |
|
58 | 79 | # assuming absolute positions. |
|
59 | CATEGORY_ORDER = [ | |
|
80 | CATEGORY_ORDER: List[bytes] = [ | |
|
60 | 81 | registrar.command.CATEGORY_REPO_CREATION, |
|
61 | 82 | registrar.command.CATEGORY_REMOTE_REPO_MANAGEMENT, |
|
62 | 83 | registrar.command.CATEGORY_COMMITTING, |
@@ -74,7 +95,7 b' CATEGORY_ORDER = [' | |||
|
74 | 95 | |
|
75 | 96 | # Human-readable category names. These are translated. |
|
76 | 97 | # Extensions with custom categories should add their names here. |
|
77 | CATEGORY_NAMES = { | |
|
98 | CATEGORY_NAMES: Dict[bytes, bytes] = { | |
|
78 | 99 | registrar.command.CATEGORY_REPO_CREATION: b'Repository creation', |
|
79 | 100 | registrar.command.CATEGORY_REMOTE_REPO_MANAGEMENT: b'Remote repository management', |
|
80 | 101 | registrar.command.CATEGORY_COMMITTING: b'Change creation', |
@@ -102,7 +123,7 b" TOPIC_CATEGORY_NONE = b'none'" | |||
|
102 | 123 | # Extensions with custom categories should insert them into this list |
|
103 | 124 | # after/before the appropriate item, rather than replacing the list or |
|
104 | 125 | # assuming absolute positions. |
|
105 | TOPIC_CATEGORY_ORDER = [ | |
|
126 | TOPIC_CATEGORY_ORDER: List[bytes] = [ | |
|
106 | 127 | TOPIC_CATEGORY_IDS, |
|
107 | 128 | TOPIC_CATEGORY_OUTPUT, |
|
108 | 129 | TOPIC_CATEGORY_CONFIG, |
@@ -112,7 +133,7 b' TOPIC_CATEGORY_ORDER = [' | |||
|
112 | 133 | ] |
|
113 | 134 | |
|
114 | 135 | # Human-readable topic category names. These are translated. |
|
115 | TOPIC_CATEGORY_NAMES = { | |
|
136 | TOPIC_CATEGORY_NAMES: Dict[bytes, bytes] = { | |
|
116 | 137 | TOPIC_CATEGORY_IDS: b'Mercurial identifiers', |
|
117 | 138 | TOPIC_CATEGORY_OUTPUT: b'Mercurial output', |
|
118 | 139 | TOPIC_CATEGORY_CONFIG: b'Mercurial configuration', |
@@ -122,7 +143,12 b' TOPIC_CATEGORY_NAMES = {' | |||
|
122 | 143 | } |
|
123 | 144 | |
|
124 | 145 | |
|
125 | def listexts(header, exts, indent=1, showdeprecated=False): | |
|
146 | def listexts( | |
|
147 | header: bytes, | |
|
148 | exts: Dict[bytes, bytes], | |
|
149 | indent: int = 1, | |
|
150 | showdeprecated: bool = False, | |
|
151 | ) -> List[bytes]: | |
|
126 | 152 | '''return a text listing of the given extensions''' |
|
127 | 153 | rst = [] |
|
128 | 154 | if exts: |
@@ -135,7 +161,7 b' def listexts(header, exts, indent=1, sho' | |||
|
135 | 161 | return rst |
|
136 | 162 | |
|
137 | 163 | |
|
138 | def extshelp(ui): | |
|
164 | def extshelp(ui: uimod.ui) -> bytes: | |
|
139 | 165 | rst = loaddoc(b'extensions')(ui).splitlines(True) |
|
140 | 166 | rst.extend( |
|
141 | 167 | listexts( |
@@ -153,7 +179,7 b' def extshelp(ui):' | |||
|
153 | 179 | return doc |
|
154 | 180 | |
|
155 | 181 | |
|
156 | def parsedefaultmarker(text): | |
|
182 | def parsedefaultmarker(text: bytes) -> Optional[Tuple[bytes, List[bytes]]]: | |
|
157 | 183 | """given a text 'abc (DEFAULT: def.ghi)', |
|
158 | 184 | returns (b'abc', (b'def', b'ghi')). Otherwise return None""" |
|
159 | 185 | if text[-1:] == b')': |
@@ -164,7 +190,7 b' def parsedefaultmarker(text):' | |||
|
164 | 190 | return text[:pos], item.split(b'.', 2) |
|
165 | 191 | |
|
166 | 192 | |
|
167 | def optrst(header, options, verbose, ui): | |
|
193 | def optrst(header: bytes, options, verbose: bool, ui: uimod.ui) -> bytes: | |
|
168 | 194 | data = [] |
|
169 | 195 | multioccur = False |
|
170 | 196 | for option in options: |
@@ -220,13 +246,15 b' def optrst(header, options, verbose, ui)' | |||
|
220 | 246 | return b''.join(rst) |
|
221 | 247 | |
|
222 | 248 | |
|
223 | def indicateomitted(rst, omitted, notomitted=None): | |
|
249 | def indicateomitted( | |
|
250 | rst: List[bytes], omitted: bytes, notomitted: Optional[bytes] = None | |
|
251 | ) -> None: | |
|
224 | 252 | rst.append(b'\n\n.. container:: omitted\n\n %s\n\n' % omitted) |
|
225 | 253 | if notomitted: |
|
226 | 254 | rst.append(b'\n\n.. container:: notomitted\n\n %s\n\n' % notomitted) |
|
227 | 255 | |
|
228 | 256 | |
|
229 | def filtercmd(ui, cmd, func, kw, doc): | |
|
257 | def filtercmd(ui: uimod.ui, cmd: bytes, func, kw: bytes, doc: bytes) -> bool: | |
|
230 | 258 | if not ui.debugflag and cmd.startswith(b"debug") and kw != b"debug": |
|
231 | 259 | # Debug command, and user is not looking for those. |
|
232 | 260 | return True |
@@ -249,11 +277,13 b' def filtercmd(ui, cmd, func, kw, doc):' | |||
|
249 | 277 | return False |
|
250 | 278 | |
|
251 | 279 | |
|
252 | def filtertopic(ui, topic): | |
|
280 | def filtertopic(ui: uimod.ui, topic: bytes) -> bool: | |
|
253 | 281 | return ui.configbool(b'help', b'hidden-topic.%s' % topic, False) |
|
254 | 282 | |
|
255 | 283 | |
|
256 |
def topicmatch( |
|
|
284 | def topicmatch( | |
|
285 | ui: uimod.ui, commands, kw: bytes | |
|
286 | ) -> Dict[bytes, List[Tuple[bytes, bytes]]]: | |
|
257 | 287 | """Return help topics matching kw. |
|
258 | 288 | |
|
259 | 289 | Returns {'section': [(name, summary), ...], ...} where section is |
@@ -326,10 +356,10 b' def topicmatch(ui, commands, kw):' | |||
|
326 | 356 | return results |
|
327 | 357 | |
|
328 | 358 | |
|
329 | def loaddoc(topic, subdir=None): | |
|
359 | def loaddoc(topic: bytes, subdir: Optional[bytes] = None) -> _DocLoader: | |
|
330 | 360 | """Return a delayed loader for help/topic.txt.""" |
|
331 | 361 | |
|
332 | def loader(ui): | |
|
362 | def loader(ui: uimod.ui) -> bytes: | |
|
333 | 363 | package = b'mercurial.helptext' |
|
334 | 364 | if subdir: |
|
335 | 365 | package += b'.' + subdir |
@@ -342,7 +372,7 b' def loaddoc(topic, subdir=None):' | |||
|
342 | 372 | return loader |
|
343 | 373 | |
|
344 | 374 | |
|
345 | internalstable = sorted( | |
|
375 | internalstable: List[_HelpEntryNoCategory] = sorted( | |
|
346 | 376 | [ |
|
347 | 377 | ( |
|
348 | 378 | [b'bid-merge'], |
@@ -407,7 +437,7 b' internalstable = sorted(' | |||
|
407 | 437 | ) |
|
408 | 438 | |
|
409 | 439 | |
|
410 | def internalshelp(ui): | |
|
440 | def internalshelp(ui: uimod.ui) -> bytes: | |
|
411 | 441 | """Generate the index for the "internals" topic.""" |
|
412 | 442 | lines = [ |
|
413 | 443 | b'To access a subtopic, use "hg help internals.{subtopic-name}"\n', |
@@ -419,7 +449,7 b' def internalshelp(ui):' | |||
|
419 | 449 | return b''.join(lines) |
|
420 | 450 | |
|
421 | 451 | |
|
422 | helptable = sorted( | |
|
452 | helptable: List[_HelpEntryWithCategory] = sorted( | |
|
423 | 453 | [ |
|
424 | 454 | ( |
|
425 | 455 | [b'bundlespec'], |
@@ -581,20 +611,27 b' helptable = sorted(' | |||
|
581 | 611 | ) |
|
582 | 612 | |
|
583 | 613 | # Maps topics with sub-topics to a list of their sub-topics. |
|
584 | subtopics = { | |
|
614 | subtopics: Dict[bytes, List[_HelpEntryNoCategory]] = { | |
|
585 | 615 | b'internals': internalstable, |
|
586 | 616 | } |
|
587 | 617 | |
|
588 | 618 | # Map topics to lists of callable taking the current topic help and |
|
589 | 619 | # returning the updated version |
|
590 | helphooks = {} | |
|
620 | helphooks: Dict[bytes, List[_TopicHook]] = {} | |
|
591 | 621 | |
|
592 | 622 | |
|
593 | def addtopichook(topic, rewriter): | |
|
623 | def addtopichook(topic: bytes, rewriter: _TopicHook) -> None: | |
|
594 | 624 | helphooks.setdefault(topic, []).append(rewriter) |
|
595 | 625 | |
|
596 | 626 | |
|
597 | def makeitemsdoc(ui, topic, doc, marker, items, dedent=False): | |
|
627 | def makeitemsdoc( | |
|
628 | ui: uimod.ui, | |
|
629 | topic: bytes, | |
|
630 | doc: bytes, | |
|
631 | marker: bytes, | |
|
632 | items: Dict[bytes, bytes], | |
|
633 | dedent: bool = False, | |
|
634 | ) -> bytes: | |
|
598 | 635 | """Extract docstring from the items key to function mapping, build a |
|
599 | 636 | single documentation block and use it to overwrite the marker in doc. |
|
600 | 637 | """ |
@@ -622,8 +659,10 b' def makeitemsdoc(ui, topic, doc, marker,' | |||
|
622 | 659 | return doc.replace(marker, entries) |
|
623 | 660 | |
|
624 | 661 | |
|
625 | def addtopicsymbols(topic, marker, symbols, dedent=False): | |
|
626 | def add(ui, topic, doc): | |
|
662 | def addtopicsymbols( | |
|
663 | topic: bytes, marker: bytes, symbols, dedent: bool = False | |
|
664 | ) -> None: | |
|
665 | def add(ui: uimod.ui, topic: bytes, doc: bytes): | |
|
627 | 666 | return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent) |
|
628 | 667 | |
|
629 | 668 | addtopichook(topic, add) |
@@ -647,7 +686,7 b' addtopicsymbols(' | |||
|
647 | 686 | ) |
|
648 | 687 | |
|
649 | 688 | |
|
650 | def inserttweakrc(ui, topic, doc): | |
|
689 | def inserttweakrc(ui: uimod.ui, topic: bytes, doc: bytes) -> bytes: | |
|
651 | 690 | marker = b'.. tweakdefaultsmarker' |
|
652 | 691 | repl = uimod.tweakrc |
|
653 | 692 | |
@@ -658,7 +697,9 b' def inserttweakrc(ui, topic, doc):' | |||
|
658 | 697 | return re.sub(br'( *)%s' % re.escape(marker), sub, doc) |
|
659 | 698 | |
|
660 | 699 | |
|
661 |
def _getcategorizedhelpcmds( |
|
|
700 | def _getcategorizedhelpcmds( | |
|
701 | ui: uimod.ui, cmdtable, name: bytes, select: Optional[_SelectFn] = None | |
|
702 | ) -> Tuple[Dict[bytes, List[bytes]], Dict[bytes, bytes], _SynonymTable]: | |
|
662 | 703 | # Category -> list of commands |
|
663 | 704 | cats = {} |
|
664 | 705 | # Command -> short description |
@@ -687,16 +728,18 b' def _getcategorizedhelpcmds(ui, cmdtable' | |||
|
687 | 728 | return cats, h, syns |
|
688 | 729 | |
|
689 | 730 | |
|
690 |
def _getcategorizedhelptopics( |
|
|
731 | def _getcategorizedhelptopics( | |
|
732 | ui: uimod.ui, topictable: List[_HelpEntry] | |
|
733 | ) -> Tuple[Dict[bytes, List[Tuple[bytes, bytes]]], Dict[bytes, List[bytes]]]: | |
|
691 | 734 | # Group commands by category. |
|
692 | 735 | topiccats = {} |
|
693 | 736 | syns = {} |
|
694 | 737 | for topic in topictable: |
|
695 | 738 | names, header, doc = topic[0:3] |
|
696 | 739 | if len(topic) > 3 and topic[3]: |
|
697 | category = topic[3] | |
|
740 | category: bytes = cast(bytes, topic[3]) # help pytype | |
|
698 | 741 | else: |
|
699 | category = TOPIC_CATEGORY_NONE | |
|
742 | category: bytes = TOPIC_CATEGORY_NONE | |
|
700 | 743 | |
|
701 | 744 | topicname = names[0] |
|
702 | 745 | syns[topicname] = list(names) |
@@ -709,15 +752,15 b" addtopichook(b'config', inserttweakrc)" | |||
|
709 | 752 | |
|
710 | 753 | |
|
711 | 754 | def help_( |
|
712 | ui, | |
|
755 | ui: uimod.ui, | |
|
713 | 756 | commands, |
|
714 | name, | |
|
715 | unknowncmd=False, | |
|
716 | full=True, | |
|
717 | subtopic=None, | |
|
718 | fullname=None, | |
|
757 | name: bytes, | |
|
758 | unknowncmd: bool = False, | |
|
759 | full: bool = True, | |
|
760 | subtopic: Optional[bytes] = None, | |
|
761 | fullname: Optional[bytes] = None, | |
|
719 | 762 | **opts |
|
720 | ): | |
|
763 | ) -> bytes: | |
|
721 | 764 | """ |
|
722 | 765 | Generate the help for 'name' as unformatted restructured text. If |
|
723 | 766 | 'name' is None, describe the commands available. |
@@ -725,7 +768,7 b' def help_(' | |||
|
725 | 768 | |
|
726 | 769 | opts = pycompat.byteskwargs(opts) |
|
727 | 770 | |
|
728 |
def helpcmd(name, subtopic |
|
|
771 | def helpcmd(name: bytes, subtopic: Optional[bytes]) -> List[bytes]: | |
|
729 | 772 | try: |
|
730 | 773 | aliases, entry = cmdutil.findcmd( |
|
731 | 774 | name, commands.table, strict=unknowncmd |
@@ -826,7 +869,7 b' def help_(' | |||
|
826 | 869 | |
|
827 | 870 | return rst |
|
828 | 871 | |
|
829 | def helplist(select=None, **opts): | |
|
872 | def helplist(select: Optional[_SelectFn] = None, **opts) -> List[bytes]: | |
|
830 | 873 | cats, h, syns = _getcategorizedhelpcmds( |
|
831 | 874 | ui, commands.table, name, select |
|
832 | 875 | ) |
@@ -846,7 +889,7 b' def help_(' | |||
|
846 | 889 | else: |
|
847 | 890 | rst.append(_(b'list of commands:\n')) |
|
848 | 891 | |
|
849 | def appendcmds(cmds): | |
|
892 | def appendcmds(cmds: Iterable[bytes]) -> None: | |
|
850 | 893 | cmds = sorted(cmds) |
|
851 | 894 | for c in cmds: |
|
852 | 895 | display_cmd = c |
@@ -955,7 +998,7 b' def help_(' | |||
|
955 | 998 | ) |
|
956 | 999 | return rst |
|
957 | 1000 | |
|
958 | def helptopic(name, subtopic=None): | |
|
1001 | def helptopic(name: bytes, subtopic: Optional[bytes] = None) -> List[bytes]: | |
|
959 | 1002 | # Look for sub-topic entry first. |
|
960 | 1003 | header, doc = None, None |
|
961 | 1004 | if subtopic and name in subtopics: |
@@ -998,7 +1041,7 b' def help_(' | |||
|
998 | 1041 | pass |
|
999 | 1042 | return rst |
|
1000 | 1043 | |
|
1001 | def helpext(name, subtopic=None): | |
|
1044 | def helpext(name: bytes, subtopic: Optional[bytes] = None) -> List[bytes]: | |
|
1002 | 1045 | try: |
|
1003 | 1046 | mod = extensions.find(name) |
|
1004 | 1047 | doc = gettext(pycompat.getdoc(mod)) or _(b'no help text available') |
@@ -1040,7 +1083,9 b' def help_(' | |||
|
1040 | 1083 | ) |
|
1041 | 1084 | return rst |
|
1042 | 1085 | |
|
1043 |
def helpextcmd( |
|
|
1086 | def helpextcmd( | |
|
1087 | name: bytes, subtopic: Optional[bytes] = None | |
|
1088 | ) -> List[bytes]: | |
|
1044 | 1089 | cmd, ext, doc = extensions.disabledcmd( |
|
1045 | 1090 | ui, name, ui.configbool(b'ui', b'strict') |
|
1046 | 1091 | ) |
@@ -1127,8 +1172,14 b' def help_(' | |||
|
1127 | 1172 | |
|
1128 | 1173 | |
|
1129 | 1174 | def formattedhelp( |
|
1130 | ui, commands, fullname, keep=None, unknowncmd=False, full=True, **opts | |
|
1131 | ): | |
|
1175 | ui: uimod.ui, | |
|
1176 | commands, | |
|
1177 | fullname: Optional[bytes], | |
|
1178 | keep: Optional[Iterable[bytes]] = None, | |
|
1179 | unknowncmd: bool = False, | |
|
1180 | full: bool = True, | |
|
1181 | **opts | |
|
1182 | ) -> bytes: | |
|
1132 | 1183 | """get help for a given topic (as a dotted name) as rendered rst |
|
1133 | 1184 | |
|
1134 | 1185 | Either returns the rendered help text or raises an exception. |
General Comments 0
You need to be logged in to leave comments.
Login now