I hope that I've really understood what you want to do.
I have tested the following macro (with DocBook) and it seems to be safe
and to work fine.
---
<command name="test">
<macro>
<sequence>
<command name="selectNode" parameter="previousSibling section"/>
<set variable="anchor" expression="$selected" />
<command name="selectNode" parameter="nextSibling section" />
<command name="cut" />
<set variable="selected" expression="$anchor/*[last()]" />
<command name="paste" parameter="after"/>
</sequence>
</macro>
</command>
<binding>
<keyPressed code="F3" />
<command name="test" />
</binding>
---
Note that the section to be moved must be explicitly selected for this
macro to work.
Bill Fenner wrote:
> 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.)