(This is a recapitulation of
<http://lists.canonical.org/pipermail/kragen-tol/1999-August/000466.html>,
although that contains more implementation notes, and this contains more
principles.  There are a few other differences of opinion.)

I have in mind an XML editor constructed on the following principles:

1. Each keystroke should have a visible effect on the screen, and
should have no effects not visible on the screen.

2. The document should be close to well-formed at all times, at least
in the sense that it should have no syntactically invalid tags,
unmatched tags, or mis-nested tags.

3. The effect of a keystroke should be predictable from the contents
of the screen; it should not depend on any invisible state.

4. The screen should display only characters from the XML document,
the cursor, and possibly a selection.

5. If, starting from an empty file, you were to type the characters of
a well-formed XML document, one after the other, without making any
mistakes, the result should be that XML document, or at least one
semantically equivalent to it.

6. If you type one wrong printable character, you should always be
able to undo your mistake by hitting the backspace key once.

(I think these constraints may already be a nearly complete
specification for the editing behavior of the editor; I may have gone
too far and specified constraints that are impossible to meet.)

Why?  Well, XML contains a lot of redundancy.  I wonder if you could
construct an XML editor that added and removed the redundant
information in as you typed, so that your document was always at least
mostly well-formed XML; but at the same time, didn't get in your way
to the extent to which you typed that information yourself.

Autocompletion of tag and attribute names, of course, is another way to do
this.

The following example interactions, with the | representing the
cursor, illustrate what I mean.

Tags and attributes:

hi |         + "<"     -> hi <|></>
<|></>       + "a"     -> <a|></a>
<a|></a>     + space   -> <a |=""></a>
<a |=""></a> + "href=" -> <a href="|"></a>
<a |=""></a> + ">"     -> <a>|</a>
<a href="|"></a>        + "x.png"      -> <a href="x.png|"></a>
<a href="x.png|"></a>   + '"'          -> <a href="x.png" |=""></a>
<a name="foo" |=""></a> + "/"          -> <a name="foo" /|>
<a name="foo" /|>       + "f"          -> <a name="foo" />f|
<b>ex|cellent</b>       + "<"          -> <b>ex<|></>cellent</b>
<b>ex<|></>cellent</b>  + "/"          -> <b>ex</|b>cellent<b></b>
<b>ex</|b>cellent       + "-"          -> <b>ex</b>-|cellent
<b>ex</|b>cellent       + "b"          -> <b>ex</b|>cellent
<b>ex</b|>cellent       + "-"          -> <b>ex</b>-|cellent
<b>ex</|b>cellent       + ">"          -> <b>ex</b>|cellent
<|i>Now.</i>            + "l"          -> <l|i>Now.</li>
<l|i>Now.</li>          + ">"          -> <li>|Now.</li>
<i>Now.</|i>            + "l"          -> <li>Now.</l|i>

Entities:

C|         + "&"        -> C&|;
C&|;       + "oacute"   -> C&oacute|;
C&oacute|; + ";"        -> C&oacute;|
A &amp|;   + space      -> A &amp; |
A &|;      + space      -> A &amp; |

Deletion:
<b>ex</|b>cellent<b></b> + backspace   -> <b>ex<|></>cellent</b>
<b>ex</b|>cellent<b></b> + backspace   -> <b>ex<|></>cellent</b>
<b>ex</b>|cellent<b></b> + backspace   -> <b>ex|cellent</b>
<i><b>ex</b>|cellent</i> + backspace   -> <i><b></b>ex|cellent</i>
<i><b>|ex</b>cellent</i> + backspace   -> <i><|>ex</>cellent</i>
<i><|>ex</>cellent</i>   + backspace   -> <i>excellent</i>
<p width="90">Y|es</p>   + backspace   -> <p width="90">|es</p>
<p width="90">|es</p>    + backspace   -> <p width="90|">es</p>
<p width="90|">es</p>    + backspace   -> <p width="9|">es</p>
<p width="9|">es</p>     + backspace   -> <p width="|">es</p>
<p width="|">es</p>      + backspace   -> <p widt|="">es</p>
<p |="">es</p>           + backspace   -> <p|>es</p>
<p|>es</p>               + backspace   -> <|>es</>
<|>es</>                 + backspace   -> |es
&quot;|                  + backspace   -> &quot|;
&quot;Yes&|quot;         + backspace   -> &quot;Yes|&quot;
&quot;Yes&|;             + backspace   -> &quot;Yes|

(other cases I haven't worked out but which I think the above six
principles will clearly guide: deletion of tag name characters,
attribute value characters, attribute name characters, entity
characters, empty tag slash, close tag without a nearby matching open
tag)

To satisfy principle 3, the idea that you should be able to predict the
effects of your actions from the screen contents, we need to display
closing tags, even if they're far away.

The nondestructive backspaces displayed above --- which merely move the
cursor inside of some construct without deleting anything --- are
necessary because typing a " or > might move you outside of those same
constructs.  To satisfy principle 6, hitting backspace must move you
back inside those delimiters, returning you to the previous state.  I
think this is encapsulated in this heuristic: don't consider deleting
something that might not be the last keystroke.

One event the previously-mentioned rules don't cover is the insertion of
an element outside the root element ("hodie natus est radici frater").
You could handle this by wrapping a new root element around the outside;
I think this may violate principle 6, though.

The examples shown all go through ill-formed states with tag names and
attribute names that are zero characters long.  This violates principle
2.  One possible solution to this problem is to insert a tag or
attribute name in the appropriate place, but highlight it --- and have
the traditional MacOS rule that typing a printable character when there
is highlighted text replaces the highlighted text with the character.

If this UI idiom is supported in general, it's possible to highlight and
try to delete all sorts of funny things: partial elements, partial tags,
partial attributes.  I'm not sure exactly how to handle this.  (I'm able
to consider not supporting this UI idiom because I don't like it that
much, and I commonly use Emacs and vim, neither of which use it by
default.)

(existing popular XML editors: Oxygen (oxygenxml.com), XMLSpy, Stylus
Studio.  XMLSpy touts the following feature list for XML editing:
 Well-formedness checking  
 Validation (DTD & schema-based)   
 Intelligent Editing (DTD/Schema based entry-help)   
 Text View with syntax-coloring   
 Advanced context-sensitive entry-helpers   
 Line Number Margin   
 Text-folding Margin   (i.e. click in the margin to fold/unfold)
 Bookmarks & Bookmark Margin   
 Visual indentation guides   (vertical dotted lines)
 Find & Replace with enhanced XML capabilities (include and exclude
   various syntactic categories)
 Find & Replace based on Regular Expressions   
 Code-completion & syntax-help   
 Pretty-printing of XML files   
 Enhanced Grid & Table View   (successive occurrences of the 
   same element become numbered rows; differing attributes and
   subelements of the rows become columns)
 Browser View (HTML/XHTML Preview)   
 "Authentic Document View*" (forms-based data entry into XML)
 Dynamic Forms for context-sensitive document editing   
 CALS/HTML Table Support   
 Spell-Checking   
 OASIS Catalog Support (subset)  

"Text View remains the most popular editing view."
<http://www.altova.com/support_freexmlspyhome.asp>
)

Reply via email to