Table of Contents

Using the XPath-Developer Plugin

Customizing TAB-completion

All TAB-completions are defined in a staticly read .xml-file. This means you can change most of the behaviour of the code-completion feature. After a restart of Eclipse, your changes will be immediately active.

The xalanCompletion.xml-file can be found in the plugin-directory of XPath-Developer (to be found at the site of your Eclipse-installation under 'plugins/de.babe.eclipse.plugins.XPathDeveloper_x.y.z' with x.y.z being the version installed on your machine. This file contains the definitions for the code-completion feature applicable to the Xalan-implementation for XPath as included with (and used by) the plugin.

The following is an excerpt from the file which serves as an example for the explanation on what can be customized and how:

	<completions>
	  <proposal key="//" value="//" allowPlain="true" displayString="Descendants" additionalInfo="Descendants - //">
	    <retrigger re=".*[^&gt;&lt;\+\-\!=/]" completion="//"/>
	    <retrigger re=".*[^&gt;&lt;\+\-\!=/]/" completion="/"/>
	  </proposal>
          ...
	  <proposal key="[...]" value="[...]" allowPlain="false" displayString="Predicate" additionalInfo="Predicate - a condition such as [name='someName']">
	    <retrigger re="(?:(?!\]).)*" completion="[]"/>
	    <retrigger re="((.*?\[)(.*?\]))*(?:(?!\[|\]).)*" completion="[]"/>
	    <retrigger re="((.*?\[)(.*?\]))*(.*?\[)(?:(?!\]).)*" completion="]"/>
	  </proposal>
          ...
	  <proposal key="child::" value="child::" allowPlain="true" displayString="child-axis" additionalInfo="child:: the child axis contains the children of the context node">
	    <wordtrigger word="child:" completion=":"/>
	  </proposal> 
          ...	
	</completions>
	

For any completion that is to be offered, there is an element <proposal> in the file. The following attributes are applicable and are all mandatory:

  1. key: a unique key for the proposal (usually the proposal itself)
  2. value: the full value of the proposal, i.e. the value that should be inserted if the completion is choosen and no part of the completion is typed yet (the "plain proposal")
  3. allowPlain: can be 'true' or 'false' - flag to indicate whether the proposal should be offered if the input is empty. This is 'false' e.g. for the Predicate-brackets [] in the above example, since we do not want to offer them if the expression currently is the empty String, see below for trigger-details
  4. displayString: The String to display for the proposal in the TAB-completion pop-up
  5. additionalInfo: The explanation to display in the hover if the proposal is selected in the pop-up

The proposal-element allows two kind of child-elements which define different types of triggers. These and their attributes are as follows:

Now consider the examples in the above xml-snippet:

  <proposal key="//" value="//" allowPlain="true" displayString="Descendants" additionalInfo="Descendants - //">
    <retrigger re=".*[^&gt;&lt;\+\-\!=/]" completion="//"/>
    <retrigger re=".*[^&gt;&lt;\+\-\!=/]/" completion="/"/>
  </proposal>
	

This defines a proposal with the value "//". This is the expression for selecting the 'child-or-descendant'-axis in abbreviated notation. We want this proposal to be shown even if the input currently is empty, thus allowPlain="true".

There are two kinds of trigger-expressions which would result in one or two slashes to be inserted (completion="/" and completion="//") if they are matched by the current contents and the proposal is selected. These are .*[^&gt;&lt;\+\-\!=/] with completion="//" and re=".*[^&gt;&lt;\+\-\!=/]/" with completion="/", i.e. the current contents is anything ending none of the symbols '>', '<', '+', '-', '!', '=' or '/' (which would result in "//" being appended or ending with a single '/' (with none of the symbols listed above directly preceding is) which would result in the missing "/" being appended.

The next example is

  <proposal key="[...]" value="[...]" allowPlain="false" displayString="Predicate" additionalInfo="Predicate - a condition such as [name='someName']">
    <retrigger re="(?:(?!\[|\]).)*" completion="[]"/>
    <retrigger re="((.*?\[)(.*?\]))*(?:(?!\[|\]).)*" completion="[]"/>
    <retrigger re="((.*?\[)(.*?\]))*(.*?\[)(?:(?!\]).)*" completion="]"/>
  </proposal>
	

This defines a proposal with the value "[]". This is used to indicate predicates in the XPath-language. We want this proposal to be shown only if the input is non-empty and when at least one of the triggers matches. Thus, here allowPlain="false".

The triggers are re="(?:(?!\[|\]).)*" (matching any non-empty input not containing "]" or "["), re="((.*?\[)(.*?\]))*(?:(?!\[|\]).)*" (matching anything containing any number of opened and closed square brackets which match (i.e. any opening '[' is followed by a closing']' with other characters between them) and ((.*?\[)(.*?\]))*(.*?\[)(?:(?!\]).)* (matching any line where the last square bracket is an opening one). In the first tow cases, completion="[]" will be inserted, in the last case the open bracket is matched with a closing one by inserting "]".

Finally, the last example is

  <proposal key="child::" value="child::" allowPlain="true" displayString="child-axis" additionalInfo="child:: the child axis contains the children of the context node">
    <wordtrigger word="child:" completion=":"/>
  </proposal> 
	

This defines a proposal with the value value="child::" - identifying the 'child'-axis of the context-node. Again, this proposal is to be shown at any time, thus allowPlain="true".

The trigger in this case is an example of a wordtrigger. This is because for this proposal we want the trigger to fire for content ending with 'c', 'ch', 'chi', ... Since we would need to construct a lot of retriggers in this case, the wordtrigger is used. A wordtrigger matches if the content ends with some 0-based substring of the word-attribute. It adds the remainder of the word-attribute plus the contents of the 'completion'-attribute if selected.

Roll your own, share it with others

Should you find improvements to the default completion-definitions which you feel might be interesting to others - or should you have a collection of ready-made XPath expressions you want to share - please let me know. I would be happy to TAB-completion definitions on my web-space.