qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Peter Xu" <peterx@redhat.com>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Gerd Hoffmann" <kraxel@redhat.com>,
	"Fabiano Rosas" <farosas@suse.de>,
	"Pavel Dovgalyuk" <pavel.dovgaluk@ispras.ru>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Ani Sinha" <anisinha@redhat.com>,
	"Michael Roth" <michael.roth@amd.com>,
	"Kevin Wolf" <kwolf@redhat.com>, "Jiri Pirko" <jiri@resnulli.us>,
	"Mads Ynddal" <mads@ynddal.dk>,
	"Jason Wang" <jasowang@redhat.com>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	qemu-block@nongnu.org,
	"Stefan Berger" <stefanb@linux.vnet.ibm.com>,
	"Victor Toso de Carvalho" <victortoso@redhat.com>,
	"Eric Blake" <eblake@redhat.com>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	"Konstantin Kostiuk" <kkostiuk@redhat.com>,
	"Lukas Straub" <lukasstraub2@web.de>,
	"Yanan Wang" <wangyanan55@huawei.com>,
	"Hanna Reitz" <hreitz@redhat.com>, "John Snow" <jsnow@redhat.com>
Subject: [PATCH 04/20] qapi/parser: preserve indentation in QAPIDoc sections
Date: Tue, 14 May 2024 17:57:23 -0400	[thread overview]
Message-ID: <20240514215740.940155-5-jsnow@redhat.com> (raw)
In-Reply-To: <20240514215740.940155-1-jsnow@redhat.com>

Prior to this patch, a section like this:

@name: lorem ipsum
   dolor sit amet
     consectetur adipiscing elit

would be parsed as:

"lorem ipsum\ndolor sit amet\n  consectetur adipiscing elit"

We want to preserve the indentation for even the first body line so that
the entire block can be parsed directly as rST. This patch would now
parse that segment as:

"lorem ipsum\n   dolor sit amet\n     consectetur adipiscing elit"

This understandably breaks qapidoc.py; so a new function is added there
to re-dedent the text. Once the new generator is merged, this function
will not be needed any longer and can be dropped.

(I verified this patch changes absolutely nothing by comparing the
md5sums of the QMP ref html pages both before and after the change, so
it's certified inert. QAPI test output has been updated to reflect the
new strategy of preserving indents for rST.)

Signed-off-by: John Snow <jsnow@redhat.com>
---
 docs/sphinx/qapidoc.py         | 36 +++++++++++++++++++++++++++++-----
 scripts/qapi/parser.py         |  8 ++++++--
 tests/qapi-schema/doc-good.out | 32 +++++++++++++++---------------
 3 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 1655682d4c7..2e3ffcbafb7 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -26,6 +26,7 @@
 
 import os
 import re
+import textwrap
 
 from docutils import nodes
 from docutils.parsers.rst import Directive, directives
@@ -51,6 +52,28 @@
 __version__ = "1.0"
 
 
+def dedent(text: str) -> str:
+    # Temporary: In service of the new QAPI domain, the QAPI doc parser
+    # now preserves indents in args/members/features text. QAPIDoc does
+    # not handle this well, so undo that change here.
+
+    # QAPIDoc is being rewritten and will be replaced soon,
+    # but this function is here in the interim as transition glue.
+
+    lines = text.splitlines(True)
+    if len(lines) > 1:
+        if re.match(r"\s+", lines[0]):
+            # First line is indented; description started on
+            # the line after the name. dedent the whole block.
+            return textwrap.dedent(text)
+        else:
+            # Descr started on same line. Dedent line 2+.
+            return lines[0] + textwrap.dedent("".join(lines[1:]))
+    else:
+        # Descr was a single line; dedent entire line.
+        return textwrap.dedent(text)
+
+
 # fmt: off
 # Function borrowed from pydash, which is under the MIT license
 def intersperse(iterable, separator):
@@ -169,7 +192,7 @@ def _nodes_for_members(self, doc, what, base=None, branches=None):
             term = self._nodes_for_one_member(section.member)
             # TODO drop fallbacks when undocumented members are outlawed
             if section.text:
-                defn = section.text
+                defn = dedent(section.text)
             else:
                 defn = [nodes.Text('Not documented')]
 
@@ -207,7 +230,7 @@ def _nodes_for_enum_values(self, doc):
                 termtext.extend(self._nodes_for_ifcond(section.member.ifcond))
             # TODO drop fallbacks when undocumented members are outlawed
             if section.text:
-                defn = section.text
+                defn = dedent(section.text)
             else:
                 defn = [nodes.Text('Not documented')]
 
@@ -242,7 +265,7 @@ def _nodes_for_features(self, doc):
         dlnode = nodes.definition_list()
         for section in doc.features.values():
             dlnode += self._make_dlitem(
-                [nodes.literal('', section.member.name)], section.text)
+                [nodes.literal('', section.member.name)], dedent(section.text))
             seen_item = True
 
         if not seen_item:
@@ -265,9 +288,12 @@ def _nodes_for_sections(self, doc):
                 continue
             snode = self._make_section(section.tag)
             if section.tag and section.tag.startswith('Example'):
-                snode += self._nodes_for_example(section.text)
+                snode += self._nodes_for_example(dedent(section.text))
             else:
-                self._parse_text_into_node(section.text, snode)
+                self._parse_text_into_node(
+                    dedent(section.text) if section.tag else section.text,
+                    snode,
+                )
             nodelist.append(snode)
         return nodelist
 
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 7b13a583ac1..8cdd5334ec6 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -448,7 +448,10 @@ def get_doc_indented(self, doc: 'QAPIDoc') -> Optional[str]:
         indent = must_match(r'\s*', line).end()
         if not indent:
             return line
-        doc.append_line(line[indent:])
+
+        # Preserve the indent, it's needed for rST formatting.
+        doc.append_line(line)
+
         prev_line_blank = False
         while True:
             self.accept(False)
@@ -465,7 +468,8 @@ def get_doc_indented(self, doc: 'QAPIDoc') -> Optional[str]:
                     self,
                     "unexpected de-indent (expected at least %d spaces)" %
                     indent)
-            doc.append_line(line[indent:])
+            # Again, preserve the indent for ReST.
+            doc.append_line(line)
             prev_line_blank = True
 
     def get_doc_paragraph(self, doc: 'QAPIDoc') -> Optional[str]:
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index 716a9a41026..435f6e6d768 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -117,8 +117,8 @@ doc symbol=Base
     body=
 
     arg=base1
-description starts on a new line,
-minimally indented
+ description starts on a new line,
+ minimally indented
 doc symbol=Variant1
     body=
 A paragraph
@@ -145,8 +145,8 @@ doc symbol=Alternate
 
     arg=i
 description starts on the same line
-remainder indented the same
-@b is undocumented
+    remainder indented the same
+    @b is undocumented
     arg=b
 
     feature=alt-feat
@@ -158,11 +158,11 @@ doc symbol=cmd
     body=
 
     arg=arg1
-description starts on a new line,
-indented
+    description starts on a new line,
+    indented
     arg=arg2
 description starts on the same line
-remainder indented differently
+    remainder indented differently
     arg=arg3
 
     feature=cmd-feat1
@@ -178,16 +178,16 @@ some
     section=TODO
 frobnicate
     section=Notes
-- Lorem ipsum dolor sit amet
-- Ut enim ad minim veniam
+ - Lorem ipsum dolor sit amet
+ - Ut enim ad minim veniam
 
-Duis aute irure dolor
+ Duis aute irure dolor
     section=Example
--> in
-<- out
+ -> in
+ <- out
     section=Examples
-- *verbatim*
-- {braces}
+ - *verbatim*
+ - {braces}
     section=Since
 2.10
 doc symbol=cmd-boxed
@@ -198,9 +198,9 @@ a feature
     feature=cmd-feat2
 another feature
     section=Example
--> in
+ -> in
 
-<- out
+ <- out
 doc symbol=EVT_BOXED
     body=
 
-- 
2.44.0



  parent reply	other threads:[~2024-05-14 22:01 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-14 21:57 [PATCH 00/20] qapi: new sphinx qapi domain pre-requisites John Snow
2024-05-14 21:57 ` [PATCH 01/20] [DO-NOT-MERGE]: Add some ad-hoc linting helpers John Snow
2024-05-14 21:57 ` [PATCH 02/20] qapi: linter fixups John Snow
2024-05-15  9:10   ` Markus Armbruster
2024-05-14 21:57 ` [PATCH 03/20] docs/qapidoc: delint a tiny portion of the module John Snow
2024-05-15  9:16   ` Markus Armbruster
2024-05-15 12:02     ` John Snow
2024-05-15 16:09     ` John Snow
2024-05-15 17:27       ` Markus Armbruster
2024-05-15 17:52         ` John Snow
2024-05-14 21:57 ` John Snow [this message]
2024-05-15 11:50   ` [PATCH 04/20] qapi/parser: preserve indentation in QAPIDoc sections Markus Armbruster
2024-05-15 12:24     ` John Snow
2024-05-15 14:17       ` Markus Armbruster
2024-05-15 17:03         ` John Snow
2024-05-14 21:57 ` [PATCH 05/20] qapi/parser: adjust info location for doc body section John Snow
2024-05-16  5:58   ` Markus Armbruster
2024-05-16 14:30     ` John Snow
2024-05-27 11:58       ` Markus Armbruster
2024-06-21 21:18         ` John Snow
2024-05-14 21:57 ` [PATCH 06/20] qapi/parser: fix comment parsing immediately following a doc block John Snow
2024-05-16  6:01   ` Markus Armbruster
2024-05-16 17:32     ` John Snow
2024-06-13 14:32       ` Markus Armbruster
2024-06-17 15:40         ` John Snow
2024-05-14 21:57 ` [PATCH 07/20] qapi/parser: add semantic 'kind' parameter to QAPIDoc.Section John Snow
2024-05-16  6:18   ` Markus Armbruster
2024-05-16 14:46     ` John Snow
2024-06-13 14:45       ` Markus Armbruster
2024-06-17 15:47         ` John Snow
2024-05-14 21:57 ` [PATCH 08/20] qapi/parser: differentiate intro and outro paragraphs John Snow
2024-05-16  9:34   ` Markus Armbruster
2024-05-16 15:06     ` John Snow
2024-05-16 17:43       ` John Snow
2024-05-14 21:57 ` [PATCH 09/20] qapi/parser: add undocumented stub members to all_sections John Snow
2024-06-14  8:52   ` Markus Armbruster
2024-06-17 16:54     ` John Snow
2024-06-18 11:32       ` Markus Armbruster
2024-05-14 21:57 ` [PATCH 10/20] qapi/schema: add __iter__ method to QAPISchemaVariants John Snow
2024-05-14 21:57 ` [PATCH 11/20] qapi/schema: add doc_visible property to QAPISchemaDefinition John Snow
2024-06-14  9:40   ` Markus Armbruster
2024-06-17 17:33     ` John Snow
2024-05-14 21:57 ` [PATCH 12/20] qapi/source: allow multi-line QAPISourceInfo advancing John Snow
2024-05-14 21:57 ` [PATCH 13/20] docs/qapidoc: fix nested parsing under untagged sections John Snow
2024-06-14  9:45   ` Markus Armbruster
2024-06-17 17:42     ` John Snow
2024-05-14 21:57 ` [PATCH 14/20] qapi: fix non-compliant JSON examples John Snow
2024-06-14 10:55   ` Markus Armbruster
2024-06-17 17:52     ` John Snow
2024-06-18  8:48       ` Markus Armbruster
2024-05-14 21:57 ` [PATCH 15/20] qapi: remove developer factoring comments from QAPI doc blocks John Snow
2024-05-14 21:57 ` [PATCH 16/20] qapi: rewrite StatsFilter comment John Snow
2024-05-14 21:57 ` [PATCH 17/20] qapi: rewrite BlockExportOptions doc block John Snow
2024-05-14 21:57 ` [PATCH 18/20] qapi: ensure all errors sections are uniformly typset John Snow
2024-06-14 11:24   ` Markus Armbruster
2024-06-17 17:56     ` John Snow
2024-06-18  8:52       ` Markus Armbruster
2024-05-14 21:57 ` [PATCH 19/20] qapi: convert "Note" sections to plain rST John Snow
2024-06-14 13:44   ` Markus Armbruster
2024-06-17 19:56     ` John Snow
2024-06-18 11:08       ` Markus Armbruster
2024-05-14 21:57 ` [PATCH 20/20] qapi: convert "Example" sections to rST John Snow
2024-06-14 14:38   ` Markus Armbruster
2024-06-17 21:27     ` John Snow
2024-06-18 11:25       ` Markus Armbruster
2024-05-16 17:56 ` [PATCH 00/20] qapi: new sphinx qapi domain pre-requisites Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240514215740.940155-5-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=anisinha@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=eblake@redhat.com \
    --cc=eduardo@habkost.net \
    --cc=farosas@suse.de \
    --cc=hreitz@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=jasowang@redhat.com \
    --cc=jiri@resnulli.us \
    --cc=kkostiuk@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=lukasstraub2@web.de \
    --cc=mads@ynddal.dk \
    --cc=marcandre.lureau@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=michael.roth@amd.com \
    --cc=mst@redhat.com \
    --cc=pavel.dovgaluk@ispras.ru \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=peterx@redhat.com \
    --cc=philmd@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanb@linux.vnet.ibm.com \
    --cc=stefanha@redhat.com \
    --cc=victortoso@redhat.com \
    --cc=wangyanan55@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).