I'm writing a macro that is similar to incrSectionLevel, but instead
of wrapping the current section in a new blank section, tries to
attach this section to its previous sibling's last child (e.g., if we
had
1.
1.1.
1.2.
2. *
and use this command, incrSectionLevel would result in
1.
1.1.
1.2.
2.
2.1. *
and my command would result in
1.
1.1.
1.2.
1.3. *
)
I use <set> and xpath to pick the element after which I want to insert
the section. This could be one of two things:
a. If the preceding-sibling section has section children, then it's
the last section child.
b. If not, it's the last element of the previous section.
My current way of picking between these is:
<set variable="anchor" context="$selected"
expression="preceding-sibling::section[position()=1]//section[position()=last()]"/>
<choice>
<sequence>
<test expression="not($anchor)"/>
<set variable="anchor" context="$selected"
expression="preceding-sibling::section[position()=1]/*[position()=last()]"/>
</sequence>
<test expression="1"/>
</choice>
<!-- fail if this got no result -->
<test expression="$anchor"/>
However, I don't feel like this is a good use of <choice> - I am
simulating my thinking process ("if that didn't work, then try this")
but I suspect there's a better way to implement this.
Here is the whole macro.
<command name="xml2rfc.increaseSectionLevel">
<macro undoable="true" trace="true">
<sequence>
<!-- Call "currentsection" either me (if I'm a section) or my
first ancestor section.
That's the first ./ancestor-or-self bit.
Permission to run: currentsection has a preceding sibling
section.
Noop prevention: that section's last child is not me.
-->
<test
expression="$implicitElement/ancestor-or-self::section[position()=1]/preceding-sibling::section[position()=1]
and
not($implicitElement/ancestor-or-self::section[position()=1]/preceding-sibling::section[position()=1]//section[position()=last()]
= $implicitElement/ancestor-or-self::section[position()=1])"/>
<!-- select the section containing the cursor -->
<command name="selectNode"
parameter="ancestorOrSelf[implicitElement] section"/>
<!-- find the previous sibling's last section (or content element)
either we want //section[position()=last()] or if
there is no section child, we want /*[position()=last()]
I feel like this choice is a hack, to try the second pattern
if the first one failed. -->
<set variable="anchor" context="$selected"
expression="preceding-sibling::section[position()=1]//section[position()=last()]"/>
<choice>
<sequence>
<test expression="not($anchor)"/>
<set variable="anchor" context="$selected"
expression="preceding-sibling::section[position()=1]/*[position()=last()]"/>
</sequence>
<test expression="1"/>
</choice>
<!-- fail if this got no result -->
<test expression="$anchor"/>
<!-- cut it -->
<command name="cut"/>
<!-- select the previos sibling's last section -->
<set variable="selected" expression="$anchor"/>
<!-- paste it -->
<command name="paste" parameter="after"/>
</sequence>
</macro>
</command>
(Advice on simplifying that <test> would be appreciated, too, but I'm
not as worried about that.)
Thanks,
Bill