From 09b9348852de8d0fe010639a1a4834657b740465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Fri, 31 Jan 2014 22:19:32 +0100 Subject: [PATCH] Improve autocomplete support for async completers --- lib/ace/autocomplete.js | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index d4491f6f..de30a740 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -60,6 +60,7 @@ var Autocomplete = function() { this.insertMatch(); e.stop(); }.bind(this)); + this.gatherCompletionsId = 0; }; this.openPopup = function(editor, prefix, keepPopupPosition) { @@ -146,6 +147,8 @@ var Autocomplete = function() { data = this.popup.getData(this.popup.getRow()); if (!data) return false; + this.gatherCompletionsId = this.gatherCompletionsId + 1; + if (data.completer && data.completer.insertMatch) { data.completer.insertMatch(this.editor); } else { @@ -191,16 +194,14 @@ var Autocomplete = function() { this.base.column -= prefix.length; var matches = []; - util.parForEach(editor.completers, function(completer, next) { + editor.completers.forEach(function(completer) { completer.getCompletions(editor, session, pos, prefix, function(err, results) { if (!err) matches = matches.concat(results); - next(); - }); - }, function() { - callback(null, { - prefix: prefix, - matches: matches + callback(null, { + prefix: prefix, + matches: matches + }); }); }); return true; @@ -229,6 +230,7 @@ var Autocomplete = function() { }; this.updateCompletions = function(keepPopupPosition) { + var that = this; if (keepPopupPosition && this.base && this.completions) { var pos = this.editor.getCursorPosition(); var prefix = this.editor.session.getTextRange({start: this.base, end: pos}); @@ -240,22 +242,39 @@ var Autocomplete = function() { this.openPopup(this.editor, prefix, keepPopupPosition); return; } + + // Save current gatherCompletions session, session is close when a match is insert + var _id = this.gatherCompletionsId; this.gatherCompletions(this.editor, function(err, results) { + // Calcul prefix + var session = that.editor.getSession(); + var pos = that.editor.getCursorPosition(); + var line = session.getLine(pos.row); + var prefix = util.retrievePrecedingIdentifier(line, pos.column); + + // Results matches var matches = results && results.matches; - if (!matches || !matches.length) - return this.detach(); // TODO reenable this when we have proper change tracking // if (matches.length == 1) // return this.insertMatch(matches[0]); + // No prefix or no results -> close + if (!prefix || !prefix.length || !matches || !matches.length) + return this.detach(); + + // Wrong prefx or wrong session -> ignore + if (prefix.indexOf(results.prefix) != 0 + || _id != this.gatherCompletionsId) + return; + this.completions = new FilteredList(matches); - this.completions.setFilter(results.prefix); + this.completions.setFilter(prefix); var filtered = this.completions.filtered; if (!filtered.length) return this.detach(); if (this.autoInsert && filtered.length == 1) return this.insertMatch(filtered[0]); - this.openPopup(this.editor, results.prefix, keepPopupPosition); + this.openPopup(this.editor, prefix, keepPopupPosition); }.bind(this)); };