4. Testing if a command can be executed

The following macro inserts a br, an XHTML line break element, at caret position. If there is no text node after the newly inserted br, the macro inserts a new text node in order to let the user continue to type text. This macro is typically bound to a keystroke such as Shift+Enter.

The problem is that we don't want to insert a new text node after a br inserted in text span elements such as b, i, em, strong, a, etc, but only after a br inserted in a text block such a p, li, etc.

Command selectNode can, not only blindly select nodes, but it can also select nodes conditionally, if theses nodes match a list of elements passed as a parameter string.

Therefore the idea is to use selectNode, not for its ability to select nodes, but for its ability to test where the caret is.

The pass and fail constructs have designed to do this: test if a command can be executed without actually executing it.

<command name="insertLineBreak">
  <macro>
    <sequence>
      <command name="insert"
        parameter="into {http://www.w3.org/1999/xhtml}br" />

      <sequence>
        <pass><command name="selectNode"
                parameter="parent {http://www.w3.org/1999/xhtml}p 
                           {http://www.w3.org/1999/xhtml}li 
                           {http://www.w3.org/1999/xhtml}dt 
                           {http://www.w3.org/1999/xhtml}dd 
                           {http://www.w3.org/1999/xhtml}th 
                           {http://www.w3.org/1999/xhtml}td"/></pass>
        <command name="insertNode" parameter="textAfter" />
        <command name="cancelSelection" />
      </sequence>
    </sequence>
  </macro>
</command>

If selectNode can be executed, then the pass construct can be executed, then the whole sequence can be executed.

Note that when the pass construct is actually executed, it does nothing at all. This is good because, in our example, if selectNode was actually executed, it would have selected, say a p or a li, after which you generally cannot add a text node (moreover adding a text node after the p or li is not what we want to do).

The last step of the sequence, cancelSelection, is just a refinement which removes the ``red border'' around the newly inserted text node.