From 947311dfdf84a33b7e8ad232de4913d62bec0896 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 18 Dec 2008 21:37:44 -0500 Subject: [PATCH 01/26] Kludge the stupid urlbar focus bug better --- common/content/events.js | 123 +++++++++++++++++++++------------------ common/content/modes.js | 10 +--- 2 files changed, 68 insertions(+), 65 deletions(-) diff --git a/common/content/events.js b/common/content/events.js index 3eadb398..401244ba 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -33,6 +33,7 @@ function AutoCommands() //{{{ /////////////////////////////////////////////////////////////////////////////{{{ var store = []; + var lastFocus = null; function matchAutoCmd(autoCmd, event, regex) { @@ -1086,65 +1087,77 @@ function Events() //{{{ if (win && win.top == content && liberator.has("tabs")) tabs.localStore.focusedFrame = win; - if (elem && elem.readOnly) - return; - - if (elem && ( - (elem instanceof HTMLInputElement && (elem.type.toLowerCase() == "text" || elem.type.toLowerCase() == "password")) || - (elem instanceof HTMLSelectElement) - )) + try { - this.wantsModeReset = false; - liberator.mode = modes.INSERT; - if (hasHTMLDocument(win)) - buffer.lastInputField = elem; - return; - } + if (elem && elem.readOnly) + return; - if (elem && elem instanceof HTMLTextAreaElement) - { - this.wantsModeReset = false; - if (options["insertmode"]) - modes.set(modes.INSERT, modes.TEXTAREA); - else if (elem.selectionEnd - elem.selectionStart > 0) - modes.set(modes.VISUAL, modes.TEXTAREA); - else - modes.main = modes.TEXTAREA; - if (hasHTMLDocument(win)) - buffer.lastInputField = elem; - return; - } - - if (config.name == "Muttator") - { - // we switch to -- MESSAGE -- mode for muttator, when the main HTML widget gets focus - if (hasHTMLDocument(win) || elem instanceof HTMLAnchorElement) + if ((elem instanceof HTMLInputElement && /^(text|password)$/.test(elem.type)) || + (elem instanceof HTMLSelectElement)) { - if (config.isComposeWindow) - { - liberator.dump("Compose editor got focus"); - modes.set(modes.INSERT, modes.TEXTAREA); - } - else if (liberator.mode != modes.MESSAGE) - liberator.mode = modes.MESSAGE; + this.wantsModeReset = false; + liberator.mode = modes.INSERT; + if (hasHTMLDocument(win)) + buffer.lastInputField = elem; return; } - } - if (liberator.mode == modes.INSERT || - liberator.mode == modes.TEXTAREA || - liberator.mode == modes.MESSAGE || - liberator.mode == modes.VISUAL) + if (elem instanceof HTMLTextAreaElement) + { + this.wantsModeReset = false; + if (options["insertmode"]) + modes.set(modes.INSERT, modes.TEXTAREA); + else if (elem.selectionEnd - elem.selectionStart > 0) + modes.set(modes.VISUAL, modes.TEXTAREA); + else + modes.main = modes.TEXTAREA; + if (hasHTMLDocument(win)) + buffer.lastInputField = elem; + return; + } + + if (config.name == "Muttator") + { + // we switch to -- MESSAGE -- mode for muttator, when the main HTML widget gets focus + if (hasHTMLDocument(win) || elem instanceof HTMLAnchorElement) + { + if (config.isComposeWindow) + { + liberator.dump("Compose editor got focus"); + modes.set(modes.INSERT, modes.TEXTAREA); + } + else if (liberator.mode != modes.MESSAGE) + liberator.mode = modes.MESSAGE; + return; + } + } + + urlbar = document.getElementById("urlbar"); + if (focus == null && urlbar && urlbar.inputField == lastFocus) + liberator.threadYield(true); + + if (liberator.mode & (modes.INSERT | modes.TEXTAREA | modes.MESSAGE | modes.VISUAL)) + { + if (0) // FIXME: currently this hack is disabled to make macros work + { + this.wantsModeReset = true; + setTimeout(function () { + if (events.wantsModeReset) + { + events.wantsModeReset = false; + modes.reset(); + } + }, 0); + } + else + { + modes.reset(); + } + } + } + finally { - // FIXME: currently this hack is disabled to make macros work - // this.wantsModeReset = true; - // setTimeout(function () { - // if (events.wantsModeReset) - // { - // events.wantsModeReset = false; - modes.reset(); - // } - // }, 0); + lastFocus = elem; } }, @@ -1198,7 +1211,6 @@ function Events() //{{{ catch (e) {} modes.reset(); - liberator.focusContent(true); break; case modes.VISUAL: @@ -1216,14 +1228,9 @@ function Events() //{{{ case modes.INSERT: if ((modes.extended & modes.TEXTAREA) && !options["insertmode"]) - { liberator.mode = modes.TEXTAREA; - } else - { modes.reset(); - liberator.focusContent(true); - } break; default: // HINTS, CUSTOM or COMMAND_LINE diff --git a/common/content/modes.js b/common/content/modes.js index de88c3be..b016048b 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -116,13 +116,7 @@ const modes = (function () //{{{ options.setPref("accessibility.browsewithcaret", false); statusline.updateUrl(); - // Kludge to prevent the input field losing focus on MS/Mac - setTimeout(function () { - let focus = document.commandDispatcher.focusedElement; - let urlbar = document.getElementById("urlbar"); - if (!urlbar || focus != urlbar.inputField) - liberator.focusContent(false); - }, 0); + liberator.focusContent(false); } } @@ -137,6 +131,8 @@ const modes = (function () //{{{ get all() mainModes.slice(), + get inputMode() main & (this.COMMAND_LINE | this.INPUT | this.TEXTAREA | this.COMPOSE), + addMode: function (name, extended, display) { let disp = name.replace("_", " ", "g"); this[name] = 1 << lastMode++; From e6d83bd03932982e8d2336348ee0fe0b7273d83b Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 18 Dec 2008 21:41:56 -0500 Subject: [PATCH 02/26] Don't hide errors on bad URLs, they're useful feedback --- common/content/liberator.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/common/content/liberator.js b/common/content/liberator.js index e2e8f4d1..ab6c9b9f 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -1090,11 +1090,7 @@ const liberator = (function () //{{{ switch (where) { case liberator.CURRENT_TAB: - try - { - getBrowser().loadURIWithFlags(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, postdata); - } - catch (e) {} + getBrowser().loadURIWithFlags(url, Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null, postdata); break; case liberator.NEW_BACKGROUND_TAB: @@ -1111,11 +1107,7 @@ const liberator = (function () //{{{ const wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); window.open(); whichwindow = wm.getMostRecentWindow("navigator:browser"); - try - { - whichwindow.loadURI(url, null, postdata); - } - catch (e) {} + whichwindow.loadURI(url, null, postdata); break; default: From f583041c8afbd541451bac900010e31c2f75d4fc Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 18 Dec 2008 21:47:36 -0500 Subject: [PATCH 03/26] Default to opening multiple URLs in windows instead of tabs when !has("tabs") --- common/content/liberator.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/content/liberator.js b/common/content/liberator.js index ab6c9b9f..73c1d445 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -1099,6 +1099,7 @@ const liberator = (function () //{{{ return open(urls, liberator.NEW_WINDOW); let tab = getBrowser().addTab(url, null, null, postdata); + if (where == liberator.NEW_TAB) getBrowser().selectedTab = tab; break; @@ -1124,8 +1125,6 @@ const liberator = (function () //{{{ for (let [i, url] in Iterator(urls)) { open(url, where); - if (i == 0 && !liberator.has("tabs")) - break; where = liberator.NEW_BACKGROUND_TAB; } From 6186ad27b4db5dc2849c5618dae266bd1bfc891f Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 00:17:18 -0500 Subject: [PATCH 04/26] Start documenting CompletionContext --- common/content/completion.js | 129 ++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) diff --git a/common/content/completion.js b/common/content/completion.js index bf4a9622..1ce28900 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -26,6 +26,25 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** + * Creates a new completion context. + * + * @class A class to provide contexts for command completion. + * Manages the filtering and formatting of completions, and keeps + * track of the positions and quoting of replacement text. Allows for + * the creation of sub-contexts with different headers and quoting + * rules. + * + * @param {nsIEditor} editor The editor for which completion is + * intended. May be a {CompletionContext} when forking a context, + * or a {string} when creating a new one. + * @param {string} name The name of this context. Used when the + * context is forked. + * @param {number} offset The offset from the parent context. + * @author Kris Maglione + * @constructor + */ + function CompletionContext(editor, name, offset) //{{{ { if (!(this instanceof arguments.callee)) @@ -44,7 +63,11 @@ function CompletionContext(editor, name, offset) //{{{ else self.contexts[name] = this; + /** + * @property {CompletionContext} This context's parent. {null} when this is a top-level context. + */ self.parent = parent; + ["filters", "keys", "title", "quote"].forEach(function (key) self[key] = parent[key] && util.cloneObject(parent[key])); ["anchored", "compare", "editor", "_filter", "filterFunc", "keys", "_process", "top"].forEach(function (key) @@ -55,10 +78,20 @@ function CompletionContext(editor, name, offset) //{{{ self.offset = parent.offset; self.advance(offset); + /** + * @property {boolean} Specifies that this context is not finished + * generating results. + * @default false + */ self.incomplete = false; self.message = null; + /** + * @property {boolean} Specifies that this context is waiting for the + * user to press . Useful when fetching completions could be + * dangerous or slow, and the user has enabled autocomplete. + */ self.waitingForTab = false; - //delete self._filter; // FIXME? + delete self._generate; delete self._ignoreCase; if (self != this) @@ -76,6 +109,11 @@ function CompletionContext(editor, name, offset) //{{{ this.editor = editor; this.compare = function (a, b) String.localeCompare(a.text, b.text); + /** + * @property {function} The function used to filter the results. + * @default Selects all results which match every predicate in the + * {@link #filters} array. + */ this.filterFunc = function (items) { let self = this; @@ -83,6 +121,10 @@ function CompletionContext(editor, name, offset) //{{{ reduce(function (res, filter) res.filter(function (item) filter.call(self, item)), items); } + /** + * @property {Array} An array of predicates on which to filter the + * results. + */ this.filters = [function (item) { let text = Array.concat(this.getKey(item, "text")); for (let [i, str] in Iterator(text)) @@ -95,22 +137,73 @@ function CompletionContext(editor, name, offset) //{{{ } return false; }]; + /** + * @property {boolean} Specifies whether this context results must + * match the filter at the begining of the string. + * @default true + */ this.anchored = true; + /** + * @property {Object} A map of all contexts, keyed on their names. + * Names are assigned when a context is forked, with its specified + * name appended, after a '/', to its parent's name. + */ this.contexts = { name: this }; + /** + * @property {Object} A mapping of keys, for {@link #getKey}. Given + * { key: value }, getKey(item, key) will return values as such: + * if value is a string, it will return item.item[value]. If it's a + * function, it will return value(item.item). + */ this.keys = { text: 0, description: 1, icon: "icon" }; + /** + * @property {number} This context's offset from the begining of + * {@link #editor}'s value. + */ this.offset = offset || 0; + /** + * @property {function} A function which is called when any subcontext + * changes its completion list. Only called when + * {@link #updateAsync} is true. + */ this.onUpdate = function () true; + /** + * @property {CompletionContext} The top-level completion context. + */ 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.reset(); } + /** + * @property {Object} A general-purpose store for functions which need to + * cache data between calls. + */ this.cache = {}; + /** + * @private + * @property {Object} A cache for return values of {@link #generate}. + */ this.itemCache = {}; + /** + * @property {string} A key detailing when the cached value of + * {@link #generate} may be used. Every call to + * {@link #generate} stores its result in {@link #itemCache}. + * When itemCache[key] exists, its value is returned, and + * {@link #generate} is not called again. + */ this.key = ""; + /** + * @property {string} A message to be shown before any results. + */ this.message = null; this.name = name || ""; + /** @private */ this._completions = []; // FIXME + /** + * Returns a key, as detailed in {@link #keys}. + * @function + */ this.getKey = function (item, key) (typeof self.keys[key] == "function") ? self.keys[key].call(this, item.item) : key in self.keys ? item.item[self.keys[key]] : item.item[key]; @@ -118,6 +211,14 @@ function CompletionContext(editor, name, offset) //{{{ CompletionContext.prototype = { // Temporary + /** + * @property {Object} + * + * An object describing the results from all sub-contexts. Results are + * adjusted so that all have the same starting offset. + * + * @deprecated + */ get allItems() { try @@ -372,6 +473,19 @@ CompletionContext.prototype = { return this._substrings = substrings; }, + /** + * Advances the context count characters. {@link #filter} is + * advanced to match. If {@link #quote} is non-null, its prefix and suffix + * are set to the null-string. + * + * This function is still imperfect for quoted strings. When + * {@link #quote} is non-null, it adjusts the count based on the quoted + * size of the count-character substring of the filter, which is + * accurate so long as unquoting and quoting a string will always map to + * the original quoted string, which is often not the case. + * + * @param {number} count The number of characters to advance the context. + */ advance: function advance(count) { delete this._ignoreCase; @@ -386,6 +500,12 @@ CompletionContext.prototype = { this._filter = this._filter.substr(count); }, + /** + * Gets a key from {@link #cache}, setting it to defVal if it + * doesn't already exists. + * @param {string} key + * @param defVal + */ getCache: function (key, defVal) { if (!(key in this.cache)) @@ -511,6 +631,13 @@ CompletionContext.prototype = { } }, + /** + * Wait for all subcontexts to complete. + * + * @param {boolean} interruptable When true, the call may be interrupted + * via . In this case, "Interrupted" may be thrown. + * @param {number} timeout The maximum time, in milliseconds, to wait. + */ wait: function wait(interruptable, timeout) { let end = Date.now() + timeout; From 194aaf46ebc0b64f4de2744f2af866cd9efeae21 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 19:07:17 +1100 Subject: [PATCH 05/26] brace formatting fixes --- common/content/commands.js | 3 ++- common/content/completion.js | 3 ++- common/content/hints.js | 6 ++++-- common/content/mappings.js | 3 ++- common/content/modes.js | 5 +++-- common/content/style.js | 6 ++++-- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/common/content/commands.js b/common/content/commands.js index 67540eb9..73beca92 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -792,7 +792,8 @@ function Commands() //{{{ argCount: nargsOpt, bang: bangOpt, count: countOpt, - completer: function (context, args) { + completer: function (context, args) + { if (completeFunc) return completeFunc(context, args) }, diff --git a/common/content/completion.js b/common/content/completion.js index 1ce28900..f9ddee03 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -1552,7 +1552,8 @@ function Completion() //{{{ }); completionService.stopSearch(); completionService.startSearch(context.filter, "", context.result, { - onSearchResult: function onSearchResult(search, result) { + onSearchResult: function onSearchResult(search, result) + { context.result = result; timer.tell(result); if (result.searchResult <= result.RESULT_SUCCESS) diff --git a/common/content/hints.js b/common/content/hints.js index ca55ac9a..55e8f043 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -581,12 +581,14 @@ function Hints() //{{{ mappings.add(myModes, [";"], "Start an extended hint mode", - function (count) { + function (count) + { extendedhintCount = count; commandline.input(";", function (arg) { setTimeout(function () hints.show(arg), 0) }, { promptHighlight: "Normal", - completer: function (context) { + completer: function (context) + { context.compare = function () 0; context.completions = [[k, v.prompt] for ([k, v] in Iterator(hintModes))]; }, diff --git a/common/content/mappings.js b/common/content/mappings.js index 13bb318a..7e35b115 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -190,7 +190,8 @@ function Mappings() //{{{ [["", ""], commands.OPTION_NOARG] ], literal: 1, - serial: function () { + serial: function () + { let noremap = this.name.indexOf("noremap") > -1; return [ { diff --git a/common/content/modes.js b/common/content/modes.js index b016048b..0159dd24 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -125,7 +125,7 @@ const modes = (function () //{{{ /////////////////////////////////////////////////////////////////////////////{{{ var self = { - NONE: 0, + NONE: 0, __iterator__: function () util.Array.iterator(this.all), @@ -133,7 +133,8 @@ const modes = (function () //{{{ get inputMode() main & (this.COMMAND_LINE | this.INPUT | this.TEXTAREA | this.COMPOSE), - addMode: function (name, extended, display) { + addMode: function (name, extended, display) + { let disp = name.replace("_", " ", "g"); this[name] = 1 << lastMode++; modeMap[name] = modeMap[this[name]] = { diff --git a/common/content/style.js b/common/content/style.js index ea4b5533..ca9f0f1c 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -504,7 +504,8 @@ liberator.registerObserver("load_commands", function () }, { bang: true, - completer: function (context, args) { + completer: function (context, args) + { let compl = []; if (args.completeArg == 0) { @@ -541,7 +542,8 @@ liberator.registerObserver("load_commands", function () commands.add(["dels[tyle]"], "Remove a user stylesheet", - function (args) { + function (args) + { styles.removeSheet(args["-name"], args[0], args.literalArg, args["-index"], false); }, { From 1ff25093c091b7888bac9f8ff5fd4e13fedc7769 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 19:12:55 +1100 Subject: [PATCH 06/26] whitespace fix --- common/content/events.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/content/events.js b/common/content/events.js index 401244ba..0007de2f 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -242,8 +242,8 @@ function AutoCommands() //{{{ liberator.echomsg("Executing " + event + " Auto commands for \"*\"", 8); let lastPattern = null; - let url = args.url || ""; + for (let [,autoCmd] in Iterator(autoCmds)) { if (autoCmd.pattern.test(url)) @@ -252,22 +252,24 @@ function AutoCommands() //{{{ liberator.echomsg("Executing " + event + " Auto commands for \"" + autoCmd.pattern.source + "\"", 8); lastPattern = autoCmd.pattern; - liberator.echomsg("autocommand " + autoCmd.command, 9); + if (typeof autoCmd.command == "function") { try { autoCmd.command.call(autoCmd, args); } - catch(e) + catch (e) { liberator.reportError(e); liberator.echoerr(e); } } else + { liberator.execute(commands.replaceTokens(autoCmd.command, args)); + } } } } From 0827c5fdaa23cbf81d6f635162c4bbd3524703cf Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 19:13:34 +1100 Subject: [PATCH 07/26] prefer let over var in liberator --- common/content/liberator.js | 85 +++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/common/content/liberator.js b/common/content/liberator.js index 73c1d445..8c49505c 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -71,7 +71,7 @@ const liberator = (function () //{{{ let nError = 0; function loadModule(name, func) { - var message = "Loading module " + name + "..."; + let message = "Loading module " + name + "..."; try { liberator.log(message, 0); @@ -228,21 +228,23 @@ const liberator = (function () //{{{ "Open a " + config.name + " dialog", function (args) { - args = args[0]; + let arg = args[0]; try { - var dialogs = config.dialogs; + let dialogs = config.dialogs; + for (let i = 0; i < dialogs.length; i++) { - if (dialogs[i][0] == args) + if (dialogs[i][0] == arg) return dialogs[i][2](); } - liberator.echoerr(args ? "Dialog " + args.quote() + " not available" : "E474: Invalid argument"); + + liberator.echoerr("E475: Invalid argument: " + arg); } catch (e) { - liberator.echoerr("Error opening '" + args + "': " + e); + liberator.echoerr("Error opening '" + arg + "': " + e); } }, { @@ -321,7 +323,7 @@ const liberator = (function () //{{{ { try { - var cmd = liberator.eval(args.string); + let cmd = liberator.eval(args.string); liberator.execute(cmd); } catch (e) @@ -491,13 +493,13 @@ const liberator = (function () //{{{ } else { - var beforeTime = Date.now(); + let beforeTime = Date.now(); method(); if (special) return; - var afterTime = Date.now(); + let afterTime = Date.now(); if (afterTime - beforeTime >= 100) liberator.echo("Total time: " + ((afterTime - beforeTime) / 1000.0).toFixed(2) + " sec"); @@ -551,7 +553,7 @@ const liberator = (function () //{{{ // similar in his config function hideGUI() { - var guioptions = config.guioptions; + let guioptions = config.guioptions; for (let option in guioptions) { guioptions[option].forEach(function (elem) { @@ -629,7 +631,7 @@ const liberator = (function () //{{{ // liberator.dump("type: " + type + " mode: " + mode + "data: " + data + "\n"); for (let i = 0; i < callbacks.length; i++) { - var [thistype, thismode, thisfunc] = callbacks[i]; + let [thistype, thismode, thisfunc] = callbacks[i]; if (mode == thismode && type == thistype) return thisfunc.call(this, data); } @@ -803,19 +805,24 @@ const liberator = (function () //{{{ evalExpression: function (string) { string = string.toString().replace(/^\s*/, "").replace(/\s*$/, ""); - var matches = string.match(/^&(\w+)/); + let matches = string.match(/^&(\w+)/); + if (matches) { - var opt = this.options.get(matches[1]); + let opt = this.options.get(matches[1]); + if (!opt) { this.echoerr("E113: Unknown option: " + matches[1]); return; } - var type = opt.type; - var value = opt.getter(); + + let type = opt.type; + let value = opt.getter(); + if (type != "boolean" && type != "number") value = value.toString(); + return value; } @@ -823,7 +830,9 @@ const liberator = (function () //{{{ else if (matches = string.match(/^(['"])([^\1]*?[^\\]?)\1/)) { if (matches) + { return matches[2].toString(); + } else { this.echoerr("E115: Missing quote: " + string); @@ -837,7 +846,8 @@ const liberator = (function () //{{{ return parseInt(match[1], 10); } - var reference = this.variableReference(string); + let reference = this.variableReference(string); + if (!reference[0]) this.echoerr("E121: Undefined variable: " + string); else @@ -929,12 +939,12 @@ const liberator = (function () //{{{ help: function (topic) { - var where = (options["newtab"] && options.get("newtab").has("all", "help")) + let where = (options["newtab"] && options.get("newtab").has("all", "help")) ? liberator.NEW_TAB : liberator.CURRENT_TAB; if (!topic) { - var helpFile = options["helpfile"]; + let helpFile = options["helpfile"]; if (config.helpFiles.indexOf(helpFile) != -1) liberator.open("chrome://liberator/locale/" + helpFile, where); @@ -957,8 +967,8 @@ const liberator = (function () //{{{ }, 500); } - var items = completion.runCompleter("help", topic); - var partialMatch = -1; + let items = completion.runCompleter("help", topic); + let partialMatch = -1; for (let [i, item] in Iterator(items)) { @@ -1032,8 +1042,8 @@ const liberator = (function () //{{{ // TODO: add proper level constants log: function (msg, level) { - var verbose = 0; - if (typeof level != "number") // XXX + let verbose = 0; + if (level == undefined) level = 1; // options does not exist at the very beginning @@ -1046,7 +1056,7 @@ const liberator = (function () //{{{ if (typeof msg == "object") msg = util.objectToString(msg, false); - var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); + const consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); consoleService.logStringMessage(config.name.toLowerCase() + ": " + msg); }, @@ -1183,8 +1193,8 @@ const liberator = (function () //{{{ const nsIAppStartup = Ci.nsIAppStartup; // notify all windows that an application quit has been requested. - var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); - var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); + const os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + const cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool); os.notifyObservers(cancelQuit, "quit-application-requested", null); // something aborted the quit process. @@ -1195,17 +1205,16 @@ const liberator = (function () //{{{ os.notifyObservers(null, "quit-application-granted", null); // enumerate all windows and call shutdown handlers - var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); - var windows = wm.getEnumerator(null); + const wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); + let windows = wm.getEnumerator(null); while (windows.hasMoreElements()) { - var win = windows.getNext(); + let win = windows.getNext(); if (("tryToClose" in win) && !win.tryToClose()) return; } - Cc["@mozilla.org/toolkit/app-startup;1"] - .getService(nsIAppStartup) - .quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit); + Cc["@mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup) + .quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit); }, // TODO: move to {muttator,vimperator,...}.js @@ -1357,7 +1366,7 @@ const liberator = (function () //{{{ if (!string) return [null, null, null]; - var matches = string.match(/^([bwtglsv]):(\w+)/); + let matches = string.match(/^([bwtglsv]):(\w+)/); if (matches) // Variable { // Other variables should be implemented @@ -1380,12 +1389,14 @@ const liberator = (function () //{{{ get windows() { - var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); - var wa = []; - var enumerator = wm.getEnumerator("navigator:browser"); + const wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator); + let windows = []; + let enumerator = wm.getEnumerator("navigator:browser"); + while (enumerator.hasMoreElements()) - wa.push(enumerator.getNext()); - return wa; + windows.push(enumerator.getNext()); + + return windows; } }; //}}} From d65b23be3dd2051a65aaa9836ad92398ec0db4e3 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 19:14:38 +1100 Subject: [PATCH 08/26] prefer let over var in Hints --- common/content/hints.js | 58 ++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/common/content/hints.js b/common/content/hints.js index 55e8f043..25803f34 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -107,19 +107,19 @@ function Hints() //{{{ if (!win) win = window.content; - var doc = win.document; - var height = win.innerHeight; - var width = win.innerWidth; - var scrollX = doc.defaultView.scrollX; - var scrollY = doc.defaultView.scrollY; + let doc = win.document; + let height = win.innerHeight; + let width = win.innerWidth; + let scrollX = doc.defaultView.scrollX; + let scrollY = doc.defaultView.scrollY; - var baseNodeAbsolute = util.xmlToDom(, doc); + let baseNodeAbsolute = util.xmlToDom(, doc); - var elem, tagname, text, span, rect; - var res = buffer.evaluateXPath(hintMode.tags(), doc, null, true); + let elem, tagname, text, span, rect; + let res = buffer.evaluateXPath(hintMode.tags(), doc, null, true); - var fragment = util.xmlToDom(
, doc); - var start = pageHints.length; + let fragment = util.xmlToDom(
, doc); + let start = pageHints.length; for (let elem in res) { // TODO: for iframes, this calculation is wrong @@ -131,7 +131,7 @@ function Hints() //{{{ if (!rect) continue; - var computedStyle = doc.defaultView.getComputedStyle(elem, null); + let computedStyle = doc.defaultView.getComputedStyle(elem, null); if (computedStyle.getPropertyValue("visibility") != "visible" || computedStyle.getPropertyValue("display") == "none") continue; @@ -171,11 +171,11 @@ function Hints() //{{{ // TODO: make it aware of imgspans function showActiveHint(newID, oldID) { - var oldElem = validHints[oldID - 1]; + let oldElem = validHints[oldID - 1]; if (oldElem) setClass(oldElem, false); - var newElem = validHints[newID - 1]; + let newElem = validHints[newID - 1]; if (newElem) setClass(newElem, true); } @@ -274,7 +274,7 @@ function Hints() //{{{ function removeHints(timeout) { - var firstElem = validHints[0] || null; + let firstElem = validHints[0] || null; for (let [,{ doc: doc, start: start, end: end }] in Iterator(docs)) { @@ -329,9 +329,9 @@ function Hints() //{{{ } } - var timeout = followFirst || events.feedingKeys ? 0 : 500; - var activeIndex = (hintNumber ? hintNumber - 1 : 0); - var elem = validHints[activeIndex]; + let timeout = followFirst || events.feedingKeys ? 0 : 500; + let activeIndex = (hintNumber ? hintNumber - 1 : 0); + let elem = validHints[activeIndex]; removeHints(timeout); if (timeout == 0) @@ -369,7 +369,7 @@ function Hints() //{{{ function tokenize(pat, string) string.split(pat).map(String.toLowerCase); function containsMatcher(hintString) //{{{ { - var tokens = tokenize(/\s+/, hintString); + let tokens = tokenize(/\s+/, hintString); return function (linkText) { linkText = linkText.toLowerCase(); @@ -379,14 +379,14 @@ function Hints() //{{{ function wordStartsWithMatcher(hintString, allowWordOverleaping) //{{{ { - var hintStrings = tokenize(/\s+/, hintString); - var wordSplitRegex = RegExp(options["wordseparators"]); + let hintStrings = tokenize(/\s+/, hintString); + let wordSplitRegex = RegExp(options["wordseparators"]); // What the **** does this do? --Kris function charsAtBeginningOfWords(chars, words, allowWordOverleaping) { - var charIdx = 0; - var numMatchedWords = 0; + let charIdx = 0; + let numMatchedWords = 0; for (let [,word] in Iterator(words)) { if (word.length == 0) @@ -414,7 +414,7 @@ function Hints() //{{{ } // the current word matches same characters as the previous word - var prevCharIdx; + let prevCharIdx; if (wcIdx > 0) { prevCharIdx = charIdx; @@ -468,7 +468,7 @@ function Hints() //{{{ function stringsAtBeginningOfWords(strings, words, allowWordOverleaping) { - var strIdx = 0; + let strIdx = 0; for (let [,word] in Iterator(words)) { if (word.length == 0) @@ -505,7 +505,7 @@ function Hints() //{{{ } } //}}} - var hintMatching = options["hintmatching"]; + let hintMatching = options["hintmatching"]; switch (hintMatching) { case "contains" : return containsMatcher(hintString); @@ -655,8 +655,8 @@ function Hints() //{{{ onEvent: function (event) { - var key = events.toString(event); - var followFirst = false; + let key = events.toString(event); + let followFirst = false; // clear any timeout which might be active after pressing a number if (activeTimeout) @@ -677,7 +677,7 @@ function Hints() //{{{ if (hintNumber == 0) hintNumber = 1; - var oldID = hintNumber; + let oldID = hintNumber; if (key == "") { if (++hintNumber > validHints.length) @@ -721,7 +721,7 @@ function Hints() //{{{ { prevInput = "number"; - var oldHintNumber = hintNumber; + let oldHintNumber = hintNumber; if (hintNumber == 0 || usedTabKey) { usedTabKey = false; From d60c81ef23608e32bfa8c059a29a7deaf6b27473 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:00:14 +1100 Subject: [PATCH 09/26] add missing semicolons --- common/content/commands.js | 8 ++++---- common/content/editor.js | 2 +- common/content/eval.js | 2 +- common/content/events.js | 4 ++-- common/content/find.js | 2 +- common/content/hints.js | 10 +++++----- common/content/io.js | 2 +- common/content/liberator-overlay.js | 2 +- common/content/liberator.js | 2 +- common/content/options.js | 6 +++--- common/content/style.js | 20 ++++++++++---------- common/content/tabs.js | 2 +- vimperator/content/bookmarks.js | 18 ++++++++++++------ vimperator/content/config.js | 2 +- 14 files changed, 44 insertions(+), 38 deletions(-) diff --git a/common/content/commands.js b/common/content/commands.js index 73beca92..75711744 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -120,7 +120,7 @@ Command.prototype = { if (matches && matches[2]) { commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"), - function (args) { exec(matches[1] + "\n" + args) }); + function (args) { exec(matches[1] + "\n" + args); }); return; } } @@ -169,7 +169,7 @@ function Commands() //{{{ const quoteMap = { "\n": "n", "\t": "t" - } + }; function quote(q, list) { let re = RegExp("[" + list + "]", "g"); @@ -184,7 +184,7 @@ function Commands() //{{{ '"': quote('"', '\n\t"\\\\'), "'": quote("'", "\\\\'"), "": quote("", "\\\\ ") - } + }; const ArgType = new Struct("description", "parse"); const argTypes = [ @@ -555,7 +555,7 @@ function Commands() //{{{ if (complete) { if (argCount == "0" || args.length > 0 && (/[1?]/.test(argCount))) - complete.highlight(i, sub.length, "SPELLCHECK") + complete.highlight(i, sub.length, "SPELLCHECK"); } if (args.length == literal) diff --git a/common/content/editor.js b/common/content/editor.js index be1b3aba..6219a4ea 100644 --- a/common/content/editor.js +++ b/common/content/editor.js @@ -857,7 +857,7 @@ function Editor() //{{{ editor.selection.deleteFromDocument(); editor.insertText(val); } - }, this) + }, this); if (res == false) throw "Couldn't create temporary file"; } diff --git a/common/content/eval.js b/common/content/eval.js index 14f5fd95..daf0dba6 100644 --- a/common/content/eval.js +++ b/common/content/eval.js @@ -1,4 +1,4 @@ -try { __liberator_eval_result = eval(__liberator_eval_string) +try { __liberator_eval_result = eval(__liberator_eval_string); } catch (e) { diff --git a/common/content/events.js b/common/content/events.js index 0007de2f..4c1d9f8c 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -689,7 +689,7 @@ function Events() //{{{ commands.add(["macros"], "List all macros", - function (args) { completion.listCompleter("macro", args[0]) }, + function (args) { completion.listCompleter("macro", args[0]); }, { argCount: "?", completer: function (context) completion.macro(context) @@ -1283,7 +1283,7 @@ function Events() //{{{ { events.feedingKeys = false; if (lastMacro) - setTimeout(function () { liberator.echomsg("Canceled playback of macro '" + lastMacro + "'") }, 100); + setTimeout(function () { liberator.echomsg("Canceled playback of macro '" + lastMacro + "'"); }, 100); event.preventDefault(); event.stopPropagation(); return true; diff --git a/common/content/find.js b/common/content/find.js index 794476ac..41b15599 100644 --- a/common/content/find.js +++ b/common/content/find.js @@ -176,7 +176,7 @@ function Search() //{{{ return; } - var baseNode = + var baseNode = ; baseNode = util.xmlToDom(baseNode, window.content.document); var body = doc.body; diff --git a/common/content/hints.js b/common/content/hints.js index 25803f34..90c7e14f 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -237,7 +237,7 @@ function Hints() //{{{ hint[IMGSPAN] = imgspan; span.parentNode.appendChild(imgspan); } - setClass(imgspan, activeHint == hintnum) + setClass(imgspan, activeHint == hintnum); } span.setAttribute("number", hintnum); @@ -289,7 +289,7 @@ function Hints() //{{{ // animate the disappearance of the first hint if (timeout && firstElem) - setTimeout(function () { firstElem.removeAttributeNS(NS.uri, "highlight") }, timeout); + setTimeout(function () { firstElem.removeAttributeNS(NS.uri, "highlight"); }, timeout); } styles.removeSheet("hint-positions", null, null, null, true); @@ -374,7 +374,7 @@ function Hints() //{{{ { linkText = linkText.toLowerCase(); return tokens.every(function (token) linkText.indexOf(token) >= 0); - } + }; } //}}} function wordStartsWithMatcher(hintString, allowWordOverleaping) //{{{ @@ -502,7 +502,7 @@ function Hints() //{{{ return charsAtBeginningOfWords(hintStrings[0], words, allowWordOverleaping); else return stringsAtBeginningOfWords(hintStrings, words, allowWordOverleaping); - } + }; } //}}} let hintMatching = options["hintmatching"]; @@ -584,7 +584,7 @@ function Hints() //{{{ function (count) { extendedhintCount = count; - commandline.input(";", function (arg) { setTimeout(function () hints.show(arg), 0) }, + commandline.input(";", function (arg) { setTimeout(function () hints.show(arg), 0); }, { promptHighlight: "Normal", completer: function (context) diff --git a/common/content/io.js b/common/content/io.js index fd111d52..8a5e3d97 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -30,7 +30,7 @@ the terms of any one of the MPL, the GPL or the LGPL. plugins.contexts = {}; function Script(file) { - let self = plugins.contexts[file.path] + let self = plugins.contexts[file.path]; if (self) { if (self.onUnload) diff --git a/common/content/liberator-overlay.js b/common/content/liberator-overlay.js index 288559e2..9b0df22b 100644 --- a/common/content/liberator-overlay.js +++ b/common/content/liberator-overlay.js @@ -13,7 +13,7 @@ { try { - loader.loadSubScript(base + script, modules) + loader.loadSubScript(base + script, modules); return; } catch (e) diff --git a/common/content/liberator.js b/common/content/liberator.js index 8c49505c..373a22d1 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -109,7 +109,7 @@ const liberator = (function () //{{{ .forEach(function (elem) { if (elem) - elem.collapsed = (opts.indexOf(opt) == -1) + elem.collapsed = (opts.indexOf(opt) == -1); }); } } diff --git a/common/content/options.js b/common/content/options.js index 460490bb..6373dcb6 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -73,7 +73,7 @@ function Option(names, description, type, defaultValue, extraInfo) //{{{ } Option.prototype = { get globalvalue() options.store.get(this.name), - set globalvalue(val) { options.store.set(this.name, val) }, + set globalvalue(val) { options.store.set(this.name, val); }, parseValues: function (value) { @@ -164,8 +164,8 @@ Option.prototype = { 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)) + // return whether some argument matches + return Array.some(arguments, function (val) test(val)); }, hasName: function (name) this.names.indexOf(name) >= 0, diff --git a/common/content/style.js b/common/content/style.js index ca9f0f1c..62c14ef2 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -166,7 +166,7 @@ function Highlights(name, store, serial) return error; style.value = newStyle; highlight[style.class] = style; - } + }; this.selector = function (class) { @@ -200,7 +200,7 @@ function Highlights(name, store, serial) if (hl.value == hl.default) this.set(class); } - } + }; } function Styles(name, store, serial) @@ -264,7 +264,7 @@ function Styles(name, store, serial) names[name] = sheet; } return null; - } + }; this.findSheets = function (name, filter, css, index, system) { @@ -324,7 +324,7 @@ function Styles(name, store, serial) } } return matches.length; - } + }; this.registerSheet = function (uri, doCheckSyntax, reload) { @@ -336,14 +336,14 @@ function Styles(name, store, serial) uri = ios.newURI(uri, null, null); if (reload || !sss.sheetRegistered(uri, sss.USER_SHEET)) sss.loadAndRegisterSheet(uri, sss.USER_SHEET); - } + }; this.unregisterSheet = function (uri) { uri = ios.newURI(uri, null, null); if (sss.sheetRegistered(uri, sss.USER_SHEET)) sss.unregisterSheet(uri, sss.USER_SHEET); - } + }; // FIXME this.registerAgentSheet = function (uri) @@ -351,14 +351,14 @@ function Styles(name, store, serial) this.unregisterAgentSheet(uri); uri = ios.newURI(uri, null, null); sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET); - } + }; this.unregisterAgentSheet = function (uri) { uri = ios.newURI(uri, null, null); if (sss.sheetRegistered(uri, sss.AGENT_SHEET)) sss.unregisterSheet(uri, sss.AGENT_SHEET); - } + }; function wrapCSS(sheet) { @@ -425,7 +425,7 @@ function Styles(name, store, serial) if (errors.length) { let err = new Error("", errors[0].sourceName.replace(/^(chrome-data:text\/css,).*/, "$1..."), errors[0].lineNumber); - err.name = "CSSError" + err.name = "CSSError"; err.message = errors.reduce(function (msg, e) msg + "; " + e.lineNumber + ": " + e.errorMessage, errors.shift().errorMessage); err.echoerr = err.fileName + ":" + err.lineNumber + ": " + err.message; @@ -516,7 +516,7 @@ liberator.registerObserver("load_commands", function () } catch (e) {} context.anchored = false; - context.completions = compl.concat([[s, ""] for each (s in styles.sites)]) + context.completions = compl.concat([[s, ""] for each (s in styles.sites)]); } else if (args.completeArg == 1) { diff --git a/common/content/tabs.js b/common/content/tabs.js index 6fee2043..6cec525d 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -598,7 +598,7 @@ function Tabs() //{{{ function (args) { let count = args.count; - args = args[0] + args = args[0]; if (count < 1) count = 1; diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index 9dd6e9b1..8acac9f7 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -238,7 +238,7 @@ function Bookmarks() //{{{ var cache = storage.newObject("bookmark-cache", Cache, false); storage.addObserver("bookmark-cache", bookmarkObserver); liberator.registerObserver("shutdown", function () { - storage.removeObserver("bookmark-cache", bookmarkObserver) + storage.removeObserver("bookmark-cache", bookmarkObserver); }); liberator.registerObserver("enter", function () { @@ -358,7 +358,7 @@ function Bookmarks() //{{{ if (!args.bang) { context.completions = [[content.document.documentURI, "Current Location"]]; - return + return; } completion.bookmark(context, args["-tags"], { keyword: args["-keyword"], title: args["-title"] }); }, @@ -784,7 +784,7 @@ function History() //{{{ function (args) { history.list(args.join(" "), args.bang, args["-max"] || 1000); }, { bang: true, - completer: function (context) { context.quote = null, completion.history(context) }, + completer: function (context) { context.quote = null, completion.history(context); }, options: [[["-max", "-m"], options.OPTION_INT]] // completer: function (filter) completion.history(filter) }); @@ -823,7 +823,7 @@ function History() //{{{ url: node.uri, title: node.title, icon: node.icon ? node.icon.spec : DEFAULT_FAVICON - } + }; }); root.containerOpen = false; // close a container after using it! @@ -844,7 +844,10 @@ function History() //{{{ { let index = window.getWebNavigation().sessionHistory.index; if (index == 0) - return liberator.beep(); // really wanted? + { + liberator.beep(); // XXX: really wanted? + return; + } window.getWebNavigation().gotoIndex(0); }, @@ -853,7 +856,10 @@ function History() //{{{ { let index = window.getWebNavigation().sessionHistory.index; if (index == window.getWebNavigation().sessionHistory.count - 1) - return liberator.beep(); + { + liberator.beep(); + return; + } window.getWebNavigation().gotoIndex(max); }, diff --git a/vimperator/content/config.js b/vimperator/content/config.js index a11c8e2c..cc353a28 100644 --- a/vimperator/content/config.js +++ b/vimperator/content/config.js @@ -171,7 +171,7 @@ const config = { //{{{ + "}", true); delete img; - } + }; //////////////////////////////////////////////////////////////////////////////// ////////////////////// MAPPINGS //////////////////////////////////////////////// From 4b896f37069d68d99d3eac96a684d49ac5266c32 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:09:37 +1100 Subject: [PATCH 10/26] remove some ancient cruft --- common/content/events.js | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/common/content/events.js b/common/content/events.js index 4c1d9f8c..c477cb80 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -1339,25 +1339,7 @@ function Events() //{{{ return false; } - // // FIXME: handle middle click in content area {{{ - // // alert(event.target.id); - // if (/*event.type == 'mousedown' && */event.button == 1 && event.target.id == 'content') - // { - // //echo("foo " + event.target.id); - // //if (document.commandDispatcher.focusedElement == command_line.inputField) - // { - // //alert(command_line.value.substring(0, command_line.selectionStart)); - // command_line.value = command_line.value.substring(0, command_line.selectionStart) + - // window.readFromClipboard() + - // command_line.value.substring(command_line.selectionEnd, command_line.value.length); - // alert(command_line.value); - // } - // //else - // // { - // // openURLs(window.readFromClipboard()); - // // } - // return true; - // } }}} + // TODO: handle middle click in content area if (key != "" && key != "") { From 92f9fcfc8d2f4d11426fa6c0a358f516bf9b7c4a Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:12:06 +1100 Subject: [PATCH 11/26] declare variable in getMenuItems#addChildren() --- common/content/liberator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/content/liberator.js b/common/content/liberator.js index 373a22d1..89893b95 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -268,7 +268,7 @@ const liberator = (function () //{{{ } else { - path = parent; + let path = parent; if (item.localName == "menu") path += item.label + "."; addChildren(item, path); From 695b3ed9eae30476e410cbfd7df56a2048a08b9c Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:17:52 +1100 Subject: [PATCH 12/26] minor refactoring of "b" action --- common/content/tabs.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/content/tabs.js b/common/content/tabs.js index 6cec525d..4e8512f2 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -252,8 +252,9 @@ function Tabs() //{{{ function (count) { if (count != -1) - return tabs.switchTo(String(count)); - commandline.open(":", "buffer! ", modes.EX); + tabs.switchTo(String(count)); + else + commandline.open(":", "buffer! ", modes.EX); }, { flags: Mappings.flags.COUNT }); From 7bba6004d989e27d81b71047919c218f27ceec31 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:24:31 +1100 Subject: [PATCH 13/26] minor refactoring of :dialog action --- common/content/liberator.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/common/content/liberator.js b/common/content/liberator.js index 89893b95..82d28f6d 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -232,12 +232,16 @@ const liberator = (function () //{{{ try { + // TODO: why are these sorts of properties arrays? --djk let dialogs = config.dialogs; - for (let i = 0; i < dialogs.length; i++) + for (let [,dialog] in Iterator(dialogs)) { - if (dialogs[i][0] == arg) - return dialogs[i][2](); + if (arg == dialog[0]) + { + dialog[2](); + return; + } } liberator.echoerr("E475: Invalid argument: " + arg); From 3801efb9add2d39284b50a5fa47056a9e0fc0888 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:50:12 +1100 Subject: [PATCH 14/26] minor refactoring of :command action --- common/content/commands.js | 42 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/common/content/commands.js b/common/content/commands.js index 75711744..7486d344 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -759,19 +759,20 @@ function Commands() //{{{ { if (/^custom,/.test(completeOpt)) { + completeOpt = completeOpt.substr(7); completeFunc = function () { try { - var completer = liberator.eval(completeOpt.substr(7)); + var completer = liberator.eval(completeOpt); if (!(completer instanceof Function)) - throw new TypeError("User-defined custom completer '" + completeOpt.substr(7) + "' is not a function"); + throw new TypeError("User-defined custom completer '" + completeOpt + "' is not a function"); } catch (e) { // FIXME: should be pushed to the MOW - liberator.echoerr("E117: Unknown function: " + completeOpt.substr(7)); + liberator.echoerr("E117: Unknown function: " + completeOpt); liberator.log(e); return undefined; } @@ -784,26 +785,23 @@ function Commands() //{{{ } } - if (!commands.addUserCommand( - [cmd], - "User defined command", - userCommand, - { - argCount: nargsOpt, - bang: bangOpt, - count: countOpt, - completer: function (context, args) - { - if (completeFunc) - return completeFunc(context, args) - }, - replacementText: args.literalArg - }, - args.bang) - ) - { + let added = commands.addUserCommand([cmd], + "User defined command", + userCommand, + { + argCount: nargsOpt, + bang: bangOpt, + count: countOpt, + completer: function (context, args) + { + if (completeFunc) + return completeFunc(context, args) + }, + replacementText: args.literalArg + }, args.bang); + + if (!added) liberator.echoerr("E174: Command already exists: add ! to replace it"); - } } else { From b98b3677769d4d7ee8328cb18b234459c37b5ded Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Fri, 19 Dec 2008 23:59:25 +1100 Subject: [PATCH 15/26] trivial refactoring of :emenu and :chdir actions --- common/content/io.js | 20 ++++++++++---------- common/content/liberator.js | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/common/content/io.js b/common/content/io.js index 8a5e3d97..136b2b13 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -194,17 +194,17 @@ function IO() //{{{ "Change the current directory", function (args) { - args = args.literalArg; + let arg = args.literalArg; - if (!args) + if (!arg) { - args = "~"; + arg = "~"; } - else if (args == "-") + else if (arg == "-") { if (oldcwd) { - args = oldcwd.path; + arg = oldcwd.path; } else { @@ -213,14 +213,14 @@ function IO() //{{{ } } - args = io.expandPath(args); + arg = io.expandPath(arg); // go directly to an absolute path or look for a relative path // match in 'cdpath' // TODO: handle ../ and ./ paths - if (isAbsolutePath(args)) + if (isAbsolutePath(arg)) { - if (io.setCurrentDirectory(args)) + if (io.setCurrentDirectory(arg)) liberator.echomsg(io.getCurrentDirectory().path); } else @@ -230,7 +230,7 @@ function IO() //{{{ for (let [,dir] in Iterator(dirs)) { - dir = joinPaths(dir, args); + dir = joinPaths(dir, arg); if (dir.exists() && dir.isDirectory() && dir.isReadable()) { @@ -243,7 +243,7 @@ function IO() //{{{ if (!found) { - liberator.echoerr("E344: Can't find directory " + args.quote() + " in cdpath\n" + liberator.echoerr("E344: Can't find directory " + arg.quote() + " in cdpath\n" + "E472: Command failed"); } } diff --git a/common/content/liberator.js b/common/content/liberator.js index 82d28f6d..54780d85 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -289,18 +289,18 @@ const liberator = (function () //{{{ "Execute the specified menu item from the command line", function (args) { - args = args.literalArg; + let arg = args.literalArg; let items = getMenuItems(); - if (!items.some(function (i) i.fullMenuPath == args)) + if (!items.some(function (i) i.fullMenuPath == arg)) { - liberator.echoerr("E334: Menu not found: " + args); + liberator.echoerr("E334: Menu not found: " + arg); return; } for (let [,item] in Iterator(items)) { - if (item.fullMenuPath == args) + if (item.fullMenuPath == arg) item.doCommand(); } }, From ad61bc83ff54dc80e2b36bed211e7b8bdd0e3327 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sat, 20 Dec 2008 00:15:13 +1100 Subject: [PATCH 16/26] fix transposed defaults in showmode and shell help --- vimperator/locale/en-US/options.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vimperator/locale/en-US/options.txt b/vimperator/locale/en-US/options.txt index 71056576..2d017a69 100644 --- a/vimperator/locale/en-US/options.txt +++ b/vimperator/locale/en-US/options.txt @@ -614,7 +614,7 @@ ____ |\'shell'| |\'sh'| -||'shell' 'sh'|| string (default: on) +||'shell' 'sh'|| string (default: "-c", Win32: "/c") ____ Shell to use for executing :! and :run commands. ____ @@ -630,7 +630,7 @@ ____ |\'nosmd'| |\'noshowmode'| |\'smd'| |\'showmode'| -||'showmode' 'smd'|| boolean (default: "-c", Win32: "/c") +||'showmode' 'smd'|| boolean (default: on) ____ Show the current mode in the command-line. ____ From 03fed06b39c36357858f1b45f7b9e51d6f838ce7 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sat, 20 Dec 2008 00:31:13 +1100 Subject: [PATCH 17/26] fix search highlighting when 'incsearch' is set - Algardas --- common/content/find.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/content/find.js b/common/content/find.js index 41b15599..923426f5 100644 --- a/common/content/find.js +++ b/common/content/find.js @@ -408,11 +408,10 @@ function Search() //{{{ if (!command) command = lastSearchPattern; + this.clear(); + if (!options["incsearch"] || !found) - { - this.clear(); this.find(command, backwards); - } lastSearchBackwards = backwards; //lastSearchPattern = command.replace(backwards ? /\?.*/ : /\/.*/, ""); // XXX From 86f14b77ccb127678c0743c3483175c15e901467 Mon Sep 17 00:00:00 2001 From: Doug Kearns Date: Sat, 20 Dec 2008 01:08:24 +1100 Subject: [PATCH 18/26] document :hardcopy >{filename}...since it was committed --- common/content/buffer.js | 18 +++++++++++------- vimperator/NEWS | 1 + vimperator/locale/en-US/print.txt | 6 ++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/common/content/buffer.js b/common/content/buffer.js index 66f15316..23989362 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -467,14 +467,18 @@ function Buffer() //{{{ "Print current document", function (args) { + let arg = args[0]; + + // FIXME: arg handling is a bit of a mess, check for filename + if (arg && (liberator.has("Win32") || arg[0] != ">")) + return liberator.echoerr("E488: Trailing characters"); + options.temporaryContext(function () { - if (args[0]) + if (arg) { - if (args[0][0] != ">") - return liberator.echoerr("E488: Trailing characters"); options.setPref("print.print_to_file", "true"); - options.setPref("print.print_to_filename", io.getFile(args[0].substr(1)).path); - liberator.echomsg("Printing to file: " + args[0].substr(1)); + options.setPref("print.print_to_filename", io.getFile(arg.substr(1)).path); + liberator.echomsg("Printing to file: " + arg.substr(1)); } else { @@ -487,8 +491,8 @@ function Buffer() //{{{ getBrowser().contentWindow.print(); }); - if (args[0]) - liberator.echomsg("Printed: " + args[0].substr(1)); + if (arg) + liberator.echomsg("Printed: " + arg.substr(1)); else liberator.echomsg("Print job sent."); }, diff --git a/vimperator/NEWS b/vimperator/NEWS index c850ec2b..f982feda 100644 --- a/vimperator/NEWS +++ b/vimperator/NEWS @@ -21,6 +21,7 @@ VimperatorLeave respectively * IMPORTANT: 'verbose' is now by default at 1, set to 0 to not show any status messages + * :hardcopy now supports output redirection to a file on Unix and MacUnix * add ";f" extended hint mode to focus a frame * add "r", "l", and "b" to 'guioptions' to toggle the scrollbars. * remove spaces and newlines when open urls starting with http:// or similar diff --git a/vimperator/locale/en-US/print.txt b/vimperator/locale/en-US/print.txt index aad69e18..397f9dbb 100644 --- a/vimperator/locale/en-US/print.txt +++ b/vimperator/locale/en-US/print.txt @@ -10,6 +10,12 @@ number of copies, orientation, etc. When used with [!], the dialog is skipped and the default printer used. ________________________________________________________________________________ + +||:ha[rdcopy][!] >{filename}|| + +________________________________________________________________________________ +As above, but write the output to {filename}. +________________________________________________________________________________ + section:Firefox{nbsp}printing{nbsp}dialogs[firefox-print-dialogs] The "Print Preview" and "Page Setup" dialogs can be opened via the :dialog command From 993ba60ee7f982ff2d69b10fbd86748c54b6b0ae Mon Sep 17 00:00:00 2001 From: Ted Pavlic Date: Fri, 19 Dec 2008 10:49:56 -0500 Subject: [PATCH 19/26] Allow empty defsearch. --- common/content/completion.js | 2 +- vimperator/content/bookmarks.js | 7 +++++++ vimperator/locale/en-US/options.txt | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/common/content/completion.js b/common/content/completion.js index f9ddee03..f7594214 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -1645,7 +1645,7 @@ function Completion() //{{{ let engines = bookmarks.getSearchEngines(); context.title = ["Search Keywords"]; - context.completions = keywords.concat(engines); + context.completions = [ bookmarks.makeKeyword("", "No default search engine", null, "") ].concat( keywords.concat(engines) ); context.keys = { text: 0, description: 1, icon: 2 }; if (!space || noSuggest) diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index 8acac9f7..e887a580 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -589,6 +589,13 @@ function Bookmarks() //{{{ return process(resp); }, + // Allows for creation of anonymous keyword (e.g., for empty + // defsearch's) + makeKeyword: function makeKeyword(keyword, title, icon, url) + { + return new Keyword( keyword, title, icon, url ); + }, + // TODO: add filtering // format of returned array: // [keyword, helptext, url] diff --git a/vimperator/locale/en-US/options.txt b/vimperator/locale/en-US/options.txt index 2d017a69..22cdd8c7 100644 --- a/vimperator/locale/en-US/options.txt +++ b/vimperator/locale/en-US/options.txt @@ -247,6 +247,9 @@ This means, it you set 'defsearch' to "youtube", then [c]:open arnold schwarzenegger[c] will be exactly the same as [c]:open youtube arnold schwarzenegger[c]. Therefore, you need to add a keyword or search engine "youtube" first. + +If 'defsearch' is empty, then Firefox will always attempt to open the +raw [[arg]]. ____ From aaab59aab6b014e70adcff79f4a220e3619f5e58 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 12:29:13 -0500 Subject: [PATCH 20/26] Revert "Allow empty defsearch." This reverts commit 3cab7c16a0ef5e39f9aeeb8ea1ed9602a6a152f4. --- common/content/completion.js | 2 +- vimperator/content/bookmarks.js | 7 ------- vimperator/locale/en-US/options.txt | 3 --- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/common/content/completion.js b/common/content/completion.js index f7594214..f9ddee03 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -1645,7 +1645,7 @@ function Completion() //{{{ let engines = bookmarks.getSearchEngines(); context.title = ["Search Keywords"]; - context.completions = [ bookmarks.makeKeyword("", "No default search engine", null, "") ].concat( keywords.concat(engines) ); + context.completions = keywords.concat(engines); context.keys = { text: 0, description: 1, icon: 2 }; if (!space || noSuggest) diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index e887a580..8acac9f7 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -589,13 +589,6 @@ function Bookmarks() //{{{ return process(resp); }, - // Allows for creation of anonymous keyword (e.g., for empty - // defsearch's) - makeKeyword: function makeKeyword(keyword, title, icon, url) - { - return new Keyword( keyword, title, icon, url ); - }, - // TODO: add filtering // format of returned array: // [keyword, helptext, url] diff --git a/vimperator/locale/en-US/options.txt b/vimperator/locale/en-US/options.txt index 22cdd8c7..2d017a69 100644 --- a/vimperator/locale/en-US/options.txt +++ b/vimperator/locale/en-US/options.txt @@ -247,9 +247,6 @@ This means, it you set 'defsearch' to "youtube", then [c]:open arnold schwarzenegger[c] will be exactly the same as [c]:open youtube arnold schwarzenegger[c]. Therefore, you need to add a keyword or search engine "youtube" first. - -If 'defsearch' is empty, then Firefox will always attempt to open the -raw [[arg]]. ____ From f95dfac83fe61f42e5e1c03f299d8b89d66b9fdf Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 12:33:22 -0500 Subject: [PATCH 21/26] Add completion for empty 'defsearch' --- vimperator/content/bookmarks.js | 6 +++++- vimperator/locale/en-US/options.txt | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/vimperator/content/bookmarks.js b/vimperator/content/bookmarks.js index 8acac9f7..afb276e4 100644 --- a/vimperator/content/bookmarks.js +++ b/vimperator/content/bookmarks.js @@ -258,7 +258,11 @@ function Bookmarks() //{{{ "Set the default search engine", "string", "google", { - completer: function completer(context) completion.search(context, true), + completer: function completer(context) + { + completion.search(context, true) + context.completions = [["", "Don't perform searches by default"]].concat(context.completions); + }, validator: Option.validateCompleter }); diff --git a/vimperator/locale/en-US/options.txt b/vimperator/locale/en-US/options.txt index 2d017a69..22cdd8c7 100644 --- a/vimperator/locale/en-US/options.txt +++ b/vimperator/locale/en-US/options.txt @@ -247,6 +247,9 @@ This means, it you set 'defsearch' to "youtube", then [c]:open arnold schwarzenegger[c] will be exactly the same as [c]:open youtube arnold schwarzenegger[c]. Therefore, you need to add a keyword or search engine "youtube" first. + +If 'defsearch' is empty, then Firefox will always attempt to open the +raw [[arg]]. ____ From 74700d3afff32c4ee2ae0ee0d059a7aec4a3427e Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 13:27:01 -0500 Subject: [PATCH 22/26] Document some more crap. --- common/content/buffer.js | 152 ++++++++++++++++++++++++++++++---- common/content/commands.js | 5 ++ common/content/completion.js | 5 ++ common/content/editor.js | 5 ++ common/content/events.js | 8 ++ common/content/find.js | 5 ++ common/content/hints.js | 5 ++ common/content/io.js | 7 +- common/content/liberator.js | 2 + common/content/mappings.js | 5 ++ common/content/modes.js | 2 + common/content/options.js | 5 ++ common/content/style.js | 155 ++++++++++++++++++++--------------- common/content/tabs.js | 2 + common/content/template.js | 3 + common/content/ui.js | 2 + common/content/util.js | 2 + 17 files changed, 285 insertions(+), 85 deletions(-) diff --git a/common/content/buffer.js b/common/content/buffer.js index 23989362..0350c852 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -26,8 +26,16 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + const Point = new Struct("x", "y"); +/** + * A class to manage the primary web content buffer. The name comes + * from vim's term, 'buffer', which signifies instances of open + * files. + * @instance buffer + */ function Buffer() //{{{ { //////////////////////////////////////////////////////////////////////////////// @@ -808,6 +816,10 @@ function Buffer() //{{{ return { + /** + * The alternative stylesheets for the current buffer. Only + * returns stylesheets for the 'screen' media type. + */ get alternateStyleSheets() { let stylesheets = window.getAllStyleSheets(window.content); @@ -817,9 +829,18 @@ function Buffer() //{{{ ); }, + /** + * @property {Object} A map of page info sections to their + * content generating functions. + */ get pageInfo() pageInfo, - // 0 if loading, 1 if loaded or 2 if load failed + /** + * Returns whether the buffer is loaded. Values may be: + * 0 - Loading. + * 1 - Fully loaded. + * 2 - Load failed. + */ get loaded() { if (window.content.document.pageIsFullyLoaded !== undefined) @@ -832,7 +853,10 @@ function Buffer() //{{{ window.content.document.pageIsFullyLoaded = value; }, - // used to keep track of the right field for "gi" + /** + * The last focused input field in the buffer. Used by the + * "gi" key binding. + */ get lastInputField() { if (window.content.document.lastInputField) @@ -845,6 +869,9 @@ function Buffer() //{{{ window.content.document.lastInputField = value; }, + /** + * The current top-level document's URL. + */ get URL() { return window.content.document.location.href; @@ -855,6 +882,10 @@ function Buffer() //{{{ return window.content.innerHeight; }, + /** + * The current browser's text zoom level, as a percentage with + * 100 as 'normal'. Only affects text size. + */ get textZoom() { return getBrowser().markupDocumentViewer.textZoom * 100; @@ -864,6 +895,11 @@ function Buffer() //{{{ setZoom(value, false); }, + /** + * 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. + */ get fullZoom() { return getBrowser().markupDocumentViewer.fullZoom * 100; @@ -873,14 +909,37 @@ function Buffer() //{{{ setZoom(value, true); }, + /** + * The current document's title. + */ get title() { return window.content.document.title; }, + /** + * + * @param {string} option The section's value in 'pageinfo'. + * @param {string} title The heading for this section's + * output. + * @param {function} fn The function to generate this + * section's output. + */ addPageInfoSection: addPageInfoSection, - // returns an XPathResult object + /** + * Evaluates an XPath expression in the current or provided + * document. It provides the xhtml and liberator XML + * namespaces. The result may be used as an iterator. + * + * @param {string} expression The XPath expression to evaluate. + * @param {Document} doc The document to evaluate the expression in. + * @default The current document. + * @param {Node} elem The context element. + * @default doc + * @param {boolean} asIterator Whether to return the results as an XPath + * iterator. + */ evaluateXPath: function (expression, doc, elem, asIterator) { if (!doc) @@ -891,15 +950,10 @@ function Buffer() //{{{ let result = doc.evaluate(expression, elem, function lookupNamespaceURI(prefix) { - switch (prefix) - { - case "xhtml": - return "http://www.w3.org/1999/xhtml"; - case "liberator": - return NS.uri; - default: - return null; - } + return { + xhtml: "http://www.w3.org/1999/xhtml", + liberator: NS.uri + }[prefix] || null; }, asIterator ? XPathResult.ORDERED_NODE_ITERATOR_TYPE : XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null @@ -912,9 +966,13 @@ function Buffer() //{{{ return result; }, - // in contrast to vim, returns the selection if one is made, - // otherwise tries to guess the current word under the text cursor - // NOTE: might change the selection + /** + * Returns the currently selected word. If the selection is + * null, it tries to guess the word that the caret is + * positioned in. + * + * NOTE: might change the selection + */ // FIXME: getSelection() doesn't always preserve line endings, see: // https://www.mozdev.org/bugs/show_bug.cgi?id=19303 getCurrentWord: function () @@ -936,8 +994,13 @@ function Buffer() //{{{ return String(selection); }, - // more advanced than a simple elem.focus() as it also works for iframes - // and image maps + /** + * Focuses the given element. In contrast to a simple + * elem.focus() call, this function works for iframes and + * image maps. + * + * @param {Node} elem The element to focus. + */ // TODO: merge with followLink()? focusElement: function (elem) { @@ -962,6 +1025,17 @@ function Buffer() //{{{ elem.dispatchEvent(evt); }, + /** + * Try to guess links the like of "next" and "prev". Though it + * has a singularly horrendous name, it turns out to be quite + * useful. + * + * @param {string} rel The relationship to look for. Looks for + * links with matching @rel or @rev attributes, and, + * failing that, looks for an option named rel + + * "pattern", and finds the last link matching that + * RegExp. + */ followDocumentRelationship: function (rel) { let regexps = options.get(rel + "pattern").values @@ -1018,7 +1092,13 @@ function Buffer() //{{{ liberator.beep(); }, - // artificially "clicks" a link in order to open it + /** + * Fakes a click on a link. + * + * @param {Node} elem The element to click. + * @param {number} where Where to open the link. See + * {@link liberator.open}. + */ followLink: function (elem, where) { let doc = elem.ownerDocument; @@ -1066,6 +1146,9 @@ function Buffer() //{{{ }); }, + /** + * The current document's selection controller. + */ get selectionController() getBrowser().docShell .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsISelectionDisplay) @@ -1090,11 +1173,19 @@ function Buffer() //{{{ } }, + /** + * Scrolls to the bottom of the current buffer. + */ scrollBottom: function () { scrollToPercentiles(-1, 100); }, + /** + * Scrolls the window laterally cols columns. + * + * @param {number} cols The number of columns to scroll. + */ scrollColumns: function (cols) { let win = findScrollableWindow(); @@ -1106,11 +1197,19 @@ function Buffer() //{{{ win.scrollBy(COL_WIDTH * cols, 0); }, + /** + * Scrolls the buffer to its rightmost position. + */ scrollEnd: function () { scrollToPercentiles(100, -1); }, + /** + * Scrolls the buffer vertically lines rows. + * + * @param {number} lines The number of lines to scroll. + */ scrollLines: function (lines) { let win = findScrollableWindow(); @@ -1118,6 +1217,11 @@ function Buffer() //{{{ win.scrollByLines(lines); }, + /** + * Scrolls the buffer vertically pages pages. + * + * @param {number} pages The number of pages to scroll. + */ scrollPages: function (pages) { let win = findScrollableWindow(); @@ -1139,16 +1243,25 @@ function Buffer() //{{{ win.scrollBy(0, win.innerHeight / 2 * direction); }, + /** + * Scrolls the current buffer vertically to percentage + */ scrollToPercentile: function (percentage) { scrollToPercentiles(-1, percentage); }, + /** + * Scrolls the current buffer laterally to its leftmost. + */ scrollStart: function () { scrollToPercentiles(0, -1); }, + /** + * Scrolls the current buffer vertically to its top. + */ scrollTop: function () { scrollToPercentiles(-1, 0); @@ -1310,6 +1423,9 @@ function Buffer() //{{{ //}}} }; //}}} +/** + * @instance marks + */ function Marks() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/commands.js b/common/content/commands.js index 7486d344..d357918d 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + // Do NOT create instances of this class yourself, use the helper method // commands.add() instead function Command(specs, description, action, extraInfo) //{{{ @@ -147,6 +149,9 @@ Command.prototype = { }; //}}} +/** + * @instance commands + */ function Commands() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/completion.js b/common/content/completion.js index f9ddee03..2c119f95 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + /** * Creates a new completion context. * @@ -647,6 +649,9 @@ CompletionContext.prototype = { } }; //}}} +/** + * @instance completion + */ function Completion() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/editor.js b/common/content/editor.js index 6219a4ea..5c9ffedb 100644 --- a/common/content/editor.js +++ b/common/content/editor.js @@ -26,9 +26,14 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + // command names taken from: // http://developer.mozilla.org/en/docs/Editor_Embedding_Guide +/** + * @instance editor + */ function Editor() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/events.js b/common/content/events.js index c477cb80..3009eee6 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -26,6 +26,11 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + +/** + * @instance autocommands + */ function AutoCommands() //{{{ { //////////////////////////////////////////////////////////////////////////////// @@ -277,6 +282,9 @@ function AutoCommands() //{{{ //}}} }; //}}} +/** + * @instance events + */ function Events() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/find.js b/common/content/find.js index 923426f5..72c77388 100644 --- a/common/content/find.js +++ b/common/content/find.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + // TODO: proper backwards search - implement our own component? // : implement our own highlighter? // : frameset pages @@ -37,6 +39,9 @@ the terms of any one of the MPL, the GPL or the LGPL. // : incremental searches shouldn't permanently update search modifiers // make sure you only create this object when the "liberator" object is ready +/** + * @instance search + */ function Search() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/hints.js b/common/content/hints.js index 90c7e14f..38f36436 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -26,6 +26,11 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + +/** + * @instance hints + */ function Hints() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/io.js b/common/content/io.js index 136b2b13..ba62b137 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -27,6 +27,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + plugins.contexts = {}; function Script(file) { @@ -52,6 +54,9 @@ function Script(file) Script.prototype = plugins; // TODO: why are we passing around strings rather than file objects? +/** + * @instance io + */ function IO() //{{{ { //////////////////////////////////////////////////////////////////////////////// @@ -838,7 +843,7 @@ lookup: } else if (/\.css$/.test(filename)) { - storage.styles.registerSheet(uri.spec, !silent, true); + storage.styles.registerSheet(uri.spec, true); } else { diff --git a/common/content/liberator.js b/common/content/liberator.js index 54780d85..1e32d051 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + const Cc = Components.classes; const Ci = Components.interfaces; const Cr = Components.results; diff --git a/common/content/mappings.js b/common/content/mappings.js index 7e35b115..d409ba79 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + // Do NOT create instances of this class yourself, use the helper method // mappings.add() instead function Map(modes, cmds, description, action, extraInfo) //{{{ @@ -76,6 +78,9 @@ Map.prototype = { }; //}}} +/** + * @instance mappings + */ function Mappings() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/modes.js b/common/content/modes.js index 0159dd24..e79a67f4 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + const modes = (function () //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/options.js b/common/content/options.js index 6373dcb6..a1844a5f 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + // do NOT create instances of this class yourself, use the helper method // options.add() instead function Option(names, description, type, defaultValue, extraInfo) //{{{ @@ -293,6 +295,9 @@ Option.validateCompleter = function (values) function (value) res.some(function (item) item[0] == value)); }; //}}} +/** + * @instance options + */ function Options() //{{{ { //////////////////////////////////////////////////////////////////////////////// diff --git a/common/content/style.js b/common/content/style.js index 62c14ef2..d2ef4d57 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -6,6 +6,19 @@ it under any or all of those licenseses. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + +/** + * @constant + * @property {string} The default highlighting rules. They have the + * form: + * rule ::= selector space css + * selector ::= group + * | group "," css-selector + * | group "," css-selector "," scope + * group ::= groupname + * | groupname css-selector + */ // Highlights.prototype.CSS = .toString(); +/** + * A class to manage highlighting rules. The parameters are the + * standard paramaters for any {@link Storage} object. + * + * @author Kris Maglione + */ function Highlights(name, store, serial) { var self = this; @@ -161,25 +180,35 @@ function Highlights(name, store, serial) .replace(";!important;", ";", "g"); // Seeming Spidermonkey bug css = style.selector + " { " + css + " }"; - let error = styles.addSheet(style.selector, style.filter, css, true, force); + let error = styles.addSheet(style.selector, style.filter, css, true); if (error) return error; style.value = newStyle; highlight[style.class] = style; }; + /** + * Gets a CSS selector given a highlight group. + */ this.selector = function (class) { let [, hl, rest] = class.match(/^(\w*)(.*)/); return "[liberator|highlight~=" + hl + "]" + rest }; + /** + * Clears all highlighting rules. Rules with default values are + * reset. + */ this.clear = function () { for (let [k, v] in Iterator(highlight)) this.set(k, null, true); }; + /** + * Reloads the values in {@link #CSS}. + */ this.reload = function () { this.CSS.replace(/\{((?:.|\n)*?)\}/g, function (_, _1) _1.replace(/\n\s*/g, " ")) @@ -203,6 +232,13 @@ function Highlights(name, store, serial) }; } +/** + * Manages named and unnamed user stylesheets, which apply to both + * chrome and content pages. The parameters are the standard + * paramaters for any {@link Storage} object. + * + * @author Kris Maglione + */ function Styles(name, store, serial) { /* Can't reference liberator or Components inside Styles -- @@ -233,7 +269,20 @@ function Styles(name, store, serial) this.__defineGetter__("systemNames", function () Iterator(systemNames)); this.__defineGetter__("userNames", function () Iterator(userNames)); - this.addSheet = function (name, filter, css, system, force) + /** + * Add a new stylesheet. + * + * @param {string} name The name given to the stylesheet by + * which it may be later referenced. + * @param {string} filter The sites to which this sheet will + * apply. Can be a domain name or a URL. Any URL ending in + * "*" is matched as a prefix. + * @param {string} css The CSS to be applied. + * @param {boolean} system Declares whether this is a system or + * user sheet. System sheets are used internally by + * @liberator. + */ + this.addSheet = function (name, filter, css, system) { let sheets = system ? systemSheets : userSheets; let names = system ? systemNames : userNames; @@ -249,7 +298,7 @@ function Styles(name, store, serial) sheet.ref = []; try { - this.registerSheet(cssUri(wrapCSS(sheet)), !force); + this.registerSheet(cssUri(wrapCSS(sheet))); this.registerAgentSheet(cssUri(wrapCSS(sheet))) } catch (e) @@ -266,6 +315,10 @@ function Styles(name, store, serial) return null; }; + /** + * Find sheets matching the parameters. See {@link #addSheet} + * for parameters. + */ this.findSheets = function (name, filter, css, index, system) { let sheets = system ? systemSheets : userSheets; @@ -284,6 +337,12 @@ function Styles(name, store, serial) return matches.map(function (i) sheets[i]); }; + /** + * Remove a stylesheet. See {@link #addSheet} for parameters. + * In cases where filter is supplied, the given filters + * are removed from matching sheets. If any remain, the sheet is + * left in place. + */ this.removeSheet = function (name, filter, css, index, system) { let self = this; @@ -326,11 +385,15 @@ function Styles(name, store, serial) return matches.length; }; - this.registerSheet = function (uri, doCheckSyntax, reload) + /** + * Register a user stylesheet at the given URI. + * + * @param {string} uri The UrI of the sheet to register. + * @param {boolean} reload Whether to reload any sheets that are + * already registered. + */ + this.registerSheet = function (uri, reload) { - //dump (uri + "\n\n"); - if (doCheckSyntax) - checkSyntax(uri); if (reload) this.unregisterSheet(uri); uri = ios.newURI(uri, null, null); @@ -338,6 +401,9 @@ function Styles(name, store, serial) sss.loadAndRegisterSheet(uri, sss.USER_SHEET); }; + /** + * Unregister a sheet at the given URI. + */ this.unregisterSheet = function (uri) { uri = ios.newURI(uri, null, null); @@ -346,6 +412,10 @@ function Styles(name, store, serial) }; // FIXME + /** + * Register an agent stylesheet. + * @deprecated + */ this.registerAgentSheet = function (uri) { this.unregisterAgentSheet(uri); @@ -353,6 +423,10 @@ function Styles(name, store, serial) sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET); }; + /** + * Unregister an agent stylesheet. + * @deprecated + */ this.unregisterAgentSheet = function (uri) { uri = ios.newURI(uri, null, null); @@ -373,65 +447,6 @@ function Styles(name, store, serial) .join(", "); return namespace + "@-moz-document " + selectors + "{\n" + css + "\n}\n"; } - - let queryinterface = XPCOMUtils.generateQI([Ci.nsIConsoleListener]); - /* What happens if more than one thread tries to use this? */ - let testDoc = document.implementation.createDocument(XHTML, "doc", null); - function checkSyntax(uri) - { - let errors = []; - let listener = { - QueryInterface: queryinterface, - observe: function (message) - { - try - { - message = message.QueryInterface(Ci.nsIScriptError); - if (message.sourceName == uri) - errors.push(message); - } - catch (e) {} - } - }; - - try - { - consoleService.registerListener(listener); - if (testDoc.documentElement.firstChild) - testDoc.documentElement.removeChild(testDoc.documentElement.firstChild); - testDoc.documentElement.appendChild(util.xmlToDom( - , testDoc)); - - while (true) - { - try - { - // Throws NS_ERROR_DOM_INVALID_ACCESS_ERR if not finished loading - testDoc.styleSheets[0].cssRules.length; - break; - } - catch (e) - { - if (e.name != "NS_ERROR_DOM_INVALID_ACCESS_ERR") - return [e.toString()]; - sleep(10); - } - } - } - finally - { - consoleService.unregisterListener(listener); - } - if (errors.length) - { - let err = new Error("", errors[0].sourceName.replace(/^(chrome-data:text\/css,).*/, "$1..."), errors[0].lineNumber); - err.name = "CSSError"; - err.message = errors.reduce(function (msg, e) msg + "; " + e.lineNumber + ": " + e.errorMessage, - errors.shift().errorMessage); - err.echoerr = err.fileName + ":" + err.lineNumber + ": " + err.message; - throw err; - } - } } let (array = util.Array) { @@ -440,8 +455,16 @@ let (array = util.Array) }; } +/** + * @property {Styles} + */ const styles = storage.newObject("styles", Styles, false); + +/** + * @property {Highlights} + */ const highlight = storage.newObject("highlight", Highlights, false); + highlight.CSS = Highlights.prototype.CSS; highlight.reload(); diff --git a/common/content/tabs.js b/common/content/tabs.js index 4e8512f2..fd3c6a24 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + // TODO: many methods do not work with Thunderbird correctly yet function Tabs() //{{{ diff --git a/common/content/template.js b/common/content/template.js index 7b937537..0f7a08a3 100644 --- a/common/content/template.js +++ b/common/content/template.js @@ -1,3 +1,6 @@ + +/** @scope modules */ + const template = { add: function add(a, b) a + b, join: function join(c) function (a, b) a + c + b, diff --git a/common/content/ui.js b/common/content/ui.js index eb3e6c9f..717dbe37 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + /* * This class is used for prompting of user input and echoing of messages * diff --git a/common/content/util.js b/common/content/util.js index d6499e57..3d3995f4 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -26,6 +26,8 @@ the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. }}} ***** END LICENSE BLOCK *****/ +/** @scope modules */ + const XHTML = "http://www.w3.org/1999/xhtml"; const NS = Namespace("liberator", "http://vimperator.org/namespaces/liberator"); default xml namespace = XHTML; From f60ea7637961c3525ae2dbb5bbcecfcc434a6fb7 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 14:57:34 -0500 Subject: [PATCH 23/26] Make sure that the hint number is in the viewport --- common/content/events.js | 81 ++++++++++++++++++++-------------------- common/content/hints.js | 4 +- common/content/util.js | 9 +++++ 3 files changed, 51 insertions(+), 43 deletions(-) diff --git a/common/content/events.js b/common/content/events.js index 3009eee6..c1432bbe 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -1201,52 +1201,51 @@ function Events() //{{{ // global escape handler, is called in ALL modes onEscape: function () { - if (!modes.passNextKey) + if (modes.passNextKey) + return; + if (modes.passAllKeys) { - if (modes.passAllKeys) - { - modes.passAllKeys = false; - return; - } + modes.passAllKeys = false; + return; + } - switch (liberator.mode) - { - case modes.NORMAL: - // clear any selection made - let selection = window.content.getSelection(); - try - { // a simple if (selection) does not seem to work - selection.collapseToStart(); - } - catch (e) {} + switch (liberator.mode) + { + case modes.NORMAL: + // clear any selection made + let selection = window.content.getSelection(); + try + { // a simple if (selection) does not seem to work + selection.collapseToStart(); + } + catch (e) {} + modes.reset(); + break; + + case modes.VISUAL: + if (modes.extended & modes.TEXTAREA) + liberator.mode = modes.TEXTAREA; + else if (modes.extended & modes.CARET) + liberator.mode = modes.CARET; + break; + + case modes.CARET: + // setting this option will trigger an observer which will + // care about all other details like setting the NORMAL mode + options.setPref("accessibility.browsewithcaret", false); + break; + + case modes.INSERT: + if ((modes.extended & modes.TEXTAREA) && !options["insertmode"]) + liberator.mode = modes.TEXTAREA; + else modes.reset(); - break; + break; - case modes.VISUAL: - if (modes.extended & modes.TEXTAREA) - liberator.mode = modes.TEXTAREA; - else if (modes.extended & modes.CARET) - liberator.mode = modes.CARET; - break; - - case modes.CARET: - // setting this option will trigger an observer which will - // care about all other details like setting the NORMAL mode - options.setPref("accessibility.browsewithcaret", false); - break; - - case modes.INSERT: - if ((modes.extended & modes.TEXTAREA) && !options["insertmode"]) - liberator.mode = modes.TEXTAREA; - else - modes.reset(); - break; - - default: // HINTS, CUSTOM or COMMAND_LINE - modes.reset(); - break; - } + default: // HINTS, CUSTOM or COMMAND_LINE + modes.reset(); + break; } }, diff --git a/common/content/hints.js b/common/content/hints.js index 38f36436..511e1894 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -154,8 +154,8 @@ function Hints() //{{{ text = elem.textContent.toLowerCase(); span = baseNodeAbsolute.cloneNode(true); - span.style.left = (rect.left + scrollX) + "px"; - span.style.top = (rect.top + scrollY) + "px"; + span.style.left = Math.max((rect.left + scrollX), scrollX) + "px"; + span.style.top = Math.max((rect.top + scrollY), scrollY) + "px"; fragment.appendChild(span); pageHints.push([elem, text, span, null, elem.style.backgroundColor, elem.style.color]); diff --git a/common/content/util.js b/common/content/util.js index 3d3995f4..cf5bdcb3 100644 --- a/common/content/util.js +++ b/common/content/util.js @@ -311,6 +311,15 @@ const util = { //{{{ identity: function identity(k) k, + intersection: function (r1, r2) ({ + get width() this.right - this.left, + get height() this.bottom - this.top, + left: Math.max(r1.left, r2.left), + right: Math.min(r1.right, r2.right), + top: Math.max(r1.top, r2.top), + bottom: Math.min(r1.bottom, r2.bottom) + }), + map: function map(obj, fn) { let ary = []; From effeef7af68912ce8018adca210ce4f1234b2ae0 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 15:00:52 -0500 Subject: [PATCH 24/26] Fix ;f --- common/content/hints.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/content/hints.js b/common/content/hints.js index 511e1894..283e153b 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -66,7 +66,7 @@ function Hints() //{{{ const hintModes = { ";": Mode("Focus hint", function (elem) buffer.focusElement(elem), extended), a: Mode("Save hint with prompt", function (elem) buffer.saveLink(elem, false)), - f: Mode("Focus frame", function (elem) elem.ownerDocument.defaultView.focus(), function () "//body | //html|body"), + f: Mode("Focus frame", function (elem) elem.ownerDocument.defaultView.focus(), function () "//body | //xhtml:body"), s: Mode("Save hint", function (elem) buffer.saveLink(elem, true)), o: Mode("Follow hint", function (elem) buffer.followLink(elem, liberator.CURRENT_TAB)), t: Mode("Follow hint in a new tab", function (elem) buffer.followLink(elem, liberator.NEW_TAB)), From f5b21739798a8b545fefdf8d1471bfd5e0bf77d7 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 15:12:38 -0500 Subject: [PATCH 25/26] Fix g<, sort-of. Fix some commandline.echo quirks, as well. --- common/content/ui.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/content/ui.js b/common/content/ui.js index 717dbe37..5b5021fe 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -568,10 +568,10 @@ function CommandLine() //{{{ * after interpolated data. */ XML.ignoreWhitespace = typeof str != "xml"; - let output = util.xmlToDom(
{template.maybeXML(str)}
, doc); + lastMowOutput =
{template.maybeXML(str)}
; + let output = util.xmlToDom(lastMowOutput, doc); XML.ignoreWhitespace = true; - lastMowOutput = output; // FIXME: need to make sure an open MOW is closed when commands // that don't generate output are executed @@ -778,8 +778,7 @@ function CommandLine() //{{{ function () { if (lastMowOutput) - commandline.echo(lastMowOutput, - commandline.HL_NORMAL, commandline.FORCE_MULTILINE); + echoMultiline(lastMowOutput, commandline.HL_NORMAL); else liberator.beep(); }); @@ -986,7 +985,10 @@ function CommandLine() //{{{ let action = echoLine; if (!single && (!outputContainer.collapsed || messageBox.value == lastEcho)) + { + highlightGroup += " Message"; action = echoMultiline; + } if ((flags & this.FORCE_MULTILINE) || (/\n/.test(str) || typeof str == "xml") && !(flags & this.FORCE_SINGLELINE)) action = echoMultiline; From 480151cc4d841fdc3bf336b0d91e930a461528ed Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 19 Dec 2008 17:11:05 -0500 Subject: [PATCH 26/26] Move 'system' arg of Styles methods to arg 0, and add completion functions --- common/content/buffer.js | 4 +- common/content/completion.js | 6 ++- common/content/hints.js | 4 +- common/content/liberator.js | 6 +-- common/content/style.js | 85 +++++++++++++++++++++++++----------- common/content/tabs.js | 4 +- common/content/ui.js | 4 +- 7 files changed, 74 insertions(+), 39 deletions(-) diff --git a/common/content/buffer.js b/common/content/buffer.js index 0350c852..b4d5fd78 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -46,8 +46,8 @@ function Buffer() //{{{ let fontSize = util.computedStyle(document.getElementById(mainWindowID)).fontSize; styles.registerSheet("chrome://liberator/skin/liberator.css"); - let error = styles.addSheet("font-size", "chrome://liberator/content/buffer.xhtml", - "body { font-size: " + fontSize + "; }", true); + let error = styles.addSheet(true, "font-size", "chrome://liberator/content/buffer.xhtml", + "body { font-size: " + fontSize + "; }"); if ("ZoomManager" in window) { diff --git a/common/content/completion.js b/common/content/completion.js index 2c119f95..7eee6591 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -920,8 +920,9 @@ function Completion() //{{{ case "}": pop("{"); /* Fallthrough */ case ";": top[FULL_STATEMENTS].push(i); + break; case ",": - top[COMMA]; + top[COMMA].push(i); break; } @@ -1158,6 +1159,7 @@ function Completion() //{{{ let [offset, obj, func] = getObjKey(-3); if (!obj.length) return; + obj = obj.slice(0, 1); try { @@ -1176,7 +1178,7 @@ function Completion() //{{{ { let arg = str.substring(prev + 1, idx); prev = idx; - args.__defineGetter__(i, function () self.eval(ret)); + args.__defineGetter__(i, function () self.eval(arg)); } let key = getKey(); args.push(key + string); diff --git a/common/content/hints.js b/common/content/hints.js index 283e153b..27a1dbb5 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -271,7 +271,7 @@ function Hints() //{{{ css.push(highlight.selector(group) + "[number='" + elem.getAttribute("number") + "'] { " + elem.style.cssText + " }"); } } - styles.addSheet("hint-positions", "*", css.join("\n"), true, true); + styles.addSheet(true, "hint-positions", "*", css.join("\n")); } return true; @@ -296,7 +296,7 @@ function Hints() //{{{ if (timeout && firstElem) setTimeout(function () { firstElem.removeAttributeNS(NS.uri, "highlight"); }, timeout); } - styles.removeSheet("hint-positions", null, null, null, true); + styles.removeSheet(true, "hint-positions"); reset(); } diff --git a/common/content/liberator.js b/common/content/liberator.js index 1e32d051..47753817 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -124,9 +124,9 @@ const liberator = (function () //{{{ let class = dir.map(function (dir) "html|html > xul|scrollbar[orient=" + dir + "]"); if (class.length) - styles.addSheet("scrollbar", "*", class.join(", ") + " { visibility: collapse !important; }", true, true); + styles.addSheet(true, "scrollbar", "*", class.join(", ") + " { visibility: collapse !important; }"); else - styles.removeSheet("scrollbar", null, null, null, true); + styles.removeSheet(true, "scrollbar"); options.safeSetPref("layout.scrollbar.side", opts.indexOf("l") >= 0 ? 3 : 2); }, validator: function (opts) (opts.indexOf("l") < 0 || opts.indexOf("r") < 0) @@ -140,7 +140,7 @@ const liberator = (function () //{{{ { let classes = [v[1] for ([k, v] in Iterator(this.opts)) if (opts.indexOf(k) < 0)]; let css = classes.length ? classes.join(",") + "{ display: none; }" : ""; - styles.addSheet("taboptions", "chrome://*", css, true, true); + styles.addSheet(true, "taboptions", "chrome://*", css); statusline.updateTabCount(); } } diff --git a/common/content/style.js b/common/content/style.js index d2ef4d57..6bdcf232 100644 --- a/common/content/style.js +++ b/common/content/style.js @@ -158,7 +158,7 @@ function Highlights(name, store, serial) return "Unknown highlight keyword: " + class; let style = highlight[key] || new Highlight(key); - styles.removeSheet(style.selector, null, null, null, true); + styles.removeSheet(true, style.selector); if (append) newStyle = (style.value || "").replace(/;?\s*$/, "; " + newStyle); @@ -169,7 +169,7 @@ function Highlights(name, store, serial) if (style.default == null) { delete highlight[style.class]; - styles.removeSheet(style.selector, null, null, null, true); + styles.removeSheet(true, style.selector); return null; } newStyle = style.default; @@ -180,7 +180,7 @@ function Highlights(name, store, serial) .replace(";!important;", ";", "g"); // Seeming Spidermonkey bug css = style.selector + " { " + css + " }"; - let error = styles.addSheet(style.selector, style.filter, css, true); + let error = styles.addSheet(true, style.selector, style.filter, css); if (error) return error; style.value = newStyle; @@ -272,22 +272,22 @@ function Styles(name, store, serial) /** * Add a new stylesheet. * + * @param {boolean} system Declares whether this is a system or + * user sheet. System sheets are used internally by + * @liberator. * @param {string} name The name given to the stylesheet by * which it may be later referenced. * @param {string} filter The sites to which this sheet will * apply. Can be a domain name or a URL. Any URL ending in * "*" is matched as a prefix. * @param {string} css The CSS to be applied. - * @param {boolean} system Declares whether this is a system or - * user sheet. System sheets are used internally by - * @liberator. */ - this.addSheet = function (name, filter, css, system) + this.addSheet = function (system, name, filter, css) { let sheets = system ? systemSheets : userSheets; let names = system ? systemNames : userNames; if (name && name in names) - this.removeSheet(name, null, null, null, system); + this.removeSheet(system, name); let sheet = sheets.filter(function (s) s.sites.join(",") == filter && s.css == css)[0]; if (!sheet) @@ -315,11 +315,27 @@ function Styles(name, store, serial) return null; }; + /** + * Get a sheet with a given name or index. + * + * @param {boolean} system + * @param {string or number} sheet The sheet to retrieve. Strings indicate + * sheet names, while numbers indicate indices. + */ + this.get = function get(system, sheet) + { + let sheets = system ? systemSheets : userSheets; + let names = system ? systemNames : userNames; + if (typeof sheet == "number") + return sheets[sheet]; + return names[sheet] + }; + /** * Find sheets matching the parameters. See {@link #addSheet} * for parameters. */ - this.findSheets = function (name, filter, css, index, system) + this.findSheets = function (system, name, filter, css, index) { let sheets = system ? systemSheets : userSheets; let names = system ? systemNames : userNames; @@ -343,7 +359,7 @@ function Styles(name, store, serial) * are removed from matching sheets. If any remain, the sheet is * left in place. */ - this.removeSheet = function (name, filter, css, index, system) + this.removeSheet = function (system, name, filter, css, index) { let self = this; let sheets = system ? systemSheets : userSheets; @@ -351,12 +367,12 @@ function Styles(name, store, serial) if (filter && filter.indexOf(",") > -1) return filter.split(",").reduce( - function (n, f) n + self.removeSheet(name, f, index, system), 0); + function (n, f) n + self.removeSheet(system, name, f, index), 0); if (filter == undefined) filter = ""; - let matches = this.findSheets(name, filter, css, index, system); + let matches = this.findSheets(system, name, filter, css, index); if (matches.length == 0) return; @@ -379,7 +395,7 @@ function Styles(name, store, serial) { let sites = sheet.sites.filter(function (f) f != filter); if (sites.length) - this.addSheet(name, sites.join(","), css, system, true); + this.addSheet(system, name, sites.join(","), css); } } return matches.length; @@ -451,7 +467,19 @@ function Styles(name, store, serial) let (array = util.Array) { Styles.prototype = { - get sites() array.uniq(array.flatten([v.sites for ([k, v] in this.userSheets)])) + get sites() array.uniq(array.flatten([v.sites for ([k, v] in this.userSheets)])), + completeSite: function (context, content) + { + let compl = []; + try + { + compl.push([content.location.host, "Current Host"]); + compl.push([content.location.href, "Current URL"]); + } + catch (e) {} + context.anchored = false; + context.completions = compl.concat([[s, ""] for each (s in styles.sites)]); + } }; } @@ -471,6 +499,18 @@ highlight.reload(); liberator.triggerObserver("load_styles", "styles"); liberator.triggerObserver("load_highlight", "highlight"); +liberator.registerObserver("load_completion", function () +{ + completion.setFunctionCompleter(["get", "addSheet", "removeSheet", "findSheets"].map(function (m) styles[m]), + [ // Prototype: (system, name, filter, css, index) + null, + function (context, obj, args) args[0] ? styles.systemNames : styles.userNames, + function (context, obj, args) styles.completeSite(context, content), + null, + function (context, obj, args) args[0] ? styles.systemSheets : styles.userSheets + ]); +}); + liberator.registerObserver("load_commands", function () { // TODO: :colo default needs :hi clear @@ -513,14 +553,14 @@ liberator.registerObserver("load_commands", function () { if ("-append" in args) { - let sheet = styles.findSheets(name, null, null, null, false)[0]; + let sheet = styles.get(false, name); if (sheet) { filter = sheet.sites.concat(filter).join(","); css = sheet.css.replace(/;?\s*$/, "; " + css); } } - let err = styles.addSheet(name, filter, css, false, args.bang); + let err = styles.addSheet(false, name, filter, css); if (err) liberator.echoerr(err); } @@ -532,18 +572,11 @@ liberator.registerObserver("load_commands", function () let compl = []; if (args.completeArg == 0) { - try - { - compl.push([content.location.host, "Current Host"]); - compl.push([content.location.href, "Current URL"]); - } - catch (e) {} - context.anchored = false; - context.completions = compl.concat([[s, ""] for each (s in styles.sites)]); + styles.completeSite(context, content); } else if (args.completeArg == 1) { - let sheet = styles.findSheets(args["-name"], null, null, null, false)[0]; + let sheet = styles.get(false, args["-name"]); if (sheet) context.completions = [[sheet.css, "Current Value"]]; } @@ -567,7 +600,7 @@ liberator.registerObserver("load_commands", function () "Remove a user stylesheet", function (args) { - styles.removeSheet(args["-name"], args[0], args.literalArg, args["-index"], false); + styles.removeSheet(false, args["-name"], args[0], args.literalArg, args["-index"]); }, { completer: function (context) { context.completions = styles.sites.map(function (site) [site, ""]); }, diff --git a/common/content/tabs.js b/common/content/tabs.js index fd3c6a24..6436f8ea 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -220,8 +220,8 @@ function Tabs() //{{{ }); let fragment = liberator.has("MacUnix") ? "tab-mac" : "tab"; // TODO: Add option, or only apply when go~=[nN] - styles.addSheet("tab-binding", "chrome://browser/content/browser.xul", - ".tabbrowser-tab { -moz-binding: url(chrome://liberator/content/bindings.xml#" + fragment + ") !important; }", true); + styles.addSheet(true, "tab-binding", "chrome://browser/content/browser.xul", + ".tabbrowser-tab { -moz-binding: url(chrome://liberator/content/bindings.xml#" + fragment + ") !important; }"); } diff --git a/common/content/ui.js b/common/content/ui.js index 5b5021fe..5cd2cc92 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -872,9 +872,9 @@ function CommandLine() //{{{ set silent(val) { silent = val; if (silent) - storage.styles.addSheet("silent-mode", "chrome://*", "#liberator-commandline > * { opacity: 0 }", true, true); + storage.styles.addSheet(true, "silent-mode", "chrome://*", "#liberator-commandline > * { opacity: 0 }"); else - storage.styles.removeSheet("silent-mode", null, null, null, true); + storage.styles.removeSheet(true, "silent-mode"); }, runSilently: function (fn, self)