Jump to: navigation, search

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

(orion.edit.validator)
(Service attributes)
 
(131 intermediate revisions by 8 users not shown)
Line 1: Line 1:
 
= Overview of contributing services to the Orion editor  =
 
= Overview of contributing services to the Orion editor  =
 +
The 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.
  
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.
+
= The Editor Context object =
 +
Orion 4.0 introduced [[Orion/Documentation/Developer Guide/Architecture#Object_References|''Object References'']], which enable two-way communication between a service provider and the host Orion page. An Object Reference exposes functions that a service provider can call to help it fulfill a service contract. Like everything in Orion's service framework, Object References work asynchronously: all functions return Promises and the caller must wait for them to fulfill to an actual value. An Object Reference is valid only during the lifetime of its parent service call. Once the provider has fulfilled the service call, any Object References created for that call are unregistered by the framework, and cannot be used thereafter.
  
= orion.edit.command =
+
Many of the service APIs documented on this page now provide a special Object Reference, called the ''Editor Context object'', as the first parameter in their function signatures. The Editor Context object contains various functions to query the state of the Orion editor, and to cause side effects. For example, if a provider needs the text from the editor buffer to fulfill its service contract, it can invoke the Editor Context's <code>getText()</code> method:
  
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.
+
<source lang="javascript" enclose="div">
 +
editorContextObject.getText().then(function(text) {
 +
    // Use text to fulfill the provider's service contract
 +
});
 +
</source>
 +
 
 +
Any plugin that uses Object References must load Orion's <code>[https://github.com/eclipse/orion.client/blob/master/bundles/org.eclipse.orion.client.core/web/orion/Deferred.js Deferred.js]</code> in addition to the usual <code>plugin.js</code> script. Failure to do this will cause runtime errors when the plugin attempts to use an Object Reference.
 +
 
 +
== Editor Context methods ==
 +
The Editor Context object provides the following methods:
 +
==== Editor methods ====
 +
: '''getCaretOffset()'''
 +
::  Resolves to <tt>Number</tt>. Returns the offset of the editing caret.
 +
: '''getLineStart(lineNumber)'''
 +
:: Resolves to <tt>Number</tt>. Returns the start offset of the given line number.
 +
: '''getSelection()'''
 +
:: Resolves to <tt>Selection</tt>. Returns the editor's current selection.
 +
: '''getText(start?, end?)'''
 +
:: Resolves to <tt>String</tt>. Returns the text in the given range.
 +
: '''isDirty()'''
 +
:: Resolves to <tt>Boolean</tt>. Returns whether the editor is dirty.
 +
: '''markClean()'''
 +
:: Resolves to <tt>undefined</tt>. Removes the dirty marker from the editor.
 +
: '''setCaretOffset(offset, show?)'''
 +
:: Resolves to <tt>undefined</tt>. Sets the caret offset. If <tt>show</tt> is true, the editor will scroll to the new caret position.
 +
: '''setSelection(selection)'''
 +
:: Resolves to <tt>undefined</tt>. Sets the editor's selection.
 +
: '''setText(text, start?, end?)'''
 +
:: Resolves to <tt>undefined</tt>. Sets the text in the given range.
 +
: '''showMarkers(problems)
 +
:: Resolves to <tt>undefined</tt>. Replaces the problem markers in the editor with the given problem markers.
 +
 
 +
==== General purpose ====
 +
: '''openDelegatedUI({ uriTemplate: string, id: string })'''
 +
:: Resolves to <tt>undefined</tt>. Programatically opens a [[#Delegating_a_UI_before_manipulating_the_editor|delegated UI iframe]]. The iframe's URL is calculated by expanding the given [[Orion/Documentation/Developer_Guide/Plugging_into_Orion_pages#URI_Templates|<tt>uriTemplate</tt>]] against the metadata of the file being edited. The given <tt>id</tt> serves to identify the opened frame: any messages posted by the frame must contain a <tt>source</tt> field equal to the given <tt>id</tt>. See the [[#Delegating_a_UI_before_manipulating_the_editor|delegated UI examples]] for details about frame-to-page messaging.
 +
: '''setStatus([[#The_Status_object|status]])'''
 +
:: Resolves to <tt>undefined</tt>. Shows the given status message in the notification area.
 +
 
 +
= orion.edit.command =
 +
The <code>orion.edit.command</code> service allows plugins to provide a command that operates on the editor. Typically, the command takes some editor text as input, performs some operation or transformation on the text, and generates 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 ==
 +
The command API allows a command to take arbitrary action using the editorContext.
  
Implementations of <tt>orion.edit.command</tt> must define the following function:
+
;execute(editorContext, options)
 +
: '''editorContext''' <code>ObjectReference</code> The [[#The_Editor_Context_object|Editor Context object]].
 +
: '''options ''' <code>Object</code>
 +
:: '''options.contentType''' <code>String</code> The [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type ID]] of the file being edited.
 +
:: '''options.input''' <code>String</code> Path and filename being edited.
 +
The <code>execute()</code> method should return a Promise, which the provider is expected to resolve when it has finished performing the command action. The command action should be performed using the Editor Context object: for example, use <code>editorContext.setText()</code>to change the editor text, or <code>editorContext.setSelection()</code> to change the editor selection. The fulfillment value of the promise is ignored.
  
;run(selectedText, text, selection, resource)
+
Note: Future versions of Orion will expose delegated UI functionality through the EditorContext object. This is currently not supported, due to [https://bugs.eclipse.org/bugs/show_bug.cgi?id=419764 Bug 419764].
: 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 ==
+
=== The CommandResult object ===
 +
A CommandResult object is either a simple <code>String</code> which will replace the current editor selection, or an <code>object</code>.
 +
* The object must either have a <code>text</code> property or a <code>uriTemplate</code> property.
 +
** If it has a <code>text</code> property, then the text is a replacement string for the entire editor buffer.
 +
** If it has a <code>uriTemplate</code> property, then a delegated UI iframe will be opened on the specified URI.
 +
* It may optionally have a <code>width</code> and/or <code>height</code> property that describes the desired size of the UI. Width and height are specified in CSS units, 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 <code>result</code> property that describes the new selection text or the replacement text object. (See example).
 +
* It may optionally have a <code>selection</code> object indicating the new selection value.
 +
* It may optionally have a [[#The_Status_object|<code>status</code> field]] giving status information to show in the notification area.
  
Implementations of <tt>orion.edit.command</tt> may define the following attributes:
+
=== The Status object ===
 +
A Status object has the following fields:
 +
: '''Severity''' <code>String</code>. Allowed values are: <code>"Warning"</code>, <code>"Error"</code>.
 +
: '''Message''' <code>String</code>. The status message to display. May include hyperlinks, given in [http://daringfireball.net/projects/markdown/syntax#link Markdown syntax].
 +
 
 +
== Service attributes ==
 +
Implementations of <code>orion.edit.command</code> must define the following attributes:
  
 
;name
 
;name
:<tt>String</tt> The command text to show to the user.
+
:<code>String</code> The command text to show to the user.
 
;id
 
;id
:<tt>String</tt> The id of the command contribution.
+
:<code>String</code> The id of the command contribution.
 
;tooltip
 
;tooltip
<tt>String</tt> Optional.  A tooltip describing the command.
+
<code>String</code> Optional.  A tooltip describing the command.
 
;img
 
;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.
+
:<code>String</code> 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> 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.
+
:<code>Array</code> Optional.  A key binding for the command. The structure of this array matches the arguments of the <code>orion.textview.KeyBinding</code> constructor. See its entry in the Client API reference for details.
 
;validationProperties
 
;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.
+
:<code>[[Orion/Documentation/Developer Guide/Plugging into Orion pages#The ValidationProperty Object|ValidationProperty]][]</code> Optional.  An array of [[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
 
;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.
+
:<code>String[]</code> Optional.  An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] for which this command is valid.
 +
;nls
 +
: <code>String</code> Optional. A path to the internationalization file to read translated names and tooltips from.
 +
;nameKey
 +
: <code>String</code> Optional. When the <code>nls</code> attribute is used, this value is used to lookup the translated name for the command.
 +
;tooltipKey
 +
: <code>String</code> Optional. When the <code>nls</code> attribute is used, this value is used to lookup the translated tooltip for the command.
  
 
== Examples  ==
 
== Examples  ==
Line 38: Line 103:
 
=== Replacing the selection ===
 
=== 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).  
 
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> var provider = new eclipse.PluginProvider();
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 +
var provider = new eclipse.PluginProvider();
 
  provider.registerServiceProvider("orion.edit.command", {
 
  provider.registerServiceProvider("orion.edit.command", {
   run&nbsp;: function(text) {
+
   run : function(text) {
 
     return text.toUpperCase();
 
     return text.toUpperCase();
 
   }
 
   }
 
  }, {
 
  }, {
   name&nbsp;: "UPPERCASE",
+
   name : "UPPERCASE",
   id&nbsp;: "uppercase.example"
+
   id : "uppercase.example"
   img&nbsp;: "/images/gear.gif",
+
   img : "/images/gear.gif",
   key&nbsp;: [ "u", true ]
+
   key : [ "u", true ]
 
  });
 
  });
 
  provider.connect();
 
  provider.connect();
</pre>  
+
</source>
  
 
=== Replacing the editor contents ===
 
=== 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.  
+
This example takes the selection and wraps it in C-style block comments. In this example the function returns a complex object with both <code>text</code> and <code>selection</code> 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> contentType: ["application/javascript"],
+
<source lang="javascript" enclose="div">
  run&nbsp;: function(selectedText, text, selection) {
+
contentType: ["application/javascript"],
 +
  run : 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 61: Line 128:
 
     selection: {start:selection.start,end:selection.end+4}};
 
     selection: {start:selection.start,end:selection.end+4}};
 
  }
 
  }
</pre>  
+
</source>
  
 
=== Delegating a UI before manipulating the editor ===
 
=== 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.  
+
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 <code>uriTemplate</code> field and <code>width</code> and <code>height</code> 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",
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
  run&nbsp;: function(selectedText, text, selection, fileName) {
+
id: "delegatedUI.example",
 +
  run : function(selectedText, text, selection, fileName) {
 
   return {uriTemplate: "http://com.example/myDelegatedUI#" + fileName, width: "600px", height: "400px"};
 
   return {uriTemplate: "http://com.example/myDelegatedUI#" + fileName, width: "600px", height: "400px"};
 
  }
 
  }
</pre>  
+
</source>  
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.  
+
The delegated UI would post a message identifying itself and including a result. The message must include a <code>pageService</code> property of "orion.page.delegatedUI", a <code>source</code> that matches the orion.edit.command service id, and either a <code>result</code> or a <code>cancelled</code> property. The following examples illustrate the different ways the result could be returned.  
<pre>/* a message containing replacement selected text */
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 +
/* a message containing replacement selected text */
 
window.parent.postMessage(JSON.stringify({
 
window.parent.postMessage(JSON.stringify({
 
   pageService: "orion.page.delegatedUI",  
 
   pageService: "orion.page.delegatedUI",  
Line 91: Line 160:
 
   cancelled: true
 
   cancelled: true
 
}), "*");
 
}), "*");
</pre>
+
</source>
  
 
=== Google Picker example  ===
 
=== Google Picker example  ===
Line 99: Line 168:
  
 
= orion.edit.contentAssist =
 
= orion.edit.contentAssist =
The <tt>orion.edit.contentAssist</tt> 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.
+
The <code>orion.edit.contentAssist</code> 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 ==
 
== Service methods ==
Implementations of <tt>orion.edit.contentAssist</tt> must define the following function:
+
; initialize()
 +
''Optional method.'' If defined, the framework will invoke the provider's <tt>initialize()</tt> method at some point early in the editor creation lifecycle before <tt>computeContentAssist()</tt> is called. The return value is ignored. <tt>initialize()</tt> serves mainly to allow the framework to frontload the expensive operation of loading the provider's plugin, in order that subsequent calls to <tt>computeContentAssist()</tt> may complete more quickly.
  
;computeProposals(buffer, offset, context)
+
If the provider does not define an <tt>initialize</tt> method, it will be loaded lazily by a call to <tt>computeContentAssist()</tt> while the user is typing, which may cause an undesirable pause before the provider's proposals are displayed to the user.
: When content assist is triggered, the editor calls this function to obtain suggestions from a content assist provider.
+
::'''buffer''' <tt>String</tt> The entire buffer being edited.
+
::'''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 "proposal" objects having the following properties:
+
; computeContentAssist(editorContext, options)
 +
: '''editorContext''' <code>ObjectReference</code> The [[#The_Editor_Context_object|Editor Context object]].
 +
: '''options ''' <code>Object</code>
 +
:: '''options.delimiter''' <code>String</code> The line delimiter being used in the editor (CRLF, LF, etc.)
 +
:: '''options.indentation''' <code>String</code> The leading whitespace at the start of the line.
 +
:: '''options.line''' <code>String</code> The text of the line.
 +
:: '''options.offset''' <code>Number</code> The offset at which content assist is being requested. Relative to the document.
 +
:: '''options.prefix''' <code>String</code> 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 was in the process of typing. It can be used to narrow down the results to be returned. The prefix is just a guess; it is not appropriate for all types of document, depending on their syntax rules.
 +
:: '''options.selection''' <code>orion.editor.Selection</code> The current selection in the editor.
 +
:: '''options.tab''' <code>String</code> The tab character being used in the editor. Typical values are a Tab character, or a sequence of four spaces.
 +
Returns a <code>[[#The Proposal object|Proposal]][]</code> giving this provider's proposals for the given context.
  
: <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>.
+
== The Proposal object ==
: <b>description</b> A <tt>String</tt> describing the completion. This text will be shown in the content assist popup.
+
A Proposal object has the following basic properties:
: <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.
+
: '''description''' <code>String</code> Description text for this proposal. Will be shown in the content assist popup.
: <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.
+
: '''escapePosition''' <code>Number</code> ''Optional.'' Gives the offset, relative to the document, where the cursor should be placed after the proposal 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).
+
: '''overwrite''' <code>Boolean</code> ''Optional, defaults to <code>false</code>.'' If true, this proposal's <code>proposal</code> will overwrite the '''prefix''' that was passed to computeProposals().
 +
: '''proposal''' <code>String</code> Completion text that will be inserted in the editor if chosen by the user. The text is inserted at the '''offset''' that was passed to computeProposals().
 +
: '''style''' <code>String</code> ''Optional.'' Gives 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).
 +
: '''prefix''' <code>String</code> ''Optional.'' Allows the proposal to specify a custom prefix that should be used when filtering and applying the proposal.
  
Alternatively, a Deferred may be returned, which allows the suggestions to be computed asynchronously.
+
A Proposal can trigger ''linked mode'' when it is inserted, by providing the following additional property:
 +
: '''positions''' <code>Position[]</code> Gives an array of positions within the completion <tt>proposal</tt> that require user input. The user can use the '''Tab''' key to iterate through the regions of the proposal that require user input. <p>For example if the proposal is offering to complete a function call in a JS file, the positions could indicate the function arguments that need to be supplied.</p> <p>Every <tt>Position</tt> object must have two integer properties: '''offset''', and '''length''' describing the regions requiring user input.</p>
  
 
== Service attributes ==
 
== Service attributes ==
Implementations of <tt>orion.edit.contentAssist</tt> must define the following attributes:
+
Implementations of <code>orion.edit.contentAssist</code> must define the following attributes:
  
;name
+
; name
:<tt>String</tt> Name for the content assist provider.
+
:<code>String</code> Name for the content assist provider.
;contentType
+
; contentType
:<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.
+
:<code>String[]</code> 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 <code>computeProposals</code> function will be called only for files having one of these content types.
 +
; charTriggers
 +
:<code>String</code> A regular expression pattern matching the characters that, when typed by the user, will cause the framework to automatically activate this provider.
 +
; excludedStyles
 +
:<code>String</code> A regular expression pattern giving the style names that are excluded from this provider's <tt>charTriggers</tt> matching. When a charTrigger character is typed, and the editing caret lies in a style region matching the <tt>excludedStyles</tt> pattern, the provider will '''not''' be automatically activated. Style names are defined by a [[Orion/Documentation/Developer Guide/Plugging into the editor#Pattern objects|orion.edit.highlighter pattern]].
  
== Examples ==
+
=== Example ===
  
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.
+
The example below provides content assist suggestions for files whose name ends in <code>.js</code>. It offers JavaScript keywords as suggestions, by checking them against the prefix provided by the content assist engine.
 
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
  var provider = new eclipse.PluginProvider();
+
  var provider = new orion.PluginProvider();
 
  provider.registerServiceProvider("orion.edit.contentAssist",
 
  provider.registerServiceProvider("orion.edit.contentAssist",
 
   {
 
   {
Line 160: Line 241:
 
   });
 
   });
 
  provider.connect();
 
  provider.connect();
 +
</source>
  
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 <tt>href</tt> attribute.
+
=== Example 2 ===
 
+
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 <code>href</code> attribute.
  var provider = new eclipse.PluginProvider();
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 +
  var provider = new orion.PluginProvider();
 
  provider.registerServiceProvider('orion.edit.contentAssist',
 
  provider.registerServiceProvider('orion.edit.contentAssist',
 
   {
 
   {
Line 181: Line 264:
 
   });
 
   });
 
  provider.connect();
 
  provider.connect();
 +
</source>
 +
 +
Here is an identical example to the HTML provider, but written against the newer (preferred) API signature:
 +
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 +
// Note that orion/Deferred is an implied dependency of orion/plugin here, because we are using an object reference.
 +
define(["orion/plugin"], function(PluginProvider) {
 +
    var provider = new PluginProvider();
 +
    provider.registerServiceProvider('orion.edit.contentAssist',
 +
      {
 +
        computeContentAssist: function(editorContext, options) {
 +
          var proposals = [];
 +
          if (options.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();
 +
});
 +
</source>
 +
More advanced content assist providers will generally use the buffer text, possibly parsing the file into an Abstract Syntax Tree (AST).
 +
 +
=== Example of charTriggers and excludedStyles ===
 +
This example shows a JavaScript provider that is automatically activated by typing the characters "<tt>.</tt>" or "<tt>(</tt>", ''except when'' the editing caret is inside a comment or a string literal. The <tt>comment.</tt> and <tt>string.</tt> style names are conventions used by the Orion JavaScript syntax highlighter. See the [[Orion/Documentation/Developer_Guide/Plugging_into_the_editor#orion.edit.highlighter|orion.edit.highlighter]] documentation for more details.
 +
 +
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 +
    provider.registerService("orion.edit.contentassist",
 +
        {
 +
            /* implementation omitted */
 +
        },
 +
        {
 +
            contentType: ["application/javascript"],
 +
    id: "orion.edit.contentassist.javascript",
 +
    charTriggers: "[.(]",
 +
    excludedStyles: "(comment.*|string.*)"
 +
        });
 +
</source>
  
 
= orion.edit.editor =
 
= orion.edit.editor =
 
This service declares a new editor. By default, the Orion client UI declares a single editor with id <code>"orion.editor"</code> 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).
 
This service declares a new editor. By default, the Orion client UI declares a single editor with id <code>"orion.editor"</code> 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:
+
Contributions to this service do not directly affect the Orion UI. Instead, this service is typically used in combination with two other services, which allow new file types to be defined and associated with editors. See:
 
* [[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.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.core.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>).
Line 198: Line 324:
 
: <code>String</code> The user-readable name of this editor.
 
: <code>String</code> The user-readable name of this editor.
 
; uriTemplate
 
; uriTemplate
: <code>String</code> Gives a URI template for constructing a URL that can be followed to drive this editor to a particular file. The parameter <tt>Location</tt> is substituted with the URL of the file being edited. The template is specified using the [http://tools.ietf.org/html/draft-gregorio-uritemplate-08 URI Template] syntax.
+
: <code>String</code> Gives a URI template for constructing a URL that can be followed to drive this editor to a particular file. The parameter <code>Location</code> is substituted with the URL of the file being edited. The template is specified using the [http://tools.ietf.org/html/draft-gregorio-uritemplate-08 URI Template] syntax.
 
; orionTemplate
 
; orionTemplate
: <code>String</code> ''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 [http://tools.ietf.org/html/draft-gregorio-uritemplate-08 URI Template]. If both fields are provided, the '''orionTemplate''' takes priority over the '''uriTemplate'''.<br />'''NOTE:''' Orion templates are not yet standardized.
+
: <code>String</code> ''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 [http://tools.ietf.org/html/draft-gregorio-uritemplate-08 URI Template]. If both fields are provided, the '''orionTemplate''' takes priority over the '''uriTemplate'''.<br>'''NOTE:''' Orion templates are not yet standardized.
  
 
== Examples ==
 
== 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 <code>"fileToEdit"</code> 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.
 
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 <code>"fileToEdit"</code> 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();
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
  provider.registerServiceProvider("orion.edit.editor", {},  
+
var provider = new eclipse.PluginProvider();
 +
provider.registerServiceProvider("orion.edit.editor", {},  
 
     { id: "example.mygreateditor",
 
     { id: "example.mygreateditor",
 
       name: "My Great Editor",
 
       name: "My Great Editor",
 
       uriTemplate: "http://mysite.com/myGreatEditor.php?fileToEdit={Location}"
 
       uriTemplate: "http://mysite.com/myGreatEditor.php?fileToEdit={Location}"
 
     });
 
     });
 
+
</source>
 
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.
 
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.
 
+
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 
   // Declare an editor
 
   // Declare an editor
 
   provider.registerServiceProvider("orion.edit.editor", {}, {
 
   provider.registerServiceProvider("orion.edit.editor", {}, {
Line 240: Line 367:
 
    
 
    
 
   provider.connect();
 
   provider.connect();
 
+
</source>
 
Note that the order of these registerServiceProvider() calls is not important.
 
Note that the order of these registerServiceProvider() calls is not important.
  
= orion.edit.highlighter =
+
= orion.edit.hover =
The <code>orion.edit.highlighter</code> service contributes syntax highlighting rules to the editor. A highlighter service may provide highlighting in one of two ways:
+
The hover service allows plugins to extend the information that will get displayed on the 'hover' popup. Each plugin can augment the data in the tooltip displayed while hovering over the editor. Each plugin that returns a non-null result will end up creating a new 'section' in the tooltip containing both a 'title' and some content.
* By passing a <i>grammar</i>, 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 <i>highlighter</i>, 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.
+
'''NOTE:''' The specification is currently in a 'prototype' state and is expected to change significantly as we explore various use-cases. For now consumers should be prepared to update their plugins as the definition changes.
  
== Service methods ==
+
When a hover event occurs any plugins registered against the appropriate content type are asked to <code>computeHoverInfo</code> given the current editor's context as well as a context object containing the following information:
Implementations of <code>orion.edit.highlighter</code> whose '''type''' attribute is "highlighter", must define the following method:
+
;offset
;setContentType(contentTypeId)
+
:<code>int</code> The offset within the file of the cursor's current position
: 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.
+
;annotations
 +
:<code>String[]</code> An array of strings representing the annotations at the given offset. This will change to being a unique identifier for a particular annotation once these have been defined.
  
When this provider's '''type''' is "grammar", no service methods are defined. In other words, the provider is purely declarative.
+
Currently the response of a call to <code>computeHoverInfo</code> should either be <code>null</code> or an object with the following fields defined:
 +
;title (optional)
 +
:<code>String</code> The title to use to identify this section. This may be either raw text or formatted as markdown.
 +
;type
 +
:<code>String</code> Defines the type of the 'content'. This is used to render the correct information into the tooltip's contents. if this field is undefined then both 'title' and 'content' are rendered as raw text.
 +
;content
 +
:<code>String</code> The content to show. This combined with the defined 'type' determine the eventual output in the tooltip
 +
 
 +
Currently the only 'type' we handle is 'markdown': This allows the presentation of formatted information in a more secure manner than allowing HTML to be returned directly. In this case both the 'title' as well as the 'content' are expected to be defined using the Orion 'markdown' syntax.
  
 
== Service attributes ==
 
== Service attributes ==
Implementations of <code>orion.edit.highlighter</code> must define the following attributes:
+
Implementations of <code>orion.edit.hover</code> define the following attributes in the 'properties' element passed in during registration:
  
;type
+
;name
:<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> The name of this plugin (for use in dialogs...)
 
;contentType
 
;contentType
:<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.
+
:<code>String</code> The content type(s) that this plugin relates to. (e.g. "text/css")
;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].
+
  
== Service events ==
+
= orion.edit.highlighter =
When the '''type''' of the provider is "highlighter", the provider must independently listen to changes in the Orion text editor by registering with the <code>orion.edit.model</code> 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 <code>"orion.edit.highlighter.styleReady"</code> containing the styles. The event will be used by the Orion editor to apply styles to the file being displayed.
+
''Note that this section has been rewritten for the new syntax styling service in the Orion 5.0 release. The implementation of the older syntax styling service is also in Orion 5.0 in order to preserve backwards-compatibility, but is considered deprecated.  Documentation for this old service can be found [https://wiki.eclipse.org/index.php?title=Orion/Documentation/Developer_Guide/Plugging_into_the_editor&oldid=356484#orion.edit.highlighter here]. All new syntax styling declaration should be implemented in terms of the new styling service that is described below.''
  
;orion.edit.highlighter.styleReady
+
The <code>orion.edit.highlighter</code> service contributes syntax styling patterns to the editor. This is done by passing a <i>grammar</i>, 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.
: This event is documented in the Orion Client API reference as <code>orion.editor.StyleReadyEvent</code>. Consult its entry there for detailed information.
+
The service also provides a list of content types. When the editor opens a file of a registered content type, the provider is invoked to obtain the styling.
  
When the '''type''' of the provider is "grammar", the provider dispatches no service events.
+
== Service methods ==
 +
None. This service is purely declarative.
  
== Example of a 'grammar' provider ==
+
== Service attributes ==
  var provider = new eclipse.PluginProvider();
+
Implementations of <code>orion.edit.highlighter</code> define the following attributes:
 +
 
 +
;id
 +
:<code>String</code> A name that uniquely identifies this grammar.
 +
;contentTypes
 +
:<code>String[]</code> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] that this grammar will be used for.
 +
;patterns
 +
:<code>Object[]</code> An array of pattern objects to be used to assign style classes. Pattern objects are described below.
 +
;repository
 +
:<code>Object</code> ''Optional''. A set of named pattern objects that can be referenced by this grammar and others.
 +
 
 +
== Pattern objects ==
 +
Patterns are defined in a similar way to [http://manual.macromates.com/en/language_grammars.html#language_rules TextMate language rules], with some minor variation to adapt to the context of Orion:
 +
* Patterns are defined using valid Javascript syntax.  As a result, every '\' character requires an extra '\' to escape it in the Javascript string (for example, use "\\t" to match a Tab character).
 +
* Regular expressions are bounded by the abilities/constraints of Javascript's RegExp (for example, no look-behinds).
 +
* Sub-patterns can be defined for both ''match:'' and ''begin:/end:'' patterns.
 +
* A pattern that references another grammar does so by its id attribute (for example: "include: 'orion.lib#number_hex'").
 +
* If a capture group is used to style part of a match then all parts of the match MUST belong to capture groups, to help the styler correctly compute the capture group range (this is due to a limitation in Javascript's RegExp).  For example, to style the escaped character sequences in match result "newline is \n, tab is \t", the capture groups could look like "(newline is )(\n)(, tab is )(\t)", with the escaped character styling applied to capture groups 2 and 4.
 +
 
 +
== Style names ==
 +
The [http://manual.macromates.com/en/language_grammars.html#naming_conventions TextMate naming conventions] are followed by the text styler. In addition to visual styling, the following styles can be used to provide semantic info about matches:
 +
* ''punctuation.section.(begin|end)'': pairs of matches with these styles are used by the editor to compute section matches (for example, showing bracket matching)
 +
* ''meta.annotation.task.todo'': a match within a comment that has this style may be handled specially by the editor's container (for example, Orion will show a corresponding TODO annotation in the editor's gutter)
 +
 
 +
== orion.lib and orion.c-like ==
 +
Many of the patterns that were defined for Orion's core language stylings are applicable across many languages (for example, strings, numbers, etc.).  In order to make these patterns easily re-usable, two generic grammars are defined that contain them and can be inherited by other language grammars as needed.  These grammars are:
 +
* ''orion.lib'': provides stylings for:
 +
** matching of (), [] and {} brackets
 +
** base-10 and base-16 numbers (for example, -1.02, 3e10, 0x8ab3, etc.)
 +
** single- and double-quoted strings
 +
* ''orion.c-like'': provides additional stylings for ''//'' and ''/* */'' comments
 +
 
 +
A grammar can include any of these patterns with an include like ''"include: 'orion.lib#number_hex'"''.  The patterns provided by these grammars for 5.0 can be found in the "repository" section of [http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/tree/bundles/org.eclipse.orion.client.editor/web/orion/editor/stylers/lib/syntax.js?id=R5.0#n18 orion.lib] and [http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/tree/bundles/org.eclipse.orion.client.editor/web/orion/editor/stylers/lib/syntax.js?id=R5.0#n103 orion.c-like]
 +
 
 +
== Example ==
 +
<source lang="javascript" enclose="div" line="GESHI_FANCY_LINE_NUMBERS">
 
  provider.registerServiceProvider("orion.edit.highlighter",
 
  provider.registerServiceProvider("orion.edit.highlighter",
 
   {
 
   {
     // "grammar" provider is purely declarative. No service methods.
+
     // no service methods
 
   }, {
 
   }, {
     type : "grammar",
+
     id: "orion.json",
     contentType: ["text/html"],
+
     contentTypes: ["application/json"],
     grammar: {
+
     patterns: [
       patterns: [
+
      {include: "orion.lib#string_doubleQuote"},
          { begin: "&lt;!--",  
+
       {include: "orion.lib#string_singleQuote"},
              end: "--&gt;",
+
      {include: "orion.lib#brace_open"},
              captures: { "0": "punctuation.definition.comment.html" },
+
      {include: "orion.lib#brace_close"},
              contentName: "comment.block.html"
+
      {include: "orion.lib#bracket_open"},
          }
+
      {include: "orion.lib#bracket_close"},
       ]
+
      {include: "orion.lib#parenthesis_open"},
    }
+
      {include: "orion.lib#parenthesis_close"},
 +
      {include: "orion.lib#number_decimal"},
 +
      {include: "orion.lib#number_hex"},
 +
       {
 +
        match: "\\b(?:false|true)\\b",
 +
        name: "keyword.json"
 +
      }
 +
    ]
 
   });
 
   });
  provider.connect();
+
</source>
 +
The above example shows Orion's grammar for styling of .json files. Since .json has many language constructs that are found in other languages it is able to inherit most of its styling from Orion's provided ''orion.lib'' grammar (the *_open/*_close patterns are to enable bracket matching in the editor). The .json grammar supplements this by defining a pattern for styling ''false'' and ''true'' as keywords (an alternate styling name for these could have been ''constant.language'').
  
The above example provides a grammar to be used for HTML files. It will assign the CSS class <code>punctuation-definition-comment-html</code> to the <code>&lt;!--</code> and <code>--&gt;</code> delimiters, and assign the CSS class <code>comment-block-html</code> to the text inside the delimiters. Consult [http://manual.macromates.com/en/language_grammars.html this reference] for a full description of the grammar format.
+
= orion.edit.model =
 +
An <code>orion.edit.model</code> service provides listeners on changes made to the <code>orion.textview.TextView</code> that powers the Orion editor.
  
<i>(Note that some aspects of the grammar format are not supported. See</i> <code>orion.editor.TextMateStyler</code> <i>in the Client API reference for a detailed explanation.)</i>
+
== Service methods ==
 +
An implementation of <code>orion.edit.model</code> may define zero or more functions depending on what event types it wants to receive. When an event of type <code>X</code> is dispatched by the TextView, this the implementation's service method named <code>onX</code> will be invoked, passing the the event. For example, when the TextView dispatches a "ModelChanged" event, the provider's "onModelChanged()" method is invoked and passed the ModelChanged event object.
  
== Example of a 'highlighter' provider ==
+
The methods are always invoked with a single parameter, <code>event</code>, containing the event data that was dispatched by the TextView. The return value is ignored.
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#L155-L175 these lines].
+
  
= orion.edit.model =
+
The current list of supported "onX" methods is as follows:
An <tt>orion.edit.model</tt> service provides listeners on changes made to the <tt>orion.textview.TextView</tt> that powers the Orion editor.
+
* onContextMenu(event)
 +
* onDestroy(event)
 +
* onDragStart(event)
 +
* onDragEnd(event)
 +
* onDragEnter(event)
 +
* onDragOver(event)
 +
* onDragLeave(event)
 +
* onDragStop(event)
 +
* onModelChanging(event)
 +
* onModelChanged(event)
 +
* onModify(event)
 +
* onMouseDown(event)
 +
* onMouseUp(event)
 +
* onMouseMove(event)
 +
* onMouseOver(event)
 +
* onMouseOut(event)
 +
* onScroll(event)
 +
* onVerify(event)
 +
* onFocus(event)
 +
* onBlur(event)
  
'''NOTE:''' This section is experimental and may change in future versions.
+
Consult the [https://orionhub.org/jsdoc/symbols/orion.editor.TextView.html TextView Client API reference] for details about these event types.
 +
 
 +
== Service attributes ==
 +
Implementations of <code>orion.edit.model</code> must define the following attributes:
 +
; contentType
 +
: <code>String[]</code> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] that this provider wants to receive events for. The provider will only be notified of events that occur when the file being edited matches (or descends from) a content type given in the array.
 +
 
 +
== Example 1 ==
 +
The following example prints out some information to the browser console when certain text events occur while a JavaScript file is being edited.
 +
<source lang="javascript" enclose="div" line="line">
 +
var provider = new orion.PluginProvider();
 +
provider.registerService("orion.edit.model",
 +
    {
 +
        onModelChanging: function(event) {
 +
            console.log("Text is about to be inserted: " + event.text);
 +
        },
 +
        onScroll: function(event) {
 +
            console.log("Editor scrolled to " + event.newValue.x + ", " + event.newValue.y);
 +
        }
 +
    },
 +
    {
 +
        contentType: [ "application/javascript" ]
 +
    }});
 +
provider.connect();
 +
</source>
 +
 
 +
== Example 2 ==
 +
See the source code of the [https://github.com/mamacdon/orion-codemirror orion-codemirror plugin], which uses onModelChanging to build a shadow copy of the Orion text buffer, which it then uses to perform syntax highlighting.
 +
 
 +
= orion.edit.occurrences =
 +
The <code>orion.edit.occurrences</code> service allows plugins to compute identifier occurrences for specific [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|content types]].
  
 
== Service methods ==
 
== Service methods ==
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.
+
Implementations of <code>orion.edit.occurrences</code> must define the following function:
  
The functions are always invoked with a single parameter, <tt>event</tt>, containing the event data that was dispatched by the TextView.
+
;computeOccurrences(editorContext, context)
<!--
+
:'''editorContext''' is an <code>orion.edit.EditorContext</code> object that contains all of the information about the current editor.
;onContextMenu(event)
+
:'''context''' is an object that contains the current selection and the content type of the editor to find occurrences for.
;onDragStart(event)
+
 
;onDragEnd(event)
+
The return value (or fulfillment value) is an Array of top-level [[#The Occurrence object | occurrence objects]], which will be automatically marked in the editor.
;onDragEnter(event)
+
 
;onDragOver(event)
+
== The Occurrence object ==
;onDragLeave(event)
+
Each occurrence object has these properties:
;onDragStop(event)
+
: <b>start</b> <code>Number</code> The offset into the file for the start of the occurrence
;onModelChanging(event)
+
: <b>end</b> <code>Number</code> The offset into the file for the end of the occurrence
;onModelChanged(event)
+
;onModify(event)
+
;onMouseDown(event)
+
;onMouseUp(event)
+
;onMouseMove(event)
+
;onMouseOver(event)
+
;onMouseOut(event)
+
;onScroll(event)
+
;onVerify(event)
+
;onFocus(event)
+
;onBlur(event)
+
-->
+
  
 
== Service attributes ==
 
== Service attributes ==
Implementations of <tt>orion.edit.model</tt> must define the following attributes:
+
Implementations of <code>orion.edit.occurrences</code> may define the following attributes:
; types
+
: <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
+
: <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 ==
+
;contentType
See the source code of the [https://github.com/mamacdon/orion-codemirror orion-codemirror plugin].
+
:<code>String[]</code> An array of [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type IDs]] for which this occurrence computer is valid.
 +
;<del>pattern</del>
 +
:<code>String</code> ''Optional, deprecated.'' A regular expression pattern that is matched against filenames to determine whether this occurrence service is valid. This attribute has been deprecated in favor of <code>contentType</code>.
 +
 
 +
== Examples ==
 +
The following example is how Orion plugs in occurrence support for JavaScript:
 +
 
 +
<source lang="javascript" enclose="div" line="line">
 +
var provider = new orion.PluginProvider();
 +
provider.registerService('orion.edit.occurrences',
 +
  {
 +
      computeOccurrences: function(editorContext, context) {
 +
  return [];
 +
      }
 +
  {
 +
    contentType: ["application/javascript"]
 +
  });
 +
provider.connect();
 +
</source>
  
 
= orion.edit.outliner =
 
= orion.edit.outliner =
An <tt>orion.edit.outliner</tt> 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.
+
An <code>orion.edit.outliner</code> 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 ==
 
== Service methods ==
Implementations of <tt>orion.edit.outliner</tt> must have a <code>getOutline</code> method that will be called to generate the outline for a resource. Its signature is as follows:
+
A provider implements the <code>computeOutline</code> method, whose signature is as follows:
 +
; computeOutline(editorContext, options)
 +
: '''editorContext''' <code>ObjectReference</code> The [[#The_Editor_Context_object|Editor Context object]].
 +
: '''options ''' <code>Object</code>
 +
:: '''options.contentType''' <code>String</code> The [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type ID]] of the file being edited.
 +
The return value (or fulfillment value) is an Array of top-level [[#The OutlineElement object | OutlineElement objects]], which will be displayed in the outline pane.
  
;getOutline(contents, title)
+
== The OutlineElement object ==
: '''contents''' <tt>String</tt> The contents of the file being edited.
+
Each OutlineElement has these properties:
: '''title''' <tt>String</tt> The path and filename of the file being edited.
+
: <b>label</b> <code>String</code> Text to be shown in the UI for this element.
Returns an <tt>Array</tt> giving the top-level elements to be shown in the outline. Each element of the returned array must have the properties:
+
: <b>className</b> <code>String</code> <i>Optional</i> A space-separated list of CSS class names to be applied to this element in the UI.
 
+
: <b>labelPre</b> <code>String</code> <i>Optional</i> Text to be shown in the UI, prior to the <b>label</b> text.
: <b>label</b> <tt>String</tt> Text to be shown in the UI for this element.
+
: <b>classNamePre</b> <code>String</code> <i>Optional</i> A space-separated list of CSS class names to be applied to the labelPre element.  Can be used to add an image before the <b>label</b> text.
: <b>className</b> <tt>String</tt> <i>Optional</i> A space-separated list of CSS class names to be applied to this element in the UI.
+
: <b>labelPost</b> <code>String</code> <i>Optional</i> Text to be shown in the UI, after the <b>label</b> text.
: <b>children</b> <tt>Array</tt> <i>Optional</i> Array of child elements of this element. Children may be nested to an arbitrary depth.
+
: <b>classNamePost</b> <code>String</code> <i>Optional</i> A space-separated list of CSS class names to be applied to the labelPost element.
: <b>line</b> <tt>Number</tt> <i>Optional</i> The line number within the file to use as the link for this element in the UI. Line numbers begin counting from 1.
+
: <b>children</b> <code>OutlineElement[]</code> <i>Optional</i> Array of child OutlineElements of this element. Children may be nested to an arbitrary depth.
::The optional properties <b>column</b>, <b>start</b>, <b>end</b>, <b>text</b> may be used for finer-grained control. (Consult the <tt>orion.util.hashFromPosition()</tt> documentation in the Client API reference for details about these parameters.)
+
: <b>start, end</b> <code>Number</code> <i>Optional</i> Start and end character to select for the link in this element.  Offsets counted from beginning of the file counting from 1.
: <b>href</b> <tt>String</tt> <i>Optional</i> When <b>line</b> is omitted, the <b>href</b> property provides a URL to use as the link.
+
: <b>line, offset, length</b> <code>Number</code> <i>Optional</i> Alternative to using start and end properties, specifies a selection to display for the link in this element. Will be ignored is start property supplied. Line numbers begin counting from 1.  Offset is the column starting at 0. Length is the length of the selection.
 +
: <b>href</b> <code>String</code> <i>Optional</i> Provides a specific URL to link this element to when start/end or line/offset/length properties are not provided.
  
 
== Service attributes ==
 
== Service attributes ==
Implementations of <tt>orion.edit.outliner</tt> must define the following attributes:
+
Implementations of <code>orion.edit.outliner</code> must define the following attributes:
  
 
;contentType
 
;contentType
:<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.
+
:<code>String[]</code> 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.
+
:<code>String</code> A unique identifier for this outline provider.
 
;name
 
;name
:<tt>String</tt> A user-readable name for this outline provider.
+
:<code>String</code> A user-readable name for this outline provider. If a <tt>nameKey</tt> is provided, <tt>name</tt> is optional.
 +
;nls
 +
:<code>String</code> ''Optional.'' Path to an NLS bundle that the Orion NLS framework will load to obtain translated strings for this provider.
 +
;nameKey
 +
:<code>String</code> ''Optional.'' The NLS key used to look up the translated name of this provider in the message bundle given by the <tt>nls</tt> field.
  
 
== Examples ==
 
== Examples ==
This example shows an outline provider that runs on .txt files. It finds Mediawiki-style <tt>=Section Headings=</tt> 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.)
+
This example shows an outline provider that runs on .txt files. It finds Mediawiki-style <code>=Section Headings=</code> 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.)
 
+
<source lang="javascript" enclose="div">
 
  var provider = new eclipse.PluginProvider();
 
  var provider = new eclipse.PluginProvider();
 
  provider.registerServiceProvider("orion.edit.outliner", {
 
  provider.registerServiceProvider("orion.edit.outliner", {
Line 398: Line 635:
 
  });
 
  });
 
  provider.connect();
 
  provider.connect();
 +
</source>
  
 
= 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 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.
+
An <code>orion.edit.validator</code> service provides a function that can check the contents of a file and return a data structure indicating where problems are. 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 ==
Implementations of <tt>orion.edit.validator</tt> must define the following function:
+
; computeProblems(editorContext, options)
;checkSyntax(title, contents)
+
: '''editorContext''' <code>ObjectReference</code> The [[#The_Editor_Context_object|Editor Context object]]. Note that a validator implementation should ''only'' rely on the text of the file being edited. Accordingly, you should not call any methods other than <tt>editorContext.getText()</tt>.
: '''title''' <tt>String</tt> The path and filename of the file being edited.
+
: '''options ''' <code>Object</code>
: '''contents''' <tt>String</tt> The contents of the file being edited.
+
:: '''options.contentType''' <code>String</code> The [[Orion/Documentation/Developer Guide/Plugging into the navigator#orion.core.contenttype|Content Type ID]] 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.  
+
:: '''options.title''' <code>String</code> The path and filename of the file being edited.
 +
Returns (or fulfills to) an <code>Object</code> giving the validation result. The returned object must have a <code>problems</code> property giving an Array of [[#The Problem object|problems]] found in the file.
  
=== The problem object ===
+
== The Problem object ==
A problem object has the following properties:
+
A Problem object has the following properties:
: <b>description</b> <tt>String</tt> A description of the problem.
+
: '''description''' <code>String</code> A description of the problem. This is optional is using the <code>descriptionKey</code> and <code>descriptionArgs</code> atributes.
: <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.)
+
: '''severity''' <code>String</code> ''Optional.'' Gives the severity of this problem. The severity affects how the problem is displayed in the Orion UI. Allowed values are <code>"warning"</code> and <code>"error"</code>. (If omitted, <code>"error"</code> is assumed.)
 +
: '''descriptionKey''' <code>String</code> ''Optional'' The key to use when looking up the problem description to be internationalized.
 +
: '''descriptionArgs''' <code>String[] | Object</code> ''Optional'' The array or object or arguments to be inserted into the problem description during internationalization.
  
 
A problem will have additional properties that give its location within the file. The location can be specified using line+column, or using offsets.
 
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:
 
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>line</b> <code>Number</code> 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>start</b> <code>Number</code> 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.)
+
: <b>end</b> <code>Number</code> ''Optional'' The column within the line where the problems ends. (If omitted, <code>start+1</code> is assumed.)
  
 
For a ''document-based'' problem, you provide character offsets:
 
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>start</b> <code>Number</code> 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.)
+
: <b>end</b> <code>Number</code> ''Optional'' The offset at which the problem ends. (If omitted, <code>start+1</code> is assumed.)
  
 
A document-based problem can span several lines.
 
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 <code>orion.edit.validator</code> have the following attributes:
 
;contentType
 
;contentType
: <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.
+
: <code>String[]</code> 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.
 
+
;nls
 +
: <code>String</code> An optional string representing the path to the NLS file to use for translation of problem descriptions.
  
 
== Examples ==
 
== Examples ==
 +
<source lang="javascript" enclose="div">
 
  var provider = new eclipse.PluginProvider();
 
  var provider = new eclipse.PluginProvider();
var serviceProvider = provider.registerServiceProvider("orion.edit.validator",
+
provider.registerServiceProvider("orion.edit.validator", {
  {
+
       computeProblems: function(editorContext, options) {
       checkSyntax: function(title, contents) {
+
          var problems = [];
        var problems = [];
+
          return editorContext.getText().then(function(contents) {
        var lines = contents.split(/\r?\n/);
+
              var lines = contents.split(/\r?\n/);
        for (var i=0; i < lines.length; i++) {
+
              for (var i=0; i < lines.length; i++) {
          var line = lines[i];
+
                  var line = lines[i];
          var match = /\t \t| \t /.exec(line);
+
                  var match = /\t \t| \t /.exec(line);
          if (match) {
+
                  if (match) {
            problems.push({
+
                      problems.push({
              description: "Mixed spaces and tabs",
+
                      description: "Mixed ${0} and ${1}.",  // not required if using descriptionKey / descriptionArgs
              line: i + 1,
+
                      descriptionKey: "spaces-and-tabs", //loads message Mixed ${0} and ${1} from NLS file
              start: match.index + 1,
+
                      descriptionArgs: {0: 'spaces', 1: 'tabs'}, // or an array ['spaces', 'tabs']
              end: match.index + match[0].length + 1,
+
                      line: i + 1,
              severity: "warning" });
+
                      start: match.index + 1,
          }
+
                      end: match.index + match[0].length + 1,
        }
+
                      severity: "warning" });
        var result = { problems: problems };
+
                  }
        return result;
+
              }
      }
+
              var result = { problems: problems };
  },
+
              return result;
  {
+
          });
       contentType: ["application/javascript"]
+
    }
  });<!--
+
    },
service.dispatchEvent = serviceProvider.dispatchEvent;-->
+
    {
 +
       contentType: ["application/javascript"],
 +
      nls: "bundle/nls/problems"
 +
    });
 
  provider.connect();
 
  provider.connect();
 +
</source>
 +
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 <code>+1</code> is necessary because column and line indices in the Orion UI are numbered from 1, not 0.
  
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 <tt>+1</tt> is necessary because column and line indices in the Orion UI are numbered from 1, not 0.
+
[[Category:Orion]]

Latest revision as of 15:32, 16 October 2014

Overview of contributing services to the Orion editor

The 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.

The Editor Context object

Orion 4.0 introduced Object References, which enable two-way communication between a service provider and the host Orion page. An Object Reference exposes functions that a service provider can call to help it fulfill a service contract. Like everything in Orion's service framework, Object References work asynchronously: all functions return Promises and the caller must wait for them to fulfill to an actual value. An Object Reference is valid only during the lifetime of its parent service call. Once the provider has fulfilled the service call, any Object References created for that call are unregistered by the framework, and cannot be used thereafter.

Many of the service APIs documented on this page now provide a special Object Reference, called the Editor Context object, as the first parameter in their function signatures. The Editor Context object contains various functions to query the state of the Orion editor, and to cause side effects. For example, if a provider needs the text from the editor buffer to fulfill its service contract, it can invoke the Editor Context's getText() method:

editorContextObject.getText().then(function(text) {
    // Use text to fulfill the provider's service contract
});

Any plugin that uses Object References must load Orion's Deferred.js in addition to the usual plugin.js script. Failure to do this will cause runtime errors when the plugin attempts to use an Object Reference.

Editor Context methods

The Editor Context object provides the following methods:

Editor methods

getCaretOffset()
Resolves to Number. Returns the offset of the editing caret.
getLineStart(lineNumber)
Resolves to Number. Returns the start offset of the given line number.
getSelection()
Resolves to Selection. Returns the editor's current selection.
getText(start?, end?)
Resolves to String. Returns the text in the given range.
isDirty()
Resolves to Boolean. Returns whether the editor is dirty.
markClean()
Resolves to undefined. Removes the dirty marker from the editor.
setCaretOffset(offset, show?)
Resolves to undefined. Sets the caret offset. If show is true, the editor will scroll to the new caret position.
setSelection(selection)
Resolves to undefined. Sets the editor's selection.
setText(text, start?, end?)
Resolves to undefined. Sets the text in the given range.
showMarkers(problems)
Resolves to undefined. Replaces the problem markers in the editor with the given problem markers.

General purpose

openDelegatedUI({ uriTemplate: string, id: string })
Resolves to undefined. Programatically opens a delegated UI iframe. The iframe's URL is calculated by expanding the given uriTemplate against the metadata of the file being edited. The given id serves to identify the opened frame: any messages posted by the frame must contain a source field equal to the given id. See the delegated UI examples for details about frame-to-page messaging.
setStatus(status)
Resolves to undefined. Shows the given status message in the notification area.

orion.edit.command

The orion.edit.command service allows plugins to provide a command that operates on the editor. Typically, the command takes some editor text as input, performs some operation or transformation on the text, and generates 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

The command API allows a command to take arbitrary action using the editorContext.

execute(editorContext, options)
editorContext ObjectReference The Editor Context object.
options Object
options.contentType String The Content Type ID of the file being edited.
options.input String Path and filename being edited.

The execute() method should return a Promise, which the provider is expected to resolve when it has finished performing the command action. The command action should be performed using the Editor Context object: for example, use editorContext.setText()to change the editor text, or editorContext.setSelection() to change the editor selection. The fulfillment value of the promise is ignored.

Note: Future versions of Orion will expose delegated UI functionality through the EditorContext object. This is currently not supported, due to Bug 419764.

The CommandResult object

A CommandResult object is either a simple 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.
    • If it 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 in CSS units, 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).
  • It may optionally have a selection object indicating the new selection value.
  • It may optionally have a status field giving status information to show in the notification area.

The Status object

A Status object has the following fields:

Severity String. Allowed values are: "Warning", "Error".
Message String. The status message to display. May include hyperlinks, given in Markdown syntax.

Service attributes

Implementations of orion.edit.command must 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
ValidationProperty[] Optional. An array of Validation Properties that must match the editor's file in order for the command to appear.
contentType
String[] Optional. An array of Content Type IDs for which this command is valid.
nls
String Optional. A path to the internationalization file to read translated names and tooltips from.
nameKey
String Optional. When the nls attribute is used, this value is used to lookup the translated name for the command.
tooltipKey
String Optional. When the nls attribute is used, this value is used to lookup the translated tooltip for the command.

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).

  1.  var provider = new eclipse.PluginProvider();
  2.  provider.registerServiceProvider("orion.edit.command", {
  3.    run : function(text) {
  4.      return text.toUpperCase();
  5.    }
  6.  }, {
  7.    name : "UPPERCASE",
  8.    id : "uppercase.example"
  9.    img : "/images/gear.gif",
  10.    key : [ "u", true ]
  11.  });
  12.  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.

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

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.

  1. /* a message containing replacement selected text */
  2. window.parent.postMessage(JSON.stringify({
  3.    pageService: "orion.page.delegatedUI",
  4.    source: "delegatedUI.example",
  5.    result: replacementSelection
  6. }), "*");
  7.  
  8. /* a message containing new content for the editor */
  9. window.parent.postMessage(JSON.stringify({
  10.    pageService: "orion.page.delegatedUI",
  11.    source: "delegatedUI.example",
  12.    result: JSON.stringify({text: replacementText})
  13. }), "*");
  14.  
  15. /* a message signifying user cancellation of the delegated UI */
  16. window.parent.postMessage(JSON.stringify({
  17.    pageService: "orion.page.delegatedUI",
  18.    source: "delegatedUI.example",
  19.    cancelled: true
  20. }), "*");

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

initialize()

Optional method. If defined, the framework will invoke the provider's initialize() method at some point early in the editor creation lifecycle before computeContentAssist() is called. The return value is ignored. initialize() serves mainly to allow the framework to frontload the expensive operation of loading the provider's plugin, in order that subsequent calls to computeContentAssist() may complete more quickly.

If the provider does not define an initialize method, it will be loaded lazily by a call to computeContentAssist() while the user is typing, which may cause an undesirable pause before the provider's proposals are displayed to the user.

computeContentAssist(editorContext, options)
editorContext ObjectReference The Editor Context object.
options Object
options.delimiter String The line delimiter being used in the editor (CRLF, LF, etc.)
options.indentation String The leading whitespace at the start of the line.
options.line String The text of the line.
options.offset Number The offset at which content assist is being requested. Relative to the document.
options.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 was in the process of typing. It can be used to narrow down the results to be returned. The prefix is just a guess; it is not appropriate for all types of document, depending on their syntax rules.
options.selection orion.editor.Selection The current selection in the editor.
options.tab String The tab character being used in the editor. Typical values are a Tab character, or a sequence of four spaces.

Returns a Proposal[] giving this provider's proposals for the given context.

The Proposal object

A Proposal object has the following basic properties:

description String Description text for this proposal. Will be shown in the content assist popup.
escapePosition Number Optional. Gives the offset, relative to the document, where the cursor should be placed after the proposal is inserted. If this value is not supplied, the cursor will be positioned at the end of the inserted text.
overwrite Boolean Optional, defaults to false. If true, this proposal's proposal will overwrite the prefix that was passed to computeProposals().
proposal String Completion text that will be inserted in the editor if chosen by the user. The text is inserted at the offset that was passed to computeProposals().
style String Optional. Gives 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).
prefix String Optional. Allows the proposal to specify a custom prefix that should be used when filtering and applying the proposal.

A Proposal can trigger linked mode when it is inserted, by providing the following additional property:

positions Position[] Gives an array of positions within the completion proposal that require user input. The user can use the Tab key to iterate through the regions of the proposal that require user input.

For example if the proposal is offering to complete a function call in a JS file, the positions could indicate the function arguments that need to be supplied.

Every Position object must have two integer properties: offset, and length describing the regions requiring user input.

Service attributes

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

name
String Name for the content assist provider.
contentType
String[] 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.
charTriggers
String A regular expression pattern matching the characters that, when typed by the user, will cause the framework to automatically activate this provider.
excludedStyles
String A regular expression pattern giving the style names that are excluded from this provider's charTriggers matching. When a charTrigger character is typed, and the editing caret lies in a style region matching the excludedStyles pattern, the provider will not be automatically activated. Style names are defined by a orion.edit.highlighter pattern.

Example

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.

  1.  var provider = new orion.PluginProvider();
  2.  provider.registerServiceProvider("orion.edit.contentAssist",
  3.    {
  4.       computeProposals: function(buffer, offset, context) {
  5.         var keywords = [ "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else",
  6.                          "finally", "for", "function", "if", "in", "instanceof", "new", "return", "switch",
  7.                          "this", "throw", "try", "typeof", "var", "void", "while", "with" ];
  8.         var proposals = [];
  9.         for (var i=0; i < keywords.length; i++) {
  10.             var keyword = keywords[i];
  11.             if (keyword.indexOf(context.prefix) === 0) {
  12.                 proposals.push({
  13.                     proposal: keyword.substring(context.prefix.length),
  14.                     description: keyword
  15.                 });
  16.             }
  17.          }
  18.         return proposals;
  19.       }
  20.    },
  21.    {
  22.      name: "JavaScript content assist",
  23.      contentType: ["application/javascript"]
  24.    });
  25.  provider.connect();

Example 2

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.

  1.  var provider = new orion.PluginProvider();
  2.  provider.registerServiceProvider('orion.edit.contentAssist',
  3.    {
  4.      computeProposals: function(buffer, offset, context) {
  5.        var proposals = [];
  6.        if (context.prefix === 'a') {
  7.          proposals.push({
  8.            proposal: ' href=""></a>',
  9.            description: '<a></a> - HTML anchor element',
  10.            escapePosition: offset+7});
  11.        }
  12.        return proposals;
  13.    },
  14.    {
  15.      name: 'HTML content assist',
  16.      contentType: ['text/html']
  17.    });
  18.  provider.connect();

Here is an identical example to the HTML provider, but written against the newer (preferred) API signature:

  1.  // Note that orion/Deferred is an implied dependency of orion/plugin here, because we are using an object reference.
  2.  define(["orion/plugin"], function(PluginProvider) {
  3.      var provider = new PluginProvider();
  4.      provider.registerServiceProvider('orion.edit.contentAssist',
  5.        {
  6.          computeContentAssist: function(editorContext, options) {
  7.            var proposals = [];
  8.            if (options.prefix === 'a') {
  9.              proposals.push({
  10.                proposal: ' href=""></a>',
  11.                description: '<a></a> - HTML anchor element',
  12.                escapePosition: offset+7});
  13.            }
  14.            return proposals;
  15.        },
  16.        {
  17.          name: 'HTML content assist',
  18.          contentType: ['text/html']
  19.        });
  20.      provider.connect();
  21.  });

More advanced content assist providers will generally use the buffer text, possibly parsing the file into an Abstract Syntax Tree (AST).

Example of charTriggers and excludedStyles

This example shows a JavaScript provider that is automatically activated by typing the characters "." or "(", except when the editing caret is inside a comment or a string literal. The comment. and string. style names are conventions used by the Orion JavaScript syntax highlighter. See the orion.edit.highlighter documentation for more details.

  1.     provider.registerService("orion.edit.contentassist",
  2.         {
  3.             /* implementation omitted */
  4.         },
  5.         {
  6.             contentType: ["application/javascript"],
  7.             id: "orion.edit.contentassist.javascript",
  8.             charTriggers: "[.(]",
  9.             excludedStyles: "(comment.*|string.*)"
  10.         });

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 combination 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.

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

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.

  1.   // Declare an editor
  2.   provider.registerServiceProvider("orion.edit.editor", {}, {
  3.     id: "orion.editor",
  4.     name: "Orion Editor",
  5.     uriTemplate: "../edit/edit.html#{Location,params*}",
  6.     orionTemplate: "../edit/edit.html#{,Location,params*}"});
  7.  
  8.   // Declare content types
  9.   provider.registerServiceProvider("orion.core.contenttype", {}, {
  10.     contentTypes:
  11.       [{ id: "text/plain",
  12.          name: "Text",
  13.          extension: ["txt"]
  14.       },
  15.       {  id: "text/html",
  16.          "extends": "text/plain",
  17.          name: "HTML",
  18.          extension: ["html", "htm"]
  19.       }]
  20.     });
  21.  
  22.   // Associate editor with content types
  23.   provider.registerServiceProvider("orion.navigate.openWith", {}, {
  24.       editor: "orion.editor",
  25.       contentType: ["text/plain", "text/html"]});
  26.  
  27.   provider.connect();

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

orion.edit.hover

The hover service allows plugins to extend the information that will get displayed on the 'hover' popup. Each plugin can augment the data in the tooltip displayed while hovering over the editor. Each plugin that returns a non-null result will end up creating a new 'section' in the tooltip containing both a 'title' and some content.

NOTE: The specification is currently in a 'prototype' state and is expected to change significantly as we explore various use-cases. For now consumers should be prepared to update their plugins as the definition changes.

When a hover event occurs any plugins registered against the appropriate content type are asked to computeHoverInfo given the current editor's context as well as a context object containing the following information:

offset
int The offset within the file of the cursor's current position
annotations
String[] An array of strings representing the annotations at the given offset. This will change to being a unique identifier for a particular annotation once these have been defined.

Currently the response of a call to computeHoverInfo should either be null or an object with the following fields defined:

title (optional)
String The title to use to identify this section. This may be either raw text or formatted as markdown.
type
String Defines the type of the 'content'. This is used to render the correct information into the tooltip's contents. if this field is undefined then both 'title' and 'content' are rendered as raw text.
content
String The content to show. This combined with the defined 'type' determine the eventual output in the tooltip

Currently the only 'type' we handle is 'markdown': This allows the presentation of formatted information in a more secure manner than allowing HTML to be returned directly. In this case both the 'title' as well as the 'content' are expected to be defined using the Orion 'markdown' syntax.

Service attributes

Implementations of orion.edit.hover define the following attributes in the 'properties' element passed in during registration:

name
String The name of this plugin (for use in dialogs...)
contentType
String The content type(s) that this plugin relates to. (e.g. "text/css")

orion.edit.highlighter

Note that this section has been rewritten for the new syntax styling service in the Orion 5.0 release. The implementation of the older syntax styling service is also in Orion 5.0 in order to preserve backwards-compatibility, but is considered deprecated. Documentation for this old service can be found here. All new syntax styling declaration should be implemented in terms of the new styling service that is described below.

The orion.edit.highlighter service contributes syntax styling patterns to the editor. This is done 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. The service also provides a list of content types. When the editor opens a file of a registered content type, the provider is invoked to obtain the styling.

Service methods

None. This service is purely declarative.

Service attributes

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

id
String A name that uniquely identifies this grammar.
contentTypes
String[] An array of Content Type IDs that this grammar will be used for.
patterns
Object[] An array of pattern objects to be used to assign style classes. Pattern objects are described below.
repository
Object Optional. A set of named pattern objects that can be referenced by this grammar and others.

Pattern objects

Patterns are defined in a similar way to TextMate language rules, with some minor variation to adapt to the context of Orion:

  • Patterns are defined using valid Javascript syntax. As a result, every '\' character requires an extra '\' to escape it in the Javascript string (for example, use "\\t" to match a Tab character).
  • Regular expressions are bounded by the abilities/constraints of Javascript's RegExp (for example, no look-behinds).
  • Sub-patterns can be defined for both match: and begin:/end: patterns.
  • A pattern that references another grammar does so by its id attribute (for example: "include: 'orion.lib#number_hex'").
  • If a capture group is used to style part of a match then all parts of the match MUST belong to capture groups, to help the styler correctly compute the capture group range (this is due to a limitation in Javascript's RegExp). For example, to style the escaped character sequences in match result "newline is \n, tab is \t", the capture groups could look like "(newline is )(\n)(, tab is )(\t)", with the escaped character styling applied to capture groups 2 and 4.

Style names

The TextMate naming conventions are followed by the text styler. In addition to visual styling, the following styles can be used to provide semantic info about matches:

  • punctuation.section.(begin|end): pairs of matches with these styles are used by the editor to compute section matches (for example, showing bracket matching)
  • meta.annotation.task.todo: a match within a comment that has this style may be handled specially by the editor's container (for example, Orion will show a corresponding TODO annotation in the editor's gutter)

orion.lib and orion.c-like

Many of the patterns that were defined for Orion's core language stylings are applicable across many languages (for example, strings, numbers, etc.). In order to make these patterns easily re-usable, two generic grammars are defined that contain them and can be inherited by other language grammars as needed. These grammars are:

  • orion.lib: provides stylings for:
    • matching of (), [] and {} brackets
    • base-10 and base-16 numbers (for example, -1.02, 3e10, 0x8ab3, etc.)
    • single- and double-quoted strings
  • orion.c-like: provides additional stylings for // and /* */ comments

A grammar can include any of these patterns with an include like "include: 'orion.lib#number_hex'". The patterns provided by these grammars for 5.0 can be found in the "repository" section of orion.lib and orion.c-like

Example

  1.  provider.registerServiceProvider("orion.edit.highlighter",
  2.    {
  3.      // no service methods
  4.    }, {
  5.      id: "orion.json",
  6.      contentTypes: ["application/json"],
  7.      patterns: [
  8.        {include: "orion.lib#string_doubleQuote"},
  9.        {include: "orion.lib#string_singleQuote"},
  10.        {include: "orion.lib#brace_open"},
  11.        {include: "orion.lib#brace_close"},
  12.        {include: "orion.lib#bracket_open"},
  13.        {include: "orion.lib#bracket_close"},
  14.        {include: "orion.lib#parenthesis_open"},
  15.        {include: "orion.lib#parenthesis_close"},
  16.        {include: "orion.lib#number_decimal"},
  17.        {include: "orion.lib#number_hex"},
  18.        {
  19.          match: "\\b(?:false|true)\\b",
  20.          name: "keyword.json"
  21.        }
  22.      ]
  23.    });

The above example shows Orion's grammar for styling of .json files. Since .json has many language constructs that are found in other languages it is able to inherit most of its styling from Orion's provided orion.lib grammar (the *_open/*_close patterns are to enable bracket matching in the editor). The .json grammar supplements this by defining a pattern for styling false and true as keywords (an alternate styling name for these could have been constant.language).

orion.edit.model

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

Service methods

An implementation of orion.edit.model may define zero or more functions depending on what event types it wants to receive. When an event of type X is dispatched by the TextView, this the implementation's service method named onX will be invoked, passing the the event. For example, when the TextView dispatches a "ModelChanged" event, the provider's "onModelChanged()" method is invoked and passed the ModelChanged event object.

The methods are always invoked with a single parameter, event, containing the event data that was dispatched by the TextView. The return value is ignored.

The current list of supported "onX" methods is as follows:

  • onContextMenu(event)
  • onDestroy(event)
  • onDragStart(event)
  • onDragEnd(event)
  • onDragEnter(event)
  • onDragOver(event)
  • onDragLeave(event)
  • onDragStop(event)
  • onModelChanging(event)
  • onModelChanged(event)
  • onModify(event)
  • onMouseDown(event)
  • onMouseUp(event)
  • onMouseMove(event)
  • onMouseOver(event)
  • onMouseOut(event)
  • onScroll(event)
  • onVerify(event)
  • onFocus(event)
  • onBlur(event)

Consult the TextView Client API reference for details about these event types.

Service attributes

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

contentType
String[] An array of Content Type IDs that this provider wants to receive events for. The provider will only be notified of events that occur when the file being edited matches (or descends from) a content type given in the array.

Example 1

The following example prints out some information to the browser console when certain text events occur while a JavaScript file is being edited.

  1. var provider = new orion.PluginProvider();
  2. provider.registerService("orion.edit.model",
  3.     {
  4.         onModelChanging: function(event) {
  5.             console.log("Text is about to be inserted: " + event.text);
  6.         },
  7.         onScroll: function(event) {
  8.             console.log("Editor scrolled to " + event.newValue.x + ", " + event.newValue.y);
  9.         }
  10.     },
  11.     {
  12.         contentType: [ "application/javascript" ]
  13.     }});
  14. provider.connect();

Example 2

See the source code of the orion-codemirror plugin, which uses onModelChanging to build a shadow copy of the Orion text buffer, which it then uses to perform syntax highlighting.

orion.edit.occurrences

The orion.edit.occurrences service allows plugins to compute identifier occurrences for specific content types.

Service methods

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

computeOccurrences(editorContext, context)
editorContext is an orion.edit.EditorContext object that contains all of the information about the current editor.
context is an object that contains the current selection and the content type of the editor to find occurrences for.

The return value (or fulfillment value) is an Array of top-level occurrence objects, which will be automatically marked in the editor.

The Occurrence object

Each occurrence object has these properties:

start Number The offset into the file for the start of the occurrence
end Number The offset into the file for the end of the occurrence

Service attributes

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

contentType
String[] An array of Content Type IDs for which this occurrence computer is valid.
pattern
String Optional, deprecated. A regular expression pattern that is matched against filenames to determine whether this occurrence service is valid. This attribute has been deprecated in favor of contentType.

Examples

The following example is how Orion plugs in occurrence support for JavaScript:

  1. var provider = new orion.PluginProvider();
  2. provider.registerService('orion.edit.occurrences',
  3.    {
  4.        computeOccurrences: function(editorContext, context) {
  5.            return [];
  6.        }
  7.    {
  8.      contentType: ["application/javascript"]
  9.    });
  10. provider.connect();

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

A provider implements the computeOutline method, whose signature is as follows:

computeOutline(editorContext, options)
editorContext ObjectReference The Editor Context object.
options Object
options.contentType String The Content Type ID of the file being edited.

The return value (or fulfillment value) is an Array of top-level OutlineElement objects, which will be displayed in the outline pane.

The OutlineElement object

Each OutlineElement has these 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.
labelPre String Optional Text to be shown in the UI, prior to the label text.
classNamePre String Optional A space-separated list of CSS class names to be applied to the labelPre element. Can be used to add an image before the label text.
labelPost String Optional Text to be shown in the UI, after the label text.
classNamePost String Optional A space-separated list of CSS class names to be applied to the labelPost element.
children OutlineElement[] Optional Array of child OutlineElements of this element. Children may be nested to an arbitrary depth.
start, end Number Optional Start and end character to select for the link in this element. Offsets counted from beginning of the file counting from 1.
line, offset, length Number Optional Alternative to using start and end properties, specifies a selection to display for the link in this element. Will be ignored is start property supplied. Line numbers begin counting from 1. Offset is the column starting at 0. Length is the length of the selection.
href String Optional Provides a specific URL to link this element to when start/end or line/offset/length properties are not provided.

Service attributes

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

contentType
String[] 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. If a nameKey is provided, name is optional.
nls
String Optional. Path to an NLS bundle that the Orion NLS framework will load to obtain translated strings for this provider.
nameKey
String Optional. The NLS key used to look up the translated name of this provider in the message bundle given by the nls field.

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. 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

computeProblems(editorContext, options)
editorContext ObjectReference The Editor Context object. Note that a validator implementation should only rely on the text of the file being edited. Accordingly, you should not call any methods other than editorContext.getText().
options Object
options.contentType String The Content Type ID of the file being edited.
options.title String The path and filename of the file being edited.

Returns (or fulfills to) an Object giving the validation result. The returned object must have a problems property giving an Array of problems found in the file.

The Problem object

A Problem object has the following properties:

description String A description of the problem. This is optional is using the descriptionKey and descriptionArgs atributes.
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.)
descriptionKey String Optional The key to use when looking up the problem description to be internationalized.
descriptionArgs String[] | Object Optional The array or object or arguments to be inserted into the problem description during internationalization.

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 have the following attributes:

contentType
String[] An array of Content Type IDs giving the types of files that this validator is capable of validating.
nls
String An optional string representing the path to the NLS file to use for translation of problem descriptions.

Examples

 var provider = new eclipse.PluginProvider();
provider.registerServiceProvider("orion.edit.validator", {
      computeProblems: function(editorContext, options) {
          var problems = [];
          return editorContext.getText().then(function(contents) {
              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 ${0} and ${1}.",  // not required if using descriptionKey / descriptionArgs
                      descriptionKey: "spaces-and-tabs",  //loads message Mixed ${0} and ${1} from NLS file
                      descriptionArgs: {0: 'spaces', 1: 'tabs'}, // or an array ['spaces', '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"],
      nls: "bundle/nls/problems"
    });
 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.