1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-22 13:48:00 +01:00

allow ^= to be used for prepending values to string options and for multiplying

number options
This commit is contained in:
Doug Kearns
2007-11-06 08:59:02 +00:00
parent d3960bd1d2
commit e1cd0e07bb
2 changed files with 136 additions and 77 deletions

View File

@@ -1641,6 +1641,7 @@ vimperator.Commands = function() //{{{
} }
)); ));
addDefaultCommand(new vimperator.Command(["se[t]"], addDefaultCommand(new vimperator.Command(["se[t]"],
// TODO: support setting multiple options at once
function(args, special, count, modifiers) function(args, special, count, modifiers)
{ {
if (special) if (special)
@@ -1652,60 +1653,61 @@ vimperator.Commands = function() //{{{
var only_non_default = false; // used for :set to print non-default options var only_non_default = false; // used for :set to print non-default options
if (!args) if (!args)
{ {
args = "all?"; args = "all";
only_non_default = true; only_non_default = true;
} }
// 1 2 3 4 5 6 // 1 2 3 4 5 6
var matches = args.match(/^\s*(no|inv)?([a-z]+)([?&!])?(([+-])?=(.*))?/); var matches = args.match(/^\s*(no|inv)?([a-z]+)([?&!])?\s*(([+-^]?)=(.*))?\s*$/);
if (!matches) if (!matches)
{ {
vimperator.echoerr("E518: Unknown option: " + args); vimperator.echoerr("E518: Unknown option: " + args);
return; return;
} }
var no = false; var unset_boolean = false;
if (matches[1] == "no") if (matches[1] == "no")
no = true; unset_boolean = true;
var opt = matches[2];
var name = matches[2];
var all = false; var all = false;
if (opt == "all") if (name == "all")
all = true; all = true;
var option = vimperator.options.get(opt); var option = vimperator.options.get(name);
if (!option && !all) if (!option && !all)
{ {
vimperator.echoerr("E518: Unknown option: " + opt); vimperator.echoerr("E518: Unknown option: " + args);
return; return;
} }
var value_given = !!matches[4];
var get = false; var get = false;
if (all || matches[3] == "?" || (option.type != "boolean" && matches[4] === undefined)) if (all || matches[3] == "?" || (option.type != "boolean" && !value_given))
get = true; get = true;
var reset = false; var reset = false;
if (matches[3] == "&") if (matches[3] == "&")
reset = true; reset = true;
var invert = false; var invert_boolean = false;
if (matches[1] == "inv" || matches[3] == "!") if (matches[1] == "inv" || matches[3] == "!")
invert = true; invert_boolean = true;
var oper = matches[5]; var operator = matches[5];
var val = matches[6]; var value = matches[6];
if (val === undefined) if (value === undefined)
val = ""; value = "";
// reset a variable to its default value // reset a variable to its default value
if (reset) if (reset)
{ {
if (all) if (all)
{ {
for (let opt in vimperator.options) for (let option in vimperator.options)
opt.reset(); option.reset();
} }
else else
{ {
@@ -1728,68 +1730,116 @@ vimperator.Commands = function() //{{{
} }
} }
// write access // write access
// NOTE: the behaviour is generally Vim compatible but could be
// improved. i.e. Vim's behaviour is pretty sloppy to no real
// benefit
else else
{ {
var type = option.type; var current_value = option.value;
if (type == "boolean") var new_value;
switch (option.type)
{ {
if (matches[4]) case "boolean":
vimperator.echoerr("E474: Invalid argument: " + option.name + "=" + val); if (value_given)
else if (invert) {
option.value = !option.value; vimperator.echoerr("E474: Invalid argument: " + args);
return;
}
if (invert_boolean)
new_value = !option.value;
else else
option.value = !no; new_value = !unset_boolean;
}
else if (type == "number") break;
case "number":
value = parseInt(value, 10);
if (isNaN(value))
{ {
var num = parseInt(val, 10); vimperator.echoerr("E521: Number required after =: " + args);
if (isNaN(num)) return;
vimperator.echoerr("E521: Number required after =: " + option.name + "=" + val); }
if (operator == "+")
new_value = current_value + value;
else if (operator == "-")
new_value = current_value - value;
else if (operator == "^")
new_value = current_value * value;
else else
new_value = value;
break;
case "charlist":
if (operator == "+")
new_value = current_value.replace(new RegExp("[" + value + "]", "g"), "") + value;
else if (operator == "-")
new_value = current_value.replace(value, "");
else if (operator == "^")
// NOTE: Vim doesn't prepend if there's a match in the current value
new_value = value + current_value.replace(new RegExp("[" + value + "]", "g"), "");
else
new_value = value;
break;
case "stringlist":
if (operator == "+")
{ {
var cur_val = option.value; if (!current_value.match(value))
if (oper == '+') num = cur_val + num; new_value = (current_value ? current_value + "," : "") + value;
if (oper == '-') num = cur_val - num; else
// FIXME new_value = current_value;
if (option.validator != null && option.validator.call(this, num) == false)
vimperator.echoerr("E474: Invalid argument: " + option.name + "=" + val); // FIXME: need to be able to specify unique parse error messages
else // all checks passed, execute option handler
option.value = num;
} }
else if (operator == "-")
{
new_value = current_value.replace(new RegExp("^" + value + ",?|," + value), "");
} }
else if (type == "charlist" || type == "stringlist" || type == "string") else if (operator == "^")
{ {
var cur_val = option.value; if (!current_value.match(value))
if (type == "charlist" || type == "string") new_value = value + (current_value ? "," : "") + current_value;
{ else
if (oper == '+' && !cur_val.match(val)) new_value = current_value;
val = cur_val + val;
if (oper == '-') val = cur_val.replace(val, '');
} }
else else
{ {
if (oper == '+' && !cur_val.match(val) && cur_val.length > 0) new_value = value;
val = cur_val + ',' + val;
if (oper == '-')
{
val = cur_val.replace(new RegExp(',?' + val), '');
val = val.replace(/^,?/, '');
}
}
// FIXME
if (option.validator != null && option.validator.call(this, val) == false)
vimperator.echoerr("E474: Invalid argument: " + option.name + "=" + val);
else // all checks passed, execute option handler
option.value = val;
} }
break;
case "string":
if (operator == "+")
new_value = current_value + value;
else if (operator == "-")
new_value = current_value.replace(value, "");
else if (operator == "^")
new_value = value + current_value;
else else
vimperator.echoerr("E685: Internal error: option format `" + type + "' not supported"); new_value = value;
break;
default:
vimperator.echoerr("E685: Internal error: option type `" + option.type + "' not supported");
}
if (option.isValidValue(new_value))
option.value = new_value;
else
// FIXME: need to be able to specify more specific errors
vimperator.echoerr("E474: Invalid argument: " + args);
} }
}, },
{ {
usage: ["se[t][!]", "se[t] {option}?", "se[t] [no]{option}", "se[t] {option}[+-]={value}", "se[t] {option}! | inv{option}", "se[t] {option}&"], usage: ["se[t][!]", "se[t] {option}?", "se[t] [no]{option}", "se[t] {option}[+-]={value}", "se[t] {option}! | inv{option}", "se[t] {option}&"],
short_help: "Set an option", short_help: "Set an option",
help: "Permanently change an option. In contrast to Vim options are currently stored throughout sessions.<br/>" + help: "Permanently change an option.<br/>" +
"<code class=\"command\">:set</code> without an argument shows all Vimperator options which differ from their default values.<br/>" + "<code class=\"command\">:set</code> without an argument shows all Vimperator options which differ from their default values.<br/>" +
"<code class=\"command\">:set!</code> without an argument shows all about:config preferences which differ from their default values.<br/>" + "<code class=\"command\">:set!</code> without an argument shows all about:config preferences which differ from their default values.<br/>" +
"There are three types of options: boolean, number and string. " + "There are three types of options: boolean, number and string. " +
@@ -1798,7 +1848,8 @@ vimperator.Commands = function() //{{{
"<code class=\"command\">:set option!</code> and <code class=\"command\">:set invoption</code> invert the value of a boolean option.<br/>" + "<code class=\"command\">:set option!</code> and <code class=\"command\">:set invoption</code> invert the value of a boolean option.<br/>" +
"<code class=\"command\">:set option?</code> or <code class=\"command\">:set option</code>(for string and list options) shows the current value of an option.<br/>" + "<code class=\"command\">:set option?</code> or <code class=\"command\">:set option</code>(for string and list options) shows the current value of an option.<br/>" +
"<code class=\"command\">:set option&amp;</code> resets an option to its default value.<br/>" + "<code class=\"command\">:set option&amp;</code> resets an option to its default value.<br/>" +
"<code class=\"command\">:set option+={value}</code> and <code class=\"command\">:set option-={value}</code> adds/subtracts {value} to a number option and append/remove {value} to a string option.<br/>" + "<code class=\"command\">:set option+={value}</code>, <code class=\"command\">:set option^={value}</code> and <code class=\"command\">:set option-={value}</code> " +
"adds/multiplies/subtracts <code class=\"argument\">{value}</code> from a number option and appends/prepends/removes <code class=\"argument\">{value}</code> from a string option.<br/>" +
"<code class=\"command\">:set all</code> shows the current value of all options and <code class=\"command\">:set all&amp;</code> resets all options to their default values.<br/>", "<code class=\"command\">:set all</code> shows the current value of all options and <code class=\"command\">:set all&amp;</code> resets all options to their default values.<br/>",
completer: function(filter) { return vimperator.completion.get_options_completions(filter); } completer: function(filter) { return vimperator.completion.get_options_completions(filter); }
} }

View File

@@ -106,6 +106,14 @@ vimperator.Option = function(names, type, extra_info) //{{{
return false; return false;
} }
this.isValidValue = function(value)
{
if (this.validator)
return this.validator(value);
else
return true;
}
this.reset = function() this.reset = function()
{ {
this.value = this.default_value; this.value = this.default_value;