diff --git a/Donators b/Donators index af7dcb26..919a68ef 100644 --- a/Donators +++ b/Donators @@ -2,6 +2,7 @@ Note: If you don't wish to appear on this list when making a donation, please tell me. 2008: +* Victor Nemkov * John Lusth * Thomas Svensen * Ryan McBride diff --git a/NEWS b/NEWS index bff0121b..d80c0bbe 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,7 @@ * keywords in :open have higher priority than local files now * add :set online to control the "work offline" menu item * add :jumps command to list current tab's history + * add :setlocal & :setglobal commands, so options can be local (per tab) & global * many small bug fixes 2008-06-03: diff --git a/TODO b/TODO index a9c78933..47391a50 100644 --- a/TODO +++ b/TODO @@ -34,6 +34,7 @@ FEATURES: google to another page and click 10 links there, [d would take me back to the google page opera's fast forward does something like this 7 make an option to disable session saving by default when you close Firefox +6 check/correct spellings in insert mode with some mappings 6 add more autocommands (TabClose, TabOpen, TabChanged, any more?) 6 jump to the next heading with ]h, next image ]i, previous textbox [t and so on 6 :grep support (needs location list) diff --git a/content/buffer.js b/content/buffer.js index 35e86725..d08b97f1 100644 --- a/content/buffer.js +++ b/content/buffer.js @@ -582,8 +582,6 @@ liberator.Buffer = function () //{{{ get URL() { - // TODO: .URL is not defined for XUL documents - //return window.content.document.URL; return window.content.document.location.href; }, @@ -615,6 +613,13 @@ liberator.Buffer = function () //{{{ return window.content.document.title; }, + get options() + { + if (!window.content.document.liberatorOptions) + window.content.document.liberatorOptions = {}; + return window.content.document.liberatorOptions; + }, + // returns an XPathResult object evaluateXPath: function (expression, doc, elem, asIterator) { diff --git a/content/options.js b/content/options.js index ffc8a4fd..b0663555 100644 --- a/content/options.js +++ b/content/options.js @@ -28,7 +28,7 @@ the terms of any one of the MPL, the GPL or the LGPL. // Do NOT create instances of this class yourself, use the helper method // liberator.options.add() instead -liberator.Option = function (names, description, type, defaultValue, getter, setter, validator, completer) //{{{ +liberator.Option = function (names, description, type, defaultValue, scope, getter, setter, validator, completer) //{{{ { if (!names || !type) return null; @@ -38,6 +38,7 @@ liberator.Option = function (names, description, type, defaultValue, getter, set this.name = names[0]; this.names = names; this.type = type; + this.scope = (scope & liberator.options.OPTION_SCOPE_BOTH) || liberator.options.OPTION_SCOPE_GLOBAL; // XXX set to BOTH by default someday? - kstep this.description = description || ""; // "", 0 are valid default values @@ -67,18 +68,30 @@ liberator.Option = function (names, description, type, defaultValue, getter, set this.__defineGetter__("value", function () { + var aValue; + + if (this.scope & liberator.options.OPTION_SCOPE_LOCAL) + aValue = liberator.buffer.options[this.name]; + if ((this.scope & liberator.options.OPTION_SCOPE_GLOBAL) && (aValue == undefined)) + aValue = value; + if (this.getter) - this.getter.call(this); - return value; + this.getter.call(this, aValue); + + return aValue; } ); this.__defineSetter__("value", function (newValue) { - value = newValue; + if (this.scope & liberator.options.OPTION_SCOPE_LOCAL) + liberator.buffer.options[this.name] = newValue; + if (this.scope & liberator.options.OPTION_SCOPE_GLOBAL) + value = newValue; + this.hasChanged = true; if (this.setter) - this.setter.call(this, value); + this.setter.call(this, newValue); } ); @@ -298,8 +311,8 @@ liberator.Options = function () //{{{ if (special) // open firefox settings gui dialog { liberator.open("about:config", - (liberator.options["newtab"] && - (liberator.options["newtab"] == "all" || liberator.options["newtab"].split(",").indexOf("prefs") != -1)) ? + (liberator.options.newtab && + (liberator.options.newtab == "all" || liberator.options.newtab.split(",").indexOf("prefs") != -1)) ? liberator.NEW_TAB : liberator.CURRENT_TAB); } else @@ -313,6 +326,38 @@ liberator.Options = function () //{{{ } }); + liberator.commands.add(["setl[ocal]"], + "Set local option", + function (args, special, count) + { + liberator.commands.get("set").execute(args, special, count, { scope: liberator.options.OPTION_SCOPE_LOCAL }); + }, + { + + completer: function (filter, special, count) + { + return liberator.commands.get("set").completer(filter, special, count, { scope: liberator.options.OPTION_SCOPE_LOCAL }); + } + + } + ); + + liberator.commands.add(["setg[lobal]"], + "Set global option", + function (args, special, count) + { + liberator.commands.get("set").execute(args, special, count, { scope: liberator.options.OPTION_SCOPE_GLOBAL }); + }, + { + + completer: function (filter, special, count) + { + return liberator.commands.get("set").completer(filter, special, count, { scope: liberator.options.OPTION_SCOPE_GLOBAL }); + } + + } + ); + // TODO: support setting multiple options at once liberator.commands.add(["se[t]"], "Set an option", @@ -396,13 +441,23 @@ liberator.Options = function () //{{{ if (name == "all") all = true; - var option = liberator.options.get(name); + var scope = liberator.options.OPTION_SCOPE_BOTH; + if (modifiers && modifiers.scope) + scope = modifiers.scope; + + var option = liberator.options.get(name, scope); + if (!option && !all) { liberator.echoerr("E518: Unknown option: " + args); return; } + var oldOptionScope = option.scope; + var newOptionScope = option.scope; + if (scope != liberator.options.OPTION_SCOPE_BOTH) + newOptionScope = scope; + var valueGiven = !!matches[4]; var get = false; @@ -441,14 +496,16 @@ liberator.Options = function () //{{{ { if (all) { - liberator.options.list(onlyNonDefault); + liberator.options.list(onlyNonDefault, scope); } else { + option.scope = newOptionScope; if (option.type == "boolean") liberator.echo((option.value ? " " : "no") + option.name); else liberator.echo(" " + option.name + "=" + option.value); + option.scope = oldOptionScope; } } // write access @@ -457,7 +514,10 @@ liberator.Options = function () //{{{ // benefit else { + option.scope = newOptionScope; var currentValue = option.value; + option.scope = oldOptionScope; + var newValue; switch (option.type) @@ -470,7 +530,7 @@ liberator.Options = function () //{{{ } if (invertBoolean) - newValue = !option.value; + newValue = !currentValue; else newValue = !unsetBoolean; @@ -552,14 +612,18 @@ liberator.Options = function () //{{{ } if (option.isValidValue(newValue)) + { + option.scope = newOptionScope; option.value = newValue; + option.scope = oldOptionScope; + } else // FIXME: need to be able to specify more specific errors liberator.echoerr("E474: Invalid argument: " + args); } }, { - completer: function (filter, special) + completer: function (filter, special, count, modifiers) { var optionCompletions = []; var prefix = filter.match(/^no|inv/) || ""; @@ -594,11 +658,18 @@ liberator.Options = function () //{{{ return [0, liberator.completion.filter(optionCompletions, filter)]; } + var scope = liberator.options.OPTION_SCOPE_BOTH; + if (modifiers && modifiers.scope) + scope = modifiers.scope; + if (!filter) { var options = []; + for (var option in liberator.options) { + if (!(option.scope & scope)) + continue; if (prefix && option.type != "boolean") continue; options.push([prefix + option.name, option.description]); @@ -611,6 +682,8 @@ liberator.Options = function () //{{{ filter = filter.substr(0, filter.length - 1); for (var option in liberator.options) { + if (!(option.scope & scope)) + continue; if (option.hasName(filter)) { if (option.completer) @@ -624,6 +697,8 @@ liberator.Options = function () //{{{ var filterLength = filter.length; for (var option in liberator.options) { + if (!(option.scope & scope)) + continue; if (prefix && option.type != "boolean") continue; @@ -674,6 +749,10 @@ liberator.Options = function () //{{{ return { + OPTION_SCOPE_GLOBAL: 1, + OPTION_SCOPE_LOCAL: 2, + OPTION_SCOPE_BOTH: 3, + __iterator__: function () { for (var i = 0; i < options.length; i++) @@ -687,8 +766,21 @@ liberator.Options = function () //{{{ if (!extraInfo) extraInfo = {}; - var option = new liberator.Option(names, description, type, defaultValue, - extraInfo.getter, extraInfo.setter, extraInfo.validator, extraInfo.completer); + var option = new liberator.Option(names, description, type, defaultValue, extraInfo.scope, + extraInfo.getter, extraInfo.setter, extraInfo.validator, extraInfo.completer); + + if (!option) + return false; + + for (var i = 0; i < options.length; i++) + { + if (options[i].name == option.name) + { + // never replace for now + liberator.log("Warning: '" + names[0] + "' already exists, NOT replacing existing option.", 1); + return false; + } + } // quickly access options with liberator.options["wildmode"]: this.__defineGetter__(option.name, function () { return option.value; }); @@ -696,6 +788,7 @@ liberator.Options = function () //{{{ // TODO: sort option options.push(option); + return true; }, destroy: function () @@ -706,22 +799,29 @@ liberator.Options = function () //{{{ storePreference("dom.popup_allowed_events", popupAllowedEvents); }, - get: function (name) + get: function (name, scope) { + if (!scope) + scope = liberator.options.OPTION_SCOPE_BOTH; + for (var i = 0; i < options.length; i++) { - if (options[i].hasName(name)) + if (options[i].hasName(name) && (options[i].scope & scope)) return options[i]; } + return null; }, - list: function (onlyNonDefault) + list: function (onlyNonDefault, scope) { var list = ":" + liberator.util.escapeHTML(liberator.commandline.getCommand()) + "
" + ""; var name, value, def; + if (!scope) + scope = liberator.options.OPTION_SCOPE_BOTH; + for (var i = 0; i < options.length; i++) { name = options[i].name; @@ -731,6 +831,9 @@ liberator.Options = function () //{{{ if (onlyNonDefault && value == def) continue; + if (!(options[i].scope & scope)) + continue; + if (options[i].type == "boolean") { name = value ? " " + name : "no" + name; diff --git a/locale/en-US/options.txt b/locale/en-US/options.txt index aaf0511f..1cfb35a5 100644 --- a/locale/en-US/options.txt +++ b/locale/en-US/options.txt @@ -81,6 +81,44 @@ exactly as they appear in the option. Remove flags one by one to avoid problems. ____ +|:setlocal| |:setl| +||:setl[ocal]|| + +||:setl[ocal] all|| + +||:setl[ocal] {option}?|| + +||:setl[ocal] {option}|| + +||:setl[ocal] no{option}|| + +||:setl[ocal] inv{option}|| + +||:setl[ocal] {option}&|| + +||:setl[ocal] all&|| + +||:setl[ocal] {option}={value}|| + +||:setl[ocal] {option}+={value}|| + +||:setl[ocal] {option}^={value}|| + +||:setl[ocal] {option}-={value}|| + + +____ +The same as [c]:set[c] command, but operates on local for current +tab options only. See [c]:set[c] for details. +____ + +|:setglobal| |:setg| +||:setg[lobal]|| + +||:setg[lobal] all|| + +||:setg[lobal] {option}?|| + +||:setg[lobal] {option}|| + +||:setg[lobal] no{option}|| + +||:setg[lobal] inv{option}|| + +||:setg[lobal] {option}&|| + +||:setg[lobal] all&|| + +||:setg[lobal] {option}={value}|| + +||:setg[lobal] {option}+={value}|| + +||:setg[lobal] {option}^={value}|| + +||:setg[lobal] {option}-={value}|| + + +____ +The same as [c]:set[c] command, but operates on global options only. +See [c]:set[c] for details. +____ + section:Setting{nbsp}Firefox{nbsp}options[firefox-options] Most Firefox options are not touched/overridden by Vimperator. In order to set
--- Options ---