{"__v":42,"_id":"567be431ee052b1700dbda49","category":{"__v":9,"_id":"54d5635632d98b0d00384b01","pages":["54d5635732d98b0d00384b10","54d5635732d98b0d00384b11","55104b632dd9010d0019e144","55104c802dd9010d0019e146","551bd2c50d209f21006cad92","552e6fcd5d4baa0d00783691","552e73705d4baa0d00783699","567be431ee052b1700dbda49","567ef29af9ffa20d008782ff","56a8dd2470a9440d00ef5fe4"],"project":"54d53c7b23010a0d001aca0c","version":"54d5635532d98b0d00384afb","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-02-07T00:03:52.618Z","from_sync":false,"order":11,"slug":"language-tooling","title":"Language Tooling"},"parentDoc":null,"project":"54d53c7b23010a0d001aca0c","user":"54d5c32a7e05890d006f150d","version":{"__v":10,"_id":"54d5635532d98b0d00384afb","forked_from":"54d53c7c23010a0d001aca0f","project":"54d53c7b23010a0d001aca0c","createdAt":"2015-02-07T00:59:01.934Z","releaseDate":"2015-02-07T00:59:01.934Z","categories":["54d5635632d98b0d00384afc","54d5635632d98b0d00384afd","54d5635632d98b0d00384afe","54d5635632d98b0d00384aff","54d5635632d98b0d00384b00","54d5635632d98b0d00384b01","54d5635632d98b0d00384b02","54d652097e05890d006f153e","54dd1315ca1e5219007e9daa","54e21e2b22de1c230094b147","54e68e62a43fe13500db3879","54fa1d3fe7a0ba2f00306309","551c453a23a1ee190034d19a","551df586e52a0b23000c62b6","551f39be6886f8230055f02a","55a6720751457325000e4d97"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"0.1.0","version":"0.1"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-12-24T12:25:21.517Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":4,"body":"Cloud9 offers a lot of ways to customize your code completer, making it more responsive and showing richer results. This page highlights some of the features provided by the [base_handler](https://docs.c9.io/api/#!/api/language.base_handler) interface.\n\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Looking for customizing JavaScript completions?\",\n  \"body\": \"See [Code Completion For JavaScript Libraries](doc:code-completion-for-javascript)  for more information about customizing JavaScript completions for custom libraries or language extensions.\"\n}\n[/block]\n# Overview\n\n- [Look & Feel](#section-look-feel)\n  - [Icons](#section-icons)\n  - [Tooltips](#section-tooltips)\n  - [Continuous Code Completion](#section-continuous-code-completion)\n  - [Generic and Contextual Code Completions](#section-generic-and-contextual-code-completions)\n- [Performance](#section-performance)\n  - [Code Completon Pre-Caching and Predictions](#section-code-completion-pre-caching-and-predictions)\n  - [Optimizing Documentation Fetching](#section-optimizing-documentation-fetching)\n  - [Asynchronous Code Completion](#section-asynchronous-code-completion)\n\n# Look & Feel\n## Icons\n\nCloud9 provides the following icons for code completion. These look different depending on the theme used. Add an icon to your completions using the `icon` property:\n\n```javascript\nhandler.complete = function(doc, ast, pos, options, callback) {\n    ...\n    callback(null, [\n        {\n            name: \"foo()\",\n            replaceText: \"foo\",\n            icon: \"method\",\n            ...\n        }\n    ]);\n};\n```\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Icon\",\n    \"h-1\": \"Name\",\n    \"0-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/event.png)\",\n    \"1-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/method.png)\",\n    \"2-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/method2.png)\",\n    \"3-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/package.png)\",\n    \"4-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/property.png)\",\n    \"5-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/property2.png)\",\n    \"6-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/unknown.png)\",\n    \"7-0\": \"![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/unknown2.png)\",\n    \"0-1\": \"`\\\"event\\\"`\",\n    \"1-1\": \"`\\\"method\\\"`\",\n    \"2-1\": \"`\\\"method2\\\"`\",\n    \"3-1\": \"`\\\"package\\\"`\",\n    \"4-1\": \"`\\\"property\\\"`\",\n    \"5-1\": \"`\\\"property2\\\"`\",\n    \"6-1\": \"`\\\"unknown\\\"`\",\n    \"8-0\": \"(no icon)\",\n    \"7-1\": \"`\\\"unknown2\\\"`\",\n    \"8-1\": \"`undefined`\",\n    \"h-2\": \"Description\",\n    \"0-2\": \"An event (or, sometimes, an HTML element).\",\n    \"1-2\": \"A method or function.\",\n    \"2-2\": \"A method or function that is less significant (e.g. a private method). This is icon is also used for dynamic analyzers when it's not 100% certain if a method exists or not.\",\n    \"3-2\": \"A package, class, or module.\",\n    \"4-2\": \"A property, variable, or field.\",\n    \"5-2\": \"A property, variable, or field that is considered less significant (e.g. a private field). This is icon is also used for dynamic analyzers when it's not 100% certain if a property exists or not.\",\n    \"6-2\": \"Something else, or unkown\",\n    \"7-2\": \"Something else, or unknown. Not as significant as `unknown`.\",\n    \"8-2\": \"Other completions that are not significant to the users, such as word completions. These don't stand out as much visually as other completions.\"\n  },\n  \"cols\": 3,\n  \"rows\": 9\n}\n[/block]\n## Tooltips\n\nTooltips can be implemented using [base_handler.tooltip()](https://docs.c9.io/api/#!/api/language.base_handler-method-tooltip). But in case you haven't implemented this abstract method, Cloud9 may still be able to guess tooltips based on the last completion provided. Simply set the `guessCompletions` property with your completion.\n\n```javascript\nhandler.complete = function(doc, ast, pos, options, callback) {\n    var completions = ...;\n    callback(null, completions.map(function(c) {\n        c.guessTooltip = true;\n    });\n}\n````\n\n## Continuous Code Completion\n\nThe `getCompletionRegex()` function is used to set a character sequence for which to start code completion. For example, for a Java-like language where you would want to complete whenever a user types \".\", use:\n\n```javascript\nhandler.getCompletionRegex = function() {\n    return /^\\.$/;\n}\n````\n\nIf a completion regex is specified, continuous completion is enabled for that language. This means that whenever a user types a character, completion is attempted with a short delay. If a character sequence matching the completion regex is typed, completion is performed immediately.\n\n## Generic and Contextual Code Completions\n\nCloud9 provides generic code completions that work for any language based on words used in files. It also provides generic completions based on [Jsonalyzer Handlers](doc:jsonalyzer-handlers) and [CTags](http://ctags.sourceforge.net/). These generic completions are generally visually distinguished by using no icon or an insignificant icon. They are also marked as generic by setting the `isGeneric` property of [base_handler.complete()](https://apidoc.c9.io/c9v3/#!/api/language.base_handler-method-complete) to `true`. \n\nFor languages that implement a \"smart\" code completer using a static analyzer it can be useful to hide generic completions. We also these \"smart\" completions contextual completions. By marking all contextual completions using the `isContextual` property, all generic completions are automatically hidden when there are any contextual ones available:\n\n```javascript\nhandler.complete = function(doc, ast, pos, options, callback) {\n    var completions = ...;\n    callback(null, completions.map(function(c) {\n        c.isContextual = true;\n    });\n}\n````\n\n# Performance\n\n## Code Completion Pre-Caching and Predictions\n\nCloud9 plugins can pre-cache the next code completion for performance,\nor even show it to the user to improve the look & feel:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/lO3XpWaATz2h7BcOlQtr_predict.png\",\n        \"predict.png\",\n        \"938\",\n        \"372\",\n        \"#60a7f4\",\n        \"\"\n      ],\n      \"sizing\": \"80\",\n      \"border\": false\n    }\n  ]\n}\n[/block]\nThese predictions can be implemented using [base_handler.predictNextCompletion()](https://docs.c9.io/api/#!/api/language.base_handler-method-predictNextCompletion). An example implementation for JavaScript returns the current\ncompletion plus a dot:\n\n```javascript\nhandler.predictNextCompletion = function(doc, ast, pos, options, callback) {\n    // Look at the current completion proposals.\n    // Only predict if we have exactly one available completion.\n    if (options.matches.length !== 1)\n        return callback();\n    // Return that completion plus a dot\n    callback(null, { predicted: predicted[0] + \".\", showEarly: true });\n};\n```\n\nTo understand how the above works, consider the again the scenario\n\n```javascript\nfunction Foo() {\n    this.myProp = 3;\n    this.foo = 3\n    th\n}\n```\n\nNormal code completion can tell us that `th` will expand to `this`. With the predictor function above we can determine that the next code completion will likely be for `this.`. That means that Cloud9 can go ahead and determine all completions for `this.`. By setting the `showEarly` property to `true`, it can even show those completions to users.\n\nBelow is a more sophisticated example which filters the current completions\nbefore making a prediction:\n\n```javascript\nhandler.predictNextCompletion = function(doc, ast, pos, options, callback) {\n    // We look at all current completion proposals, but first filter for\n    // contextual completions and ignore any keyword predictions\n    var predicted = options.matches.filter(function(m) {\n        return m.isContextual && !m.replaceText.match(KEYWORD_REGEX);\n    });\n    // Let's predict only if we have exactly one proposal left over to\n    // make a prediction for (e.g., we know the user is going to type \"foo\")\n    if (predicted.length !== 1)\n        return callback();\n    // Predict that the current user is going to type this identifier\n    // followed by a dot (e.g., \"foo.\")\n    callback(null, { predicted: predicted[0] + \".\" });\n};\n```\n\n## Optimizing Documentation Fetching\n\nNormally the Cloud9 code completion interface expects documentation for all completion suggestions. For certain completers it can be hamper performance to retrieve and send these documentation blocks with every completion. [base_handler.complete()](https://apidoc.c9.io/c9v3/#!/api/language.worker_util-method-completeUpdate) provides a `noDoc` option that allows language handlers to leave out documentation until it is actually demanded by the UI.\n\nThe example below returns a single completion, and only retrieves documentation for it when it is actually needed:\n\n```javascript\nhandler.complete = function(doc, ast, pos, options, callback) {\n    var result = {\n        name: \"foo()\",\n        replaceText: \"foo\",\n        icon: \"method\",\n        ...\n    };\n    if (options.noDoc)\n        result.noDoc = true; // just tell Cloud9 documentation will come later\n    }\n    else {\n        result.doc = ...; // ok, documentation was requested, let's get it\n    }\n    callback(null, [result]);\n}\n```\n\n## Asynchronous Code Completion\n\nTo cope with slow code completion engines, it can be useful to use asynchronous code completion: compute basic completions early, and get additional completions in the background. The [worker_util.completeUpdate()](https://apidoc.c9.io/c9v3/#!/api/language.worker_util-method-completeUpdate) function makes this possible. Simply get the additional completions in the background and call `completeUpdate()` when ready:\n\n```javascript\nvar asyncResult = {};\n\nhandler.complete = function(doc, ast, pos, options, callback) {\n    var completions = ...;\n    if (asyncResult && asyncResult.doc === doc\n        && asyncResult.pos.row === pos.row && asyncResult.pos.column === pos.column) {\n        completions = completions.concat(asyncResult.matches)\n    } else {\n        fetchAsyncCompletions();\n    }\n    callback(null, completions);\n}\n\nfunction fetchAsyncCompletions(doc, pos, line) {\n    // Get additional completions, e.g. by calling some remote\n    // API or doing type inference or what not\n    var matches = ...;\n    asyncResult = { pos: pos, doc: doc, matches: matches };\n    // Once done, retrigger completion\n    worker_util.completeUpdate(pos, line);\n}\n````\n\nThe `completeUpdate()` method takes the current position and line as a sanity measure, to make sure the completion is still relevant as the user may have changed the document in the mean time.","excerpt":"","slug":"customizing-code-completers","type":"basic","title":"Customizing Code Completers"}

Customizing Code Completers


Cloud9 offers a lot of ways to customize your code completer, making it more responsive and showing richer results. This page highlights some of the features provided by the [base_handler](https://docs.c9.io/api/#!/api/language.base_handler) interface. [block:callout] { "type": "info", "title": "Looking for customizing JavaScript completions?", "body": "See [Code Completion For JavaScript Libraries](doc:code-completion-for-javascript) for more information about customizing JavaScript completions for custom libraries or language extensions." } [/block] # Overview - [Look & Feel](#section-look-feel) - [Icons](#section-icons) - [Tooltips](#section-tooltips) - [Continuous Code Completion](#section-continuous-code-completion) - [Generic and Contextual Code Completions](#section-generic-and-contextual-code-completions) - [Performance](#section-performance) - [Code Completon Pre-Caching and Predictions](#section-code-completion-pre-caching-and-predictions) - [Optimizing Documentation Fetching](#section-optimizing-documentation-fetching) - [Asynchronous Code Completion](#section-asynchronous-code-completion) # Look & Feel ## Icons Cloud9 provides the following icons for code completion. These look different depending on the theme used. Add an icon to your completions using the `icon` property: ```javascript handler.complete = function(doc, ast, pos, options, callback) { ... callback(null, [ { name: "foo()", replaceText: "foo", icon: "method", ... } ]); }; ``` [block:parameters] { "data": { "h-0": "Icon", "h-1": "Name", "0-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/event.png)", "1-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/method.png)", "2-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/method2.png)", "3-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/package.png)", "4-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/property.png)", "5-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/property2.png)", "6-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/unknown.png)", "7-0": "![](https://raw.githubusercontent.com/c9/c9.ide.language/master/images/unknown2.png)", "0-1": "`\"event\"`", "1-1": "`\"method\"`", "2-1": "`\"method2\"`", "3-1": "`\"package\"`", "4-1": "`\"property\"`", "5-1": "`\"property2\"`", "6-1": "`\"unknown\"`", "8-0": "(no icon)", "7-1": "`\"unknown2\"`", "8-1": "`undefined`", "h-2": "Description", "0-2": "An event (or, sometimes, an HTML element).", "1-2": "A method or function.", "2-2": "A method or function that is less significant (e.g. a private method). This is icon is also used for dynamic analyzers when it's not 100% certain if a method exists or not.", "3-2": "A package, class, or module.", "4-2": "A property, variable, or field.", "5-2": "A property, variable, or field that is considered less significant (e.g. a private field). This is icon is also used for dynamic analyzers when it's not 100% certain if a property exists or not.", "6-2": "Something else, or unkown", "7-2": "Something else, or unknown. Not as significant as `unknown`.", "8-2": "Other completions that are not significant to the users, such as word completions. These don't stand out as much visually as other completions." }, "cols": 3, "rows": 9 } [/block] ## Tooltips Tooltips can be implemented using [base_handler.tooltip()](https://docs.c9.io/api/#!/api/language.base_handler-method-tooltip). But in case you haven't implemented this abstract method, Cloud9 may still be able to guess tooltips based on the last completion provided. Simply set the `guessCompletions` property with your completion. ```javascript handler.complete = function(doc, ast, pos, options, callback) { var completions = ...; callback(null, completions.map(function(c) { c.guessTooltip = true; }); } ```` ## Continuous Code Completion The `getCompletionRegex()` function is used to set a character sequence for which to start code completion. For example, for a Java-like language where you would want to complete whenever a user types ".", use: ```javascript handler.getCompletionRegex = function() { return /^\.$/; } ```` If a completion regex is specified, continuous completion is enabled for that language. This means that whenever a user types a character, completion is attempted with a short delay. If a character sequence matching the completion regex is typed, completion is performed immediately. ## Generic and Contextual Code Completions Cloud9 provides generic code completions that work for any language based on words used in files. It also provides generic completions based on [Jsonalyzer Handlers](doc:jsonalyzer-handlers) and [CTags](http://ctags.sourceforge.net/). These generic completions are generally visually distinguished by using no icon or an insignificant icon. They are also marked as generic by setting the `isGeneric` property of [base_handler.complete()](https://apidoc.c9.io/c9v3/#!/api/language.base_handler-method-complete) to `true`. For languages that implement a "smart" code completer using a static analyzer it can be useful to hide generic completions. We also these "smart" completions contextual completions. By marking all contextual completions using the `isContextual` property, all generic completions are automatically hidden when there are any contextual ones available: ```javascript handler.complete = function(doc, ast, pos, options, callback) { var completions = ...; callback(null, completions.map(function(c) { c.isContextual = true; }); } ```` # Performance ## Code Completion Pre-Caching and Predictions Cloud9 plugins can pre-cache the next code completion for performance, or even show it to the user to improve the look & feel: [block:image] { "images": [ { "image": [ "https://files.readme.io/lO3XpWaATz2h7BcOlQtr_predict.png", "predict.png", "938", "372", "#60a7f4", "" ], "sizing": "80", "border": false } ] } [/block] These predictions can be implemented using [base_handler.predictNextCompletion()](https://docs.c9.io/api/#!/api/language.base_handler-method-predictNextCompletion). An example implementation for JavaScript returns the current completion plus a dot: ```javascript handler.predictNextCompletion = function(doc, ast, pos, options, callback) { // Look at the current completion proposals. // Only predict if we have exactly one available completion. if (options.matches.length !== 1) return callback(); // Return that completion plus a dot callback(null, { predicted: predicted[0] + ".", showEarly: true }); }; ``` To understand how the above works, consider the again the scenario ```javascript function Foo() { this.myProp = 3; this.foo = 3 th } ``` Normal code completion can tell us that `th` will expand to `this`. With the predictor function above we can determine that the next code completion will likely be for `this.`. That means that Cloud9 can go ahead and determine all completions for `this.`. By setting the `showEarly` property to `true`, it can even show those completions to users. Below is a more sophisticated example which filters the current completions before making a prediction: ```javascript handler.predictNextCompletion = function(doc, ast, pos, options, callback) { // We look at all current completion proposals, but first filter for // contextual completions and ignore any keyword predictions var predicted = options.matches.filter(function(m) { return m.isContextual && !m.replaceText.match(KEYWORD_REGEX); }); // Let's predict only if we have exactly one proposal left over to // make a prediction for (e.g., we know the user is going to type "foo") if (predicted.length !== 1) return callback(); // Predict that the current user is going to type this identifier // followed by a dot (e.g., "foo.") callback(null, { predicted: predicted[0] + "." }); }; ``` ## Optimizing Documentation Fetching Normally the Cloud9 code completion interface expects documentation for all completion suggestions. For certain completers it can be hamper performance to retrieve and send these documentation blocks with every completion. [base_handler.complete()](https://apidoc.c9.io/c9v3/#!/api/language.worker_util-method-completeUpdate) provides a `noDoc` option that allows language handlers to leave out documentation until it is actually demanded by the UI. The example below returns a single completion, and only retrieves documentation for it when it is actually needed: ```javascript handler.complete = function(doc, ast, pos, options, callback) { var result = { name: "foo()", replaceText: "foo", icon: "method", ... }; if (options.noDoc) result.noDoc = true; // just tell Cloud9 documentation will come later } else { result.doc = ...; // ok, documentation was requested, let's get it } callback(null, [result]); } ``` ## Asynchronous Code Completion To cope with slow code completion engines, it can be useful to use asynchronous code completion: compute basic completions early, and get additional completions in the background. The [worker_util.completeUpdate()](https://apidoc.c9.io/c9v3/#!/api/language.worker_util-method-completeUpdate) function makes this possible. Simply get the additional completions in the background and call `completeUpdate()` when ready: ```javascript var asyncResult = {}; handler.complete = function(doc, ast, pos, options, callback) { var completions = ...; if (asyncResult && asyncResult.doc === doc && asyncResult.pos.row === pos.row && asyncResult.pos.column === pos.column) { completions = completions.concat(asyncResult.matches) } else { fetchAsyncCompletions(); } callback(null, completions); } function fetchAsyncCompletions(doc, pos, line) { // Get additional completions, e.g. by calling some remote // API or doing type inference or what not var matches = ...; asyncResult = { pos: pos, doc: doc, matches: matches }; // Once done, retrigger completion worker_util.completeUpdate(pos, line); } ```` The `completeUpdate()` method takes the current position and line as a sanity measure, to make sure the completion is still relevant as the user may have changed the document in the mean time.