codemirror-rails 3.14 → 3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +178 -94
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +3 -3
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +3 -1
  6. data/vendor/assets/javascripts/codemirror/addons/edit/matchtags.js +51 -0
  7. data/vendor/assets/javascripts/codemirror/addons/fold/brace-fold.js +9 -6
  8. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +9 -4
  9. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +122 -0
  10. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +3 -2
  11. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +24 -17
  12. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +34 -0
  13. data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +5 -3
  14. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +7 -3
  15. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +4 -2
  16. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +4 -2
  17. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +6 -2
  18. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -2
  19. data/vendor/assets/javascripts/codemirror/addons/lint/coffeescript-lint.js +3 -2
  20. data/vendor/assets/javascripts/codemirror/addons/lint/javascript-lint.js +3 -6
  21. data/vendor/assets/javascripts/codemirror/addons/lint/json-lint.js +3 -2
  22. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +12 -6
  23. data/vendor/assets/javascripts/codemirror/addons/merge/dep/diff_match_patch.js +50 -0
  24. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +40 -24
  25. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +3 -1
  26. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +3 -1
  27. data/vendor/assets/javascripts/codemirror/addons/search/match-highlighter.js +11 -9
  28. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +608 -0
  30. data/vendor/assets/javascripts/codemirror/addons/tern/worker.js +39 -0
  31. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +120 -101
  32. data/vendor/assets/javascripts/codemirror/modes/clike.js +2 -1
  33. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +2 -1
  34. data/vendor/assets/javascripts/codemirror/modes/css.js +33 -16
  35. data/vendor/assets/javascripts/codemirror/modes/groovy.js +2 -1
  36. data/vendor/assets/javascripts/codemirror/modes/jade.js +90 -0
  37. data/vendor/assets/javascripts/codemirror/modes/javascript.js +21 -18
  38. data/vendor/assets/javascripts/codemirror/modes/markdown.js +26 -1
  39. data/vendor/assets/javascripts/codemirror/modes/nginx.js +163 -0
  40. data/vendor/assets/javascripts/codemirror/modes/python.js +19 -2
  41. data/vendor/assets/javascripts/codemirror/modes/rst.js +30 -19
  42. data/vendor/assets/javascripts/codemirror/modes/ruby.js +4 -4
  43. data/vendor/assets/javascripts/codemirror/modes/rust.js +2 -1
  44. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +1 -1
  45. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +12 -2
  46. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +170 -0
  47. data/vendor/assets/javascripts/codemirror/modes/sparql.js +4 -2
  48. data/vendor/assets/javascripts/codemirror/modes/vbscript.js +330 -22
  49. data/vendor/assets/javascripts/codemirror/modes/xml.js +18 -3
  50. data/vendor/assets/stylesheets/codemirror.css +10 -0
  51. data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +39 -29
  52. data/vendor/assets/stylesheets/codemirror/addons/tern/tern.css +85 -0
  53. data/vendor/assets/stylesheets/codemirror/themes/3024-day.css +33 -0
  54. data/vendor/assets/stylesheets/codemirror/themes/3024-night.css +33 -0
  55. data/vendor/assets/stylesheets/codemirror/themes/base16-dark.css +33 -0
  56. data/vendor/assets/stylesheets/codemirror/themes/base16-light.css +33 -0
  57. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +1 -1
  58. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +5 -14
  59. data/vendor/assets/stylesheets/codemirror/themes/tomorrow-night-eighties.css +33 -0
  60. data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +2 -2
  61. metadata +17 -2
@@ -29,7 +29,7 @@
29
29
  }
30
30
 
31
31
  function updateActiveLine(cm) {
32
- var line = cm.getLineHandle(cm.getCursor().line);
32
+ var line = cm.getLineHandleVisualStart(cm.getCursor().line);
33
33
  if (cm.state.activeLine == line) return;
34
34
  clearActiveLine(cm);
35
35
  cm.addLineClass(line, "wrap", WRAP_CLASS);
@@ -0,0 +1,608 @@
1
+ // Glue code between CodeMirror and Tern.
2
+ //
3
+ // Create a CodeMirror.TernServer to wrap an actual Tern server,
4
+ // register open documents (CodeMirror.Doc instances) with it, and
5
+ // call its methods to activate the assisting functions that Tern
6
+ // provides.
7
+ //
8
+ // Options supported (all optional):
9
+ // * defs: An array of JSON definition data structures.
10
+ // * plugins: An object mapping plugin names to configuration
11
+ // options.
12
+ // * getFile: A function(name, c) that can be used to access files in
13
+ // the project that haven't been loaded yet. Simply do c(null) to
14
+ // indicate that a file is not available.
15
+ // * fileFilter: A function(value, docName, doc) that will be applied
16
+ // to documents before passing them on to Tern.
17
+ // * switchToDoc: A function(name) that should, when providing a
18
+ // multi-file view, switch the view or focus to the named file.
19
+ // * showError: A function(editor, message) that can be used to
20
+ // override the way errors are displayed.
21
+ // * completionTip: Customize the content in tooltips for completions.
22
+ // Is passed a single argument—the completion's data as returned by
23
+ // Tern—and may return a string, DOM node, or null to indicate that
24
+ // no tip should be shown. By default the docstring is shown.
25
+ // * typeTip: Like completionTip, but for the tooltips shown for type
26
+ // queries.
27
+ //
28
+ // It is possible to run the Tern server in a web worker by specifying
29
+ // these additional options:
30
+ // * useWorker: Set to true to enable web worker mode. You'll probably
31
+ // want to feature detect the actual value you use here, for example
32
+ // !!window.Worker.
33
+ // * workerScript: The main script of the worker. Point this to
34
+ // wherever you are hosting worker.js from this directory.
35
+ // * workerDeps: An array of paths pointing (relative to workerScript)
36
+ // to the Acorn and Tern libraries and any Tern plugins you want to
37
+ // load. Or, if you minified those into a single script and included
38
+ // them in the workerScript, simply leave this undefined.
39
+
40
+ (function() {
41
+ "use strict";
42
+
43
+ CodeMirror.TernServer = function(options) {
44
+ var self = this;
45
+ this.options = options || {};
46
+ var plugins = this.options.plugins || (this.options.plugins = {});
47
+ if (!plugins.doc_comment) plugins.doc_comment = true;
48
+ if (this.options.useWorker) {
49
+ this.server = new WorkerServer(this);
50
+ } else {
51
+ this.server = new tern.Server({
52
+ getFile: function(name, c) { return getFile(self, name, c); },
53
+ async: true,
54
+ defs: this.options.defs || [],
55
+ plugins: plugins
56
+ });
57
+ }
58
+ this.docs = Object.create(null);
59
+ this.trackChange = function(doc, change) { trackChange(self, doc, change); };
60
+
61
+ this.cachedArgHints = null;
62
+ this.activeArgHints = null;
63
+ this.jumpStack = [];
64
+ };
65
+
66
+ CodeMirror.TernServer.prototype = {
67
+ addDoc: function(name, doc) {
68
+ var data = {doc: doc, name: name, changed: null};
69
+ this.server.addFile(name, docValue(this, data));
70
+ CodeMirror.on(doc, "change", this.trackChange);
71
+ return this.docs[name] = data;
72
+ },
73
+
74
+ delDoc: function(name) {
75
+ var found = this.docs[name];
76
+ if (!found) return;
77
+ CodeMirror.off(found.doc, "change", this.trackChange);
78
+ delete this.docs[name];
79
+ this.server.delFile(name);
80
+ },
81
+
82
+ hideDoc: function(name) {
83
+ closeArgHints(this);
84
+ var found = this.docs[name];
85
+ if (found && found.changed) sendDoc(this, found);
86
+ },
87
+
88
+ complete: function(cm) {
89
+ var self = this;
90
+ CodeMirror.showHint(cm, function(cm, c) { return hint(self, cm, c); }, {async: true});
91
+ },
92
+
93
+ getHint: function(cm, c) { return hint(this, cm, c); },
94
+
95
+ showType: function(cm) { showType(this, cm); },
96
+
97
+ updateArgHints: function(cm) { updateArgHints(this, cm); },
98
+
99
+ jumpToDef: function(cm) { jumpToDef(this, cm); },
100
+
101
+ jumpBack: function(cm) { jumpBack(this, cm); },
102
+
103
+ rename: function(cm) { rename(this, cm); },
104
+
105
+ request: function(cm, query, c) {
106
+ this.server.request(buildRequest(this, findDoc(this, cm.getDoc()), query), c);
107
+ }
108
+ };
109
+
110
+ var Pos = CodeMirror.Pos;
111
+ var cls = "CodeMirror-Tern-";
112
+ var bigDoc = 250;
113
+
114
+ function getFile(ts, name, c) {
115
+ var buf = ts.docs[name];
116
+ if (buf)
117
+ c(docValue(ts, buf));
118
+ else if (ts.options.getFile)
119
+ ts.options.getFile(name, c);
120
+ else
121
+ c(null);
122
+ }
123
+
124
+ function findDoc(ts, doc, name) {
125
+ for (var n in ts.docs) {
126
+ var cur = ts.docs[n];
127
+ if (cur.doc == doc) return cur;
128
+ }
129
+ if (!name) for (var i = 0;; ++i) {
130
+ n = "[doc" + (i || "") + "]";
131
+ if (!ts.docs[n]) { name = n; break; }
132
+ }
133
+ return ts.addDoc(name, doc);
134
+ }
135
+
136
+ function trackChange(ts, doc, change) {
137
+ var data = findDoc(ts, doc);
138
+
139
+ var argHints = ts.cachedArgHints;
140
+ if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
141
+ ts.cachedArgHints = null;
142
+
143
+ var changed = data.changed;
144
+ if (changed == null)
145
+ data.changed = changed = {from: change.from.line, to: change.from.line};
146
+ var end = change.from.line + (change.text.length - 1);
147
+ if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end);
148
+ if (end >= changed.to) changed.to = end + 1;
149
+ if (changed.from > change.from.line) changed.from = change.from.line;
150
+
151
+ if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() {
152
+ if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data);
153
+ }, 200);
154
+ }
155
+
156
+ function sendDoc(ts, doc) {
157
+ ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {
158
+ if (error) console.error(error);
159
+ else doc.changed = null;
160
+ });
161
+ }
162
+
163
+ // Completion
164
+
165
+ function hint(ts, cm, c) {
166
+ ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
167
+ if (error) return showError(ts, cm, error);
168
+ var completions = [], after = "";
169
+ var from = data.start, to = data.end;
170
+ if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
171
+ cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
172
+ after = "\"]";
173
+
174
+ for (var i = 0; i < data.completions.length; ++i) {
175
+ var completion = data.completions[i], className = typeToIcon(completion.type);
176
+ if (data.guess) className += " " + cls + "guess";
177
+ completions.push({text: completion.name + after,
178
+ displayText: completion.name,
179
+ className: className,
180
+ data: completion});
181
+ }
182
+
183
+ var obj = {from: from, to: to, list: completions};
184
+ var tooltip = null;
185
+ CodeMirror.on(obj, "close", function() { remove(tooltip); });
186
+ CodeMirror.on(obj, "update", function() { remove(tooltip); });
187
+ CodeMirror.on(obj, "select", function(cur, node) {
188
+ remove(tooltip);
189
+ var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
190
+ if (content) {
191
+ tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
192
+ node.getBoundingClientRect().top + window.pageYOffset, content);
193
+ tooltip.className += " " + cls + "hint-doc";
194
+ }
195
+ });
196
+ c(obj);
197
+ });
198
+ }
199
+
200
+ function typeToIcon(type) {
201
+ var suffix;
202
+ if (type == "?") suffix = "unknown";
203
+ else if (type == "number" || type == "string" || type == "bool") suffix = type;
204
+ else if (/^fn\(/.test(type)) suffix = "fn";
205
+ else if (/^\[/.test(type)) suffix = "array";
206
+ else suffix = "object";
207
+ return cls + "completion " + cls + "completion-" + suffix;
208
+ }
209
+
210
+ // Type queries
211
+
212
+ function showType(ts, cm) {
213
+ ts.request(cm, "type", function(error, data) {
214
+ if (error) return showError(ts, cm, error);
215
+ if (ts.options.typeTip) {
216
+ var tip = ts.options.typeTip(data);
217
+ } else {
218
+ var tip = elt("span", null, elt("strong", null, data.type || "not found"));
219
+ if (data.doc)
220
+ tip.appendChild(document.createTextNode(" — " + data.doc));
221
+ if (data.url) {
222
+ tip.appendChild(document.createTextNode(" "));
223
+ tip.appendChild(elt("a", null, "[docs]")).href = data.url;
224
+ }
225
+ }
226
+ tempTooltip(cm, tip);
227
+ });
228
+ }
229
+
230
+ // Maintaining argument hints
231
+
232
+ function updateArgHints(ts, cm) {
233
+ closeArgHints(ts);
234
+
235
+ if (cm.somethingSelected()) return;
236
+ var lex = cm.getTokenAt(cm.getCursor()).state.lexical;
237
+ if (lex.info != "call") return;
238
+
239
+ var ch = lex.column, pos = lex.pos || 0;
240
+ for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line)
241
+ if (cm.getLine(line).charAt(ch) == "(") {found = true; break;}
242
+ if (!found) return;
243
+
244
+ var start = Pos(line, ch);
245
+ var cache = ts.cachedArgHints;
246
+ if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
247
+ return showArgHints(ts, cm, pos);
248
+
249
+ ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
250
+ if (error || !data.type || !(/^fn\(/).test(data.type)) return;
251
+ ts.cachedArgHints = {
252
+ start: pos,
253
+ type: parseFnType(data.type),
254
+ name: data.exprName || data.name || "fn",
255
+ guess: data.guess,
256
+ doc: cm.getDoc()
257
+ };
258
+ showArgHints(ts, cm, pos);
259
+ });
260
+ }
261
+
262
+ function showArgHints(ts, cm, pos) {
263
+ closeArgHints(ts);
264
+
265
+ var cache = ts.cachedArgHints, tp = cache.type;
266
+ var tip = elt("span", cache.guess ? cls + "fhint-guess" : null,
267
+ elt("span", cls + "fname", cache.name), "(");
268
+ for (var i = 0; i < tp.args.length; ++i) {
269
+ if (i) tip.appendChild(document.createTextNode(", "));
270
+ var arg = tp.args[i];
271
+ tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?"));
272
+ if (arg.type != "?") {
273
+ tip.appendChild(document.createTextNode(":\u00a0"));
274
+ tip.appendChild(elt("span", cls + "type", arg.type));
275
+ }
276
+ }
277
+ tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
278
+ if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
279
+ var place = cm.cursorCoords(null, "page");
280
+ ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
281
+ }
282
+
283
+ function parseFnType(text) {
284
+ var args = [], pos = 3;
285
+
286
+ function skipMatching(upto) {
287
+ var depth = 0, start = pos;
288
+ for (;;) {
289
+ var next = text.charAt(pos);
290
+ if (upto.test(next) && !depth) return text.slice(start, pos);
291
+ if (/[{\[\(]/.test(next)) ++depth;
292
+ else if (/[}\]\)]/.test(next)) --depth;
293
+ ++pos;
294
+ }
295
+ }
296
+
297
+ // Parse arguments
298
+ if (text.charAt(pos) != ")") for (;;) {
299
+ var name = text.slice(pos).match(/^([^, \(\[\{]+): /);
300
+ if (name) {
301
+ pos += name[0].length;
302
+ name = name[1];
303
+ }
304
+ args.push({name: name, type: skipMatching(/[\),]/)});
305
+ if (text.charAt(pos) == ")") break;
306
+ pos += 2;
307
+ }
308
+
309
+ var rettype = text.slice(pos).match(/^\) -> (.*)$/);
310
+
311
+ return {args: args, rettype: rettype && rettype[1]};
312
+ }
313
+
314
+ // Moving to the definition of something
315
+
316
+ function jumpToDef(ts, cm) {
317
+ function inner(varName) {
318
+ var req = {type: "definition", variable: varName || null};
319
+ var doc = findDoc(ts, cm.getDoc());
320
+ ts.server.request(buildRequest(ts, doc, req), function(error, data) {
321
+ if (error) return showError(ts, cm, error);
322
+ if (!data.file && data.url) { window.open(data.url); return; }
323
+
324
+ if (data.file) {
325
+ var localDoc = ts.docs[data.file], found;
326
+ if (localDoc && (found = findContext(localDoc.doc, data))) {
327
+ ts.jumpStack.push({file: doc.name,
328
+ start: cm.getCursor("from"),
329
+ end: cm.getCursor("to")});
330
+ moveTo(ts, doc, localDoc, found.start, found.end);
331
+ return;
332
+ }
333
+ }
334
+ showError(ts, cm, "Could not find a definition.");
335
+ });
336
+ }
337
+
338
+ if (!atInterestingExpression(cm))
339
+ dialog(cm, "Jump to variable", function(name) { if (name) inner(name); });
340
+ else
341
+ inner();
342
+ }
343
+
344
+ function jumpBack(ts, cm) {
345
+ var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file];
346
+ if (!doc) return;
347
+ moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end);
348
+ }
349
+
350
+ function moveTo(ts, curDoc, doc, start, end) {
351
+ doc.doc.setSelection(end, start);
352
+ if (curDoc != doc && ts.options.switchToDoc) {
353
+ closeArgHints(ts);
354
+ ts.options.switchToDoc(doc.name);
355
+ }
356
+ }
357
+
358
+ // The {line,ch} representation of positions makes this rather awkward.
359
+ function findContext(doc, data) {
360
+ var before = data.context.slice(0, data.contextOffset).split("\n");
361
+ var startLine = data.start.line - (before.length - 1);
362
+ var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length);
363
+
364
+ var text = doc.getLine(startLine).slice(start.ch);
365
+ for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur)
366
+ text += "\n" + doc.getLine(cur);
367
+ if (text.slice(0, data.context.length) == data.context) return data;
368
+
369
+ var cursor = doc.getSearchCursor(data.context, 0, false);
370
+ var nearest, nearestDist = Infinity;
371
+ while (cursor.findNext()) {
372
+ var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000;
373
+ if (!dist) dist = Math.abs(from.ch - start.ch);
374
+ if (dist < nearestDist) { nearest = from; nearestDist = dist; }
375
+ }
376
+ if (!nearest) return null;
377
+
378
+ if (before.length == 1)
379
+ nearest.ch += before[0].length;
380
+ else
381
+ nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length);
382
+ if (data.start.line == data.end.line)
383
+ var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch));
384
+ else
385
+ var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch);
386
+ return {start: nearest, end: end};
387
+ }
388
+
389
+ function atInterestingExpression(cm) {
390
+ var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
391
+ if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
392
+ return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
393
+ }
394
+
395
+ // Variable renaming
396
+
397
+ function rename(ts, cm) {
398
+ var token = cm.getTokenAt(cm.getCursor());
399
+ if (!/\w/.test(token.string)) showError(ts, cm, "Not at a variable");
400
+ dialog(cm, "New name for " + token.string, function(newName) {
401
+ ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {
402
+ if (error) return showError(ts, cm, error);
403
+ applyChanges(ts, data.changes);
404
+ });
405
+ });
406
+ }
407
+
408
+ var nextChangeOrig = 0;
409
+ function applyChanges(ts, changes) {
410
+ var perFile = Object.create(null);
411
+ for (var i = 0; i < changes.length; ++i) {
412
+ var ch = changes[i];
413
+ (perFile[ch.file] || (perFile[ch.file] = [])).push(ch);
414
+ }
415
+ for (var file in perFile) {
416
+ var known = ts.docs[file], chs = perFile[file];;
417
+ if (!known) continue;
418
+ chs.sort(function(a, b) { return cmpPos(b, a); });
419
+ var origin = "*rename" + (++nextChangeOrig);
420
+ for (var i = 0; i < chs.length; ++i) {
421
+ var ch = chs[i];
422
+ known.doc.replaceRange(ch.text, ch.start, ch.end, origin);
423
+ }
424
+ }
425
+ }
426
+
427
+ // Generic request-building helper
428
+
429
+ function buildRequest(ts, doc, query) {
430
+ var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
431
+ if (!allowFragments) delete query.fullDocs;
432
+ if (typeof query == "string") query = {type: query};
433
+ query.lineCharPositions = true;
434
+ if (query.end == null) {
435
+ query.end = doc.doc.getCursor("end");
436
+ if (doc.doc.somethingSelected())
437
+ query.start = doc.doc.getCursor("start");
438
+ }
439
+ var startPos = query.start || query.end;
440
+
441
+ if (doc.changed) {
442
+ if (doc.doc.lineCount() > bigDoc && allowFragments !== false &&
443
+ doc.changed.to - doc.changed.from < 100 &&
444
+ doc.changed.from <= startPos.line && doc.changed.to > query.end.line) {
445
+ files.push(getFragmentAround(doc, startPos, query.end));
446
+ query.file = "#0";
447
+ var offsetLines = files[0].offsetLines;
448
+ if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch);
449
+ query.end = Pos(query.end.line - offsetLines, query.end.ch);
450
+ } else {
451
+ files.push({type: "full",
452
+ name: doc.name,
453
+ text: docValue(ts, doc)});
454
+ query.file = doc.name;
455
+ doc.changed = null;
456
+ }
457
+ } else {
458
+ query.file = doc.name;
459
+ }
460
+ for (var name in ts.docs) {
461
+ var cur = ts.docs[name];
462
+ if (cur.changed && cur != doc) {
463
+ files.push({type: "full", name: cur.name, text: docValue(ts, cur)});
464
+ cur.changed = null;
465
+ }
466
+ }
467
+
468
+ return {query: query, files: files};
469
+ }
470
+
471
+ function getFragmentAround(data, start, end) {
472
+ var doc = data.doc;
473
+ var minIndent = null, minLine = null, endLine, tabSize = 4;
474
+ for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) {
475
+ var line = doc.getLine(p), fn = line.search(/\bfunction\b/);
476
+ if (fn < 0) continue;
477
+ var indent = CodeMirror.countColumn(line, null, tabSize);
478
+ if (minIndent != null && minIndent <= indent) continue;
479
+ minIndent = indent;
480
+ minLine = p;
481
+ }
482
+ if (minLine == null) minLine = min;
483
+ var max = Math.min(doc.lastLine(), end.line + 20);
484
+ if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize))
485
+ endLine = max;
486
+ else for (endLine = end.line + 1; endLine < max; ++endLine) {
487
+ var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize);
488
+ if (indent <= minIndent) break;
489
+ }
490
+ var from = Pos(minLine, 0);
491
+
492
+ return {type: "part",
493
+ name: data.name,
494
+ offsetLines: from.line,
495
+ text: doc.getRange(from, Pos(endLine, 0))};
496
+ }
497
+
498
+ // Generic utilities
499
+
500
+ function cmpPos(a, b) { return a.line - b.line || a.ch - b.ch; }
501
+
502
+ function elt(tagname, cls /*, ... elts*/) {
503
+ var e = document.createElement(tagname);
504
+ if (cls) e.className = cls;
505
+ for (var i = 2; i < arguments.length; ++i) {
506
+ var elt = arguments[i];
507
+ if (typeof elt == "string") elt = document.createTextNode(elt);
508
+ e.appendChild(elt);
509
+ }
510
+ return e;
511
+ }
512
+
513
+ function dialog(cm, text, f) {
514
+ if (cm.openDialog)
515
+ cm.openDialog(text + ": <input type=text>", f);
516
+ else
517
+ f(prompt(text, ""));
518
+ }
519
+
520
+ // Tooltips
521
+
522
+ function tempTooltip(cm, content) {
523
+ var where = cm.cursorCoords();
524
+ var tip = makeTooltip(where.right + 1, where.bottom, content);
525
+ function clear() {
526
+ if (!tip.parentNode) return;
527
+ cm.off("cursorActivity", clear);
528
+ fadeOut(tip);
529
+ }
530
+ setTimeout(clear, 1700);
531
+ cm.on("cursorActivity", clear);
532
+ }
533
+
534
+ function makeTooltip(x, y, content) {
535
+ var node = elt("div", cls + "tooltip", content);
536
+ node.style.left = x + "px";
537
+ node.style.top = y + "px";
538
+ document.body.appendChild(node);
539
+ return node;
540
+ }
541
+
542
+ function remove(node) {
543
+ var p = node && node.parentNode;
544
+ if (p) p.removeChild(node);
545
+ }
546
+
547
+ function fadeOut(tooltip) {
548
+ tooltip.style.opacity = "0";
549
+ setTimeout(function() { remove(tooltip); }, 1100);
550
+ }
551
+
552
+ function showError(ts, cm, msg) {
553
+ if (ts.options.showError)
554
+ ts.options.showError(cm, msg);
555
+ else
556
+ tempTooltip(cm, String(msg));
557
+ }
558
+
559
+ function closeArgHints(ts) {
560
+ if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
561
+ }
562
+
563
+ function docValue(ts, doc) {
564
+ var val = doc.doc.getValue();
565
+ if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc);
566
+ return val;
567
+ }
568
+
569
+ // Worker wrapper
570
+
571
+ function WorkerServer(ts) {
572
+ var worker = new Worker(ts.options.workerScript);
573
+ worker.postMessage({type: "init",
574
+ defs: ts.options.defs,
575
+ plugins: ts.options.plugins,
576
+ scripts: ts.options.workerDeps});
577
+ var msgId = 0, pending = {};
578
+
579
+ function send(data, c) {
580
+ if (c) {
581
+ data.id = ++msgId;
582
+ pending[msgId] = c;
583
+ }
584
+ worker.postMessage(data);
585
+ }
586
+ worker.onmessage = function(e) {
587
+ var data = e.data;
588
+ if (data.type == "getFile") {
589
+ getFile(ts, name, function(err, text) {
590
+ send({type: "getFile", err: String(err), text: text, id: data.id});
591
+ });
592
+ } else if (data.type == "debug") {
593
+ console.log(data.message);
594
+ } else if (data.id && pending[data.id]) {
595
+ pending[data.id](data.err, data.body);
596
+ delete pending[data.id];
597
+ }
598
+ };
599
+ worker.onerror = function(e) {
600
+ for (var id in pending) pending[id](e);
601
+ pending = {};
602
+ };
603
+
604
+ this.addFile = function(name, text) { send({type: "add", name: name, text: text}); };
605
+ this.delFile = function(name) { send({type: "del", name: name}); };
606
+ this.request = function(body, c) { send({type: "req", body: body}, c); };
607
+ }
608
+ })();