Re: Getting the reST source of a section node in a Sphinx extension

Kayce Basques via Docutils-users <[email protected]> Wed, 8 Jan 2025 11:05:24 -0800
Newsgroups gmane.text.docutils.user
Message-ID <CAGBRUqX5ycFx7TDT1HuGbxkV7zcCjwohQPyUdjX04Pz+VkTP_w@mail.gmail.com>
--===============2997657075201273717==
Content-Type: multipart/alternative; boundary="00000000000070c8e6062b368d54"

--00000000000070c8e6062b368d54
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi Guenter, thanks for the information. Using the starting line of the next
sibling (or child) node sounds like a promising and elegant solution! I
usually walk the node tree section-by-section so that feels like it may
work very well. I'll try it out and follow up here with results.

On Mon, Jan 6, 2025 at 3:01=E2=80=AFAM Guenter Milde via Docutils-users <
[email protected]> wrote:

> On 2025-01-02, Kayce Basques via Docutils-users wrote:
> ...
> > Hello! I believe this is my first message in the Docutils community. I'=
m
> a
> > big fan of Sphinx and appreciate the core role that Docutils plays in
> > Sphinx. I subscribed to this list and am excited to be more active in t=
he
> > community.
>
> Hello and welcome to the list.
>
> > I'm working on a Sphinx extension. In my doctree-resolved handler I
> > recursively walk through all section nodes. When the extension detects
> > something that can be improved in the underlying content, it's often
> > possible for the extension to make the edits automatically. Is the line
> > property of the Node class the only reference back to the underlying
> > reStructuredText?
>
> The internal attributes ``node.source`` and ``node.line`` hold the path
> or description of the input source and its start-line number respectively
> (cf. docutils.nodes.Node.source and docutils.nodes.Node.line).
>
> * ``node.source`` differs from the global document source for parts
>   included by the "include" directive.
> * Not every node has these attributes
>   (cf. https://sourceforge.net/p/docutils/feature-requests/41/).
>   For inline nodes, the attributes of the parent block-level node are use=
d
>   in error reporting.
>
> Additionally, there is the internal `rawsource` attribute that is set in
> docutils.nodes.Element.__init__`. It comes with a caveat::
>
>         """The raw text from which this element was constructed.
>
>         For informative and debugging purposes. Don't rely on its value!
>
>         NOTE: some elements do not set this value (default '').
>         """
>
> > Just wanted to check that there's no explicit reference
> > to the end line of the node, and I'm expected to manually compute the e=
nd
> > line. The manual computation has been kinda error-prone and brittle for
> me
> > so far. Seems like the implementation could be much simpler and
> bulletproof
> > if reST explicitly gave me the end line. Just wanted to make sure there=
's
> > no better way to do this.
>
> For block-level elements, you may consider using the start line of the
> next node as a starting point.
>
> > One example of the manual computation I'm alluding to:
>
> > from docutils.nodes import section
>
> > def do_stuff(app, doc_tree, doc_name):
> >     for node in doc_tree.traverse(section):
> >         text =3D node.astext()
> >         start =3D node.line
> >         end =3D start + len(text.splitlines())  # Often incorrect
> >         =E2=80=A6
> >         # A better approach might be to get the first and last lines
> >         # of text and search for those delimiters in the source
>
> Two suggestions (untested)::
>
> -         text =3D node.astext()
> +         text =3D node.rawsource or node.astext()
>
> or ::
>
> -         end =3D start + len(text.splitlines())  # Often incorrect
> +         end =3D node.next_node(descend=3DFalse, siblings=3DTrue,
> +                              ascend=3DTrue).line - 1
>
>
> I hope this may get you started on experimenting...
>
>
> A happy new year to all Docutils users and developers,
>
> G=C3=BCnter
>
>
>
> _______________________________________________
> Docutils-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/docutils-users
>
> Please use "Reply All" to reply to the list.
>

--00000000000070c8e6062b368d54
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi Guenter, thanks for the information. Using the starting=
 line of the next sibling (or child) node sounds like a promising and elega=
nt solution! I usually walk the node tree section-by-section so that feels =
like it may work very well. I&#39;ll try it out and follow up here with res=
ults.</div><br><div class=3D"gmail_quote gmail_quote_container"><div dir=3D=
"ltr" class=3D"gmail_attr">On Mon, Jan 6, 2025 at 3:01=E2=80=AFAM Guenter M=
ilde via Docutils-users &lt;<a href=3D"mailto:[email protected]=
rge.net">[email protected]</a>&gt; wrote:<br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:=
1px solid rgb(204,204,204);padding-left:1ex">On 2025-01-02, Kayce Basques v=
ia Docutils-users wrote:<br>
...<br>
&gt; Hello! I believe this is my first message in the Docutils community. I=
&#39;m a<br>
&gt; big fan of Sphinx and appreciate the core role that Docutils plays in<=
br>
&gt; Sphinx. I subscribed to this list and am excited to be more active in =
the<br>
&gt; community.<br>
<br>
Hello and welcome to the list.<br>
<br>
&gt; I&#39;m working on a Sphinx extension. In my doctree-resolved handler =
I<br>
&gt; recursively walk through all section nodes. When the extension detects=
<br>
&gt; something that can be improved in the underlying content, it&#39;s oft=
en<br>
&gt; possible for the extension to make the edits automatically. Is the lin=
e<br>
&gt; property of the Node class the only reference back to the underlying<b=
r>
&gt; reStructuredText? <br>
<br>
The internal attributes ``node.source`` and ``node.line`` hold the path<br>
or description of the input source and its start-line number respectively<b=
r>
(cf. docutils.nodes.Node.source and docutils.nodes.Node.line).<br>
<br>
* ``node.source`` differs from the global document source for parts<br>
=C2=A0 included by the &quot;include&quot; directive.<br>
* Not every node has these attributes<br>
=C2=A0 (cf.=C2=A0<a href=3D"https://sourceforge.net/p/docutils/feature-requ=
ests/41/" rel=3D"noreferrer" target=3D"_blank">https://sourceforge.net/p/do=
cutils/feature-requests/41/</a>).<br>
=C2=A0 For inline nodes, the attributes of the parent block-level node are =
used<br>
=C2=A0 in error reporting.<br>
<br>
Additionally, there is the internal `rawsource` attribute that is set in<br=
>
docutils.nodes.Element.__init__`. It comes with a caveat::<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;&quot;&quot;The raw text from which this =
element was constructed.<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 For informative and debugging purposes. Don&#39=
;t rely on its value!<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 NOTE: some elements do not set this value (defa=
ult &#39;&#39;).<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 &quot;&quot;&quot;<br>
<br>
&gt; Just wanted to check that there&#39;s no explicit reference<br>
&gt; to the end line of the node, and I&#39;m expected to manually compute =
the end<br>
&gt; line. The manual computation has been kinda error-prone and brittle fo=
r me<br>
&gt; so far. Seems like the implementation could be much simpler and bullet=
proof<br>
&gt; if reST explicitly gave me the end line. Just wanted to make sure ther=
e&#39;s<br>
&gt; no better way to do this.<br>
<br>
For block-level elements, you may consider using the start line of the<br>
next node as a starting point.<br>
<br>
&gt; One example of the manual computation I&#39;m alluding to:<br>
<br>
&gt; from docutils.nodes import section<br>
<br>
&gt; def do_stuff(app, doc_tree, doc_name):<br>
&gt;=C2=A0 =C2=A0 =C2=A0for node in doc_tree.traverse(section):<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0text =3D node.astext()<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0start =3D node.line<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0end =3D start + len(text.splitlines()=
)=C2=A0 # Often incorrect<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=E2=80=A6<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# A better approach might be to get t=
he first and last lines<br>
&gt;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# of text and search for those delimi=
ters in the source<br>
<br>
Two suggestions (untested)::<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0text =3D node.astext()<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0text =3D node.rawsource or node.astext()=
<br>
<br>
or ::<br>
<br>
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0end =3D start + len(text.splitlines())=
=C2=A0 # Often incorrect<br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0end =3D node.next_node(descend=3DFalse, =
siblings=3DTrue, <br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ascend=3DTrue).line - 1<br>
<br>
<br>
I hope this may get you started on experimenting...<br>
<br>
<br>
A happy new year to all Docutils users and developers,<br>
<br>
G=C3=BCnter<br>
<br>
<br>
<br>
_______________________________________________<br>
Docutils-users mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">D=
[email protected]</a><br>
<a href=3D"https://lists.sourceforge.net/lists/listinfo/docutils-users" rel=
=3D"noreferrer" target=3D"_blank">https://lists.sourceforge.net/lists/listi=
nfo/docutils-users</a><br>
<br>
Please use &quot;Reply All&quot; to reply to the list.<br>
</blockquote></div>

--00000000000070c8e6062b368d54--


--===============2997657075201273717==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


--===============2997657075201273717==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline