From 61002641a35a6fafff69165d594ff01da9251ae5 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 20 Nov 2009 15:37:39 -0500 Subject: [PATCH 01/27] Context-specific completer options. Option refactoring. New review Owner: dougkearns Hopefully the changeset hash will actually be linked this time. If not, it's the tip of the testing branch, presumably r4161. I've been meaning to do this for a while. It allows case matching, sorting, and auto completion options to be assigned on a per context basis, with fine grained control. It also adds builtin regex support to options since it's used fairly extensively. There are definitely other options that would benefit from the regexlist type, if I can dig them up. The interface (and perhaps the doc wording) is the only place I'm really ambivalent. --HG-- branch : testing --- common/content/bookmarks.js | 12 + common/content/commandline.js | 80 +----- common/content/commands.js | 4 +- common/content/completion.js | 93 ++++++- common/content/help.xsl | 12 +- common/content/io.js | 10 +- common/content/options.js | 405 +++++++++++++++++------------- common/content/sanitizer.js | 5 +- common/content/style.js | 2 + common/content/tabs.js | 6 +- common/content/template.js | 2 - common/locale/en-US/developer.xml | 2 +- common/locale/en-US/options.xml | 109 ++++++-- common/locale/en-US/various.xml | 28 ++- 14 files changed, 469 insertions(+), 301 deletions(-) diff --git a/common/content/bookmarks.js b/common/content/bookmarks.js index 077c1e8c..207cb3b1 100644 --- a/common/content/bookmarks.js +++ b/common/content/bookmarks.js @@ -598,6 +598,18 @@ const Bookmarks = Module("bookmarks", { context.completions = [["", "Don't perform searches by default"]].concat(context.completions); } }); + + options.add(["suggestengines"], + "Engine Alias which has a feature of suggest", + "stringlist", "google", + { + completer: function completer(value) { + let engines = services.get("browserSearch").getEngines({}) + .filter(function (engine) engine.supportsResponseType("application/x-suggestions+json")); + + return engines.map(function (engine) [engine.alias, engine.description]); + } + }); }, completion: function () { completion.bookmark = function bookmark(context, tags, extra) { diff --git a/common/content/commandline.js b/common/content/commandline.js index 79a4b4f2..16d06985 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -102,7 +102,7 @@ const CommandLine = Module("commandline", { }); this._autocompleteTimer = new Timer(200, 500, function autocompleteTell(tabPressed) { - if (!events.feedingKeys && self._completions && options.get("wildoptions").has("auto")) { + if (!events.feedingKeys && self._completions && options.get("autocomplete").values.length) { self._completions.complete(true, false); self._completions.itemList.show(); } @@ -1516,84 +1516,6 @@ const CommandLine = Module("commandline", { options.add(["showmode", "smd"], "Show the current mode in the command line", "boolean", true); - - options.add(["suggestengines"], - "Engine Alias which has a feature of suggest", - "stringlist", "google", - { - completer: function completer(value) { - let engines = services.get("browserSearch").getEngines({}) - .filter(function (engine) engine.supportsResponseType("application/x-suggestions+json")); - - return engines.map(function (engine) [engine.alias, engine.description]); - } - }); - - options.add(["complete", "cpt"], - "Items which are completed at the :open prompts", - "charlist", typeof(config.defaults["complete"]) == "string" ? config.defaults["complete"] : "slf", - { - completer: function (context) array(values(completion.urlCompleters)) - }); - - options.add(["wildcase", "wic"], - "Completion case matching mode", - "string", "smart", - { - completer: function () [ - ["smart", "Case is significant when capital letters are typed"], - ["match", "Case is always significant"], - ["ignore", "Case is never significant"] - ] - }); - - options.add(["wildignore", "wig"], - "List of file patterns to ignore when completing files", - "stringlist", "", - { - validator: function validator(values) { - // TODO: allow for escaping the "," - try { - RegExp("^(" + values.join("|") + ")$"); - return true; - } - catch (e) { - return false; - } - } - }); - - options.add(["wildmode", "wim"], - "Define how command line completion works", - "stringlist", "list:full", - { - completer: function (context) [ - // Why do we need ""? - ["", "Complete only the first match"], - ["full", "Complete the next full match"], - ["longest", "Complete to longest common string"], - ["list", "If more than one match, list all matches"], - ["list:full", "List all and complete first match"], - ["list:longest", "List all and complete common string"] - ], - checkHas: function (value, val) { - let [first, second] = value.split(":", 2); - return first == val || second == val; - } - }); - - options.add(["wildoptions", "wop"], - "Change how command line completion is done", - "stringlist", "", - { - completer: function completer(value) { - return [ - ["", "Default completion that won't show or sort the results"], - ["auto", "Automatically show this._completions while you are typing"], - ["sort", "Always sort the completion list"] - ]; - } - }); }, styles: function () { let fontSize = util.computedStyle(document.getElementById(config.mainWindowId)).fontSize; diff --git a/common/content/commands.js b/common/content/commands.js index 0b15f55e..f085507c 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -894,10 +894,10 @@ const Commands = Module("commands", { } [prefix] = context.filter.match(/^(?:\w*[\s!]|!)\s*/); - let cmdContext = context.fork(cmd, prefix.length); + let cmdContext = context.fork(command.name, prefix.length); let argContext = context.fork("args", prefix.length); args = command.parseArgs(cmdContext.filter, argContext, { count: count, bang: bang }); - if (args) { + if (args && !cmdContext.waitingForTab) { // FIXME: Move to parseCommand args.count = count; args.bang = bang; diff --git a/common/content/completion.js b/common/content/completion.js index 16aa7398..cd25a49a 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -34,6 +34,11 @@ const CompletionContext = Class("CompletionContext", { if (editor instanceof this.constructor) { let parent = editor; name = parent.name + "/" + name; + + this.autoComplete = options.get("autocomplete").getKey(name); + this.sortResults = options.get("wildsort").getKey(name); + this.wildcase = options.get("wildcase").getKey(name); + this.contexts = parent.contexts; if (name in this.contexts) self = this.contexts[name]; @@ -146,6 +151,8 @@ const CompletionContext = Class("CompletionContext", { this.top = this; this.__defineGetter__("incomplete", function () this.contextList.some(function (c) c.parent && c.incomplete)); this.__defineGetter__("waitingForTab", function () this.contextList.some(function (c) c.parent && c.waitingForTab)); + this.__defineSetter__("incomplete", function (val) {}); + this.__defineSetter__("waitingForTab", function (val) {}); this.reset(); } /** @@ -333,7 +340,7 @@ const CompletionContext = Class("CompletionContext", { get ignoreCase() { if ("_ignoreCase" in this) return this._ignoreCase; - let mode = options["wildcase"]; + let mode = this.wildcase; if (mode == "match") return this._ignoreCase = false; if (mode == "ignore") @@ -367,7 +374,7 @@ const CompletionContext = Class("CompletionContext", { if (this.maxItems) filtered = filtered.slice(0, this.maxItems); - if (options.get("wildoptions").has("sort") && this.compare) + if (this.sortResults && this.compare) filtered.sort(this.compare); let quote = this.quote; if (quote) @@ -498,8 +505,14 @@ const CompletionContext = Class("CompletionContext", { completer = self[completer]; let context = CompletionContext(this, name, offset); this.contextList.push(context); - if (completer) + + if (!context.autoComplete && !context.tabPressed && context.editor) + context.waitingForTab = true; + else if (completer) return completer.apply(self || this, [context].concat(Array.slice(arguments, arguments.callee.length))); + + if (completer) + return null; return context; }, @@ -741,6 +754,80 @@ const Completion = Module("completion", { //}}} }, { UrlCompleter: Struct("name", "description", "completer") +}, { + commands: function () { + commands.add(["contexts"], + "List the completion contexts used during completion of an ex command", + function (args) { + commandline.echo(template.commandOutput( +
+ { template.completionRow(["Context", "Title"], "CompTitle") } + { template.map(completion.contextList || [], function (item) template.completionRow(item, "CompItem")) } +
), + null, commandline.FORCE_MULTILINE); + + }, + { + argCount: "1", + completer: function (context, args) { + let PREFIX = "/ex/contexts"; + context.fork("ex", 0, completion, "ex"); + completion.contextList = [[k.substr(PREFIX.length), v.title[0]] for ([k, v] in iter(context.contexts)) if (k.substr(0, PREFIX.length) == PREFIX)]; + }, + literal: 0 + }); + }, + options: function () { + options.add(["autocomplete", "au"], + "Automatically update the completion list on any key press", + "regexlist", ".*"); + + options.add(["complete", "cpt"], + "Items which are completed at the :open prompts", + "charlist", typeof(config.defaults["complete"]) == "string" ? config.defaults["complete"] : "slf", + { + completer: function (context) array(values(completion.urlCompleters)) + }); + + options.add(["wildcase", "wic"], + "Completion case matching mode", + "regexmap", "smart", + { + completer: function () [ + ["smart", "Case is significant when capital letters are typed"], + ["match", "Case is always significant"], + ["ignore", "Case is never significant"] + ] + }); + + options.add(["wildmode", "wim"], + "Define how command line completion works", + "stringlist", "list:full", + { + completer: function (context) [ + // Why do we need ""? + // Because its description is useful during completion. --Kris + ["", "Complete only the first match"], + ["full", "Complete the next full match"], + ["longest", "Complete to longest common string"], + ["list", "If more than one match, list all matches"], + ["list:full", "List all and complete first match"], + ["list:longest", "List all and complete common string"] + ], + checkHas: function (value, val) { + let [first, second] = value.split(":", 2); + return first == val || second == val; + }, + has: function () { + test = function (val) this.values.some(function (value) this.checkHas(value, val), this); + return Array.some(arguments, test, this); + } + }); + + options.add(["wildsort", "wis"], + "Regexp list of which contexts to sort", + "regexlist", ".*"); + } }); // vim: set fdm=marker sw=4 ts=4 et: diff --git a/common/content/help.xsl b/common/content/help.xsl index 1ad7ee76..e9766465 100644 --- a/common/content/help.xsl +++ b/common/content/help.xsl @@ -202,7 +202,7 @@ (default: - + @@ -351,9 +351,13 @@ - - - + + + + # + + + diff --git a/common/content/io.js b/common/content/io.js index 3e5bd21a..713423f5 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -240,7 +240,7 @@ const File = Class("File", { */ MODE_EXCL: 0x80, - expandPathList: function (list) list.split(",").map(this.expandPath).join(","), + expandPathList: function (list) list.map(this.expandPath), expandPath: function (path, relative) { @@ -1028,8 +1028,8 @@ lookup: b.isdir - a.isdir || String.localeCompare(a.text, b.text); if (options["wildignore"]) { - let wigRegexp = RegExp("(^" + options.get("wildignore").values.join("|") + ")$"); - context.filters.push(function ({item: f}) f.isDirectory() || !wigRegexp.test(f.leafName)); + let wig = options.get("wildignore"); + context.filters.push(function ({item: f}) f.isDirectory() || !wig.getKey(this.name)); } // context.background = true; @@ -1099,6 +1099,10 @@ lookup: options.add(["shellcmdflag", "shcf"], "Flag passed to shell when executing :! and :run commands", "string", shellcmdflag); + + options.add(["wildignore", "wig"], + "List of file patterns to ignore when completing files", + "regexlist", ""); } }); diff --git a/common/content/options.js b/common/content/options.js index e304339f..55430c8b 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -22,7 +22,6 @@ * getter - see {@link Option#getter} * completer - see {@link Option#completer} * valdator - see {@link Option#validator} - * checkHas - see {@link Option#checkHas} * @optional * @private */ @@ -33,6 +32,17 @@ const Option = Class("Option", { this.type = type; this.description = description; + if (this.type in Option.getKey) + this.getKey = Option.getKey[this.type]; + + if (this.type in Option.parseValues) + this.parseValues = Option.parseValues[this.type]; + + if (this.type in Option.joinValues) + this.joinValues = Option.joinValues[this.type]; + + this._op = Option.ops[this.type]; + if (arguments.length > 3) this.defaultValue = defaultValue; @@ -44,7 +54,7 @@ const Option = Class("Option", { this.names = array([name, "no" + name] for (name in values(names))).flatten().__proto__; if (this.globalValue == undefined) - this.globalValue = this.defaultValue; + this.globalValue = this.parseValues(this.defaultValue); }, /** @property {value} The option's global value. @see #scope */ @@ -58,13 +68,7 @@ const Option = Class("Option", { * @param {value} value The option value. * @returns {value|string[]} */ - parseValues: function (value) { - if (this.type == "stringlist") - return (value === "") ? [] : value.split(","); - if (this.type == "charlist") - return Array.slice(value); - return value; - }, + parseValues: function (value) value, /** * Returns values packed in the appropriate format for the option @@ -73,16 +77,10 @@ const Option = Class("Option", { * @param {value|string[]} values The option value. * @returns {value} */ - joinValues: function (values) { - if (this.type == "stringlist") - return values.join(","); - if (this.type == "charlist") - return values.join(""); - return values; - }, + joinValues: function (vals) vals, /** @property {value|string[]} The option value or array of values. */ - get values() this.parseValues(this.value), + get values() this.getValues(this.scope), set values(values) this.setValues(values, this.scope), /** @@ -93,7 +91,26 @@ const Option = Class("Option", { * {@link Option#scope}). * @returns {value|string[]} */ - getValues: function (scope) this.parseValues(this.get(scope)), + getValues: function (scope) { + if (scope) { + if ((scope & this.scope) == 0) // option doesn't exist in this scope + return null; + } + else + scope = this.scope; + + let values; + + if (liberator.has("tabs") && (scope & Option.SCOPE_LOCAL)) + values = tabs.options[this.name]; + if ((scope & Option.SCOPE_GLOBAL) && (values == undefined)) + values = this.globalValue; + + if (this.getter) + return liberator.trapErrors(this.getter, this, values); + + return values; + }, /** * Sets the option's value from an array of values if the option type is @@ -102,8 +119,22 @@ const Option = Class("Option", { * @param {number} scope The scope to apply these values to (see * {@link Option#scope}). */ - setValues: function (values, scope) { - this.set(this.joinValues(values), scope || this.scope); + setValues: function (newValues, scope, skipGlobal) { + scope = scope || this.scope; + if ((scope & this.scope) == 0) // option doesn't exist in this scope + return; + + if (this.setter) + newValues = liberator.trapErrors(this.setter, this, newValues); + if (newValues === undefined) + return; + + if (liberator.has("tabs") && (scope & Option.SCOPE_LOCAL)) + tabs.options[this.name] = newValues; + if ((scope & Option.SCOPE_GLOBAL) && !skipGlobal) + this.globalValue = newValues; + + this.hasChanged = true; }, /** @@ -115,26 +146,7 @@ const Option = Class("Option", { * {@link Option#scope}). * @returns {value} */ - get: function (scope) { - if (scope) { - if ((scope & this.scope) == 0) // option doesn't exist in this scope - return null; - } - else - scope = this.scope; - - let value; - - if (liberator.has("tabs") && (scope & Option.SCOPE_LOCAL)) - value = tabs.options[this.name]; - if ((scope & Option.SCOPE_GLOBAL) && (value == undefined)) - value = this.globalValue; - - if (this.getter) - return liberator.trapErrors(this.getter, this, value); - - return value; - }, + get: function (scope) this.joinValues(this.getValues(scope)), /** * Sets the option value to newValue for the specified scope. @@ -145,21 +157,7 @@ const Option = Class("Option", { * @param {number} scope The scope to apply this value to (see * {@link Option#scope}). */ - set: function (newValue, scope) { - scope = scope || this.scope; - if ((scope & this.scope) == 0) // option doesn't exist in this scope - return; - - if (this.setter) - newValue = liberator.trapErrors(this.setter, this, newValue); - - if (liberator.has("tabs") && (scope & Option.SCOPE_LOCAL)) - tabs.options[this.name] = newValue; - if ((scope & Option.SCOPE_GLOBAL) && newValue != this.globalValue) - this.globalValue = newValue; - - this.hasChanged = true; - }, + set: function (newValue, scope) this.setValues(this.parseValues(newValue), scope), /** * @property {value} The option's current value. The option's local value, @@ -169,21 +167,15 @@ const Option = Class("Option", { get value() this.get(), set value(val) this.set(val), + getKey: function (key) undefined, + /** * Returns whether the option value contains one or more of the specified * arguments. * * @returns {boolean} */ - has: function () { - let self = this; - let test = function (val) values.indexOf(val) >= 0; - if (this.checkHas) - test = function (val) values.some(function (value) self.checkHas(value, val)); - let values = this.values; - // return whether some argument matches - return Array.some(arguments, function (val) test(val)); - }, + has: function () Array.some(arguments, function (val) this.values.indexOf(val) >= 0, this), /** * Returns whether this option is identified by name. @@ -216,97 +208,16 @@ const Option = Class("Option", { * @param {boolean} invert Whether this is an invert boolean operation. */ op: function (operator, values, scope, invert) { - let newValue = null; - let self = this; - switch (this.type) { - case "boolean": - if (operator != "=") - break; + let newValues = this._op(operator, values, scope, invert); - if (invert) - newValue = !this.value; - else - newValue = values; - break; - - case "number": - // TODO: support floats? Validators need updating. - if (!/^[+-]?(?:0x[0-9a-f]+|0[0-7]+|0|[1-9]\d*)$/i.test(values)) - return "E521: Number required after := " + this.name + "=" + values; - - let value = parseInt(values/* deduce radix */); - - switch (operator) { - case "+": - newValue = this.value + value; - break; - case "-": - newValue = this.value - value; - break; - case "^": - newValue = this.value * value; - break; - case "=": - newValue = value; - break; - } - - break; - - case "charlist": - case "stringlist": - values = Array.concat(values); - switch (operator) { - case "+": - newValue = util.Array.uniq(Array.concat(this.values, values), true); - break; - case "^": - // NOTE: Vim doesn't prepend if there's a match in the current value - newValue = util.Array.uniq(Array.concat(values, this.values), true); - break; - case "-": - newValue = this.values.filter(function (item) values.indexOf(item) == -1); - break; - case "=": - newValue = values; - if (invert) { - let keepValues = this.values.filter(function (item) values.indexOf(item) == -1); - let addValues = values.filter(function (item) self.values.indexOf(item) == -1); - newValue = addValues.concat(keepValues); - } - break; - } - - break; - - case "string": - switch (operator) { - case "+": - newValue = this.value + values; - break; - case "-": - newValue = this.value.replace(values, ""); - break; - case "^": - newValue = values + this.value; - break; - case "=": - newValue = values; - break; - } - - break; - - default: - return "E685: Internal error: option type `" + this.type + "' not supported"; - } - - if (newValue == null) + if (newValues == null) return "Operator " + operator + " not supported for option type " + this.type; - if (!this.isValidValue(newValue)) + + if (!this.isValidValue(newValues)) return "E474: Invalid argument: " + values; - this.setValues(newValue, scope); + + this.setValues(newValues, scope); return null; }, @@ -319,11 +230,13 @@ const Option = Class("Option", { /** * @property {string} The option's data type. One of: - * "boolean" - Boolean E.g. true - * "number" - Integer E.g. 1 - * "string" - String E.g. "Vimperator" - * "charlist" - Character list E.g. "rb" - * "stringlist" - String list E.g. "homepage,quickmark,tabopen,paste" + * "boolean" - Boolean, e.g., true + * "number" - Integer, e.g., 1 + * "string" - String, e.g., "Vimperator" + * "charlist" - Character list, e.g., "rb" + * "regexlist" - Regex list, e.g., "^foo,bar$" + * "stringmap" - String map, e.g., "key=v,foo=bar" + * "regexmap" - Regex map, e.g., "^key=v,foo$=bar" */ type: null, @@ -370,12 +283,6 @@ const Option = Class("Option", { return Option.validateCompleter.apply(this, arguments); return true; }, - /** - * @property The function called to determine whether the option already - * contains a specified value. - * @see #has - */ - checkHas: null, /** * @property {boolean} Set to true whenever the option is first set. This @@ -410,6 +317,131 @@ const Option = Class("Option", { */ SCOPE_BOTH: 3, + parseRegex: function (val, result) { + let [, bang, val] = /^(!?)(.*)/.exec(val); + let re = RegExp(val); + re.bang = bang; + re.result = arguments.length == 2 ? result : !bang; + return re; + }, + unparseRegex: function (re) re.bang + re.source + (typeof re.result == "string" ? "=" + re.result : ""), + + getKey: { + stringlist: function (k) this.values.indexOf(k) >= 0, + regexlist: function (k) { + for (let re in values(this.values)) + if (re.test(k)) + return re.result; + return null; + } + }, + + joinValues: { + charlist: function (vals) vals.join(""), + stringlist: function (vals) vals.join(","), + stringmap: function (vals) [k + "=" + v for ([k, v] in Iterator(vals))].join(","), + regexlist: function (vals) vals.map(Option.unparseRegex).join(","), + }, + + parseValues: { + number: function (value) Number(value), + boolean: function (value) value == "true" || value == true ? true : false, + charlist: function (value) Array.slice(value), + stringlist: function (value) (value === "") ? [] : value.split(","), + stringmap: function (value) array(v.split("=") for (v in values(value.split(",")))).toObject(), + regexlist: function (value) (value === "") ? [] : value.split(",").map(Option.parseRegex), + regexmap: function (value) value.split(",").map(function (v) v.split("=")) + .map(function ([k, v]) v != null ? Option.parseRegex(k, v) : Option.parseRegex('.?', k)) + }, + + ops: { + boolean: function (operator, values, scope, invert) { + if (operator != "=") + return null; + if (invert) + return !this.value; + return values; + }, + + number: function (operator, values, scope, invert) { + // TODO: support floats? Validators need updating. + if (!/^[+-]?(?:0x[0-9a-f]+|0[0-7]*|[1-9]+)$/i.test(values)) + return "E521: Number required after := " + this.name + "=" + values; + + let value = parseInt(values); + + switch (operator) { + case "+": + return this.value + value; + case "-": + return this.value - value; + case "^": + return this.value * value; + case "=": + return value; + } + return null; + }, + + stringmap: function (operator, values, scope, invert) { + values = Array.concat(values); + orig = [k + "=" + v for ([k, v] in Iterator(this.values))]; + + switch (operator) { + case "+": + return util.Array.uniq(Array.concat(orig, values), true); + case "^": + // NOTE: Vim doesn't prepend if there's a match in the current value + return util.Array.uniq(Array.concat(values, orig), true); + case "-": + return orig.filter(function (item) values.indexOf(item) == -1); + case "=": + if (invert) { + let keepValues = orig.filter(function (item) values.indexOf(item) == -1); + let addValues = values.filter(function (item) self.values.indexOf(item) == -1); + return addValues.concat(keepValues); + } + return values; + } + return null; + }, + + stringlist: function (operator, values, scope, invert) { + values = Array.concat(values); + switch (operator) { + case "+": + return util.Array.uniq(Array.concat(this.values, values), true); + case "^": + // NOTE: Vim doesn't prepend if there's a match in the current value + return util.Array.uniq(Array.concat(values, this.values), true); + case "-": + return this.values.filter(function (item) values.indexOf(item) == -1); + case "=": + if (invert) { + let keepValues = this.values.filter(function (item) values.indexOf(item) == -1); + let addValues = values.filter(function (item) self.values.indexOf(item) == -1); + return addValues.concat(keepValues); + } + return values; + } + return null; + }, + + string: function (operator, values, scope, invert) { + switch (operator) { + case "+": + return this.value + values; + case "-": + return this.value.replace(values, ""); + case "^": + return values + this.value; + case "=": + return values; + } + return null; + } + }, + // TODO: Run this by default? /** * Validates the specified values against values generated by the @@ -423,10 +455,21 @@ const Option = Class("Option", { let res = context.fork("", 0, this, this.completer); if (!res) res = context.allItems.items.map(function (item) [item.text]); + if (this.type == "regexmap") + return Array.concat(values).every(function (re) res.some(function (item) item[0] == re.result)); return Array.concat(values).every(function (value) res.some(function (item) item[0] == value)); } }); +Option.joinValues["regexmap"] = Option.joinValues["regexlist"]; + +Option.getKey["charlist"] = Option.getKey["stringlist"]; +Option.getKey["regexmap"] = Option.getKey["regexlist"]; + +Option.ops["charlist"] = Option.ops["stringlist"]; +Option.ops["regexlist"] = Option.ops["stringlist"]; +Option.ops["regexmap"] = Option.ops["stringlist"]; + /** * @instance options */ @@ -462,7 +505,7 @@ const Options = Module("options", { // Trigger any setters. let opt = options.get(option); if (event == "change" && opt) - opt.set(opt.value, Option.SCOPE_GLOBAL); + opt.setValues(opt.globalValue, Option.SCOPE_GLOBAL, true); } storage.newMap("options", { store: false }); @@ -1008,8 +1051,6 @@ const Options = Module("options", { } } // write access - // NOTE: the behavior is generally Vim compatible but could be - // improved. i.e. Vim's behavior is pretty sloppy to no real benefit else { option.setFrom = modifiers.setFrom || null; @@ -1017,7 +1058,12 @@ const Options = Module("options", { liberator.assert(!opt.valueGiven, "E474: Invalid argument: " + arg); opt.values = !opt.unsetBoolean; } - let res = opt.option.op(opt.operator || "=", opt.values, opt.scope, opt.invert); + try { + var res = opt.option.op(opt.operator || "=", opt.values, opt.scope, opt.invert); + } + catch (e) { + res = e; + } if (res) liberator.echoerr(res); } @@ -1244,8 +1290,15 @@ const Options = Module("options", { if (!completer) return; - let curValues = curValue != null ? opt.parseValues(curValue) : opt.values; - let newValues = opt.parseValues(context.filter); + try { + var curValues = curValue != null ? opt.parseValues(curValue) : opt.values; + var newValues = opt.parseValues(context.filter); + } + catch (e) { + context.message = "Error: " + e; + context.completions = []; + return; + } let len = context.filter.length; switch (opt.type) { @@ -1253,9 +1306,18 @@ const Options = Module("options", { if (!completer) completer = function () [["true", ""], ["false", ""]]; break; + case "regexlist": + newValues = context.filter.split(","); + // Fallthrough case "stringlist": - let target = newValues.pop(); - len = target ? target.length : 0; + let target = newValues.pop() || ""; + len = target.length; + break; + case "stringmap": + case "regexmap": + let vals = context.filter.split(","); + target = vals.pop() || ""; + len = target.length - (target.indexOf("=") + 1); break; case "charlist": len = 0; @@ -1268,9 +1330,10 @@ const Options = Module("options", { let completions = completer(context); if (!completions) return; + // Not Vim compatible, but is a significant enough improvement // that it's worth breaking compatibility. - if (newValues instanceof Array) { + if (isarray(newValues)) { completions = completions.filter(function (val) newValues.indexOf(val[0]) == -1); switch (op) { case "+": diff --git a/common/content/sanitizer.js b/common/content/sanitizer.js index b0a9eb16..1b3afcc4 100644 --- a/common/content/sanitizer.js +++ b/common/content/sanitizer.js @@ -213,10 +213,9 @@ const Sanitizer = Module("sanitizer", { { setter: function (values) { for (let [, pref] in Iterator(sanitizer.prefNames)) { - continue; options.setPref(pref, false); - for (let [, value] in Iterator(this.parseValues(values))) { + for (let [, value] in Iterator(values)) { if (Sanitizer.prefToArg(pref) == value) { options.setPref(pref, true); break; @@ -226,7 +225,7 @@ const Sanitizer = Module("sanitizer", { return values; }, - getter: function () sanitizer.prefNames.filter(function (pref) options.getPref(pref)).map(Sanitizer.prefToArg).join(","), + getter: function () sanitizer.prefNames.filter(function (pref) options.getPref(pref)).map(Sanitizer.prefToArg), completer: function (value) [ ["cache", "Cache"], ["commandline", "Command-line history"], diff --git a/common/content/style.js b/common/content/style.js index 9183df53..dc206c5f 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -167,6 +167,8 @@ Highlights.prototype.CSS = :{commandline.command}
{xml}; }, - // every item must have a .xml property which defines how to draw itself - // @param headers is an array of strings, the text for the header columns genericTable: function genericTable(items, format) { completion.listCompleter(function (context) { context.filterFunc = null; diff --git a/common/locale/en-US/developer.xml b/common/locale/en-US/developer.xml index 3e7a8052..5bf793a7 100644 --- a/common/locale/en-US/developer.xml +++ b/common/locale/en-US/developer.xml @@ -179,7 +179,7 @@

-
boolean
can only be on or off
-
number
has a numeric value
-
string
has a string value
-
charlist
like a string but with unique characters
-
stringlist
a comma-separated list of strings
+
boolean
Can only be on or off
+
number
A numeric value
+
string
A string value
+
charlist
A string containing a discrete set of distinct characters
+
stringlist
A comma-separated list of strings
+
stringmap
A comma-separated list of key-value pairs, e.g., key=val,foo=bar
+
regexlist
+
+ A comma-separated list of regular expressions. Expressions may be + prefixed with a !, in which case the match will be negated. A + literal ! at the begining of the expression may be matched with + [!]. Generally, the first matching regular expression is used. +
+
regexmap
+
+ A combination of a stringmap and a regexlist. Each key + in the key=value pair is a regexp. If the regexp begins with a + !, the sense match is negated, such that a non-matching + expression will be considered a match and vice versa. + The first key to match yields value. +

Setting options

@@ -293,6 +309,40 @@ + + 'au' 'autocomplete' + 'autocomplete' 'au' + regexlist + .* + +

+ A list of regexps defining which completion contexts should be + autocompleted. When the value is non-empty, the completion list is + automatically opened along with the commandline. Thereafter, any key + press triggers a completion update for the matching contexts. + Non-matching contexts will only be updated when the tab key is + pressed. This option is useful for disabling autocompletion for + computationally intense contexts that don't perform well on your + system under load. +

+ + + To enable autocompletion for everything but :history or + :bmarks, you would choose a value such as, + !/ex/bmarks,.? + + + + Completion contexts have names very much like Unix path names. This + denotes the tree in which they're called. A completer will never be + called unless every completer preceding it in the tree was also + called. For example, if your completer excludes /ex/, it + will also exclude /ex/bmarks, and so on. + + +

See also :contexts

+
+
$CDPATH @@ -1249,41 +1299,50 @@ - - 'wildcase' 'wic' + 'wic' 'wildcase' 'wildcase' 'wic' - string + regexmap smart -

Defines how completions are matched with regard to character case. Possible values:

+

+ Defines how completions are matched for a given completion context + with regard to character case. +

+ +

Possible values:

smart
Case is significant when capital letters are typed
match
Case is always significant
ignore
Case is never significant
+ +

See also :contexts

- 'wildignore' 'wig' 'wildignore' 'wig' - stringlist + regexlist

List of file patterns to ignore when completing files. E.g., to ignore object files and Vim swap files - :set wildignore=.\\.o,\\..\\.s[a-z]\\2

+ :set wildignore=\.o$,^\..*\.s[a-z]2$ + Unlike Vim each pattern is a regex rather than a glob. + + The only way to include a literal comma in a pattern is with the + escape \u0044. +
- 'wim' 'wildmode' 'wildmode' 'wim' @@ -1318,25 +1377,23 @@ - - 'wop' 'wildoptions' - 'wildoptions' 'wop' - stringlist - + 'wis' 'wildsort' + 'wildsort' 'wis' + regexlist + .* -

A list of words that change how command-line completion is done.

+

+ A list of regexps defining which completion contexts + should be sorted. The main purpose of this option is to + prevent sorting of certain completion lists that don't + perform well under load. +

-

Possible words:

- -
-
auto
Automatically show completions while you are typing.
-
sort
Always sort the completion list, overriding the complete option.
-
+

See also :contexts

- 'wsp' 'wordseparators' 'wordseparators' 'wsp' diff --git a/common/locale/en-US/various.xml b/common/locale/en-US/various.xml index 9fc05efb..7f7f7327 100644 --- a/common/locale/en-US/various.xml +++ b/common/locale/en-US/various.xml @@ -17,16 +17,27 @@ :beep :beep -

Play a system beep.

+

+ Play a system beep. This should not be used for any purpose other + than testing the visual bell. +

- CTRL-L :redr :redraw]]> - :redraw + :contexts + :contexts ex-command -

Redraws the screen. Useful to update the screen halfway executing a script or function.

+

+ Lists the completion contexts used during the completion of its + arguments. These context names are used in options such as + autocomplete and wildcase. Note that completion must + be triggered in order for this command to be effective, so if + autocompletion is not active, you'll need to press the + key at least once. You should also be aware that + this command is only useful from the commandline. +

@@ -46,6 +57,15 @@ + + CTRL-L :redr :redraw]]> + :redraw + +

Redraws the screen. Useful to update the screen halfway executing a script or function.

+
+
+ + :run :! :!cmd :!cmd From 03236cec0b69a5ce8275008b01337cf5558b4d85 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Tue, 24 Nov 2009 21:10:44 -0500 Subject: [PATCH 02/27] Fix toolbar completion. --HG-- branch : testing --- common/content/liberator.js | 1 + 1 file changed, 1 insertion(+) diff --git a/common/content/liberator.js b/common/content/liberator.js index a4b00ded..189888d0 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -1729,6 +1729,7 @@ const Liberator = Module("liberator", { context.completions = liberator.menuItems; }; + var toolbox = document.getElementById("navigator-toolbox"); completion.toolbar = function toolbar(context) { context.title = ["Toolbar"]; context.keys = { text: function (item) item.getAttribute("toolbarname"), description: function () "" }; From 9d75ceb8c0847445120d3e89fe6f0380a59c4c8b Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Tue, 1 Dec 2009 07:00:38 -0500 Subject: [PATCH 03/27] Fix some crap. --HG-- branch : testing --- common/content/liberator.js | 1 + common/content/options.js | 1 + 2 files changed, 2 insertions(+) diff --git a/common/content/liberator.js b/common/content/liberator.js index 189888d0..07380be7 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -1842,6 +1842,7 @@ const Liberator = Module("liberator", { statusline.update(); liberator.log(config.name + " fully initialized", 0); + liberator.initialized = true; } }); diff --git a/common/content/options.js b/common/content/options.js index 55430c8b..bbc7461b 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -407,6 +407,7 @@ const Option = Class("Option", { }, stringlist: function (operator, values, scope, invert) { + const self = this; values = Array.concat(values); switch (operator) { case "+": From bf5fb6d44e7447381418d115e9ec4fe1e97af616 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Tue, 1 Dec 2009 07:08:05 -0500 Subject: [PATCH 04/27] Finish adding missing copyright notices. --HG-- branch : testing --- common/content/autocommands.js | 4 +++- common/content/bookmarks.js | 4 +++- common/content/browser.js | 2 +- common/content/buffer.js | 2 +- common/content/commandline.js | 4 +++- common/content/commands.js | 2 +- common/content/completion.js | 5 +++-- common/content/configbase.js | 4 +++- common/content/events.js | 2 +- common/content/finder.js | 4 +++- common/content/hints.js | 4 +++- common/content/history.js | 4 +++- common/content/io.js | 4 +++- common/content/liberator-overlay.js | 2 +- common/content/liberator.js | 4 +++- common/content/mappings.js | 2 +- common/content/marks.js | 4 +++- common/content/modes.js | 4 +++- common/content/options.js | 4 +++- common/content/quickmarks.js | 4 +++- common/content/statusline.js | 4 +++- common/content/tabs.js | 2 +- common/content/template.js | 2 +- common/content/util.js | 4 +++- 24 files changed, 56 insertions(+), 25 deletions(-) diff --git a/common/content/autocommands.js b/common/content/autocommands.js index 52ceecb6..1417e684 100644 --- a/common/content/autocommands.js +++ b/common/content/autocommands.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/bookmarks.js b/common/content/bookmarks.js index 207cb3b1..b822f7b7 100644 --- a/common/content/bookmarks.js +++ b/common/content/bookmarks.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/browser.js b/common/content/browser.js index aec8bf25..2f47a583 100644 --- a/common/content/browser.js +++ b/common/content/browser.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 by Kris Maglione // diff --git a/common/content/buffer.js b/common/content/buffer.js index d70de3e5..a2424496 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 by Kris Maglione // diff --git a/common/content/commandline.js b/common/content/commandline.js index 16d06985..b4d027bc 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/commands.js b/common/content/commands.js index f085507c..ab9cebbb 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 by Kris Maglione // diff --git a/common/content/completion.js b/common/content/completion.js index cd25a49a..c5beb117 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -1,5 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott -// Copyright (c) 2008-2009 by Kris Maglione +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/configbase.js b/common/content/configbase.js index 7cb438b2..215695ef 100644 --- a/common/content/configbase.js +++ b/common/content/configbase.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/events.js b/common/content/events.js index cfab6641..e96a67bc 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 by Kris Maglione // diff --git a/common/content/finder.js b/common/content/finder.js index 158ce928..cf4ebba2 100644 --- a/common/content/finder.js +++ b/common/content/finder.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/hints.js b/common/content/hints.js index 48974c7e..4459c0b2 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/history.js b/common/content/history.js index 8f3ae5c8..281d797d 100644 --- a/common/content/history.js +++ b/common/content/history.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/io.js b/common/content/io.js index 713423f5..2aa3f9e8 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // Some code based on Venkman // // This work is licensed for reuse under an MIT license. Details are diff --git a/common/content/liberator-overlay.js b/common/content/liberator-overlay.js index 478ecd9e..ae32b8a2 100644 --- a/common/content/liberator-overlay.js +++ b/common/content/liberator-overlay.js @@ -1,4 +1,4 @@ -// Copyright (c) 2008-2009 Kris Maglione +// Copyright (c) 2008-2008 Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/liberator.js b/common/content/liberator.js index 07380be7..5403ad16 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/mappings.js b/common/content/mappings.js index af181120..7d1fa3fa 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 by Kris Maglione // diff --git a/common/content/marks.js b/common/content/marks.js index ab4c4789..44aadbc8 100644 --- a/common/content/marks.js +++ b/common/content/marks.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/modes.js b/common/content/modes.js index e6048bea..5a4948fc 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/options.js b/common/content/options.js index bbc7461b..f34a721e 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/quickmarks.js b/common/content/quickmarks.js index b6d6914b..20cb8b33 100644 --- a/common/content/quickmarks.js +++ b/common/content/quickmarks.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/statusline.js b/common/content/statusline.js index 9214b75d..d8fbfe05 100644 --- a/common/content/statusline.js +++ b/common/content/statusline.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/tabs.js b/common/content/tabs.js index 283c9262..6cd4083d 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott // Copyright (c) 2007-2009 by Doug Kearns // Copyright (c) 2008-2009 by Kris Maglione // diff --git a/common/content/template.js b/common/content/template.js index 26f0e512..7f8a1f09 100644 --- a/common/content/template.js +++ b/common/content/template.js @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 by Kris Maglione +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. diff --git a/common/content/util.js b/common/content/util.js index e313747d..d1c5656f 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -1,4 +1,6 @@ -// Copyright (c) 2006-2009 by Martin Stubenschrott +// Copyright (c) 2006-2008 by Martin Stubenschrott +// Copyright (c) 2007-2009 by Doug Kearns +// Copyright (c) 2008-2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. From 7a3d35991cca325ac2caefb85ad034c798c5e25f Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Tue, 11 May 2010 06:01:02 -0400 Subject: [PATCH 05/27] Fix some general brokenness. --HG-- branch : testing --- common/content/bookmarks.js | 3 +-- common/content/buffer.js | 18 +++++++++++------- common/content/commandline.js | 2 +- common/skin/liberator.css | 4 ++++ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/common/content/bookmarks.js b/common/content/bookmarks.js index b822f7b7..95ecdba9 100644 --- a/common/content/bookmarks.js +++ b/common/content/bookmarks.js @@ -366,7 +366,6 @@ const Bookmarks = Module("bookmarks", { // ripped from Firefox function getShortcutOrURI(url) { - var shortcutURL = null; var keyword = url; var param = ""; var offset = url.indexOf(" "); @@ -381,7 +380,7 @@ const Bookmarks = Module("bookmarks", { return [submission.uri.spec, submission.postData]; } - [shortcutURL, postData] = PlacesUtils.getURLAndPostDataForKeyword(keyword); + let [shortcutURL, postData] = PlacesUtils.getURLAndPostDataForKeyword(keyword); if (!shortcutURL) return [url, null]; diff --git a/common/content/buffer.js b/common/content/buffer.js index a2424496..904d415f 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -19,9 +19,10 @@ const Point = Struct("x", "y"); * @instance buffer */ const Buffer = Module("buffer", { - requires: ["config"], + requires: ["config", "util"], init: function () { + this.evaluateXPath = util.evaluateXPath; this.pageInfo = {}; this.addPageInfoSection("f", "Feeds", function (verbose) { @@ -1470,16 +1471,19 @@ const Buffer = Module("buffer", { if (count < 1 && buffer.lastInputField) buffer.focusElement(buffer.lastInputField); else { - let xpath = ["input[not(@type) or @type='text' or @type='password' or @type='file']", - "textarea[not(@disabled) and not(@readonly)]"]; + let xpath = ["input", "textarea[not(@disabled) and not(@readonly)]"]; - let elements = [m for (m in util.evaluateXPath(xpath))].filter(function (match) { - let computedStyle = util.computedStyle(match); + let elements = [m for (m in util.evaluateXPath(xpath))].filter(function (elem) { + if (elem.readOnly || elem instanceof HTMLInputElement && ["text", "password", "file"].indexOf(elem.type) < 0) + return false; + let computedStyle = util.computedStyle(elem); return computedStyle.visibility != "hidden" && computedStyle.display != "none"; }); liberator.assert(elements.length > 0); - buffer.focusElement(elements[util.Math.constrain(count, 1, elements.length) - 1]); + let elem = elements[util.Math.constrain(count, 1, elements.length) - 1]; + elem.scrollIntoView(); + buffer.focusElement(elem); } }, { count: true }); @@ -1599,7 +1603,7 @@ const Buffer = Module("buffer", { "Desired info in the :pageinfo output", "charlist", "gfm", { - completer: function (context) [[k, v[1]] for ([k, v] in Iterator(this.pageInfo))] + completer: function (context) [[k, v[1]] for ([k, v] in Iterator(buffer.pageInfo))] }); options.add(["scroll", "scr"], diff --git a/common/content/commandline.js b/common/content/commandline.js index b4d027bc..3d358b7c 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -1109,7 +1109,7 @@ const CommandLine = Module("commandline", { */ Completions: Class("Completions", { init: function (input) { - this.context = CompletionContext(input.editor); + this.context = CompletionContext(input.QueryInterface(Ci.nsIDOMNSEditableElement).editor); this.context.onUpdate = this.closure._reset; this.editor = input.editor; this.selected = null; diff --git a/common/skin/liberator.css b/common/skin/liberator.css index 146619a1..ff67a8f5 100644 --- a/common/skin/liberator.css +++ b/common/skin/liberator.css @@ -1,4 +1,5 @@ @namespace liberator url("http://vimperator.org/namespaces/liberator"); +@namespace html url("http://www.w3.org/1999/xhtml"); /* Applied to all content */ [liberator|activeframe] { @@ -122,6 +123,9 @@ statusbarpanel { color: inherit; margin: 0px; } +#liberator-commandline-command html|*:focus { + outline-width: 0px !important +} #liberator-message { margin: 0px; } From ae1d7fe5ea7d40661668a7bfc544011589f50f52 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 14 May 2010 09:21:02 -0400 Subject: [PATCH 06/27] Get rid of silly zoom status messages. --HG-- branch : testing --- common/content/buffer.js | 42 +++++++++++++++++------------ common/content/liberator.xul | 3 ++- common/content/statusline.js | 48 +++++++++++++++++++++++----------- common/locale/en-US/buffer.xml | 20 +++++++------- 4 files changed, 70 insertions(+), 43 deletions(-) diff --git a/common/content/buffer.js b/common/content/buffer.js index 904d415f..cdcdba97 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -280,7 +280,10 @@ const Buffer = Module("buffer", { autocommands.trigger("LocationChange", { url: buffer.URL }); // if this is not delayed we get the position of the old buffer - setTimeout(function () { statusline.updateBufferPosition(); }, 500); + setTimeout(function () { + statusline.updateBufferPosition(); + statusline.updateZoomLevel(); + }, 500); }, // called at the very end of a page load asyncUpdateUI: function () { @@ -385,19 +388,18 @@ const Buffer = Module("buffer", { get pageHeight() window.content.innerHeight, /** - * @property {number} The current browser's text zoom level, as a - * percentage with 100 as 'normal'. Only affects text size. + * @property {number} The current browser's zoom level, as a + * percentage with 100 as 'normal'. */ - get textZoom() config.browser.markupDocumentViewer.textZoom * 100, - set textZoom(value) { Buffer.setZoom(value, false); }, + get zoomLevel() config.browser.markupDocumentViewer[this.fullZoom ? "textZoom" : "fullZoom"] * 100, + set zoomLevel(value) { Buffer.setZoom(value, this.fullZoom); }, /** - * @property {number} The current browser's text zoom level, as a - * percentage with 100 as 'normal'. Affects text size, as well as - * image size and block size. + * @property {boolean} Whether the current browser is using full + * zoom, as opposed to text zoom. */ - get fullZoom() config.browser.markupDocumentViewer.fullZoom * 100, - set fullZoom(value) { Buffer.setZoom(value, true); }, + get fullZoom() ZoomManager.useFullZoom, + set fullZoom(value) { Buffer.setZoom(this.zoomLevel, value); }, /** * @property {string} The current document's title. @@ -961,14 +963,20 @@ const Buffer = Module("buffer", { liberator.assert(value >= Buffer.ZOOM_MIN || value <= Buffer.ZOOM_MAX, "Zoom value out of range (" + Buffer.ZOOM_MIN + " - " + Buffer.ZOOM_MAX + "%)"); - ZoomManager.useFullZoom = fullZoom; + if (fullZoom !== undefined) + ZoomManager.useFullZoom = fullZoom; ZoomManager.zoom = value / 100; + if ("FullZoom" in window) FullZoom._applySettingToPref(); - liberator.echomsg((fullZoom ? "Full" : "Text") + " zoom: " + value + "%"); + + statusline.updateZoomLevel(value, ZoomManager.useFullZoom); }, bumpZoomLevel: function bumpZoomLevel(steps, fullZoom) { + if (fullZoom === undefined) + fullZoom = ZoomManager.useFullZoom; + let values = ZoomManager.zoomValues; let cur = values.indexOf(ZoomManager.snap(ZoomManager.zoom)); let i = util.Math.constrain(cur + steps, 0, values.length - 1); @@ -1555,27 +1563,27 @@ const Buffer = Module("buffer", { function (count) { buffer.textZoom = count > 1 ? count : 100; }, { count: true }); - mappings.add(myModes, ["zI"], + mappings.add(myModes, ["ZI", "zI"], "Enlarge full zoom of current web page", function (count) { buffer.zoomIn(Math.max(count, 1), true); }, { count: true }); - mappings.add(myModes, ["zM"], + mappings.add(myModes, ["ZM", "zM"], "Enlarge full zoom of current web page by a larger amount", function (count) { buffer.zoomIn(Math.max(count, 1) * 3, true); }, { count: true }); - mappings.add(myModes, ["zO"], + mappings.add(myModes, ["ZO", "zO"], "Reduce full zoom of current web page", function (count) { buffer.zoomOut(Math.max(count, 1), true); }, { count: true }); - mappings.add(myModes, ["zR"], + mappings.add(myModes, ["ZR", "zR"], "Reduce full zoom of current web page by a larger amount", function (count) { buffer.zoomOut(Math.max(count, 1) * 3, true); }, { count: true }); - mappings.add(myModes, ["zZ"], + mappings.add(myModes, ["ZZ", "zZ"], "Set full zoom value of current web page", function (count) { buffer.fullZoom = count > 1 ? count : 100; }, { count: true }); diff --git a/common/content/liberator.xul b/common/content/liberator.xul index c1acf2bb..d2e9429d 100644 --- a/common/content/liberator.xul +++ b/common/content/liberator.xul @@ -86,12 +86,13 @@