Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Orion/Documentation/Developer Guide/Plugging into the editor"

m (Service events)
(Example of a 'highlighter' provider)
(38 intermediate revisions by 6 users not shown)
Line 5: Line 5:
 
= orion.edit.command =
 
= orion.edit.command =
  
The <tt>orion.edit.command</tt> service is the simplest kind of editor extension. A command service simply provides a function that takes some text as input, performs some operation or transformation on the text, and returns a new text value. The command can also optionally receive and return selection information for changing the editor selection.
+
The <tt>orion.edit.command</tt> service allows plugins to provide a function that takes some editor text as input, performs some operation or transformation on the text, and returns a new text value. The command can also optionally receive and return selection information for changing the editor selection.  The transformation can happen directly, or indirectly through a delegated UI provided by the plugin.
  
 
== Service methods ==
 
== Service methods ==
Line 11: Line 11:
 
Implementations of <tt>orion.edit.command</tt> must define the following function:
 
Implementations of <tt>orion.edit.command</tt> must define the following function:
  
;run(selectedText, text, selection)
+
;run(selectedText, text, selection, resource)
: selectedText is a string containing the text that is currently selected in the editor. The <tt>text</tt> argument provides the entire editor buffer. The <tt>selection</tt> argument is a selection object with <tt>start</tt> and <tt>end</tt> fields.
+
: selectedText is a string containing the text that is currently selected in the editor. The <tt>text</tt> argument provides the entire editor buffer. The <tt>selection</tt> argument is a selection object with <tt>start</tt> and <tt>end</tt> fields. The <tt>resource</tt> argument describes the full path name of the text being edited.  The return value is either a string which will replace the current editor selection, or an object. The object must either have a <tt>text</tt> property or a <tt>uriTemplate</tt> property.  If it has a <tt>text</tt> property, then the text is a replacement string for the entire editor buffer.  It may optionally have a <tt>selection</tt> object indicating the new selection value.  If the return object has a <tt>uriTemplate</tt> property, then a delegated UI iframe will be opened on the specified URI.  It may optionally have a <tt>width</tt> and/or <tt>height</tt> property that describes the desired size of the UI.  Width and height are specified as CSS strings, such as "100px" or "50em".  The delegated UI must post a message back to the host window with an object that identifies itself as a delegatedUI and contains a <tt>result</tt> property that describes the new selection text or the replacement text object.  (See example).
  
 
== Service attributes ==
 
== Service attributes ==
Line 18: Line 18:
 
Implementations of <tt>orion.edit.command</tt> may define the following attributes:
 
Implementations of <tt>orion.edit.command</tt> may define the following attributes:
  
;img
 
:<tt>String</tt> The URL of an icon to associate with the command.
 
 
;name
 
;name
:<tt>String</tt> The command text show to the user.
+
:<tt>String</tt> The command text to show to the user.
 +
;id
 +
:<tt>String</tt> The id of the command contribution.
 +
;tooltip
 +
<tt>String</tt> Optional.  A tooltip describing the command.
 +
;img
 +
:<tt>String</tt> Optional.  The URL of an icon to associate with the command.  The icon may not appear in all situations.  For example, the main toolbar may not show the icon, but a menu item might show the icon.
 
;key
 
;key
:<tt>Array</tt> An optional key binding for the command. The structure of this array matches the arguments of the <tt>orion.textview.KeyBinding</tt> constructor. See its entry in the Client API reference for details.
+
:<tt>Array</tt> Optional.  A key binding for the command. The structure of this array matches the arguments of the <tt>orion.textview.KeyBinding</tt> constructor. See its entry in the Client API reference for details.
 +
;validationProperties
 +
:<tt>Array</tt> Optional.  An array [[Orion/Documentation/Developer Guide/Plugging into Orion pages#Validation Properties|Validation Properties]] that must match the editor's file in order for the command to appear.
 +
;contentType
 +
:<tt>Array</tt> Optional.  An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] for which this command is valid.
  
== Examples ==
+
== Examples ==
 +
The following examples start with the simplest editor command and then add more complexity.
  
The following simple example just converts the selected text to upper case. In this example the function return value is a simple string, so this is interpreted by the editor as replacement for the original editor selection. In the service properties, we see the command provides a key binding of Ctrl+U (or Cmd+U on Mac).
+
=== Replacing the selection ===
 
+
This example converts the selected text to upper case. The function return value is a simple string, so this is interpreted by the editor as replacement for the original editor selection. In the service properties, we see the command provides a key binding of Ctrl+U (or Cmd+U on Mac).  
<pre>
+
<pre> var provider = new eclipse.PluginProvider();
var provider = new eclipse.PluginProvider();
+
 
  provider.registerServiceProvider("orion.edit.command", {
 
  provider.registerServiceProvider("orion.edit.command", {
   run : function(text) {
+
   run&nbsp;: function(text) {
 
     return text.toUpperCase();
 
     return text.toUpperCase();
 
   }
 
   }
 
  }, {
 
  }, {
   name : "UPPERCASE",
+
   name&nbsp;: "UPPERCASE",
   img : "/images/gear.gif",
+
  id&nbsp;: "uppercase.example"
   key : [ "u", true ]
+
   img&nbsp;: "/images/gear.gif",
 +
   key&nbsp;: [ "u", true ]
 
  });
 
  });
 
  provider.connect();
 
  provider.connect();
</pre>
+
</pre>  
  
Here is an example of a slightly more complex run function that takes the selection and wraps it in C-style block comments. In this example the function returns a complex object with both <tt>text</tt> and <tt>selection</tt> fields. These are interpreted by the editor as the new editor buffer contents, and the new editor selection.
+
=== Replacing the editor contents ===
 
+
This example takes the selection and wraps it in C-style block comments. In this example the function returns a complex object with both <tt>text</tt> and <tt>selection</tt> fields. These are interpreted by the editor as the new editor buffer contents, and the new editor selection. A content type is used so that this command is only available for javascript files.
<pre>
+
<pre> contentType: ["application/javascript"],
  run : function(selectedText, text, selection) {
+
  run&nbsp;: function(selectedText, text, selection) {
 
   return {text: text.substring(0,selection.start) + "/*" +  
 
   return {text: text.substring(0,selection.start) + "/*" +  
 
     text.substring(selection.start,selection.end) + "*/" +  
 
     text.substring(selection.start,selection.end) + "*/" +  
Line 52: Line 61:
 
     selection: {start:selection.start,end:selection.end+4}};
 
     selection: {start:selection.start,end:selection.end+4}};
 
  }
 
  }
 +
</pre>
 +
 +
=== Delegating a UI before manipulating the editor ===
 +
Here is an example of a delegated UI run function that computes a URL for the delegated UI based on the file name of the edited file. In this example, the function returns a complex object with a <tt>uriTemplate</tt> field and <tt>width</tt> and <tt>height</tt> properties. The UI that is opened will be responsible for posting a message back to the editor with a result object that contains either a String for the selected text or a complex object with replacement content.
 +
<pre> id: "delegatedUI.example",
 +
run&nbsp;: function(selectedText, text, selection, fileName) {
 +
  return {uriTemplate: "http://com.example/myDelegatedUI#" + fileName, width: "600px", height: "400px"};
 +
}
 +
</pre>
 +
The delegated UI would post a message identifying itself and including a result. The message must include a <tt>pageService</tt> property of "orion.page.delegatedUI", a <tt>source</tt> that matches the orion.edit.command service id, and either a <tt>result</tt> or a <tt>cancelled</tt> property. The following examples illustrate the different ways the result could be returned.
 +
<pre>/* a message containing replacement selected text */
 +
window.parent.postMessage(JSON.stringify({
 +
  pageService: "orion.page.delegatedUI",
 +
  source: "delegatedUI.example",
 +
  result: replacementSelection
 +
}), "*");
 +
 +
/* a message containing new content for the editor */
 +
window.parent.postMessage(JSON.stringify({
 +
  pageService: "orion.page.delegatedUI",
 +
  source: "delegatedUI.example",
 +
  result: JSON.stringify({text: replacementText})
 +
}), "*");
 +
 +
/* a message signifying user cancellation of the delegated UI */
 +
window.parent.postMessage(JSON.stringify({
 +
  pageService: "orion.page.delegatedUI",
 +
  source: "delegatedUI.example",
 +
  cancelled: true
 +
}), "*");
 
</pre>
 
</pre>
 +
 +
=== Google Picker example  ===
 +
 +
The Google Picker is a fully functioning example of a delegated UI in an editor command.  It opens a Google Picker allowing the user to pick a resource, and then inserts a link to that resource into the editor text.
 +
To install the plug-in, open [http://szbra.github.com/GPicker4OEdtr/ this link]. The code is available [https://github.com/szbra/GPicker4OEdtr here].
  
 
= orion.edit.contentAssist =
 
= orion.edit.contentAssist =
Line 60: Line 104:
 
Implementations of <tt>orion.edit.contentAssist</tt> must define the following function:
 
Implementations of <tt>orion.edit.contentAssist</tt> must define the following function:
  
;computeProposals(prefix, buffer, selection)
+
;computeProposals(buffer, offset, context)
: When content assist is triggered, the editor calls this function to obtain suggestions from a content assist provider.<br>Alternatively, a [http://dojotoolkit.org/documentation/tutorials/1.6/promises/ Dojo promise] may be returned, which allows the suggestions to be computed asynchronously.
+
: When content assist is triggered, the editor calls this function to obtain suggestions from a content assist provider.
::'''prefix''' <tt>String</tt> The substring extending from the first non-word character preceding the editing caret up to the editing caret. This may give a clue about what the user intended to type, and can be used to narrow down the results to be returned. The content assist engine will discard any proposals that don't start with this prefix.
+
 
::'''buffer''' <tt>String</tt> The entire buffer being edited.
 
::'''buffer''' <tt>String</tt> The entire buffer being edited.
::'''selection''' <tt>orion.textview.Selection</tt> The current selection in the editor.
+
::'''offset''' <tt>Number</tt> Offset in the text buffer at which content assist is being invoked.
 +
::'''context''' <tt>Object</tt> Additional contextual information about the content assist invocation. This object has the following properties:
 +
:::'''line''' <tt>String</tt> Text of the entire line that the editing caret is on.
 +
:::'''prefix''' <tt>String</tt> The substring extending from the first non-word character preceding the editing caret up to the editing caret. This may give a clue about what the user intended to type, and can be used to narrow down the results to be returned. The prefix may not be appropriate for all types of document, depending on their syntax rules.
 +
:::'''selection''' <tt>orion.textview.Selection</tt> The current selection in the editor.
  
Returns an <tt>Array</tt> giving possible completions that may be inserted into the editor. Result elements must be either <tt>String</tt> objects with literal string completions, or proposal objects with the following properties:
+
Returns an <tt>Array</tt> giving possible completions that may be inserted into the editor. Result elements must be "proposal" objects having the following properties:
  
: <b>proposal</b> <tt>String</tt> completion text that will be inserted in the editor if chosen. The prefix, if any, will be removed from this text automatically by the Orion code completion engine.
+
: <b>proposal</b> <tt>String</tt> completion text that will be inserted in the editor if chosen. The text is inserted at the <b>offset</b>.
: <b>description</b> An optional <tt>String</tt> describing the completion. If provided, this text will be shown in the content assist popup. If not provided, the <b>proposal</b> will be shown instead.
+
: <b>description</b> A <tt>String</tt> describing the completion. This text will be shown in the content assist popup.
: <b>positions</b> An optional array of positions within the completion proposal that require user input. Supplying this property will cause the editor to enter <i>linked mode</i>, and the user can use the <b>Tab</b> key to iterate through the regions of the proposal that require user input. For example if the completion is a function, the positions could indicate the function arguments that need to be supplied. Entries in this position array must be objects with two integer properties: <b>offset</b>, and <b>length</b> describing the regions requiring user input.
+
: <b>positions</b> An optional <tt>Array</tt> of positions within the completion proposal that require user input. Supplying this property will cause the editor to enter <i>linked mode</i>, and the user can use the <b>Tab</b> key to iterate through the regions of the proposal that require user input. For example if the completion is a function, the positions could indicate the function arguments that need to be supplied. Entries in this position array must be objects with two integer properties: <b>offset</b>, and <b>length</b> describing the regions requiring user input.
: <b>escapePosition</b> An optional integer indicating the offset the cursor should have in the document after the completion is inserted. If this value is not supplied, the cursor will be positioned at the end of the inserted text.
+
: <b>escapePosition</b> An optional <tt>Number</tt> indicating the offset the cursor should have in the document after the completion is inserted. If this value is not supplied, the cursor will be positioned at the end of the inserted text.
 +
: <b>style</b> A String giving styling information for the proposal. The available styles are: <code>"default"</code> (no styling, also used if this property is not present), <code>"emphasis"</code> (proposal displayed in bold), <code>"noemphasis"</code> (proposal is greyed out with a colored background), <code>"hr"</code> (proposal displayed as a &lt;hr/&gt; and is not selectable by up and down arrows).
 +
 
 +
Alternatively, a Deferred may be returned, which allows the suggestions to be computed asynchronously.
  
 
== Service attributes ==
 
== Service attributes ==
Line 79: Line 129:
 
:<tt>String</tt> Name for the content assist provider.
 
:<tt>String</tt> Name for the content assist provider.
 
;contentType
 
;contentType
:<tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Core client services#orion.file.contenttype|Content Type IDs]] that this provider can provide content assist for. The provider's <tt>computeProposals</tt> function will be called only for files having one of these content types.
+
:<tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] that this provider can provide content assist for. The provider's <tt>computeProposals</tt> function will be called only for files having one of these content types.
  
 
== Examples ==
 
== Examples ==
  
The example below provides content assist suggestions for files whose name ends in <tt>.js</tt>. It offers JavaScript keywords as suggestions.
+
The example below provides content assist suggestions for files whose name ends in <tt>.js</tt>. It offers JavaScript keywords as suggestions, by checking them against the prefix provided by the content assist engine.
  
 
  var provider = new eclipse.PluginProvider();
 
  var provider = new eclipse.PluginProvider();
 
  provider.registerServiceProvider("orion.edit.contentAssist",
 
  provider.registerServiceProvider("orion.edit.contentAssist",
 
   {
 
   {
       computeProposals: function(prefix, buffer, selection) {
+
       computeProposals: function(buffer, offset, context) {
         return [ "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else",
+
         var keywords = [ "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else",
                "finally", "for", "function", "if", "in", "instanceof", "new", "return", "switch", "this",
+
                        "finally", "for", "function", "if", "in", "instanceof", "new", "return", "switch",
                "throw", "try", "typeof", "var", "void", "while", "with" ];
+
                        "this", "throw", "try", "typeof", "var", "void", "while", "with" ];
 +
        var proposals = [];
 +
        for (var i=0; i < keywords.length; i++) {
 +
            var keyword = keywords[i];
 +
            if (keyword.indexOf(context.prefix) === 0) {
 +
                proposals.push({
 +
                    proposal: keyword.substring(context.prefix.length),
 +
                    description: keyword
 +
                });
 +
            }
 +
        }
 +
        return proposals;
 
       }
 
       }
 
   },
 
   },
 
   {
 
   {
 
     name: "JavaScript content assist",
 
     name: "JavaScript content assist",
     contentType: ["text.javascript"]
+
     contentType: ["application/javascript"]
 
   });
 
   });
 
  provider.connect();
 
  provider.connect();
Line 103: Line 164:
  
 
  var provider = new eclipse.PluginProvider();
 
  var provider = new eclipse.PluginProvider();
  provider.registerServiceProvider("orion.edit.contentAssist",
+
  provider.registerServiceProvider('orion.edit.contentAssist',
 
   {
 
   {
     computeProposals: function(prefix, buffer, selection) {
+
     computeProposals: function(buffer, offset, context) {
 
       var proposals = [];
 
       var proposals = [];
       if (prefix === 'a') {
+
       if (context.prefix === 'a') {
 
         proposals.push({
 
         proposals.push({
           proposal: "a href=\"\"></a>",  
+
           proposal: ' href=""></a>',
           description: "<a></a> - HTML anchor element",  
+
           description: '<a></a> - HTML anchor element',  
           escapePosition: selection.offset+7});
+
           escapePosition: offset+7});
 
       }
 
       }
 
       return proposals;
 
       return proposals;
 
   },
 
   },
 
   {
 
   {
     name: "HTML content assist",
+
     name: 'HTML content assist',
     contentType: ["text.html"]
+
     contentType: ['text/html']
 
   });
 
   });
 
  provider.connect();
 
  provider.connect();
Line 125: Line 186:
  
 
Contributions to this service do not directly affect the Orion UI. Instead, this service is typically used in conjunction with two other services, which allow new file types to be defined and associated with editors. See:
 
Contributions to this service do not directly affect the Orion UI. Instead, this service is typically used in conjunction with two other services, which allow new file types to be defined and associated with editors. See:
* [[Orion/Documentation/Developer_Guide/Core_client_services#orion.file.contenttype | orion.file.contenttype]]: Registers a new content type for files.
+
* [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype | orion.core.contenttype]]: Registers a new content type for files.
* [[Orion/Documentation/Developer_Guide/Plugging_into_the_navigator#orion.navigate.openWith | orion.navigate.openWith]]: Associates a content type (registered via <code>orion.file.contenttype</code>) to an editor (registered via <code>orion.edit.editor</code>).
+
* [[Orion/Documentation/Developer_Guide/Plugging_into_the_navigator#orion.navigate.openWith | orion.navigate.openWith]]: Associates a content type (registered via <code>orion.core.contenttype</code>) to an editor (registered via <code>orion.edit.editor</code>).
  
 
== Service methods ==
 
== Service methods ==
Line 150: Line 211:
 
     });
 
     });
  
The code below shows a complete example of how to use the <code>orion.editor</code>, <code>orion.file.contenttype</code>, and <code>orion.navigate.openWith</code> services in conjunction to declare a new editor, declare new file types, and associate them together. The example is adapted from Orion's own source code.
+
The code below shows a complete example of how to use the <code>orion.editor</code>, <code>orion.core.contenttype</code>, and <code>orion.navigate.openWith</code> services in conjunction to declare a new editor, declare new file types, and associate them together. The example is adapted from Orion's own source code.
  
 
   // Declare an editor
 
   // Declare an editor
Line 160: Line 221:
 
    
 
    
 
   // Declare content types
 
   // Declare content types
   provider.registerServiceProvider("orion.file.contenttype", {}, {
+
   provider.registerServiceProvider("orion.core.contenttype", {}, {
 
     contentTypes:
 
     contentTypes:
       [{ id: "text.plain",
+
       [{ id: "text/plain",
 
         name: "Text",
 
         name: "Text",
 
         extension: ["txt"]
 
         extension: ["txt"]
 
       },
 
       },
       {  id: "text.html",
+
       {  id: "text/html",
         "extends": "text.plain",
+
         "extends": "text/plain",
 
         name: "HTML",
 
         name: "HTML",
 
         extension: ["html", "htm"]
 
         extension: ["html", "htm"]
Line 176: Line 237:
 
   provider.registerServiceProvider("orion.navigate.openWith", {}, {
 
   provider.registerServiceProvider("orion.navigate.openWith", {}, {
 
       editor: "orion.editor",
 
       editor: "orion.editor",
       contentType: ["text.plain", "text.html"]});
+
       contentType: ["text/plain", "text/html"]});
 
    
 
    
 
   provider.connect();
 
   provider.connect();
Line 203: Line 264:
 
:<code>String</code> What kind of highlight provider is being registered. Allowed values are <code>"grammar"</code> and <code>"highlighter"</code>. Future versions may support more.
 
:<code>String</code> What kind of highlight provider is being registered. Allowed values are <code>"grammar"</code> and <code>"highlighter"</code>. Future versions may support more.
 
;contentType
 
;contentType
:<code>Array</code> An array of [[Orion/Documentation/Developer Guide/Core client services#orion.file.contenttype|Content Type IDs]] that this provider will be used for.
+
:<code>Array</code> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] that this provider will be used for.
 
;grammar
 
;grammar
 
:<code>Object</code> ''Optional''. When the '''type''' of this provider is "grammar", this attribute holds an object giving the grammar to be used to assign style classes. This object is a JavaScript equivalent of the format described [http://manual.macromates.com/en/language_grammars.html here].
 
:<code>Object</code> ''Optional''. When the '''type''' of this provider is "grammar", this attribute holds an object giving the grammar to be used to assign style classes. This object is a JavaScript equivalent of the format described [http://manual.macromates.com/en/language_grammars.html here].
Line 222: Line 283:
 
   }, {
 
   }, {
 
     type : "grammar",
 
     type : "grammar",
     contentType: ["text.html"],
+
     contentType: ["text/html"],
 
     grammar: {
 
     grammar: {
 
       patterns: [
 
       patterns: [
Line 240: Line 301:
  
 
== Example of a 'highlighter' provider ==
 
== Example of a 'highlighter' provider ==
See the source code of the [https://github.com/mamacdon/orion-codemirror orion-codemirror plugin].
+
See the source code of the [https://github.com/mamacdon/orion-codemirror orion-codemirror plugin], particularly [https://github.com/mamacdon/orion-codemirror/blob/master/src/js/codeMirrorPlugin.js#L163-L183 these lines].
<!-- particularly [https://github.com/mamacdon/orion-codemirror/blob/master/lib/codeMirrorPlugin.js#L225-240 this file] from the -->
+
  
 
= orion.edit.model =
 
= orion.edit.model =
Line 249: Line 309:
  
 
== Service methods ==
 
== Service methods ==
Implementations of <tt>orion.edit.model</tt> '''may''' define zero or more of the following functions:
+
An implementation of <tt>orion.edit.model</tt> may define zero or more functions depending on what event types it gives in its '''types''' attribute. For every event type in '''types''', the function with the name <tt>"on" + eventType</tt> will be invoked. For example, a "ModelChanged" event type causes the the provider's '''onModelChanged''' function to be invoked.
<!--
+
 
 +
The functions are always invoked with a single parameter, <tt>event</tt>, containing the event data that was dispatched by the TextView.
 +
<!--  
 
;onContextMenu(event)
 
;onContextMenu(event)
 
;onDragStart(event)
 
;onDragStart(event)
Line 258: Line 320:
 
;onDragLeave(event)
 
;onDragLeave(event)
 
;onDragStop(event)
 
;onDragStop(event)
-->
 
 
;onModelChanging(event)
 
;onModelChanging(event)
 
;onModelChanged(event)
 
;onModelChanged(event)
 
;onModify(event)
 
;onModify(event)
:
+
;onMouseDown(event)
<!--
+
;onMouseUp(event)
;onMouseDown
+
;onMouseMove(event)
;onMouseUp
+
;onMouseOver(event)
;onMouseMove
+
;onMouseOut(event)
;onMouseOver
+
;onMouseOut
+
-->
+
 
;onScroll(event)
 
;onScroll(event)
<!--
+
;onVerify(event)
;onVerify
+
;onFocus(event)
;onUnlaod
+
;onBlur(event)
;onFocus
+
;onBlur
+
 
-->
 
-->
  
Line 283: Line 339:
 
: <tt>Array</tt> An array of TextView event types that this provider is interested in. When an event of one of these types is dispatched by the TextView, this provider's corresponding function will be invoked. For example, a provider with "ModelChanged" in its types array will have its '''onModelChanged''' function invoked whenever the TextView dispatches a <tt>ModelChanged</tt> event.
 
: <tt>Array</tt> An array of TextView event types that this provider is interested in. When an event of one of these types is dispatched by the TextView, this provider's corresponding function will be invoked. For example, a provider with "ModelChanged" in its types array will have its '''onModelChanged''' function invoked whenever the TextView dispatches a <tt>ModelChanged</tt> event.
 
; contentType
 
; contentType
: <tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Core client services#orion.file.contenttype|Content Type IDs]] that this provider is interested in listening to changes for. The provider will only be notified of events that occur when a file matching one of these content types is being edited.
+
: <tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] that this provider is interested in listening to changes for. The provider will only be notified of events that occur when a file matching one of these content types is being edited.
 +
 
 +
== Example ==
 +
See the source code of the [https://github.com/mamacdon/orion-codemirror orion-codemirror plugin].
  
 
= orion.edit.outliner =
 
= orion.edit.outliner =
Line 307: Line 366:
  
 
;contentType
 
;contentType
:<tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Core client services#orion.file.contenttype|Content Type IDs]] giving the types of files that this outliner can provide an outline for.
+
:<tt>Array</tt> An array of [[Orion/Documentation/Developer_Guide/Plugging_into_the_navigator#orion.core.contenttype|Content Type IDs]] giving the types of files that this outliner can provide an outline for.
 
;id
 
;id
 
:<tt>String</tt> A unique identifier for this outline provider.
 
:<tt>String</tt> A unique identifier for this outline provider.
Line 334: Line 393:
 
   }
 
   }
 
  }, {
 
  }, {
   contentType: ["text.plain"],
+
   contentType: ["text/plain"],
 
   name: "Headings",
 
   name: "Headings",
 
   id: "orion.outliner.example.headings"
 
   id: "orion.outliner.example.headings"
Line 341: Line 400:
  
 
= orion.edit.validator =
 
= orion.edit.validator =
An <tt>orion.edit.validator</tt> service provides a function that can check the contents of a file and return a data structure indicating which lines (if any) have problems. The result of this service is used by the Orion UI to create annotations in the ruler beside each problematic line, and also to underline the specific portion of a line where the problem occurs.
+
An <tt>orion.edit.validator</tt> service provides a function that can check the contents of a file and return a data structure indicating where problems are in the document. The result of this service is used by the Orion UI to create annotations in the ruler beside each problematic line, and also to underline the specific portion of the document where the problem occurs.
  
 
== Service methods ==
 
== Service methods ==
Line 348: Line 407:
 
: '''title''' <tt>String</tt> The path and filename of the file being edited.
 
: '''title''' <tt>String</tt> The path and filename of the file being edited.
 
: '''contents''' <tt>String</tt> The contents of the file being edited.
 
: '''contents''' <tt>String</tt> The contents of the file being edited.
Returns an <tt>Object</tt> giving the validation result. The returned object must have a <tt>problems</tt> property whose value is an array giving the problems found in the file. Each problem object must have the properties:
+
Returns an <tt>Object</tt> giving the validation result. The returned object must have a <tt>problems</tt> property whose value is an array giving the problems found in the file.  
 +
 
 +
=== The problem object ===
 +
A problem object has the following properties:
 
: <b>description</b> <tt>String</tt> A description of the problem.
 
: <b>description</b> <tt>String</tt> A description of the problem.
: <b>line</b> <tt>Number</tt> Gives the line number where the problem was found. (Line numbers begin counting from 1.)
 
: <b>start</b> <tt>Number</tt> Gives the column within the line where the problem begins.
 
: <b>end</b> <tt>Number</tt> ''Optional'' Gives the column within the line where the problems ends. (If omitted, <tt>start+1</tt> is assumed.)
 
 
: <b>severity</b> <tt>String</tt> ''Optional'' Gives the severity of this problem. The severity affects how the problem is displayed in the Orion UI. Allowed values are <tt>"warning"</tt> and <tt>"error"</tt>. (If omitted, <tt>"error"</tt> is assumed.)
 
: <b>severity</b> <tt>String</tt> ''Optional'' Gives the severity of this problem. The severity affects how the problem is displayed in the Orion UI. Allowed values are <tt>"warning"</tt> and <tt>"error"</tt>. (If omitted, <tt>"error"</tt> is assumed.)
 +
 +
A problem will have additional properties that give its location within the file. The location can be specified using line+column, or using offsets.
 +
 +
For a ''line-based'' problem, you provide a line number and columns:
 +
: <b>line</b> <tt>Number</tt> The line number where the problem was found. (Line numbers begin counting from 1.)
 +
: <b>start</b> <tt>Number</tt> The column within the line where the problem begins. (Columns begin counting from 1.)
 +
: <b>end</b> <tt>Number</tt> ''Optional'' The column within the line where the problems ends. (If omitted, <tt>start+1</tt> is assumed.)
 +
 +
For a ''document-based'' problem, you provide character offsets:
 +
: <b>start</b> <tt>Number</tt> The offset at which the problem begins. (0=first character in the document.)
 +
: <b>end</b> <tt>Number</tt> ''Optional'' The offset at which the problem ends. (If omitted, <tt>start+1</tt> is assumed.)
 +
 +
A document-based problem can span several lines.
  
 
== Service attributes ==
 
== Service attributes ==
 
Implementations of <tt>orion.edit.validator</tt> must define the following attributes:
 
Implementations of <tt>orion.edit.validator</tt> must define the following attributes:
 
;contentType
 
;contentType
: <tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Core client services#orion.file.contenttype|Content Type IDs]] giving the types of files that this validator is capable of validating.
+
: <tt>Array</tt> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] giving the types of files that this validator is capable of validating.
  
  
Line 373: Line 445:
 
           if (match) {
 
           if (match) {
 
             problems.push({
 
             problems.push({
               reason: "Mixed spaces and tabs",
+
               description: "Mixed spaces and tabs",
 
               line: i + 1,
 
               line: i + 1,
               character: match.index + 1,
+
               start: match.index + 1,
 
               end: match.index + match[0].length + 1,
 
               end: match.index + match[0].length + 1,
 
               severity: "warning" });
 
               severity: "warning" });
Line 385: Line 457:
 
   },
 
   },
 
   {
 
   {
       contentType: ["text.javascript"]
+
       contentType: ["application/javascript"]
 
   });<!--
 
   });<!--
 
  service.dispatchEvent = serviceProvider.dispatchEvent;-->
 
  service.dispatchEvent = serviceProvider.dispatchEvent;-->

Revision as of 10:45, 20 August 2013

Overview of contributing services to the Orion editor

The built Orion editor defines a number of services for customizing its appearance and behavior. These services will typically be defined by a plug-in providing editing functionality for different programming languages or file extensions. This section will outline the services that are available for editor customization.

orion.edit.command

The orion.edit.command service allows plugins to provide a function that takes some editor text as input, performs some operation or transformation on the text, and returns a new text value. The command can also optionally receive and return selection information for changing the editor selection. The transformation can happen directly, or indirectly through a delegated UI provided by the plugin.

Service methods

Implementations of orion.edit.command must define the following function:

run(selectedText, text, selection, resource)
selectedText is a string containing the text that is currently selected in the editor. The text argument provides the entire editor buffer. The selection argument is a selection object with start and end fields. The resource argument describes the full path name of the text being edited. The return value is either a string which will replace the current editor selection, or an object. The object must either have a text property or a uriTemplate property. If it has a text property, then the text is a replacement string for the entire editor buffer. It may optionally have a selection object indicating the new selection value. If the return object has a uriTemplate property, then a delegated UI iframe will be opened on the specified URI. It may optionally have a width and/or height property that describes the desired size of the UI. Width and height are specified as CSS strings, such as "100px" or "50em". The delegated UI must post a message back to the host window with an object that identifies itself as a delegatedUI and contains a result property that describes the new selection text or the replacement text object. (See example).

Service attributes

Implementations of orion.edit.command may define the following attributes:

name
String The command text to show to the user.
id
String The id of the command contribution.
tooltip

String Optional. A tooltip describing the command.

img
String Optional. The URL of an icon to associate with the command. The icon may not appear in all situations. For example, the main toolbar may not show the icon, but a menu item might show the icon.
key
Array Optional. A key binding for the command. The structure of this array matches the arguments of the orion.textview.KeyBinding constructor. See its entry in the Client API reference for details.
validationProperties
Array Optional. An array Validation Properties that must match the editor's file in order for the command to appear.
contentType
Array Optional. An array of Content Type IDs for which this command is valid.

Examples

The following examples start with the simplest editor command and then add more complexity.

Replacing the selection

This example converts the selected text to upper case. The function return value is a simple string, so this is interpreted by the editor as replacement for the original editor selection. In the service properties, we see the command provides a key binding of Ctrl+U (or Cmd+U on Mac).

 var provider = new eclipse.PluginProvider();
 provider.registerServiceProvider("orion.edit.command", {
   run : function(text) {
     return text.toUpperCase();
   }
 }, {
   name : "UPPERCASE",
   id : "uppercase.example"
   img : "/images/gear.gif",
   key : [ "u", true ]
 });
 provider.connect();

Replacing the editor contents

This example takes the selection and wraps it in C-style block comments. In this example the function returns a complex object with both text and selection fields. These are interpreted by the editor as the new editor buffer contents, and the new editor selection. A content type is used so that this command is only available for javascript files.

 contentType: ["application/javascript"],
 run : function(selectedText, text, selection) {
   return {text: text.substring(0,selection.start) + "/*" + 
     text.substring(selection.start,selection.end) + "*/" + 
     text.substring(selection.end),
     selection: {start:selection.start,end:selection.end+4}};
 }

Delegating a UI before manipulating the editor

Here is an example of a delegated UI run function that computes a URL for the delegated UI based on the file name of the edited file. In this example, the function returns a complex object with a uriTemplate field and width and height properties. The UI that is opened will be responsible for posting a message back to the editor with a result object that contains either a String for the selected text or a complex object with replacement content.

 id: "delegatedUI.example",
 run : function(selectedText, text, selection, fileName) {
   return {uriTemplate: "http://com.example/myDelegatedUI#" + fileName, width: "600px", height: "400px"};
 }

The delegated UI would post a message identifying itself and including a result. The message must include a pageService property of "orion.page.delegatedUI", a source that matches the orion.edit.command service id, and either a result or a cancelled property. The following examples illustrate the different ways the result could be returned.

/* a message containing replacement selected text */
window.parent.postMessage(JSON.stringify({
   pageService: "orion.page.delegatedUI", 
   source: "delegatedUI.example", 
   result: replacementSelection
}), "*");

/* a message containing new content for the editor */
window.parent.postMessage(JSON.stringify({
   pageService: "orion.page.delegatedUI", 
   source: "delegatedUI.example", 
   result: JSON.stringify({text: replacementText})
}), "*");

/* a message signifying user cancellation of the delegated UI */
window.parent.postMessage(JSON.stringify({
   pageService: "orion.page.delegatedUI", 
   source: "delegatedUI.example", 
   cancelled: true
}), "*");

Google Picker example

The Google Picker is a fully functioning example of a delegated UI in an editor command. It opens a Google Picker allowing the user to pick a resource, and then inserts a link to that resource into the editor text. To install the plug-in, open this link. The code is available here.

orion.edit.contentAssist

The orion.edit.contentAssist service contributes content assist providers to the editor. A content assist provider produces suggestions for text that may be inserted into the editor at a given point. Providers are invoked when the user triggers the "content assist" action by pressing Ctrl+Space in the editor.

Service methods

Implementations of orion.edit.contentAssist must define the following function:

computeProposals(buffer, offset, context)
When content assist is triggered, the editor calls this function to obtain suggestions from a content assist provider.
buffer String The entire buffer being edited.
offset Number Offset in the text buffer at which content assist is being invoked.
context Object Additional contextual information about the content assist invocation. This object has the following properties:
line String Text of the entire line that the editing caret is on.
prefix String The substring extending from the first non-word character preceding the editing caret up to the editing caret. This may give a clue about what the user intended to type, and can be used to narrow down the results to be returned. The prefix may not be appropriate for all types of document, depending on their syntax rules.
selection orion.textview.Selection The current selection in the editor.

Returns an Array giving possible completions that may be inserted into the editor. Result elements must be "proposal" objects having the following properties:

proposal String completion text that will be inserted in the editor if chosen. The text is inserted at the offset.
description A String describing the completion. This text will be shown in the content assist popup.
positions An optional Array of positions within the completion proposal that require user input. Supplying this property will cause the editor to enter linked mode, and the user can use the Tab key to iterate through the regions of the proposal that require user input. For example if the completion is a function, the positions could indicate the function arguments that need to be supplied. Entries in this position array must be objects with two integer properties: offset, and length describing the regions requiring user input.
escapePosition An optional Number indicating the offset the cursor should have in the document after the completion is inserted. If this value is not supplied, the cursor will be positioned at the end of the inserted text.
style A String giving styling information for the proposal. The available styles are: "default" (no styling, also used if this property is not present), "emphasis" (proposal displayed in bold), "noemphasis" (proposal is greyed out with a colored background), "hr" (proposal displayed as a <hr/> and is not selectable by up and down arrows).

Alternatively, a Deferred may be returned, which allows the suggestions to be computed asynchronously.

Service attributes

Implementations of orion.edit.contentAssist must define the following attributes:

name
String Name for the content assist provider.
contentType
Array An array of Content Type IDs that this provider can provide content assist for. The provider's computeProposals function will be called only for files having one of these content types.

Examples

The example below provides content assist suggestions for files whose name ends in .js. It offers JavaScript keywords as suggestions, by checking them against the prefix provided by the content assist engine.

var provider = new eclipse.PluginProvider();
provider.registerServiceProvider("orion.edit.contentAssist",
  {
     computeProposals: function(buffer, offset, context) {
       var keywords = [ "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else",
                        "finally", "for", "function", "if", "in", "instanceof", "new", "return", "switch",
                        "this", "throw", "try", "typeof", "var", "void", "while", "with" ];
       var proposals = [];
       for (var i=0; i < keywords.length; i++) {
           var keyword = keywords[i];
           if (keyword.indexOf(context.prefix) === 0) {
               proposals.push({
                   proposal: keyword.substring(context.prefix.length),
                   description: keyword
               });
           }
        }
       return proposals;
     }
  },
  {
    name: "JavaScript content assist",
    contentType: ["application/javascript"]
  });
provider.connect();

The example below will provide completion on the character 'a' that will insert an HTML anchor element. After completion the cursor will be positioned within the href attribute.

var provider = new eclipse.PluginProvider();
provider.registerServiceProvider('orion.edit.contentAssist',
  {
    computeProposals: function(buffer, offset, context) {
      var proposals = [];
      if (context.prefix === 'a') {
        proposals.push({
          proposal: ' href=""></a>',
          description: '<a></a> - HTML anchor element', 
          escapePosition: offset+7});
      }
      return proposals;
  },
  {
    name: 'HTML content assist',
    contentType: ['text/html']
  });
provider.connect();

orion.edit.editor

This service declares a new editor. By default, the Orion client UI declares a single editor with id "orion.editor" which is used to edit source code. Using this service, you can declare entirely new editors (for example, you could register an editor that provided a paint interface for drawing images).

Contributions to this service do not directly affect the Orion UI. Instead, this service is typically used in conjunction with two other services, which allow new file types to be defined and associated with editors. See:

Service methods

None. This service is purely declarative.

Service attributes

id
String The unique identifier of this editor.
name
String The user-readable name of this editor.
uriTemplate
String Gives a URI template for constructing a URL that can be followed to drive this editor to a particular file. The parameter Location is substituted with the URL of the file being edited. The template is specified using the URI Template syntax.
orionTemplate
String Optional. Gives an Orion template for constructing the editor URL. This serves the same purpose as the uriTemplate field. However an Orion template allows a more human-readable parameter encoding scheme than a URI Template. If both fields are provided, the orionTemplate takes priority over the uriTemplate.
NOTE: Orion templates are not yet standardized.

Examples

This example code declares an editor called "My Great Editor". When My Great Editor is used to edit a file in Orion, the user will be pointed to a URL containing the location of the file they want to edit as "fileToEdit" in the query portion of the URL. Presumably myGreatEditor.php would read the string and open the file. Authentication is beyond the scope of this example.

 var provider = new eclipse.PluginProvider();
 provider.registerServiceProvider("orion.edit.editor", {}, 
   { id: "example.mygreateditor",
     name: "My Great Editor",
     uriTemplate: "http://mysite.com/myGreatEditor.php?fileToEdit={Location}"
   });

The code below shows a complete example of how to use the orion.editor, orion.core.contenttype, and orion.navigate.openWith services in conjunction to declare a new editor, declare new file types, and associate them together. The example is adapted from Orion's own source code.

 // Declare an editor
 provider.registerServiceProvider("orion.edit.editor", {}, {
   id: "orion.editor",
   name: "Orion Editor",
   uriTemplate: "../edit/edit.html#{Location,params*}",
   orionTemplate: "../edit/edit.html#{,Location,params*}"});
 
 // Declare content types
 provider.registerServiceProvider("orion.core.contenttype", {}, {
   contentTypes:
     [{ id: "text/plain",
        name: "Text",
        extension: ["txt"]
     },
     {  id: "text/html",
        "extends": "text/plain",
        name: "HTML",
        extension: ["html", "htm"]
     }]
   });
 
 // Associate editor with content types
 provider.registerServiceProvider("orion.navigate.openWith", {}, {
     editor: "orion.editor",
     contentType: ["text/plain", "text/html"]});
 
 provider.connect();

Note that the order of these registerServiceProvider() calls is not important.

orion.edit.highlighter

The orion.edit.highlighter service contributes syntax highlighting rules to the editor. A highlighter service may provide highlighting in one of two ways:

  • By passing a grammar, which is a declarative description of a language's syntax. The grammar tells the Orion editor how to recognize and style language constructs in a file.
  • By writing a highlighter, which allows highlighting information to be calculated asynchronously by the provider itself and sent to the Orion editor for display.

The service also provides a list of content types. When the editor opens a file of a registered content type, the provider is invoked (using one of the two methods described above) to obtain the styling.

NOTE: The "highlighter" API is experimental and subject to change in future versions.

Service methods

Implementations of orion.edit.highlighter whose type attribute is "highlighter", must define the following method:

setContentType(contentTypeId)
Orion invokes this method to inform the provider what kind of file it must provide highlighting for. This allows the provider that to register itself with several content types, but implement different logic for each type.

When this provider's type is "grammar", no service methods are defined. In other words, the provider is purely declarative.

Service attributes

Implementations of orion.edit.highlighter must define the following attributes:

type
String What kind of highlight provider is being registered. Allowed values are "grammar" and "highlighter". Future versions may support more.
contentType
Array An array of Content Type IDs that this provider will be used for.
grammar
Object Optional. When the type of this provider is "grammar", this attribute holds an object giving the grammar to be used to assign style classes. This object is a JavaScript equivalent of the format described here.

Service events

When the type of the provider is "highlighter", the provider must independently listen to changes in the Orion text editor by registering with the orion.edit.model service, and calculate the necessary highlighting information in response to the changes. Whenever highlighting information is available, the provider must dispatch an event of type "orion.edit.highlighter.styleReady" containing the styles. The event will be used by the Orion editor to apply styles to the file being displayed.

orion.edit.highlighter.styleReady
This event is documented in the Orion Client API reference as orion.editor.StyleReadyEvent. Consult its entry there for detailed information.

When the type of the provider is "grammar", the provider dispatches no service events.

Example of a 'grammar' provider

var provider = new eclipse.PluginProvider();
provider.registerServiceProvider("orion.edit.highlighter",
  {
    // "grammar" provider is purely declarative. No service methods.
  }, {
    type : "grammar",
    contentType: ["text/html"],
    grammar: {
      patterns: [
          {  begin: "<!--", 
             end: "-->",
             captures: { "0": "punctuation.definition.comment.html" },
             contentName: "comment.block.html"
          }
      ]
    }
  });
provider.connect();

The above example provides a grammar to be used for HTML files. It will assign the CSS class punctuation-definition-comment-html to the <!-- and --> delimiters, and assign the CSS class comment-block-html to the text inside the delimiters. Consult this reference for a full description of the grammar format.

(Note that some aspects of the grammar format are not supported. See orion.editor.TextMateStyler in the Client API reference for a detailed explanation.)

Example of a 'highlighter' provider

See the source code of the orion-codemirror plugin, particularly these lines.

orion.edit.model

An orion.edit.model service provides listeners on changes made to the orion.textview.TextView that powers the Orion editor.

NOTE: This section is experimental and may change in future versions.

Service methods

An implementation of orion.edit.model may define zero or more functions depending on what event types it gives in its types attribute. For every event type in types, the function with the name "on" + eventType will be invoked. For example, a "ModelChanged" event type causes the the provider's onModelChanged function to be invoked.

The functions are always invoked with a single parameter, event, containing the event data that was dispatched by the TextView.

Service attributes

Implementations of orion.edit.model must define the following attributes:

types
Array An array of TextView event types that this provider is interested in. When an event of one of these types is dispatched by the TextView, this provider's corresponding function will be invoked. For example, a provider with "ModelChanged" in its types array will have its onModelChanged function invoked whenever the TextView dispatches a ModelChanged event.
contentType
Array An array of Content Type IDs that this provider is interested in listening to changes for. The provider will only be notified of events that occur when a file matching one of these content types is being edited.

Example

See the source code of the orion-codemirror plugin.

orion.edit.outliner

An orion.edit.outliner service provides an overview of a file being edited. The overview is given as a tree, which the Orion UI renders in the left-hand pane alongside the file you are editing. Items in the tree can be links that take you to the appropriate position in the file, or to another URL entirely.

Service methods

Implementations of orion.edit.outliner must have a getOutline method that will be called to generate the outline for a resource. Its signature is as follows:

getOutline(contents, title)
contents String The contents of the file being edited.
title String The path and filename of the file being edited.

Returns an Array giving the top-level elements to be shown in the outline. Each element of the returned array must have the properties:

label String Text to be shown in the UI for this element.
className String Optional A space-separated list of CSS class names to be applied to this element in the UI.
children Array Optional Array of child elements of this element. Children may be nested to an arbitrary depth.
line Number Optional The line number within the file to use as the link for this element in the UI. Line numbers begin counting from 1.
The optional properties column, start, end, text may be used for finer-grained control. (Consult the orion.util.hashFromPosition() documentation in the Client API reference for details about these parameters.)
href String Optional When line is omitted, the href property provides a URL to use as the link.

Service attributes

Implementations of orion.edit.outliner must define the following attributes:

contentType
Array An array of Content Type IDs giving the types of files that this outliner can provide an outline for.
id
String A unique identifier for this outline provider.
name
String A user-readable name for this outline provider.

Examples

This example shows an outline provider that runs on .txt files. It finds Mediawiki-style =Section Headings= and generates a flat outline from them. (A more elaborate implementation might also find subsections and include them as children of the top-level sections.)

var provider = new eclipse.PluginProvider();
provider.registerServiceProvider("orion.edit.outliner", {
  getOutline: function(contents, title) {
    var outline = [];
    var lines = contents.split(/\r?\n/);
    for (var i=0; i < lines.length; i++) {
      var line = lines[i];
      var match = /^=\s*(.+?)\s*=$/.exec(line);
      if (match) {
        outline.push({
           label: match[1],
           line: i+1  // lines are numbered from 1
        });
      }
    }
    return outline;
  }
}, {
  contentType: ["text/plain"],
  name: "Headings",
  id: "orion.outliner.example.headings"
});
provider.connect();

orion.edit.validator

An orion.edit.validator service provides a function that can check the contents of a file and return a data structure indicating where problems are in the document. The result of this service is used by the Orion UI to create annotations in the ruler beside each problematic line, and also to underline the specific portion of the document where the problem occurs.

Service methods

Implementations of orion.edit.validator must define the following function:

checkSyntax(title, contents)
title String The path and filename of the file being edited.
contents String The contents of the file being edited.

Returns an Object giving the validation result. The returned object must have a problems property whose value is an array giving the problems found in the file.

The problem object

A problem object has the following properties:

description String A description of the problem.
severity String Optional Gives the severity of this problem. The severity affects how the problem is displayed in the Orion UI. Allowed values are "warning" and "error". (If omitted, "error" is assumed.)

A problem will have additional properties that give its location within the file. The location can be specified using line+column, or using offsets.

For a line-based problem, you provide a line number and columns:

line Number The line number where the problem was found. (Line numbers begin counting from 1.)
start Number The column within the line where the problem begins. (Columns begin counting from 1.)
end Number Optional The column within the line where the problems ends. (If omitted, start+1 is assumed.)

For a document-based problem, you provide character offsets:

start Number The offset at which the problem begins. (0=first character in the document.)
end Number Optional The offset at which the problem ends. (If omitted, start+1 is assumed.)

A document-based problem can span several lines.

Service attributes

Implementations of orion.edit.validator must define the following attributes:

contentType
Array An array of Content Type IDs giving the types of files that this validator is capable of validating.


Examples

var provider = new eclipse.PluginProvider();
var serviceProvider = provider.registerServiceProvider("orion.edit.validator",
  {
     checkSyntax: function(title, contents) {
       var problems = [];
       var lines = contents.split(/\r?\n/);
       for (var i=0; i < lines.length; i++) {
         var line = lines[i];
         var match = /\t \t| \t /.exec(line);
         if (match) {
           problems.push({
             description: "Mixed spaces and tabs",
             line: i + 1,
             start: match.index + 1,
             end: match.index + match[0].length + 1,
             severity: "warning" });
         }
       }
       var result = { problems: problems };
       return result;
     }
  },
  {
     contentType: ["application/javascript"]
  });
provider.connect();

This example will validate JavaScript files. It finds lines containing a sequence of space-tab-space or tab-space-tab and produces a warning on every such line. Note that +1 is necessary because column and line indices in the Orion UI are numbered from 1, not 0.

Back to the top