From 31a32f2659d6e3fab85135d8993876e593174c1d Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Thu, 20 Mar 2014 15:27:51 +0100 Subject: [PATCH] Fixes asynchronous autocompleter prefix updating Before it could happen (if an async autocompleter returned late) that the prefix used in the autocomplete was out of date. This fixes that. --- lib/ace/autocomplete.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index b243727f..e14b1da7 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -47,7 +47,7 @@ var Autocomplete = function() { this.changeListener = this.changeListener.bind(this); this.mousedownListener = this.mousedownListener.bind(this); this.mousewheelListener = this.mousewheelListener.bind(this); - + this.changeTimer = lang.delayedCall(function() { this.updateCompletions(true); }.bind(this)) @@ -74,10 +74,10 @@ var Autocomplete = function() { this.popup.setFontSize(editor.getFontSize()); var lineHeight = renderer.layerConfig.lineHeight; - - var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); + + var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); pos.left -= this.popup.getTextLeftOffset(); - + var rect = editor.container.getBoundingClientRect(); pos.top += rect.top - renderer.layerConfig.offset; pos.left += rect.left - editor.renderer.scrollLeft; @@ -94,7 +94,7 @@ var Autocomplete = function() { this.editor.off("mousedown", this.mousedownListener); this.editor.off("mousewheel", this.mousewheelListener); this.changeTimer.cancel(); - + if (this.popup) this.popup.hide(); @@ -182,10 +182,10 @@ var Autocomplete = function() { this.gatherCompletions = function(editor, callback) { var session = editor.getSession(); var pos = editor.getCursorPosition(); - + var line = session.getLine(pos.row); var prefix = util.retrievePrecedingIdentifier(line, pos.column); - + this.base = editor.getCursorPosition(); this.base.column -= prefix.length; @@ -197,8 +197,11 @@ var Autocomplete = function() { next(); }); }, function() { + // Fetch prefix again, because they may have changed by now + var pos = editor.getCursorPosition(); + var line = session.getLine(pos.row); callback(null, { - prefix: prefix, + prefix: util.retrievePrecedingIdentifier(line, pos.column), matches: matches }); }); @@ -208,7 +211,7 @@ var Autocomplete = function() { this.showPopup = function(editor) { if (this.editor) this.detach(); - + this.activated = true; this.editor = editor; @@ -223,10 +226,10 @@ var Autocomplete = function() { editor.on("blur", this.blurListener); editor.on("mousedown", this.mousedownListener); editor.on("mousewheel", this.mousewheelListener); - + this.updateCompletions(); }; - + this.updateCompletions = function(keepPopupPosition) { if (keepPopupPosition && this.base && this.completions) { var pos = this.editor.getCursorPosition(); @@ -243,7 +246,7 @@ var Autocomplete = function() { var matches = results && results.matches; if (!matches || !matches.length) return this.detach(); - // TODO reenable this when we have proper change tracking + // TODO reenable this when we have proper change tracking // if (matches.length == 1) // return this.insertMatch(matches[0]); @@ -299,16 +302,16 @@ var FilteredList = function(array, filterText, mutateData) { matches = matches.sort(function(a, b) { return b.exactMatch - a.exactMatch || b.score - a.score; }); - + // make unique var prev = null; matches = matches.filter(function(item){ - var caption = item.value || item.caption || item.snippet; + var caption = item.value || item.caption || item.snippet; if (caption === prev) return false; prev = caption; return true; }); - + this.filtered = matches; }; this.filterCompletions = function(items, needle) {