mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 10:37:59 +01:00
Implement (with an e) an experimental ‘ex’ namespace.
This commit is contained in:
@@ -133,7 +133,7 @@ const Browser = Module("browser", {
|
|||||||
|
|
||||||
mappings.add([modes.NORMAL], ["<C-l>"],
|
mappings.add([modes.NORMAL], ["<C-l>"],
|
||||||
"Redraw the screen",
|
"Redraw the screen",
|
||||||
function () { commands.get("redraw").action(); });
|
function () { ex.redraw(); });
|
||||||
},
|
},
|
||||||
|
|
||||||
commands: function () {
|
commands: function () {
|
||||||
|
|||||||
@@ -35,13 +35,16 @@
|
|||||||
* @property {boolean} multiple Whether this option can be specified multiple times
|
* @property {boolean} multiple Whether this option can be specified multiple times
|
||||||
* @property {string} description A description of the option
|
* @property {string} description A description of the option
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CommandOption = Struct("names", "type", "validator", "completer", "multiple", "description");
|
const CommandOption = Struct("names", "type", "validator", "completer", "multiple", "description");
|
||||||
CommandOption.defaultValue("description", function () "");
|
CommandOption.defaultValue("description", function () "");
|
||||||
CommandOption.defaultValue("type", function () CommandOption.NOARG);
|
CommandOption.defaultValue("type", function () CommandOption.NOARG);
|
||||||
CommandOption.defaultValue("multiple", function () false);
|
CommandOption.defaultValue("multiple", function () false);
|
||||||
|
|
||||||
|
const ArgType = Struct("description", "parse");
|
||||||
update(CommandOption, {
|
update(CommandOption, {
|
||||||
/**
|
/**
|
||||||
* @property {number} The option argument is unspecified. Any argument
|
* @property {object} The option argument is unspecified. Any argument
|
||||||
* is accepted and caller is responsible for parsing the return
|
* is accepted and caller is responsible for parsing the return
|
||||||
* value.
|
* value.
|
||||||
* @final
|
* @final
|
||||||
@@ -49,36 +52,36 @@ update(CommandOption, {
|
|||||||
ANY: 0,
|
ANY: 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property {number} The option doesn't accept an argument.
|
* @property {object} The option doesn't accept an argument.
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
NOARG: 1,
|
NOARG: ArgType("no arg", function (arg) !arg || null),
|
||||||
/**
|
/**
|
||||||
* @property {number} The option accepts a boolean argument.
|
* @property {object} The option accepts a boolean argument.
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
BOOL: 2,
|
BOOL: ArgType("boolean", function (val) Commands.parseBool(val)),
|
||||||
/**
|
/**
|
||||||
* @property {number} The option accepts a string argument.
|
* @property {object} The option accepts a string argument.
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
STRING: 3,
|
STRING: ArgType("string", function (val) val),
|
||||||
/**
|
/**
|
||||||
* @property {number} The option accepts an integer argument.
|
* @property {object} The option accepts an integer argument.
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
INT: 4,
|
INT: ArgType("int", parseInt),
|
||||||
/**
|
/**
|
||||||
* @property {number} The option accepts a float argument.
|
* @property {object} The option accepts a float argument.
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
FLOAT: 5,
|
FLOAT: ArgType("float", parseFloat),
|
||||||
/**
|
/**
|
||||||
* @property {number} The option accepts a string list argument.
|
* @property {object} The option accepts a string list argument.
|
||||||
* E.g. "foo,bar"
|
* E.g. "foo,bar"
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
LIST: 6
|
LIST: ArgType("list", function (arg) arg && arg.split(/\s*,\s*/))
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,6 +255,9 @@ const Command = Class("Command", {
|
|||||||
* @see Commands@parseArguments
|
* @see Commands@parseArguments
|
||||||
*/
|
*/
|
||||||
options: [],
|
options: [],
|
||||||
|
optionMap: Class.memoize(function () array(this.options)
|
||||||
|
.map(function (opt) opt.names.map(function (name) [name, opt]))
|
||||||
|
.flatten.toObject()),
|
||||||
/**
|
/**
|
||||||
* @property {boolean|function(args)} When true, invocations of this
|
* @property {boolean|function(args)} When true, invocations of this
|
||||||
* command may contain private data which should be purged from
|
* command may contain private data which should be purged from
|
||||||
@@ -343,10 +349,47 @@ const Command = Class("Command", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Prototype.
|
||||||
|
const ex = {
|
||||||
|
__noSuchMethod__: function (meth, args) {
|
||||||
|
let cmd = commands.get(meth);
|
||||||
|
dactyl.assert(cmd, "No such command");
|
||||||
|
|
||||||
|
if (isObject(args[0]))
|
||||||
|
for (let [k, v] in Iterator(args.shift()))
|
||||||
|
if (k == "!")
|
||||||
|
args.bang = v;
|
||||||
|
else if (k == "#")
|
||||||
|
args.count = v;
|
||||||
|
else {
|
||||||
|
let opt = cmd.optionMap["-" + k];
|
||||||
|
let val = opt.type && opt.type.parse(v);
|
||||||
|
dactyl.assert(val != null && (typeof val !== "number" || !isNaN(val)),
|
||||||
|
"No such option: " + k);
|
||||||
|
args[opt.names[0]] = val;
|
||||||
|
}
|
||||||
|
if (cmd.literal != null)
|
||||||
|
args.literalArg = args[cmd.literal];
|
||||||
|
|
||||||
|
// FIXME: Duplicated in parseArgs.
|
||||||
|
|
||||||
|
dactyl.assert((args.length > 0 || !/^[1+]$/.test(this.argCount)) &&
|
||||||
|
(this.literal == null || !/[1+]/.test(this.argCount) || /\S/.test(args.literalArg || "")),
|
||||||
|
"E471: Argument required");
|
||||||
|
|
||||||
|
// This logic eludes me... --Kris
|
||||||
|
dactyl.assert((args.length == 0 || this.argCount !== "0") &&
|
||||||
|
(args.length <= 1 || !/^[01?]$/.test(this.argCount)),
|
||||||
|
"E488: Trailing characters");
|
||||||
|
|
||||||
|
// TODO: memoize(args, "string", function () { ... });
|
||||||
|
return cmd.execute(args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @instance commands
|
* @instance commands
|
||||||
*/
|
*/
|
||||||
const ArgType = Struct("description", "parse");
|
|
||||||
const Commands = Module("commands", {
|
const Commands = Module("commands", {
|
||||||
init: function () {
|
init: function () {
|
||||||
this._exCommands = [];
|
this._exCommands = [];
|
||||||
@@ -771,13 +814,12 @@ const Commands = Module("commands", {
|
|||||||
args.quote = Commands.complQuote[quote] || Commands.complQuote[""];
|
args.quote = Commands.complQuote[quote] || Commands.complQuote[""];
|
||||||
}
|
}
|
||||||
if (!complete || arg != null) {
|
if (!complete || arg != null) {
|
||||||
let type = Commands.argTypes[opt.type];
|
if (opt.type) {
|
||||||
if (type) {
|
|
||||||
let orig = arg;
|
let orig = arg;
|
||||||
arg = type.parse(arg);
|
arg = opt.type.parse(arg);
|
||||||
if (arg == null || (typeof arg == "number" && isNaN(arg))) {
|
if (arg == null || (typeof arg == "number" && isNaN(arg))) {
|
||||||
if (!complete || orig != "" || args.completeStart != str.length)
|
if (!complete || orig != "" || args.completeStart != str.length)
|
||||||
fail("Invalid argument for " + type.description + " option: " + optname);
|
fail("Invalid argument for " + opt.type.description + " option: " + optname);
|
||||||
if (complete)
|
if (complete)
|
||||||
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
|
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
|
||||||
}
|
}
|
||||||
@@ -1420,15 +1462,6 @@ const Commands = Module("commands", {
|
|||||||
return false;
|
return false;
|
||||||
return NaN;
|
return NaN;
|
||||||
};
|
};
|
||||||
Commands.argTypes = [
|
|
||||||
null,
|
|
||||||
ArgType("no arg", function (arg) !arg || null),
|
|
||||||
ArgType("boolean", Commands.parseBool),
|
|
||||||
ArgType("string", function (val) val),
|
|
||||||
ArgType("int", parseInt),
|
|
||||||
ArgType("float", parseFloat),
|
|
||||||
ArgType("list", function (arg) arg && arg.split(/\s*,\s*/))
|
|
||||||
];
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// vim: set fdm=marker sw=4 ts=4 et:
|
// vim: set fdm=marker sw=4 ts=4 et:
|
||||||
|
|||||||
@@ -956,7 +956,7 @@ const Tabs = Module("tabs", {
|
|||||||
if (dactyl.has("tabs_undo")) {
|
if (dactyl.has("tabs_undo")) {
|
||||||
mappings.add([modes.NORMAL], ["u"],
|
mappings.add([modes.NORMAL], ["u"],
|
||||||
"Undo closing of a tab",
|
"Undo closing of a tab",
|
||||||
function (count) { commands.get("undo").action({ count: count }); },
|
function (count) { ex.undo({ "#": count }); },
|
||||||
{ count: true });
|
{ count: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user