changeset 51882:76387080f238

help: add :config-doc:`section.key` shorthand to insert documentation The config items defined in the configitems.toml file can already hold their documentation. Having some way to automatically insert it was a long standing low hanging fruit. So I did a first implementation on that. It fairly simple, but it open the door to more. It will be used in the next changeset.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 05 Sep 2024 12:28:12 +0200
parents fe08a0bfa9fd
children cd72a88c5599
files doc/gendoc.py mercurial/help.py
diffstat 2 files changed, 55 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/doc/gendoc.py	Wed Sep 11 20:52:51 2024 +0200
+++ b/doc/gendoc.py	Thu Sep 05 12:28:12 2024 +0200
@@ -156,7 +156,8 @@
     for extensionname in sorted(allextensionnames()):
         mod = extensions.load(ui, extensionname, None)
         ui.write(minirst.subsection(extensionname))
-        ui.write(b"%s\n\n" % gettext(pycompat.getdoc(mod)))
+        ext_doc = help.ext_help(ui, mod)
+        ui.write(b"%s\n\n" % ext_doc)
         cmdtable = getattr(mod, 'cmdtable', None)
         if cmdtable:
             ui.write(minirst.subsubsection(_(b'Commands')))
--- a/mercurial/help.py	Wed Sep 11 20:52:51 2024 +0200
+++ b/mercurial/help.py	Thu Sep 05 12:28:12 2024 +0200
@@ -159,6 +159,15 @@
     return rst
 
 
+def ext_help(ui: uimod.ui, ext) -> bytes:
+    doc = pycompat.getdoc(ext)
+    if doc is None:
+        return b""
+    assert doc is not None
+    doc = gettext(doc)
+    return sub_config_item_help(ui, doc)
+
+
 def extshelp(ui: uimod.ui) -> bytes:
     rst = loaddoc(b'extensions')(ui).splitlines(True)
     rst.extend(
@@ -365,6 +374,7 @@
             doc = gettext(fp.read())
         for rewriter in helphooks.get(topic, []):
             doc = rewriter(ui, topic, doc)
+        doc = sub_config_item_help(ui, doc)
         return doc
 
     return loader
@@ -695,6 +705,44 @@
     return re.sub(br'( *)%s' % re.escape(marker), sub, doc)
 
 
+_CONFIG_DOC_RE = re.compile(b'(^ *)?:config-doc:`([^`]+)`', flags=re.MULTILINE)
+
+
+def sub_config_item_help(ui: uimod.ui, doc: bytes) -> bytes:
+    """replace :config-doc:`foo.bar` markup with the item documentation
+
+    This allow grouping config item declaration and help without having to
+    repeat it in the help text file and keep that in sync.
+    """
+    pieces = []
+    last_match_end = 0
+    for match in _CONFIG_DOC_RE.finditer(doc):
+        # finditer is expected to yield result in order
+        start = match.start()
+        assert last_match_end <= match.start()
+        pieces.append(doc[last_match_end:start])
+        item_name = match.group(2)
+        section, key = item_name.split(b'.', 1)
+        section_items = ui._knownconfig.get(section)
+        if section_items is None:
+            item = None
+        else:
+            item = section_items.get(key)
+        if item is None or not item.documentation:
+            item_doc = b'<missing help text for `%s`>' % item_name
+        else:
+            item_doc = gettext(item.documentation)
+            item_doc = sub_config_item_help(ui, item_doc)
+            indent = match.group(1)
+            if indent:  # either None or 0 should be ignored
+                indent = indent
+                item_doc = indent + item_doc.replace(b'\n', b'\n' + indent)
+        pieces.append(item_doc)
+        last_match_end = match.end()
+    pieces.append(doc[last_match_end:])
+    return b''.join(pieces)
+
+
 def _getcategorizedhelpcmds(
     ui: uimod.ui, cmdtable, name: bytes, select: Optional[_SelectFn] = None
 ) -> Tuple[Dict[bytes, List[bytes]], Dict[bytes, bytes], _SynonymTable]:
@@ -822,6 +870,7 @@
                     doc,
                     source,
                 )
+        doc = sub_config_item_help(ui, doc)
         doc = doc.splitlines(True)
         if ui.quiet or not full:
             rst.append(doc[0])
@@ -1042,12 +1091,15 @@
     def helpext(name: bytes, subtopic: Optional[bytes] = None) -> List[bytes]:
         try:
             mod = extensions.find(name)
-            doc = gettext(pycompat.getdoc(mod)) or _(b'no help text available')
+            doc = ext_help(ui, mod)
+            if not doc:
+                doc = _(b'no help text available')
         except KeyError:
             mod = None
             doc = extensions.disabled_help(name)
             if not doc:
                 raise error.UnknownCommand(name)
+            doc = sub_config_item_help(ui, doc)
 
         if b'\n' not in doc:
             head, tail = doc, b""