diff --git a/common/content/completion.js b/common/content/completion.js index 14144f97..c37e9cd5 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -1544,14 +1544,21 @@ function Completion() //{{{ cmdContext.advance(args.completeStart); cmdContext.quote = args.quote; cmdContext.filter = args.completeFilter; - let compObject = command.completer.call(command, cmdContext, args); - if (compObject instanceof Array) // for now at least, let completion functions return arrays instead of objects - compObject = { start: compObject[0], items: compObject[1] }; - if (compObject != null) + try { - cmdContext.advance(compObject.start); - cmdContext.filterFunc = null; - cmdContext.completions = compObject.items; + let compObject = command.completer.call(command, cmdContext, args); + if (compObject instanceof Array) // for now at least, let completion functions return arrays instead of objects + compObject = { start: compObject[0], items: compObject[1] }; + if (compObject != null) + { + cmdContext.advance(compObject.start); + cmdContext.filterFunc = null; + cmdContext.completions = compObject.items; + } + } + catch (e) + { + liberator.reportError(e); } } } diff --git a/common/content/mappings.js b/common/content/mappings.js index c72f40c5..d8502044 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -254,14 +254,12 @@ function Mappings() //{{{ ////////////////////// COMMANDS //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - addMapCommands("", [modes.NORMAL], ""); - addMapCommands("c", [modes.COMMAND_LINE], "command line"); - addMapCommands("i", [modes.INSERT, modes.TEXTAREA], "insert"); - // FIXME - if (liberator.has("mail")) - addMapCommands("m", [modes.MESSAGE], "message"); - if (liberator.has("player")) - addMapCommands("p", [modes.PLAYER], "player"); + addMapCommands("", [modes.NORMAL, modes.VISUAL], ""); + for (let mode in modes.mainModes) + if (mode.char) + addMapCommands(mode.char, + [m.mask for (m in modes.mainModes) if (m.char == mode.char)], + [mode.disp.toLowerCase()]); /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// diff --git a/common/content/modes.js b/common/content/modes.js index e4a5c0c3..3099662b 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -135,16 +135,24 @@ const modes = (function () //{{{ get inputMode() main & (this.COMMAND_LINE | this.INPUT | this.TEXTAREA | this.COMPOSE), - addMode: function (name, extended, display) + get mainModes() (mode for ([k, mode] in Iterator(modeMap)) if (!mode.extended && mode.name == k)), + + addMode: function (name, extended, options) { let disp = name.replace("_", " ", "g"); this[name] = 1 << lastMode++; - modeMap[name] = modeMap[this[name]] = { + if (typeof extended == "object") + { + options = extended; + extended = false; + } + modeMap[name] = modeMap[this[name]] = util.extend({ extended: extended, mask: this[name], name: name, - display: display || function () disp - }; + disp: disp + }, options); + modeMap[name].display = modeMap[name].display || function () disp; if (!extended) mainModes.push(this[name]); }, @@ -260,16 +268,18 @@ const modes = (function () //{{{ var modeMap = {}; // main modes, only one should ever be active - self.addMode("NORMAL", false, -1); - self.addMode("INSERT"); - self.addMode("VISUAL", false, function () "VISUAL" + (extended & modes.LINE ? " LINE" : "")); - self.addMode("COMMAND_LINE"); + self.addMode("NORMAL", { char: "n", display: -1 }); + self.addMode("INSERT", { char: "i" }); + self.addMode("VISUAL", { char: "v", display: function () "VISUAL" + (extended & modes.LINE ? " LINE" : "") }); + self.addMode("COMMAND_LINE", { char: "c" }); self.addMode("CARET"); // text cursor is visible - self.addMode("TEXTAREA"); // text cursor is in a HTMLTextAreaElement - self.addMode("MESSAGE"); // for now only used in Muttator when the message has focus + self.addMode("TEXTAREA", { char: "i" }); // text cursor is in a HTMLTextAreaElement + self.addMode("CUSTOM", { display: function () plugins.mode }); + // FIXME: These belong elsewhere + // So too, probably, do most of the others. + self.addMode("MESSAGE", { char: "m" }); // for now only used in Muttator when the message has focus self.addMode("COMPOSE"); - self.addMode("CUSTOM", false, function () plugins.mode); - self.addMode("PLAYER"); // Player mode for songbird + self.addMode("PLAYER", { char: "p" }); // Player mode for songbird // extended modes, can include multiple modes, and even main modes self.addMode("EX", true); self.addMode("HINTS", true); diff --git a/common/content/options.js b/common/content/options.js index fb9bbeae..4973a957 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -579,7 +579,7 @@ function Options() //{{{ }); } - completion.optionValue(context, opt.name, opt.operator); + context.fork("values", 0, completion, "optionValue", opt.name, opt.operator); } // diff --git a/common/content/style.js b/common/content/style.js index 004542f0..0db9da25 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -1,5 +1,6 @@ /***** BEGIN LICENSE BLOCK ***** {{{ Copyright © 2008-2009 by Kris Maglione + Distributable under the terms of the MIT license, which allows for sublicensing under any compatible license, including the MPL, GPL, and MPL. Anyone who changes this file is welcome to relicense @@ -490,21 +491,28 @@ function Styles(name, store, serial) } let (array = util.Array) { - Styles.prototype = { + util.extend(Styles.prototype, { get sites() array([v.sites for ([k, v] in this.userSheets)]).flatten().uniq().__proto__, completeSite: function (context, content) { - let compl = []; + context.anchored = false; try { - compl.push([content.location.host, "Current Host"]); - compl.push([content.location.href, "Current URL"]); + context.fork("current", 0, this, function(context) { + context.title = ["Current Site"]; + context.completions = [ + [content.location.host, "Current Host"], + [content.location.href, "Current URL"] + ]; + }); } catch (e) {} - context.anchored = false; - context.completions = compl.concat([[s, ""] for each (s in styles.sites)]); + context.fork("others", 0, this, function(context) { + context.title = ["Site"]; + context.completions = [[s, ""] for each (s in styles.sites)]; + }); } - }; + }); } /** diff --git a/common/content/util.js b/common/content/util.js index 158d337b..78fbe884 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -160,6 +160,24 @@ const util = { //{{{ return delimiter + str.replace(/([\\'"])/g, "\\$1").replace("\n", "\\n", "g").replace("\t", "\\t", "g") + delimiter; }, + extend: function extend(dest) { + Array.slice(arguments, 1).filter(util.identity).forEach(function (src) + { + for (let [k, v] in Iterator(src)) + { + let get = src.__lookupGetter__(k), + set = src.__lookupSetter__(k); + if (!get && !set) + dest[k] = v; + if (get) + dest.__defineGetter__(k, get); + if (set) + dest.__defineSetter__(k, set); + } + }); + return dest; + }, + /** * Split a string on literal occurances of a marker. *