blob: 12c45ccadcb9cd0ab951ce8156e9c80dd5038ef0 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtext - Web Editor Support</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description"
content="The website of Eclipse Xtext, an open-source framework for development of programming languages and domain-specific languages">
<meta name="author" content="Sven Efftinge">
<meta name="author" content="Miro Spoenemann">
<!-- styles -->
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="/Xtext/images/favicon.png">
<link href="/Xtext/css/bootstrap.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/bootstrap-responsive.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/shield-responsive.css" rel="stylesheet" type='text/css'>
<link href='/Xtext/css/fonts.css' rel='stylesheet' type='text/css'>
<link href="/Xtext/css/prettyPhoto.css" rel="stylesheet" media="screen" type='text/css'>
<link href="/Xtext/css/prettify.css" type="text/css" rel="stylesheet"/>
<link href="/Xtext/css/style.css" rel="stylesheet" type='text/css'>
<!-- cover flow -->
<link href="/Xtext/css/coverflow.css" rel="stylesheet" type='text/css'>
<!--[if lt IE 9]>
<link href="/css/iebugs.css" rel="stylesheet" type='text/css'>
<![endif]-->
<!-- BEGIN Cookie Consent
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
<script>
window.addEventListener("load", function(){
window.cookieconsent.initialise({
"palette": {
"popup": {
"background": "#000"
},
"button": {
"background": "#f1d600"
}
},
"theme": "edgeless",
"type": "opt-in",
onInitialise: function (status) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onStatusChange: function(status, chosenBefore) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onRevokeChoice: function() {
var type = this.options.type;
if (type == 'opt-in') {
// TODO: disable cookies
}
if (type == 'opt-out') {
// TODO: enable cookies
}
},
"content": {
"href": "http://www.eclipse.org/legal/privacy.php"
}
})});
</script>
END Cookie Consent -->
</head>
<body>
<header class="site-header">
<!-- Navbar -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="/Xtext/index.html"></a>
<div class="nav-collapse collapse" style="height: 0px;">
<ul class="nav">
<!--li ><a href="/Xtext/news.html">News</a></li-->
<li ><a href="/Xtext/download.html">Download</a></li>
<li ><a href="/Xtext/documentation/index.html">Documentation</a></li>
<li ><a href="/Xtext/community.html">Community</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Support &amp; Trainings<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://www.itemis.com/en/xtext/support-and-team/" target="_blank">itemis</a></li>
<li><a href="https://typefox.io/trainings-2" target="_blank">TypeFox</a></li>
</ul>
</li>
<li ><a href="http://xtend-lang.org">Xtend</a></li>
</ul>
<!--div class="nav pull-right">
<li ><a><iframe src="https://ghbtns.com/github-btn.html?user=eclipse&repo=xtext&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></a></li>
</div-->
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Navbar End -->
</header>
<div class="page-content">
<script>
function startSearch(event) {
if (event.keyCode == 13) {
var q = 'site:eclipse.org/Xtext/documentation+' + event.target.value;
window.open('https://www.google.com/search?q=' + q, "_self");
}
}
</script>
<div class="wrapper">
<div id="page">
<div class="inner">
<div id="maincontainer" class="container">
<span class="edit-on-github pull-right">
<a href="https://github.com/eclipse/xtext/edit/website-published/xtext-website/documentation/330_web_support.md">Edit on Github</a>
</span>
<div class="span3" style="margin-left: 0px;">
<div class="search-bar">
<img src="/Xtext/images/search-gray.png"/>
<input type="search" id="google-search" onkeyup="startSearch(event);"/>
</div>
<ul id="nav-outline" style="margin-left: 0px;">
<li class="nav-part">Getting Started</li>
<li><a href="102_domainmodelwalkthrough.html">15 Minutes Tutorial</a></li>
<li><a href="103_domainmodelnextsteps.html">15 Minutes Tutorial - Extended</a></li>
<li><a href="104_jvmdomainmodel.html">Five simple steps to your JVM language</a></li>
<li class="nav-part">Reference Documentation</li>
<li><a href="301_grammarlanguage.html">The Grammar Language</a></li>
<li><a href="302_configuration.html">Configuration</a></li>
<li><a href="303_runtime_concepts.html">Language Implementation</a></li>
<li><a href="305_xbase.html">Integration with Java</a></li>
<li><a href="307_special_languages.html">Typical Language Configurations</a></li>
<li><a href="308_emf_integration.html">Integration with EMF</a></li>
<li><a href="310_eclipse_support.html">Eclipse Support</a></li>
<li><a href="330_web_support.html">Web Editor Support</a></li>
<li><a href="340_lsp_support.html">LSP Support</a></li>
<li><a href="350_continuous_integration.html">Continuous Integration</a></li>
</ul>
</div>
<div class="span8 doc-contents">
<h1 id="web-integration">Web Editor Support</h1>
<p>Since version 2.9 Xtext offers an interface for integration of text editors in web applications. The text editors are implemented in JavaScript, and the language-related services such as code completion are realized through HTTP requests to a server-side component.</p>
<h2 id="client">The Client</h2>
<p>Xtext supports three JavaScript text editor libraries:</p>
<ul>
<li><a href="http://eclipse.org/orion/">Orion</a></li>
<li><a href="http://ace.c9.io">Ace</a></li>
<li><a href="http://codemirror.net">CodeMirror</a></li>
</ul>
<p>The set of supported language-related services depends on which editor library is chosen, as shown in the following table.</p>
<table class="table table-bordered">
<thead>
<tr>
<th></th>
<th>Orion</th>
<th>Ace</th>
<th>CodeMirror</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#content-assist">Content assist</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="303_runtime_concepts.html#validation">Validation</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="#syntax-highlighting">Syntax highlighting</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="#semantic-highlighting">Semantic highlighting</a></td>
<td><div class="supported"></div></td>
<td><div class="not-supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="#mark-occurrences">Mark occurrences</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="#hover-info">Hover information</a></td>
<td><div class="supported"></div></td>
<td><div class="not-supported"></div></td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="303_runtime_concepts.html#formatting">Formatting</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="303_runtime_concepts.html#code-generation">Code generator</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="#persistence">Persistence</a></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
<td><div class="supported"></div></td>
</tr>
</tbody>
</table>
<p>The JavaScript integration of Xtext uses <a href="http://requirejs.org">RequireJS</a> for managing modules and their dependencies. The main module is <code>xtext/xtext-orion</code>, <code>xtext/xtext-ace</code>, or <code>xtext/xtext-codemirror</code>, depending on which editor library is used. Examples for loading these libraries together with Xtext can be generated by the <code>WebIntegrationFragment</code> by setting the option <code>generateHtmlExample = true</code> (see <a href="302_configuration.html#generator">The Language Generator</a>). A minimal setup based on <a href="https://www.webjars.org/">WebJars</a> is shown in the following listings.</p>
<h4 id="orion">Orion</h4>
<pre><code class="language-javascript">require.config({
paths: {
"text": "webjars/requirejs-text/&lt;version&gt;/text",
"jquery": "webjars/jquery/&lt;version&gt;/jquery.min",
"xtext/xtext-orion": "xtext/&lt;version&gt;/xtext-orion"
}
});
require(["orion/code_edit/built-codeEdit-amd"], function() {
require(["xtext/xtext-orion"], function(xtext) {
xtext.createEditor();
});
});
</code></pre>
<p>Since Orion is not available on WebJars, it has to be downloaded manually at <a href="http://download.eclipse.org/orion/">download.eclipse.org</a>.</p>
<h4 id="ace">Ace</h4>
<pre><code class="language-javascript">require.config({
paths: {
"jquery": "webjars/jquery/&lt;version&gt;/jquery.min",
"ace/ext/language_tools": "webjars/ace/&lt;version&gt;/src/ext-language_tools",
"xtext/xtext-ace": "xtext/&lt;version&gt;/xtext-ace"
}
});
require(["webjars/ace/&lt;version&gt;/src/ace"], function() {
require(["xtext/xtext-ace"], function(xtext) {
xtext.createEditor();
});
});
</code></pre>
<h4 id="codemirror">CodeMirror</h4>
<pre><code class="language-javascript">require.config({
paths: {
"jquery": "webjars/jquery/&lt;version&gt;/jquery.min",
"xtext/xtext-codemirror": "xtext/&lt;version&gt;/xtext-codemirror"
},
packages: [{
name: "codemirror",
location: "webjars/codemirror/&lt;version&gt;",
main: "lib/codemirror"
}]
});
require(["xtext/xtext-codemirror"], function(xtext) {
xtext.createEditor();
});
</code></pre>
<h3 id="javascript-api">JavaScript API</h3>
<h4 id="xtextcreateeditoroptions"><code>xtext.createEditor(options)</code></h4>
<p>Creates one or more editor instances and initializes Xtext services for them. The available options are described below. The return value is the created editor if exactly one was created, or an array of editors otherwise:</p>
<pre><code class="language-javascript">var editor = xtext.createEditor();
</code></pre>
<p>For Orion the editor is not returned directly, but through a <em>promise</em>:</p>
<pre><code class="language-javascript">xtext.createEditor().done(function(editorViewer) {
...
});
</code></pre>
<p>If the parent element for the editor is not specified through the options, this function looks for an element with <code>id="xtext-editor"</code>. If none exists, the function looks for elements with <code>class="xtext-editor"</code>.</p>
<h4 id="xtextcreateserviceseditor-options"><code>xtext.createServices(editor, options)</code></h4>
<p>Initializes Xtext services for an already created editor. Use this variant if you want full control over the editor creation.</p>
<h4 id="xtextremoveserviceseditor"><code>xtext.removeServices(editor)</code></h4>
<p>Removes all services and associated listeners from the given editor. The JavaScript-based syntax highlighting is not affected by this operation.</p>
<h3 id="options">Options</h3>
<p>Options can be specified with an object passed to the <code>createEditor</code> or <code>createServices</code> functions:</p>
<pre><code class="language-javascript">xtext.createEditor({
resourceId: "example.statemachine",
syntaxDefinition: "xtext/ace-mode-statemachine"
});
</code></pre>
<p>Alternatively, if <code>createEditor</code> is used, options can be set as attributes of the HTML element into which the editor is created. The attribute name is derived from the JavaScript option name by converting CamelCase to hyphen-separated and prefixing with <code>data-editor-</code>, e.g. <code>resourceId</code> becomes <code>data-editor-resource-id</code>:</p>
<pre><code class="language-html">&lt;div id="xtext-editor"
data-editor-resource-id="example.statemachine"
data-editor-syntax-definition="xtext/ace-mode-statemachine"&gt;&lt;/div&gt;
</code></pre>
<p>See below for a <a href="#options-reference">full list of available options</a>.</p>
<h3 id="getting-text-content">Getting the Text Content</h3>
<p>The text content is either loaded from the Xtext server or provided through JavaScript. In either case, the Xtext server needs to identify the language you are using in order to process any requests. A language is usually identified using a file extension or a content type. The file extension can be specified with the <code>xtextLang</code> option, while the content type is given with the <code>contentType</code> option.</p>
<h4 id="loading-text-from-the-server">Loading text from the server</h4>
<p>If you specify a value for the <code>resourceId</code> option, the language may be identified from the file extension included in that id. In this case it is not necessary to provide the <code>xtextLang</code> option. Another effect of using <code>resourceId</code> is that the server will try to load the respective resource from its persistence layer. The Xtext server does not define any default persistence, so you have to customize it as described in the <a href="#persistence">Persistence</a> section in order to use this approach.</p>
<p>The <code>resourceId</code> string may contain whatever information you need to identify a specific text content on the server. Usually the <a href="https://en.wikipedia.org/wiki/Uniform_Resource_Identifier">URI</a> syntax is used, but this is not mandatory.</p>
<h4 id="providing-text-through-javascript">Providing text through JavaScript</h4>
<p>The persistence layer of the Xtext server is totally optional, so you can use whatever means you like to fetch the content, e.g. generate it in the client or request it through your own service. If the DOM element into which the editor is created already contains some text, this text is used as the initial content. Otherwise the editor is initially empty, and you can use the API of the chosen editor framework to change the content whenever you like.</p>
<p>If you would like to specify a <code>resourceId</code> without using the persistence services shipped with Xtext, you can do so by setting the option <code>loadFromServer</code> to <code>false</code>.</p>
<h3 id="operation-modes">Operation Modes</h3>
<p>The web integration of Xtext supports two operation modes, which are described in the following.</p>
<h4 id="stateful-mode">Stateful mode</h4>
<p>This mode is active when <code>sendFullText</code> is <code>false</code>, which is the default setting. In stateful mode, an update request is sent to the server whenever the text content of the editor changes. With this approach a copy of the text is kept in the session state of the server, and many Xtext-related services such as AST parsing and validation are cached together with that copy. This means that services run much faster on the server, and the message size of most requests is very small. Use this mode in order to optimize response times of service requests.</p>
<h4 id="stateless-mode">Stateless mode</h4>
<p>This mode is active when <code>sendFullText</code> is set to <code>true</code>. In this case no update request is necessary when the text content changes, but the full text content is attached to all other service requests. This means that the text has to be parsed again for each request, and the message size is proportional to the size of the text content. Use this mode only when you want to avoid server-side sessions and respective session ids stored in cookies.</p>
<h3 id="syntax-highlighting">Syntax Highlighting</h3>
<p>In contrast to <a href="#semantic-highlighting">semantic highlighting</a>, syntax highlighting can be computed purely in JavaScript without requiring a connection to the server. This is realized with the highlighting capabilities of the employed editor libraries. All three libraries offer a JavaScript API for specifying highlighting rules. The <code>WebIntegrationFragment</code> of the Xtext language generator is able to generate a highlighting specification that includes keywords and some basic tokens such as numbers and comments (see <a href="302_configuration.html#generator">The Language Generator</a>). If the highlighting generated in this way is not sufficient, you can still implement the specification yourself following the documentation of the chosen editor library.</p>
<p>The path to the highlighting specification is set with the <code>syntaxDefinition</code> option while setting up the Xtext editor. If no value is specified for that option, it is built from the <code>xtextLang</code> option in the form <code>'xtext-resources/{xtextLang}-syntax'</code> (Orion) or <code>'xtext-resources/mode-{xtextLang}'</code> (Ace). For CodeMirror syntax highlighting is configured by registering a <em>mode</em> and setting the <code>mode</code> option accordingly (default mode name: <code>'xtext/{xtextLang}'</code>).</p>
<h3 id="invoking-services">Invoking Services</h3>
<p>The <code>createEditor</code> and <code>createServices</code> functions set up listeners for editor events such that most services are invoked automatically while using the editor. However, all services can also be invoked programmatically using the <code>xtextServices</code> object that is attached to each editor instance. For example, the following code saves the resource associated with the editor when the button with the id <code>save-button</code> is clicked:</p>
<pre><code class="language-javascript">var editor = xtext.createEditor();
$("#save-button").click(function() {
editor.xtextServices.saveResource();
});
</code></pre>
<p>The following functions are available, provided that the respective services are enabled and supported by the employed editor library. All functions return a <em>promise</em> that is eventually resolved to the requested data. Furthermore, all these functions can be supplied with an <code>options</code> parameter to override some of the options declared when the editor was built.</p>
<ul>
<li><code>getContentAssist()</code><br />
Returns the content assist proposals in the format explained in the <a href="#content-assist">Content Assist</a> section.</li>
<li><code>validate()</code><br />
Returns the validation result. The returned object has a property <code>issues</code>, which is an array of objects with the following properties:
<ul>
<li><code>description</code>: A description to be displayed to the user.</li>
<li><code>severity</code>: one of <code>'error'</code>, <code>'warning'</code>, or <code>'info'</code></li>
<li><code>line</code>: the line where the issue occurs (one-based)</li>
<li><code>column</code>: the column where the issue occurs (one-based)</li>
<li><code>offset</code>: the character offset in the document (zero-based)</li>
<li><code>length</code>: the length of the affected text region</li>
</ul>
</li>
<li><code>computeHighlighting()</code><br />
Returns the text styling data for semantic highlighting (see the <a href="#semantic-highlighting">Semantic Highlighting</a> section).</li>
<li><code>getOccurrences()</code><br />
Returns the occurrences of the element at the current cursor position (see the <a href="#mark-occurrences">Mark Occurrences</a> section).</li>
<li><code>getHoverInfo()</code><br />
Returns the hover information at the current cursor position (see the <a href="#hover-info">Hover Information</a> section).</li>
<li><code>format()</code><br />
Formats the current selection (or the whole document if the selection has zero length) and returns the formatted text.</li>
<li><code>generate()</code><br />
Returns the document generated from the associated resource. If more than one document has been generated, an object with a property <code>documents</code> is returned, which is an array of objects with the properties <code>name</code>, <code>contentType</code>, and <code>content</code>.</li>
<li><code>loadResource()</code><br />
Loads the associated resource and returns an object with properties <code>fullText</code> and <code>dirty</code>. If the resource has been modified during the current session, the modified version is returned even if the page is reloaded.</li>
<li><code>saveResource()</code><br />
Saves the current state of the resource.</li>
<li><code>revertResource()</code><br />
Reverts the resource to the last saved state and returns an object with properties <code>fullText</code> and <code>dirty</code>.</li>
<li><code>update()</code><br />
Computes the difference between the current editor content and the last version that has been committed to the server. If there is a difference, an update request is sent to refresh the server state. The return value has a single property <code>stateId</code>, which is an identifier for the new server state. All requests have to include the last obtained state identifier in order to succeed.</li>
</ul>
<h3 id="options-reference">Full List of Options</h3>
<ul>
<li><code>baseUrl</code><br />
The path segment where the Xtext service is found (default: <code>'/'</code>). See the <code>serviceUrl</code> option.</li>
<li><code>contentAssistCharTriggers</code><br />
Characters that invoke the content assist service when typed (Orion only).</li>
<li><code>contentAssistExcludedStyles</code><br />
Excluded styles for character triggers (Orion only).</li>
<li><code>contentType</code><br />
The content type included in requests to the Xtext server. If no content type is given, the file extension in the <code>resourceId</code> option is used to determine the language.</li>
<li><code>dirtyElement</code><br />
An element into which the dirty status class is written when the editor is marked dirty; it can be either a DOM element or an id for a DOM element.</li>
<li><code>dirtyStatusClass</code><br />
A CSS class name written into the dirtyElement when the editor is marked dirty (default: <code>'dirty'</code>).</li>
<li><code>document</code><br />
The document; if not specified, the global document is used.</li>
<li><code>enableContentAssistService</code><br />
Whether content assist should be enabled (default: <code>true</code>).</li>
<li><code>enableCors</code><br />
Whether CORS should be enabled for service request (default: <code>false</code>).</li>
<li><code>enableFormattingAction</code><br />
Whether the formatting action should be bound to the standard keystroke <kbd>Ctrl</kbd>+<kbd></kbd>+<kbd>F</kbd> (<kbd>Ctrl</kbd>+<kbd></kbd>+<kbd>S</kbd> on CodeMirror) / <kbd></kbd>+<kbd></kbd>+<kbd>F</kbd> (default: <code>false</code>).</li>
<li><code>enableFormattingService</code><br />
Whether text formatting should be enabled (default: <code>true</code>).</li>
<li><code>enableGeneratorService</code><br />
Whether code generation should be enabled (default: <code>true</code>). No default keystroke is bound for the generator, so it must be triggered through JavaScript code.</li>
<li><code>enableHoverService</code><br />
Whether mouse hover information should be enabled (default: <code>true</code>).</li>
<li><code>enableHighlightingService</code><br />
Whether semantic highlighting should be enabled (default: <code>true</code>). In contrast to <a href="#syntax-highlighting">syntax highlighting</a>, semantic highlighting is computed on the server.</li>
<li><code>enableOccurrencesService</code><br />
Whether marking occurrences should be enabled (default: <code>true</code>).</li>
<li><code>enableSaveAction</code><br />
Whether the save action should be bound to the standard keystroke <kbd>Ctrl</kbd>+<kbd>S</kbd> / <kbd></kbd>+<kbd>S</kbd> (default: <code>false</code>).</li>
<li><code>enableValidationService</code><br />
Whether validation should be enabled (default: <code>true</code>).</li>
<li><code>loadFromServer</code><br />
Whether to load the editor content from the server. The default value is <code>true</code> if the <code>resourceId</code> option is set and <code>false</code> otherwise.</li>
<li><code>mouseHoverDelay</code><br />
The number of milliseconds to wait after a mouse hover before the information tooltip is displayed (default: 500).</li>
<li><code>parent</code><br />
The parent element into which the editor should be created. It can be either a DOM element or an id for a DOM element (default: <code>'xtext-editor'</code>).</li>
<li><code>parentClass</code><br />
If the <code>parent</code> option is not given, this option is used to find elements that match the given class name (default: <code>'xtext-editor'</code>).</li>
<li><code>resourceId</code><br />
The identifier of the resource displayed in the text editor. This option is sent to the server to communicate required information on the respective resource.</li>
<li><code>selectionUpdateDelay</code><br />
The number of milliseconds to wait after a selection change before Xtext services are invoked (default: 550).</li>
<li><code>sendFullText</code><br />
Whether the full text shall be sent to the server with each request (default: <code>false</code>). Use this if you want the server to run in stateless mode. If the option is inactive, the server state is updated regularly.</li>
<li><code>serviceUrl</code><br />
The URL of the Xtext servlet. If no value is given, it is constructed using the <code>baseUrl</code> option in the form <code>{location.protocol}//{location.host}{baseUrl}xtext-service</code>.</li>
<li><code>showErrorDialogs</code><br />
Whether errors should be displayed in popup dialogs (default: <code>false</code>).</li>
<li><code>syntaxDefinition</code><br />
A path to a JS file containing a syntax definition. Set this option to <code>'none'</code> to disable syntax highlighting. See the <a href="#syntax-highlighting">Syntax Highlighting</a> section for more details.</li>
<li><code>textUpdateDelay</code><br />
The number of milliseconds to wait after a text change before Xtext services are invoked (default: 500).</li>
<li><code>xtextLang</code><br />
The language name (usually the file extension configured for the language). This is used to set the <code>resourceId</code> and <code>syntaxDefinition</code> options if they have not been specified.</li>
</ul>
<h2 id="server">The Server</h2>
<p>The language-specific resources are provided through HTTP requests which are processed by the <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web.servlet/src/main/java/org/eclipse/xtext/web/servlet/XtextServlet.java">XtextServlet</a>. This class is also responsible for managing the lifecycle of the language <a href="https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Injector.html">Injector</a> (see <a href="302_configuration.html#dependency-injection">Dependency Injection</a>). The default approach is to create an injector when the servlet is started and to register it in the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/IResourceServiceProvider.java">IResourceServiceProvider.Registry</a>. In order to override the default behavior, you can change or add bindings in the <code>&lt;LanguageName&gt;WebModule</code> or <code>&lt;LanguageName&gt;IdeModule</code> of your language.</p>
<p>The usual way to include the Xtext servlet in a server application is to create a subclass of <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web.servlet/src/main/java/org/eclipse/xtext/web/servlet/XtextServlet.java">XtextServlet</a>, override <code>init()</code> and <code>destroy()</code> to manage the runtime resources, and add a <a href="https://docs.oracle.com/javaee/7/api/javax/servlet/annotation/WebServlet.html">WebServlet</a> annotation with <code>urlPatterns = "/xtext-service/*"</code> as parameter. See <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web.example.jetty/src/main/java/org/eclipse/xtext/web/example/jetty/MyXtextServlet.java">MyXtextServlet</a> for an example.</p>
<p>If you want to implement your own communication channel to provide the language-specific services without using XtextServlet, you can do so by injecting an instance of <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web/src/main/java/org/eclipse/xtext/web/server/XtextServiceDispatcher.java">XtextServiceDispatcher</a> and calling <code>getService(IServiceContext)</code>. The input to this method is an <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web/src/main/java/org/eclipse/xtext/web/server/IServiceContext.java">IServiceContext</a>, which must be implemented to provide the request parameters and the client session. The return value is a descriptor that can be used to invoke the actual service. Furthermore, <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web/src/main/java/org/eclipse/xtext/web/server/XtextServiceDispatcher.java">XtextServiceDispatcher</a> can be subclassed in order to add custom services with access to the document AST and all related Xtext APIs.</p>
<p>The following sections describe how to customize the standard services for web editors.</p>
<h3 id="content-assist">Content Assist</h3>
<p>Content assist proposals for cross-references are created by <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeCrossrefProposalProvider.java">IdeCrossrefProposalProvider</a>, while for other grammar elements <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeContentProposalProvider.java">IdeContentProposalProvider</a> is used. In order to customize the proposals, create subclasses of these providers and register them in your IDE Guice module.</p>
<p><a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeContentProposalProvider.java">IdeContentProposalProvider</a> has one <code>_createProposals(...)</code> dispatch method for each type of grammar element. In most cases the best choice is to override the method for <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/emf-gen/org/eclipse/xtext/Assignment.java">Assignments</a> and to filter the correct assignments by comparing them with the instances in the generated GrammarAccess of your language. A proposal is submitted by creating and configuring an instance of <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/ContentAssistEntry.java">ContentAssistEntry</a> and passing it to the given acceptor. This entry class contains all information required to display the proposal in the web browser and to apply it to the document. Usually it is sent to the client in JSON format.</p>
<p>The typical customization point for <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeCrossrefProposalProvider.java">IdeCrossrefProposalProvider</a> is the method <code>createProposal(...)</code>, which is called for each element found by the scope provider. Here you can fine-tune the information to put into the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/ContentAssistEntry.java">ContentAssistEntry</a>.</p>
<h3 id="semantic-highlighting">Semantic Highlighting</h3>
<p>The default behavior of Xtext editors is to have no semantic highlighting (syntactic highlighting, e.g. for keywords and strings, is done on the client side as described in <a href="#syntax-highlighting">Syntax Highlighting</a>). In order to add styling to your text, create a subclass of <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/syntaxcoloring/DefaultSemanticHighlightingCalculator.java">DefaultSemanticHighlightingCalculator</a> and override <code>highlightElement(...)</code>. Here you can mark text regions with CSS classes by submitting a text offset, a length, and the CSS class name to the given acceptor. You can specify the actual text style in a CSS file that is included by the web page containing the Xtext editor.</p>
<h3 id="mark-occurrences">Mark Occurrences</h3>
<p>The service for marking occurrences of a selected element is handled by <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web/src/main/java/org/eclipse/xtext/web/server/occurrences/OccurrencesService.java">OccurrencesService</a>. Here you can override <code>filter(EObject)</code> to exclude some elements from this service. The actual text regions to be marked are computed automatically from the cross-references present in the model.</p>
<h3 id="hover-info">Hover Information</h3>
<p>The information displayed for mouse hover popups is created in HTML format and consists of two parts: a title and a description.</p>
<p>The title is composed of a text label and an image. The label is computed by the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/labels/INameLabelProvider.java">INameLabelProvider</a>, and the default is the value of the <code>name</code> property of an element, if it exists. The image is determined by an implementation of <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/labels/IImageDescriptionProvider.java">IImageDescriptionProvider</a>. The default behavior is to generate a <code>&lt;div&gt;</code> and annotate it with a CSS class of the form <code>&lt;class&gt;-icon</code>, where <code>&lt;class&gt;</code> is the name of the EClass of the corresponding element. The actual images can be assigned to these classes in a CSS file using the <code>background-image</code> CSS property.</p>
<p>The description part of the hover popup is determined by the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/documentation/IEObjectDocumentationProvider.java">IEObjectDocumentationProvider</a>. For this part the default content is fetched from the comments in the document: if the definition of the element is preceded by a multi-line comment (e.g. <code>/* ... */</code>), the content of that comment is used as description.</p>
<h3 id="persistence">Persistence</h3>
<p>Without further adaptation the Xtext server does not provide any persistence functionality. As described in the <a href="#getting-text-content">Getting the Text Content</a> section, there are multiple ways to fill the web editor with text. If you would like to use the persistence service included in the Xtext server, you need to implement <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web/src/main/java/org/eclipse/xtext/web/server/persistence/IServerResourceHandler.java">IServerResourceHandler</a>. The <code>get</code> and <code>put</code> operations declared in that interface should delegate to the persistence layer you would like to connect. For a simple example see <a href="https://github.com/eclipse/xtext-web/blob/master/org.eclipse.xtext.web/src/main/java/org/eclipse/xtext/web/server/persistence/FileResourceHandler.java">FileResourceHandler</a>.</p>
<hr />
<p><strong><a href="340_lsp_support.html">Next Chapter: LSP Support</a></strong></p>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<div id="extra">
<div class="inner">
<div class="container">
<div class="row">
<div class="span6">
<h3 class="footer-links-header">Quick Links</h3>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/legal/">Legal</a></li>
</ul>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org">Eclipse Home</a></li>
<li><a href="http://marketplace.eclipse.org/">Market Place</a></li>
<li><a href="http://www.planeteclipse.org/">Eclipse Planet</a></li>
<li><a href="https://www.eclipse.org/forums/index.php/f/27/">Xtext Forum</a></li>
</ul>
</div>
<div class="span6">
<!-- Social Media Links -->
<h3 class="footer-links-header"">Social Media</h3>
<ul class="footer-links clearfix">
<li>
<a href="https://twitter.com/xtext"><img src="/Xtext/images/Twitter-bird-darkgray.png" class="img-responsive" style="margin-right: 5px;height: 1em;" alt="Twitter icon">@xtext on Twitter</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<a href="#" class="scrollup fadeOutRight animated" style="display: none;">ScrollUp</a>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/Xtext/js/jquery-1.11.3.min.js"></script>
<script src="/Xtext/js/bootstrap.min.js"></script>
<script src="/Xtext/js/jquery.easing.1.3.js" type="text/javascript"></script>
<script src="/Xtext/js/jquery.prettyPhoto.js" type="text/javascript"></script>
<script src="/Xtext/js/prettify.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-xtend.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-common.js" type="text/javascript"></script>
<script src="/Xtext/js/custom.js" type="text/javascript"></script>
<!--script src="https://apis.google.com/js/platform.js" async defer></script-->
<!--script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push([ '_setAccount', 'UA-2429174-3' ]);
_gaq.push([ '_trackPageview' ]);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl'
: 'http://www')
+ '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script-->
<script src="/Xtext/js/coverflow.min.js" type="text/javascript"></script>
<script>
$(function() {
$('#coverflow').coverflow({
active : 1,
visibleAside: 2,
overlap : 0.5,
scale : 0.9,
angle : 20,
trigger : {
"itemfocus" : true,
"swipe" : true,
"mousewheel" : false
}
});
$('#coverflow :hidden').toggle();
$(window).resize(function() {
$('#coverflow').coverflow();
});
});
</script>
</footer>
</body>
</html>