From 1b093e51ccda3e43f84a5b74ef03979324bf189b Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 9 Oct 2008 21:50:00 +0000 Subject: [PATCH] Add rudimentary paren/brace/quote matching for JS --- content/completion.js | 6 +++++- content/ui.js | 24 ++++++++++++++++++++++-- content/util.js | 5 +++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/content/completion.js b/content/completion.js index bf3646ac..ba109249 100644 --- a/content/completion.js +++ b/content/completion.js @@ -225,6 +225,8 @@ liberator.Completion = function () //{{{ { if (top[CHAR] != arg) throw new Error("Invalid JS"); + if (i == str.length - 1) + liberator.completion.parenMatch = top[OFFSET]; // The closing character of this stack frame will have pushed a new // statement, leaving us with an empty statement. This doesn't matter, // now, as we simply throw away the frame when we pop it, but it may later. @@ -798,6 +800,8 @@ liberator.Completion = function () //{{{ // provides completions for ex commands, including their arguments ex: function (str) { + this.filterString = ""; + this.parenMatch = null; substrings = []; if (str.indexOf(cacheFilter["ex"]) != 0) { @@ -935,7 +939,7 @@ liberator.Completion = function () //{{{ if (h[0].indexOf(begin) == 0 && (!end.length || h[0].substr(-end.length) == end)) { let query = h[0].substring(begin.length, h[0].length - end.length); - searches.push([decodeURIComponent(query), + searches.push([decodeURIComponent(query.replace("+", "%20")), <>{begin}{query}{end}, k[2]]); } diff --git a/content/ui.js b/content/ui.js index 4be8c005..d442caf9 100644 --- a/content/ui.js +++ b/content/ui.js @@ -1150,13 +1150,33 @@ liberator.CommandLine = function () //{{{ } }, - // to allow asynchronous adding of completions, broken - // since the completion -> ItemList rewrite + // to allow asynchronous adding of completions setCompletions: function (compl, start) { if (liberator.mode != liberator.modes.COMMAND_LINE) return; + // FIXME: Kludge. + try // Firefox <3.1 doesn't have repaintSelection + { + const SEL_TYPE = Components.interfaces.nsISelectionController.SELECTION_FIND; + let editor = document.getElementById("liberator-commandline-command") + .inputField.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).editor; + let sel = editor.selectionController.getSelection(SEL_TYPE); + sel.removeAllRanges(); + if (liberator.completion.parenMatch != null) + { + let range = editor.selection.getRangeAt(0).cloneRange(); + let paren = liberator.completion.parenMatch + this.getCommand().indexOf(" ") + 1; + let node = range.startContainer; + range.setStart(node, paren); + range.setEnd(node, paren + 1); + sel.addRange(range); + editor.selectionController.repaintSelection(SEL_TYPE); + } + } + catch (e) {} + /* Only hide if not pending. if (compl.length == 0) return completionList.hide(); diff --git a/content/util.js b/content/util.js index 7485953b..60f7ea77 100644 --- a/content/util.js +++ b/content/util.js @@ -256,6 +256,7 @@ liberator.util = { //{{{ obj = {obj}.toXMLString(); string += obj + "::\n"; + let keys = []; try // window.content often does not want to be queried with "var i in object" { for (let i in object) @@ -273,12 +274,12 @@ liberator.util = { //{{{ value = value.toXMLString(); i = {i}.toXMLString(); } - string += i + ": " + value + "\n"; + keys.push(i + ": " + value); } } catch (e) {} - return string; + return string + keys.sort().join("\n") + "\n"; }, range: function (start, end)