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()) + "
" +
"| --- Options --- |
";
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