Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Orion/Documentation/Developer Guide/Plugging into the editor
Contents
- 1 Overview of contributing services to the Orion editor
- 2 The Editor Context object
- 3 orion.edit.command
- 4 orion.edit.contentAssist
- 5 orion.edit.editor
- 6 orion.edit.format
- 7 orion.edit.hover
- 8 orion.edit.highlighter
- 9 orion.edit.model
- 10 orion.edit.occurrences
- 11 orion.edit.open.declaration
- 12 orion.edit.outliner
- 13 orion.edit.references
- 14 orion.edit.validator
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 callbacks that a service provider can invoke to help it fulfill a service contract. Like everything in Orion's service framework, Object References work asynchronously: all functions return "then-able" 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. - options.offset
Number
The current caret offset in the file being edited.
- options.contentType
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 a CommandResult object. Rejecting the promise with a Status object will show it in the notification area.
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
. If the object is null
or undefined
, it will be ignored.
- The object must either have a
text
property or auriTemplate
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.
- If it has a
- It may optionally have a
width
and/orheight
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 aresult
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 typically has the following fields:
- Severity
String
. Allowed values are:"Warning"
,"Error"
. - Message
String
. The status message to display.
Alternatively, to provide a rich-text message in Markdown syntax Markdown syntax, the following fields may be used instead:
- Severity
String
. Allowed values are:"Warning"
,"Error"
. - type
String
. The type of content being provided. The only supported value at present is "markdown". - content
String
. The content (i.e. Markdown source) to be rendered.
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 theorion.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.
Examples
The following examples start with the simplest editor command and then add more complexity.
Replacing the selection
This example converts the selected text to upper case. The function return value is a simple string, so this is interpreted by the editor as replacement for the original editor selection. In the service properties, we see the command provides a key binding of Ctrl+U (or Cmd+U on Mac).
- var provider = new orion.PluginProvider();
- provider.registerServiceProvider("orion.edit.command", {
- run : function(text) {
- return text.toUpperCase();
- }
- }, {
- name : "UPPERCASE",
- id : "uppercase.example",
- img : "/images/gear.gif",
- key : [ "u", true ]
- });
- provider.connect();
Replacing the editor contents
This example takes the selection and wraps it in C-style block comments. In this example the function returns a complex object with both text
and selection
fields. These are interpreted by the editor as the new editor buffer contents, and the new editor selection. A content type is used so that this command is only available for javascript files.
run : function(selectedText, text, selection) {
return {text: text.substring(0,selection.start) + "/*" +
text.substring(selection.start,selection.end) + "*/" +
text.substring(selection.end),
selection: {start:selection.start,end:selection.end+4}};
}
Delegating a UI before manipulating the editor
Here is an example of a delegated UI run function that computes a URL for the delegated UI based on the file name of the edited file. In this example, the function returns a complex object with a uriTemplate
field and width
and height
properties. The UI that is opened will be responsible for posting a message back to the editor with a result object that contains either a String for the selected text or a complex object with replacement content.
- id: "delegatedUI.example",
- run : function(selectedText, text, selection, fileName) {
- return {uriTemplate: "http://com.example/myDelegatedUI#" + fileName, width: "600px", height: "400px"};
- }
The delegated UI would post a message identifying itself and including a result. The message must include a pageService
property of "orion.page.delegatedUI", a source
that matches the orion.edit.command service id, and either a result
or a cancelled
property. The following examples illustrate the different ways the result could be returned.
- /* a message containing replacement selected text */
- window.parent.postMessage(JSON.stringify({
- pageService: "orion.page.delegatedUI",
- source: "delegatedUI.example",
- result: replacementSelection
- }), "*");
- /* a message containing new content for the editor */
- window.parent.postMessage(JSON.stringify({
- pageService: "orion.page.delegatedUI",
- source: "delegatedUI.example",
- result: JSON.stringify({text: replacementText})
- }), "*");
- /* a message signifying user cancellation of the delegated UI */
- window.parent.postMessage(JSON.stringify({
- pageService: "orion.page.delegatedUI",
- source: "delegatedUI.example",
- cancelled: true
- }), "*");
Google Picker example
The Google Picker is a fully functioning example of a delegated UI in an editor command. It opens a Google Picker allowing the user to pick a resource, and then inserts a link to that resource into the editor text. To install the plug-in, open this link. The code is available here.
orion.edit.contentAssist
The orion.edit.contentAssist
service contributes content assist providers to the editor. A content assist provider produces suggestions for text that may be inserted into the editor at a given point. Providers are invoked when the user triggers the "content assist" action by pressing Ctrl+Space in the editor.
Service methods
- 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.
- options.delimiter
Returns a Proposal[]
giving this provider's proposals for the given context.
- computePrefix(editorContext, offset)
- editorContext
ObjectReference
The Editor Context object. - offset
Number
The offset at which content assist is being requested. Relative to the document.
Returns a String
that will be the options.prefix property used to call the computeContentAssist(editorContext, options)
. This function should be defined when the user wants to customize the computation of the prefix according to the provider.
The Proposal object
A Proposal object has the following basic properties:
- 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(). - description
String
Description text for this proposal. Will be shown in the content assist popup. - name
String
Optional, defaults todescription
Name for this proposal to display 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 tofalse
. If true, this proposal'sproposal
will overwrite the prefix 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) or"strikethrough"
(proposal displayed in bold and has strikethrough line). - prefix
String
Optional. Allows the proposal to specify a custom prefix that should be used when filtering and applying the proposal. - tags
[{content, cssClass, color}, ...]
Optional. An array of tag objects which will be inserted at the start of the proposal. Allows proposals to display styled tags and icons. content specifies the text content of the tag and is optional. cssClass specifies a CSS class to apply to the tag and is optional (defaults to a bordered style). color specifies a string color name that will be displayed as a rectangle and is optional.
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'scomputeProposals
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.- autoApply
Boolean
An optional flag introduced in Orion 13.0 that tells the content assist framework if single-computed proposals should be automatically applied rather than shown in the proposal popup. If not specified, the default value istrue
.
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.
- var provider = new orion.PluginProvider();
- provider.registerServiceProvider("orion.edit.contentAssist",
- {
- computeProposals: function(buffer, offset, context) {
- var keywords = [ "break", "case", "catch", "continue", "debugger", "default", "delete", "do", "else",
- "finally", "for", "function", "if", "in", "instanceof", "new", "return", "switch",
- "this", "throw", "try", "typeof", "var", "void", "while", "with" ];
- var proposals = [];
- for (var i=0; i < keywords.length; i++) {
- var keyword = keywords[i];
- if (keyword.indexOf(context.prefix) === 0) {
- proposals.push({
- proposal: keyword.substring(context.prefix.length),
- description: keyword
- });
- }
- }
- return proposals;
- }
- },
- {
- name: "JavaScript content assist",
- contentType: ["application/javascript"]
- });
- provider.connect();
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.
- var provider = new orion.PluginProvider();
- provider.registerServiceProvider('orion.edit.contentAssist',
- {
- computeProposals: function(buffer, offset, context) {
- var proposals = [];
- if (context.prefix === 'a') {
- proposals.push({
- proposal: ' href=""></a>',
- description: '<a></a> - HTML anchor element',
- escapePosition: offset+7});
- }
- return proposals;
- },
- {
- name: 'HTML content assist',
- contentType: ['text/html']
- });
- provider.connect();
Here is an identical example to the HTML provider, but written against the newer (preferred) API signature:
- // 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();
- });
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.
- provider.registerService("orion.edit.contentassist",
- {
- /* implementation omitted */
- },
- {
- contentType: ["application/javascript"],
- id: "orion.edit.contentassist.javascript",
- charTriggers: "[.(]",
- excludedStyles: "(comment.*|string.*)"
- });
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:
- orion.core.contenttype: Registers a new content type for files.
- orion.navigate.openWith: Associates a content type (registered via
orion.core.contenttype
) to an editor (registered viaorion.edit.editor
).
There are two distinct ways this service can be used:
- To declare an editor that is implemented on a separate page. In this case the service is purely declarative (has no service methods).
- To declare a pluggable editor that is embedded into the right-hand pane of Orion's edit.html. In this case several service methods must be implemented (see below). The Orion page makes visible the IFRAME of a plugin providing a pluggable editor. The plugin fully controls its visuals and interaction, and can render to its own DOM and handle events.
Service methods: separate page
When implementing a separate-page editor, no service methods are provided.
Service methods: pluggable editor
When implementing a pluggable editor, the following service methods must be provided:
- setTextModel(pluggableEditorContext) - returns Promise
- Called by the framework to provide access to the model as text. This method must return a Promise, which is left un-settled (meaning its .resolve() and .reject() methods are never called) for the lifetime of the editor.
- setBlob(blob)
- Optional. Called by the framework to provide the model as binary data. This method should be implemented by an editor that needs to treat the file being edited as binary data rather than text. See imageViewerPlugin.js for an example.
- onChanged(modelChangedEvent)
- Called by the framework to inform the editor of a change to the model.
- registerKeys(keybindings)
- Called by the framework to inform the editor of active key bindings. The editor should register corresponding keyboard listeners against its own DOM (commandsProxy.js can help here.)
Service attributes
- id
-
String
The unique identifier of this editor. - default
-
boolean
Optional, default is false. Whether this editor should be the default editor for any content types it can handle.
The Orion UI opens the default editor when a file is clicked. Other editors are shown in an Open with context menu. - 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 parameterLocation
is substituted with the URL of the file being edited. The template is specified using the URI Template syntax. For a pluggable editor, a template like the following should be used, replacing myEditorId with the id property of this editor:
uriTemplate: "{+OrionHome}/edit/edit.html#{,Location,params*},editor=myEditorId"
This is a special URL that will cause edit.html to activate myEditorId to handle the file.
Examples
Declaring an external editor
This example code declares an editor called "My Great Editor". When My Great Editor is used to edit a file in Orion, the user will be pointed to a URL containing the location of the file they want to edit as "fileToEdit"
in the query portion of the URL. Presumably myGreatEditor.php would read the string and open the file. Authentication is beyond the scope of this example.
- var provider = new orion.PluginProvider();
- provider.registerServiceProvider("orion.edit.editor", {},
- { id: "example.mygreateditor",
- name: "My Great Editor",
- uriTemplate: "http://mysite.com/myGreatEditor.php?fileToEdit={Location}"
- });
The code below shows a complete example of how to use the orion.editor
, orion.core.contenttype
, and orion.navigate.openWith
services in conjunction to declare a new editor, declare new file types, and associate them together. The example is adapted from Orion's own source code.
- // Declare an editor
- provider.registerServiceProvider("orion.edit.editor", {}, {
- id: "orion.editor",
- name: "Orion Editor",
- uriTemplate: "../edit/edit.html#{Location,params*}",
- orionTemplate: "../edit/edit.html#{,Location,params*}"});
- // Declare content types
- provider.registerServiceProvider("orion.core.contenttype", {}, {
- contentTypes:
- [{ id: "text/plain",
- name: "Text",
- extension: ["txt"]
- },
- { id: "text/html",
- "extends": "text/plain",
- name: "HTML",
- extension: ["html", "htm"]
- }]
- });
- // Associate editor with content types
- provider.registerServiceProvider("orion.navigate.openWith", {}, {
- editor: "orion.editor",
- contentType: ["text/plain", "text/html"]});
- provider.connect();
Note that the order of these registerServiceProvider() calls is not important.
Declaring a pluggable editor
This example declares a pluggable editor that handles JSON files. It is adapted from jsonEditorPlugin.js.
- define([
- "orion/Deferred", // Deferred is mandatory because Object References are used
- "orion/commandsProxy",
- ], function(Deferred, CommandsProxy) {
- var EDITOR_ID = "orion.editor.json";
- var commandsProxy = new mCommandsProxy.CommandsProxy();
- var context;
- function refreshEditor() {
- // Omitted
- }
- provider.registerService("orion.edit.editor", {
- setTextModel: function(pluggableEditorContext) {
- context = pluggableEditorContext;
- refreshEditor();
- commandsProxy.setProxy(pluggableEditorContext);
- return new Deferred(); // Keep the channel open
- },
- onChanged: function(evt) {
- refreshEditor();
- },
- registerKeys: function(keys) {
- var bindings = keys.map(function(key) {
- return new mKeyBinding.KeyBinding(key.keyCode, key.mod1, key.mod2, key.mod3, key.mod4);
- });
- commandsProxy.setKeyBindings(bindings);
- }
- }, {
- id: EDITOR_ID,
- name: "JSON Editor",
- uriTemplate: "../edit/edit.html#{,Location,params*},editor=" + EDITOR_ID
- });
- provider.registerService("orion.navigate.openWith", null, {
- editor: EDITOR_ID,
- contentType: ["application/json"]
- });
- provider.connect();
orion.edit.format
The orion.edit.format
service allows plugins to contribute a formatter for specific content types.
Service methods
Implementations of orion.edit.format
must define the following function:
- format(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 other information to help with formatting.
There is no return value from the function. Instead, consumers must call editorContext.setText() with the formatted text. This allows plugins to format potentially very large amounts of text without having to send all of the text and formatting back for further processing in the platform - it is asynchronously set in the editor by the command.
Service attributes
Implementations of orion.edit.format
may define the following attributes:
- contentType
String[]
An array of Content Type IDs for which this formatter is valid.- name
String
Optional. A human-readable name for the formatter - for example 'JavaScript Formatter'- id
String
Optional. A unique identifier for the formatter - for example 'orion.format.js'
Examples
The following example is how Orion plugs in occurrence support for JavaScript:
- var provider = new orion.PluginProvider();
- provider.registerServiceProvider("orion.edit.format",
- {
- format: function format(editorContext, context) {
- //format the code
- }
- }, {
- name: javascriptMessages["javascriptFormatter"],
- contentType: ["application/javascript"],
- id: "orion.format.js.formatter"
- });
- provider.connect();
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 or content assist. 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.
computeHoverInfo(editorContext, context)
When a hover event occurs, any hover services registered against the appropriate content type will be called to computeHoverInfo
. The state of the editor can be accessed using the editorContext object. Information on the source of the hover call is provided in the context
object. The call is expected to return null
to not display a hover or a hover info object to display.
Context
The context
object provided to computeHoverInfo
will have the following contents:
- 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. Available when hovering over an annotation (in the ruler or the text).- offset
int
The offset within the file of the cursor's current position when. Available when hovering over text.- proposal
{Proposal}
The proposal object currently selected in the content assist window. Available when the content assist window is open.
Hover Object
The return
of a call to computeHoverInfo
should either be null
or an object with the following contents:
- title (optional)
String
The title to use to identify this section. This may be either raw text or formatted as markdown.- content
String
The content to show. This combined with the defined 'type' determine the eventual output in the tooltip.- 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. The type 'markdown' will render the content and title text as markdown (sanitized to remove HTML tags). The type 'html' will render the content text as HTML inside of an iframe.- offsetStart (optional)
int
Along withoffsetEnd
, specifies the text offset range associated with the returned hover content. If not provided, the closest word to theoffset
will be used.- offsetEnd (optional)
int
Along withoffsetStart
, specifies the text offset range associated with the returned hover content. If not provided, the closest word to theoffset
will be used.- width (optional)
String
When the content 'type' is 'html', this string is set as the 'width' style of the iframe containing the content (ex. "200px").- height (optional)
String
When the content 'type' is 'html', this string is set as the 'height' style of the iframe containing the content (ex. "200px").- allowFullWidth (optional)
Boolean
By default the tooltip width is restricted to half of the editor width. This allows long contents to not cover the entire editor and instead wrap and scroll. This behavior can be overridden by setting theallowFullWidth
property to true. When true, the tooltip can open as wide as the editor.
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
- provider.registerServiceProvider("orion.edit.highlighter",
- {
- // no service methods
- }, {
- id: "orion.json",
- contentTypes: ["application/json"],
- patterns: [
- {include: "orion.lib#string_doubleQuote"},
- {include: "orion.lib#string_singleQuote"},
- {include: "orion.lib#brace_open"},
- {include: "orion.lib#brace_close"},
- {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"
- }
- ]
- });
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).
Notice that the TextStyler expects block patterns at the beginning of the 'patterns' array. Bracket matching does not work, if the (.begin|.end) patterns are followed by a block pattern.
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, the implementation's service method named onX
is 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 provider's method is listen-only; the return value is ignored.
The event object contains the exact data of the event that was dispatched by the TextView. Consult the TextView Client API reference for details about what fields are present on each event type. In addition to the TextView data, the following additional property is also provided:
- file
- Object Holds metadata about the file currently being edited, such as name, location, and contentType.
Here is a list of the currently supported service methods:
- 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)
- onSaving(event)
- onInputChanged(event)
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: A simple listener
The following example prints out some information to the browser console when certain text events occur while a JavaScript file is being edited.
- 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();
Example 2: Using metadata
The following example uses the file field of the event object to print the name of the CSS file being edited whenever the textview receives focus.
- var provider = new orion.PluginProvider();
- provider.registerService("orion.edit.model",
- {
- onFocus: function(event) {
- console.log("User is editing: " + event.file.location);
- }
- },
- {
- contentType: [ "text/css" ]
- }});
- provider.connect();
Example 3
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 dynamic syntax highlighting in code.
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.patternString
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 ofcontentType
.
Examples
The following example is how Orion plugs in occurrence support for JavaScript:
- var provider = new orion.PluginProvider();
- provider.registerService('orion.edit.occurrences',
- {
- computeOccurrences: function(editorContext, context) {
- return [];
- }
- {
- contentType: ["application/javascript"]
- });
- provider.connect();
In the example above if you want to implement the computeOccurrences asynchronously, you can use Deferred as shown below:
- var provider = new orion.PluginProvider();
- provider.registerService('orion.edit.occurrences',
- {
- computeOccurrences: function(editorContext, context) {
- return new Deferred().resolve([]);
- }
- {
- contentType: ["application/javascript"]
- });
- provider.connect();
orion.edit.open.declaration
The orion.edit.open.declaration
service allows plugins to contribute functionality to find declarations for specific content types.
Service methods
Implementations of orion.edit.open.declaration
must define the following function:
- findDeclaration(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 other options for finding declarations.
The function returns a single declaration object or null. If the function is returning asynchronously, then the promise must resolve a declaration object or null.
Declaration object
The value returned from the service method provides enough data that an editor location can be opened / scrolled to.
Each declaration object has these properties:
- start
Number
The offset into the file for the start of the declaration - end
Number
The offset into the file for the end of the declaration - file
String
The full resource path of the file the declaration is found in - mode
Optional, String
The mode that the editor should open in. Can be one of replace, tab, or split. Default is replace.
Service attributes
Implementations of orion.edit.open.declaration
may define the following attributes:
- contentType
String[]
An array of Content Type IDs for which this command contribution is valid.- id
String
Optional. A unique identifier for the command contribution - for example 'orion.open.declaration.js'
Examples
The following example is how Orion plugs in open declaration support for JavaScript:
- var provider = new orion.PluginProvider();
- provider.registerServiceProvider("orion.edit.open.declaration",
- {
- findDeclaration: function findDeclaration(editorContext, options) {
- //find decls
- }
- }, {
- contentType: ["application/javascript", "text/html"],
- id: "orion.open.declaration.js"
- });
- 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.
- options.contentType
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.
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.)
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.references
An orion.edit.references
service provides a function that can find references to a selected term across multiple files within a project context.
Service methods
- findReferences(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 other options for finding references.
The call to findReferences() must be handled asynchronously using a promise because it is long-running by nature. The promise ultimately must resolve to an array of Reference objects, an empty array, an error object or null.
The Reference object
A Reference object has the following properties:
- searchParams
String
The parameters that were searched - this is displayed in the results slide-out - categories
String[]
Optional. All of the names of the categories used while collecting references. This is used in the UI to properly show references in their categorized manner. - references
Match object[]
The array or match objects
The Match object
A Match object has the following properties:
- children
Text Match[]
. The array of text-locations for each match - totalMatches
Number
. The total number of references found - this is displayed in the slide-out for the end user - location
String
. The full resource location path
The Text Match object
- lineNumber
Number
. The line that matches were found on - name
String
. The name to use when displaying the match - matches
Inline Match[]
The array of ranges of matches within the given line described by this text match object
The Inline Match object
- category
String
Optional. The name of the category to place the match in - confidence
Number
Optional. The confidence level of the match - end
Number
. The end offset in the text match - length
Number
. The length within the text match - start
Number
. The start offset in the text match - startIndex
Number
. The beginning index into the text match
Service attributes
Implementations of orion.edit.references
have the following attributes:
- contentType
-
String[]
An array of Content Type IDs that this contribution can find references within. - id
-
String
A unique id to describe the contribution
Examples
provider.registerServiceProvider("orion.edit.references", {
findReferences: function findReferences(editorContext, context) {
//find refs
}
},
{
contentType: ["application/javascript"]
});
provider.connect();
This example will validate JavaScript files. It finds lines containing a sequence of space-tab-space or tab-space-tab and produces a warning on every such line. Note that +1
is necessary because column and line indices in the Orion UI are numbered from 1, not 0.
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
- initialize(loc, contentType)
- loc
String
The optional location the validator is initializing from - contentType
Object
The optional content type object
Optional function. If defined, the framework will invoke the provider's initialize() method at some point early in the syntax checker creation lifecycle before computeProblems() 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 computeProblems() may complete more quickly.
If the provider does not define an initialize method, it will be loaded lazily by a call to computeProblems().
- 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.
- options.contentType
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 thedescriptionKey
anddescriptionArgs
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.) - id
String
Optional The identifier for the problem - data
Object
Optional An object of information about the problem
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.
Examples
var provider = new orion.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) {
continue;
}
problems.push({
description: "Mixed spaces and tabs.",
line: i + 1,
start: match.index + 1,
end: match.index + match[0].length + 1,
severity: "warning"
});
}
var result = { problems: problems };
return result;
});
}
},
{ contentType: ["application/javascript"]
});
provider.connect();
This example will validate JavaScript files. It finds lines containing a sequence of space-tab-space or tab-space-tab and produces a warning on every such line. Note that +1
is necessary because column and line indices in the Orion UI are numbered from 1, not 0.