Permalink
Browse files

[complete_strings addon] Add

  • Loading branch information...
1 parent e7ac199 commit 5c7aff9bab295a17f63867c985f505c7d04333d6 @marijnh marijnh committed Dec 17, 2014
Showing with 95 additions and 4 deletions.
  1. +2 −1 .tern-project
  2. +1 −1 doc/demo.html
  3. +1 −1 doc/demo/demo.js
  4. +10 −0 doc/manual.html
  5. +9 −0 doc/src/manual.txt
  6. +3 −1 lib/tern.js
  7. +61 −0 plugin/complete_strings.js
  8. +7 −0 test/cases/complete_strings.js
  9. +1 −0 test/runcases.js
View
@@ -2,6 +2,7 @@
"libs": [
],
"plugins": {
- "node": {}
+ "node": {},
+ "complete_strings": {}
}
}
View
@@ -31,7 +31,7 @@
<script src="demo/demo.js"></script>
<script src="../plugin/requirejs.js"></script>
<script src="../plugin/doc_comment.js"></script>
-
+ <script src="../plugin/complete_strings.js"></script>
<div id=top>
<div id=head>
View
@@ -94,7 +94,7 @@ function initEditor() {
server = new CodeMirror.TernServer({
defs: defs,
- plugins: {requirejs: {}, doc_comment: true},
+ plugins: {requirejs: {}, doc_comment: true, complete_strings: true},
switchToDoc: function(name) { selectDoc(docID(name)); },
workerDeps: ["../../../acorn/acorn.js", "../../../acorn/acorn_loose.js",
"../../../acorn/util/walk.js", "../../../../lib/signal.js", "../../../../lib/tern.js",
View
@@ -57,6 +57,11 @@
</li>
<li>
<p>
+<a href="#plugin_complete_strings">String completion</a>
+</p>
+</li>
+<li>
+<p>
<a href="#plugin_node">node</a>
</p>
</li>
@@ -1029,6 +1034,11 @@
</p>
</dd>
</dl>
+<h4> <a id="plugin_complete_strings"></a>String completion plugin</h4>
+<p> When enabled, this plugin will gather (short) strings in your code,
+and completing when inside a string will try to complete to previously
+seen strings. Takes a single option, <code>maxLength</code>, which controls the
+maximum length of string values to gather, and defaults to 15.</p>
<h4> <a id="plugin_node"></a>Node.js plugin</h4>
<p> The <a href="http://nodejs.org">node.js</a> plugin, called <code>"node"</code>, provides
variables that are part of the node environment, such as <code>process</code> and
View
@@ -16,6 +16,7 @@ engine>> to do the actual type inference.
** <<typedef,JSON type definitions>>
** <<plugins,Server plugins>>
*** <<plugin_doc_comment,Doc comments>>
+*** <<plugin_complete_strings,String completion>>
*** <<plugin_node,node>>
*** <<plugin_requirejs,RequireJS>>
*** <<plugin_angular,Angular.js>>
@@ -572,6 +573,14 @@ The plugin understands the following configuration parameters:
`fullDocs`:: Can be set to `true` to return the full comment text instead of the first sentence.
+[[plugin_complete_strings]]
+==== String completion plugin ====
+
+When enabled, this plugin will gather (short) strings in your code,
+and completing when inside a string will try to complete to previously
+seen strings. Takes a single option, `maxLength`, which controls the
+maximum length of string values to gather, and defaults to 15.
+
[[plugin_node]]
==== Node.js plugin ====
View
@@ -74,7 +74,9 @@
function updateText(file, text, srv) {
file.text = text;
- file.ast = infer.parse(text, srv.passes, {directSourceFile: file, allowReturnOutsideFunction: true});
+ infer.withContext(srv.cx, function() {
+ file.ast = infer.parse(text, srv.passes, {directSourceFile: file, allowReturnOutsideFunction: true});
+ });
file.lineOffsets = null;
}
@@ -0,0 +1,61 @@
+// Parses comments above variable declarations, function declarations,
+// and object properties as docstrings and JSDoc-style type
+// annotations.
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ return mod(require("../lib/infer"), require("../lib/tern"), require("acorn/util/walk"));
+ if (typeof define == "function" && define.amd) // AMD
+ return define(["../lib/infer", "../lib/tern", "acorn/util/walk"], mod);
+ mod(tern, tern, acorn.walk);
+})(function(infer, tern, walk) {
+ "use strict";
+
+ tern.registerPlugin("complete_strings", function(server, options) {
+ server._completeStrings = { maxLen: options && options.maxLength || 15,
+ seen: Object.create(null) };
+ server.on("reset", function() {
+ server._completeStrings.seen = Object.create(null);
+ });
+ return {
+ passes: {
+ postParse: postParse,
+ completion: complete
+ }
+ };
+ });
+
+ function postParse(ast) {
+ var data = infer.cx().parent._completeStrings;
+ walk.simple(ast, {
+ Literal: function(node) {
+ if (typeof node.value == "string" && node.value && node.value.length < data.maxLen)
+ data.seen[node.value] = ast.sourceFile.name;
+ }
+ });
+ }
+
+ function complete(file, query) {
+ var pos = tern.resolvePos(file, query.end);
+ var lit = infer.findExpressionAround(file.ast, null, pos, file.scope, "Literal");
+ if (!lit || typeof lit.node.value != "string") return;
+ var before = lit.node.value.slice(0, pos - lit.node.start - 1);
+ var matches = [], seen = infer.cx().parent._completeStrings.seen;
+ for (var str in seen) if (str.length > before.length && str.indexOf(before) == 0) {
+ if (query.types || query.docs || query.urls || query.origins) {
+ var rec = {name: JSON.stringify(str), displayName: str};
+ matches.push(rec);
+ if (query.types) rec.type = "string";
+ if (query.origins) rec.origin = seen[str];
+ } else {
+ matches.push(JSON.stringify(str));
+ }
+ }
+ if (matches.length) return {
+ start: tern.outputPos(query, file, lit.node.start),
+ end: tern.outputPos(query, file, pos + (file.text.charAt(pos) == file.text.charAt(lit.node.start) ? 1 : 0)),
+ isProperty: false,
+ completions: matches
+ };
+ }
+});
@@ -0,0 +1,7 @@
+// plugin=complete_strings
+// blank-comments=true
+
+if (x == "foobar") {
+ apparently(x == "f
+//<+ "foobar"
+}
View
@@ -8,6 +8,7 @@ require("../plugin/node.js");
require("../plugin/doc_comment.js");
require("../plugin/component.js");
require("../plugin/angular.js");
+require("../plugin/complete_strings.js");
var util = require("./util");
var defData = {

0 comments on commit 5c7aff9

Please sign in to comment.