On Thu, May 16, 2024, 5:34 AM Markus Armbruster <arm...@redhat.com> wrote:

> John Snow <js...@redhat.com> writes:
>
> > Add a semantic tag to paragraphs that appear *before* tagged
> > sections/members/features and those that appear after. This will control
> > how they are inlined when doc sections are merged and flattened.
>
> This future use is not obvious to me now.  I guess the effective way to
> help me see it is actual patches, which will come in due time.
>

Head recursion and tail recursion, respectively :)

* intro
* inherited intro
* members [ancestor-descendent]
* features [ancestor-descendent]
* inherited outro
* outro

Child gets the first and final words. Inherited stuff goes in the sandwich
fillings.

It feels like a simple rule that's easy to internalize. As a bonus, you can
explain it by analogy to Americans as a burger, which is the only metaphor
we understand.


> > Signed-off-by: John Snow <js...@redhat.com>
> > ---
> >  scripts/qapi/parser.py | 22 +++++++++++++++++-----
> >  1 file changed, 17 insertions(+), 5 deletions(-)
> >
> > diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
> > index cf4cbca1c1f..b1794f71e12 100644
> > --- a/scripts/qapi/parser.py
> > +++ b/scripts/qapi/parser.py
> > @@ -503,6 +503,10 @@ def get_doc(self) -> 'QAPIDoc':
> >              self.accept(False)
> >              line = self.get_doc_line()
> >              no_more_args = False
> > +            # Paragraphs before members/features/tagged are "intro"
> paragraphs.
> > +            # Any appearing subsequently are "outro" paragraphs.
> > +            # This is only semantic metadata for the doc generator.
>
> Not sure about the last sentence.  Isn't it true for almost everything
> around here?
>

I guess I was trying to say "There's no real difference between the two
mechanically, it's purely based on where it appears in the doc block, which
offers only a heuristic for its semantic value- introductory statements or
additional detail."

In my mind: the other "kind" values have some more mechanical difference to
them, but intro/outro don't.


> Also, long line.
>
> > +            intro = True
> >
> >              while line is not None:
> >                  # Blank lines
> > @@ -532,6 +536,7 @@ def get_doc(self) -> 'QAPIDoc':
> >                          raise QAPIParseError(
> >                              self, 'feature descriptions expected')
> >                      no_more_args = True
> > +                    intro = False
>
> After feature descriptions.
>
> >                  elif match := self._match_at_name_colon(line):
> >                      # description
> >                      if no_more_args:
> > @@ -547,6 +552,7 @@ def get_doc(self) -> 'QAPIDoc':
> >                              doc.append_line(text)
> >                          line = self.get_doc_indented(doc)
> >                      no_more_args = True
> > +                    intro = False
>
> Or after member descriptions.
>
> >                  elif match := re.match(
> >                          r'(Returns|Errors|Since|Notes?|Examples?|TODO):
> *',
> >                          line):
> > @@ -557,13 +563,14 @@ def get_doc(self) -> 'QAPIDoc':
> >                          doc.append_line(text)
> >                      line = self.get_doc_indented(doc)
> >                      no_more_args = True
> > +                    intro = False
>
> Or after the first tagged section.
>
> Okay, it does what it says on the tin.
>
> >                  elif line.startswith('='):
> >                      raise QAPIParseError(
> >                          self,
> >                          "unexpected '=' markup in definition
> documentation")
> >                  else:
> >                      # tag-less paragraph
> > -                    doc.ensure_untagged_section(self.info)
> > +                    doc.ensure_untagged_section(self.info, intro)
> >                      doc.append_line(line)
> >                      line = self.get_doc_paragraph(doc)
> >          else:
> > @@ -617,7 +624,7 @@ def __init__(
> >              self,
> >              info: QAPISourceInfo,
> >              tag: Optional[str] = None,
> > -            kind: str = 'paragraph',
> > +            kind: str = 'intro-paragraph',
>
> The question "why is this optional?" crossed my mind when reviewing the
> previous patch.  I left it unasked, because I felt challenging the
> overlap between @kind and @tag was more useful.  However, the new
> default value 'intro-paragraph' feels more arbitrary to me than the old
> one 'paragraph', and that makes the question pop right back into my
> mind.
>

Just "don't break API" habit, nothing more. I can make it mandatory.


> Unless I'm mistaken, all calls but one @tag and @kind.  Making that one
> pass it too feels simpler to me.
>
> Moot if we fuse @tag and @kind, of course.


> >          ):
> >              # section source info, i.e. where it begins
> >              self.info = info
> > @@ -625,7 +632,7 @@ def __init__(
> >              self.tag = tag
> >              # section text without tag
> >              self.text = ''
> > -            # section type - {paragraph, feature, member, tagged}
> > +            # section type - {<intro|outro>-paragraph, feature, member,
> tagged}
>
> Long line.


Oops, default for black is longer. Forgot to enable the "I still use email
patches as part of my penance" setting


> >              self.kind = kind
> >
> >          def append_line(self, line: str) -> None:
> > @@ -666,7 +673,11 @@ def end(self) -> None:
> >                  raise QAPISemError(
> >                      section.info, "text required after '%s:'" %
> section.tag)
> >
> > -    def ensure_untagged_section(self, info: QAPISourceInfo) -> None:
> > +    def ensure_untagged_section(
> > +        self,
> > +        info: QAPISourceInfo,
> > +        intro: bool = True,
>
> Two callers, one passes @info, one doesn't.  Passing it always might be
> simpler.
>

Okeydokey.


> > +    ) -> None:
> >          if self.all_sections and not self.all_sections[-1].tag:
> >              section = self.all_sections[-1]
> >              # Section is empty so far; update info to start *here*.
> > @@ -677,7 +688,8 @@ def ensure_untagged_section(self, info:
> QAPISourceInfo) -> None:
> >                  self.all_sections[-1].text += '\n'
> >              return
> >          # start new section
> > -        section = self.Section(info)
> > +        kind = ("intro" if intro else "outro") + "-paragraph"
> > +        section = self.Section(info, kind=kind)
> >          self.sections.append(section)
> >          self.all_sections.append(section)
>
>

Reply via email to