Skip to content

Commit ef19fdb

Browse files
gjtorikiannightwing
authored andcommitted
First pass at Haurtyun UI + C9 doc parsing
1 parent e43bee0 commit ef19fdb

7 files changed

Lines changed: 511 additions & 39 deletions

File tree

lib/ace/autocomplete.js

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,16 @@ var UndoManager = require("ace/undomanager").UndoManager;
3838
var dom = require("ace/lib/dom");
3939
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
4040
var TextMode = require("ace/mode/text").Mode;
41+
var WorkerClient = require("./worker/worker_client").WorkerClient;
4142

4243
var mode = new TextMode();
4344
mode.$tokenizer = {
4445
getLineTokens: function(line) {
4546

4647
}
4748
};
49+
var worker = new WorkerClient(["ace"], "ace/autocomplete/autocomplete_worker", "AutocompleteWorker");
50+
4851
var Autocomplete = function() {
4952
this.keyboardHandler = new HashHandler();
5053
this.keyboardHandler.bindKeys(this.commands);
@@ -68,28 +71,28 @@ var Autocomplete = function() {
6871
el.style.display = "none"
6972
popup.renderer.content.style.cursor="default"
7073

71-
var nop = function(){};
74+
var noop = function(){};
7275

73-
popup.focus = nop;
76+
popup.focus = noop;
7477
popup.$isFocused = true;
7578

76-
popup.renderer.$cursorLayer.restartTimer = nop
77-
popup.renderer.$cursorLayer.update = nop
79+
popup.renderer.$cursorLayer.restartTimer = noop;
80+
popup.renderer.$cursorLayer.update = noop;
7881
popup.renderer.$cursorLayer.element.style.display = "none";
7982

8083
popup.renderer.maxLines = 6
8184
popup.renderer.$keepTextAreaAtCursor=false
8285

8386

84-
popup.setHighlightActiveLine(true)
85-
popup.setSession(new EditSession(""))
87+
popup.setHighlightActiveLine(true);
88+
popup.setSession(new EditSession(""));
8689

8790
popup.on("mousedown", function(e) {
8891
var pos = e.getDocumentPosition();
8992
popup.moveCursorToPosition(pos);
9093
popup.selection.clearSelection();
9194
e.stop();
92-
})
95+
});
9396

9497
/* popup.session.setMode({
9598
$
@@ -158,20 +161,6 @@ var Autocomplete = function() {
158161
el.style.display = "";
159162
};
160163

161-
this.attachToEditor = function(editor) {
162-
if (this.editor)
163-
this.detach();
164-
this.editor = editor;
165-
if (editor.Autocomplete != this) {
166-
if (editor.Autocomplete)
167-
editor.Autocomplete.detach();
168-
editor.Autocomplete = this;
169-
}
170-
editor.keyBinding.addKeyboardHandler(this.keyboardHandler)
171-
editor.on("changeSelection", this.$changeListener)
172-
editor.on("blur", this.$blurListener)
173-
};
174-
175164
this.detach = function() {
176165
this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);
177166
this.editor.removeEventListener("changeSelection", this.changeListener);
@@ -232,20 +221,38 @@ var Autocomplete = function() {
232221
};
233222

234223
this.complete = function(editor) {
235-
this.attachToEditor(editor);
236-
var data = this.gatherCompletions(editor);
237-
this.completions = new FilteredList(data);
238-
this.completions.setFilter("a")
239-
if (data) {
240-
if (data.length == 1)
241-
this.insertMatch(0);
242-
else
243-
this.openPopup(editor);
224+
if (this.editor)
225+
this.detach();
226+
227+
var _self = this;
228+
this.editor = editor;
229+
if (editor.Autocomplete != this) {
230+
if (editor.Autocomplete)
231+
editor.Autocomplete.detach();
232+
editor.Autocomplete = this;
244233
}
245-
};
246-
247-
this.gatherCompletions = function() {
248-
return ["asdaf", "foo", "bar", "baz"];
234+
235+
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
236+
editor.on("changeSelection", this.$changeListener);
237+
editor.on("blur", this.$blurListener);
238+
239+
worker.attachToDocument(editor.session.getDocument(), {cursor: editor.getCursorPosition()});
240+
241+
worker.on("complete", function(data) {
242+
_self.completions = new FilteredList(data.data.matches);
243+
_self.completions.setFilter("a");
244+
245+
if (data) {
246+
if (data.length == 1)
247+
_self.insertMatch(0);
248+
else
249+
_self.openPopup(editor);
250+
}
251+
});
252+
253+
worker.on("terminate", function() {
254+
console.log("term");
255+
});
249256
};
250257

251258
this.$singleLineEditor = function(el) {
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/* ***** BEGIN LICENSE BLOCK *****
2+
* Distributed under the BSD license:
3+
*
4+
* Copyright (c) 2010, Ajax.org B.V.
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* * Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
* * Neither the name of Ajax.org B.V. nor the
15+
* names of its contributors may be used to endorse or promote products
16+
* derived from this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
22+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
*
29+
* ***** END LICENSE BLOCK ***** */
30+
31+
define(function(require, exports, module) {
32+
"use strict";
33+
34+
var oop = require("../lib/oop");
35+
var Mirror = require("../worker/mirror").Mirror;
36+
37+
var SyntaxDetector = require("./syntax_detector");
38+
var completer = require("./text_completer");
39+
40+
var AutocompleteWorker = exports.AutocompleteWorker = function(sender) {
41+
Mirror.call(this, sender);
42+
};
43+
44+
oop.inherits(AutocompleteWorker, Mirror);
45+
46+
(function() {
47+
// For code completion
48+
function removeDuplicateMatches(matches) {
49+
// First sort
50+
matches.sort(function(a, b) {
51+
if (a.name < b.name)
52+
return 1;
53+
else if (a.name > b.name)
54+
return -1;
55+
else
56+
return 0;
57+
});
58+
for (var i = 0; i < matches.length - 1; i++) {
59+
var a = matches[i];
60+
var b = matches[i + 1];
61+
if (a.name === b.name) {
62+
// Duplicate!
63+
if (a.priority < b.priority)
64+
matches.splice(i, 1);
65+
else if (a.priority > b.priority)
66+
matches.splice(i+1, 1);
67+
else if (a.score < b.score)
68+
matches.splice(i, 1);
69+
else if (a.score > b.score)
70+
matches.splice(i+1, 1);
71+
else
72+
matches.splice(i, 1);
73+
i--;
74+
}
75+
}
76+
};
77+
78+
this.onUpdate = function() {
79+
var _self = this;
80+
81+
var doc = this.doc.getValue();
82+
var pos = this.data.cursor;
83+
var part = SyntaxDetector.getContextSyntaxPart(this.doc, this.data.cursor, "javascript");
84+
var language = part.language;
85+
86+
var currentPos = { line: pos.row, col: pos.column };
87+
var currentNode = null;
88+
var matches = [], ast = null;
89+
90+
completer.complete(_self.doc, ast, this.data.cursor, currentNode, function(completions) {
91+
if (completions)
92+
matches = matches.concat(completions);
93+
removeDuplicateMatches(matches);
94+
// Sort by priority, score
95+
matches.sort(function(a, b) {
96+
if (a.priority < b.priority)
97+
return 1;
98+
else if (a.priority > b.priority)
99+
return -1;
100+
else if (a.score < b.score)
101+
return 1;
102+
else if (a.score > b.score)
103+
return -1;
104+
else if (a.id && a.id === b.id) {
105+
if (a.isFunction)
106+
return -1;
107+
else if (b.isFunction)
108+
return 1;
109+
}
110+
if (a.name < b.name)
111+
return -1;
112+
else if(a.name > b.name)
113+
return 1;
114+
else
115+
return 0;
116+
});
117+
_self.sender.emit("complete", {
118+
pos: pos,
119+
matches: matches,
120+
line: _self.doc.getLine(pos.row)
121+
});
122+
return;
123+
});
124+
};
125+
126+
}).call(AutocompleteWorker.prototype);
127+
128+
});
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
define(function(require, exports, module) {
2+
3+
var ID_REGEX = /[a-zA-Z_0-9\$]/;
4+
5+
function retrievePrecedingIdentifier(text, pos, regex) {
6+
regex = regex || ID_REGEX;
7+
var buf = [];
8+
for (var i = pos-1; i >= 0; i--) {
9+
if (regex.test(text[i]))
10+
buf.push(text[i]);
11+
else
12+
break;
13+
}
14+
return buf.reverse().join("");
15+
}
16+
17+
function retrieveFollowingIdentifier(text, pos, regex) {
18+
regex = regex || ID_REGEX;
19+
var buf = [];
20+
for (var i = pos; i < text.length; i++) {
21+
if (regex.test(text[i]))
22+
buf.push(text[i]);
23+
else
24+
break;
25+
}
26+
return buf;
27+
}
28+
29+
function prefixBinarySearch(items, prefix) {
30+
var startIndex = 0;
31+
var stopIndex = items.length - 1;
32+
var middle = Math.floor((stopIndex + startIndex) / 2);
33+
34+
while (stopIndex > startIndex && middle >= 0 && items[middle].indexOf(prefix) !== 0) {
35+
if (prefix < items[middle]) {
36+
stopIndex = middle - 1;
37+
}
38+
else if (prefix > items[middle]) {
39+
startIndex = middle + 1;
40+
}
41+
middle = Math.floor((stopIndex + stopIndex) / 2);
42+
}
43+
44+
// Look back to make sure we haven't skipped any
45+
while (middle > 0 && items[middle-1].indexOf(prefix) === 0)
46+
middle--;
47+
return middle >= 0 ? middle : 0; // ensure we're not returning a negative index
48+
}
49+
50+
function findCompletions(prefix, allIdentifiers) {
51+
allIdentifiers.sort();
52+
var startIdx = prefixBinarySearch(allIdentifiers, prefix);
53+
var matches = [];
54+
for (var i = startIdx; i < allIdentifiers.length && allIdentifiers[i].indexOf(prefix) === 0; i++)
55+
matches.push(allIdentifiers[i]);
56+
return matches;
57+
}
58+
59+
function fetchText(staticPrefix, path) {
60+
var xhr = new XMLHttpRequest();
61+
xhr.open('GET', staticPrefix + "/" + path, false);
62+
try {
63+
xhr.send();
64+
}
65+
// Likely we got a cross-script error (equivalent with a 404 in our cloud setup)
66+
catch(e) {
67+
return false;
68+
}
69+
if (xhr.status === 200)
70+
return xhr.responseText;
71+
else
72+
return false;
73+
}
74+
75+
/** @deprecated Use retrievePrecedingIdentifier */
76+
exports.retrievePreceedingIdentifier = function() {
77+
console.error("Deprecated: 'retrievePreceedingIdentifier' - use 'retrievePrecedingIdentifier' instead");
78+
return retrievePrecedingIdentifier.apply(null, arguments);
79+
};
80+
exports.retrievePrecedingIdentifier = retrievePrecedingIdentifier;
81+
exports.retrieveFollowingIdentifier = retrieveFollowingIdentifier;
82+
exports.findCompletions = findCompletions;
83+
exports.fetchText = fetchText;
84+
85+
});

0 commit comments

Comments
 (0)