From 818dba5dbab8daf39415cf267138ffa2075ed99a Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Mon, 24 Dec 2012 02:07:33 -0800 Subject: [PATCH] Some added UX behaviors --- lib/ace/autocomplete.js | 30 +++++++++--------- lib/ace/autocomplete/autocomplete_worker.js | 35 ++++++++++----------- lib/ace/autocomplete/text_completer.js | 5 ++- lib/ace/worker/mirror.js | 12 +++++-- lib/ace/worker/worker_client.js | 4 +-- 5 files changed, 46 insertions(+), 40 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index df71dcc2..33c41f93 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -38,7 +38,9 @@ var UndoManager = require("ace/undomanager").UndoManager; var dom = require("ace/lib/dom"); var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var TextMode = require("ace/mode/text").Mode; + var WorkerClient = require("./worker/worker_client").WorkerClient; +var worker = new WorkerClient(["ace"], "ace/autocomplete/autocomplete_worker", "AutocompleteWorker"); var mode = new TextMode(); mode.$tokenizer = { @@ -46,7 +48,6 @@ mode.$tokenizer = { } }; -var worker = new WorkerClient(["ace"], "ace/autocomplete/autocomplete_worker", "AutocompleteWorker"); var Autocomplete = function() { this.keyboardHandler = new HashHandler(); @@ -82,7 +83,6 @@ var Autocomplete = function() { popup.renderer.maxLines = 6 popup.renderer.$keepTextAreaAtCursor=false - popup.setHighlightActiveLine(true); popup.setSession(new EditSession("")); @@ -104,6 +104,7 @@ var Autocomplete = function() { line = -1; return line; }; + popup.setRow = function(line) { popup.setHighlightActiveLine(line != -1); popup.gotoLine(line + 1); @@ -165,7 +166,9 @@ var Autocomplete = function() { this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); this.editor.removeEventListener("changeSelection", this.changeListener); this.editor.removeEventListener("blur", this.changeListener); - this.popup.container.style.display = "none"; + + if (this.popup) + this.popup.container.style.display = "none"; }; this.changeListener = function(e) { @@ -203,6 +206,9 @@ var Autocomplete = function() { var text = this.completions.filtered[row]; if (text.value) text = text.value; + + // should be good enough, otherwise we can use getDocument().removeInLine + this.editor.removeWordLeft(); this.editor.insert(text); this.detach(); }; @@ -214,6 +220,7 @@ var Autocomplete = function() { "ctrl-down": function(editor) { editor.Autocomplete.goTo("end"); }, "esc": function(editor) { editor.Autocomplete.detach(); }, + "space": function(editor) { editor.Autocomplete.detach(); editor.insert(" ");}, "Return": function(editor) { editor.Autocomplete.insertMatch(); }, "Shift-Return": function(editor) { editor.Autocomplete.insertMatch(true); }, "Tab": function(editor) { editor.Autocomplete.insertMatch(); }, @@ -236,22 +243,15 @@ var Autocomplete = function() { editor.on("changeSelection", this.$changeListener); editor.on("blur", this.$blurListener); - worker.attachToDocument(editor.session.getDocument(), {cursor: editor.getCursorPosition()}); + worker.attachToDocument(editor.session.getDocument(), {cursor: editor.getCursorPosition()}, true); worker.on("complete", function(data) { - _self.completions = new FilteredList(data.data.matches); + var matches = data.data.matches; + _self.completions = new FilteredList(matches); _self.completions.setFilter("a"); - if (data) { - if (data.length == 1) - _self.insertMatch(0); - else - _self.openPopup(editor); - } - }); - - worker.on("terminate", function() { - console.log("term"); + if (matches.length) + _self.openPopup(editor); }); }; diff --git a/lib/ace/autocomplete/autocomplete_worker.js b/lib/ace/autocomplete/autocomplete_worker.js index 2656b086..c85f2e8c 100644 --- a/lib/ace/autocomplete/autocomplete_worker.js +++ b/lib/ace/autocomplete/autocomplete_worker.js @@ -1,7 +1,7 @@ /* ***** BEGIN LICENSE BLOCK ***** * Distributed under the BSD license: * - * Copyright (c) 2010, Ajax.org B.V. + * Copyright (c) 2012, Ajax.org B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +38,9 @@ var SyntaxDetector = require("./syntax_detector"); var completer = require("./text_completer"); var AutocompleteWorker = exports.AutocompleteWorker = function(sender) { + this.setTimeout(0); Mirror.call(this, sender); + this.setDeferredUpdate(false); }; oop.inherits(AutocompleteWorker, Mirror); @@ -55,24 +57,16 @@ oop.inherits(AutocompleteWorker, Mirror); else return 0; }); - for (var i = 0; i < matches.length - 1; i++) { - var a = matches[i]; - var b = matches[i + 1]; - if (a.name === b.name) { - // Duplicate! - if (a.priority < b.priority) - matches.splice(i, 1); - else if (a.priority > b.priority) - matches.splice(i+1, 1); - else if (a.score < b.score) - matches.splice(i, 1); - else if (a.score > b.score) - matches.splice(i+1, 1); - else - matches.splice(i, 1); - i--; + + for(var i = 1; i < matches.length; ){ + if (matches[i - 1] == matches[i]){ + matches.splice(i, 1); + } else { + i++; } } + + return matches; }; this.onUpdate = function() { @@ -87,7 +81,7 @@ oop.inherits(AutocompleteWorker, Mirror); var currentNode = null; var matches = [], ast = null; - completer.complete(_self.doc, ast, this.data.cursor, currentNode, function(completions) { + completer.complete(_self.doc, ast, this.data.cursor, currentNode, function(identifier, completions) { if (completions) matches = matches.concat(completions); removeDuplicateMatches(matches); @@ -115,7 +109,10 @@ oop.inherits(AutocompleteWorker, Mirror); return 0; }); _self.sender.emit("complete", { - pos: pos, + startRow: pos.row, + startColumn: pos.column - identifier.length, + endRow: pos.row, + endColumn: Infinity, matches: matches, line: _self.doc.getLine(pos.row) }); diff --git a/lib/ace/autocomplete/text_completer.js b/lib/ace/autocomplete/text_completer.js index d98ec95f..9ffa9c67 100644 --- a/lib/ace/autocomplete/text_completer.js +++ b/lib/ace/autocomplete/text_completer.js @@ -53,13 +53,16 @@ define(function(require, exports, module) { var line = doc.getLine(pos.row); var identifier = completeUtil.retrievePrecedingIdentifier(line, pos.column); + if (identifier === "") + return callback(null); + var allIdentifiers = []; for (var ident in identDict) { allIdentifiers.push(ident); } var matches = completeUtil.findCompletions(identifier, allIdentifiers); - callback(matches); + callback(identifier, matches); /*callback(matches.map(function(m) { return { name : m, diff --git a/lib/ace/worker/mirror.js b/lib/ace/worker/mirror.js index 47412452..dd804865 100644 --- a/lib/ace/worker/mirror.js +++ b/lib/ace/worker/mirror.js @@ -10,22 +10,28 @@ var Mirror = exports.Mirror = function(sender) { this.data = {}; var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this)); - + var _self = this; sender.on("change", function(e) { doc.applyDeltas(e.data); - deferredUpdate.schedule(_self.$timeout); + if (_self.$defer) + deferredUpdate.schedule(_self.$timeout); }); }; (function() { this.$timeout = 500; - + this.$defer = true; + this.setTimeout = function(timeout) { this.$timeout = timeout; }; + this.setDeferredUpdate = function(defer) { + this.$defer = defer; + }; + this.setValue = function(value, data) { this.doc.setValue(value); this.data = data; diff --git a/lib/ace/worker/worker_client.js b/lib/ace/worker/worker_client.js index f48599c4..91dc6ca5 100644 --- a/lib/ace/worker/worker_client.js +++ b/lib/ace/worker/worker_client.js @@ -144,8 +144,8 @@ var WorkerClient = function(topLevelNamespaces, mod, classname) { catch(ex) {} }; - this.attachToDocument = function(doc, data) { - if (this.$doc) + this.attachToDocument = function(doc, data, ignore) { + if (this.$doc && !ignore) this.terminate(); this.$doc = doc;