mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-02-05 12:45:45 +01:00
Merge default.
--HG-- branch : mode-refactoring extra : close : 1
This commit is contained in:
@@ -169,7 +169,7 @@ const AutoCommands = Module("autocommands", {
|
||||
cmd.toString = function toString() "-javascript " + cmd.source;
|
||||
}
|
||||
else {
|
||||
cmd = function cmd(args) dactyl.execute(commands.replaceTokens(cmd.source, args), null, true, cmd.sourcing);
|
||||
cmd = function cmd(args) commands.execute(cmd.source, args, false, null, cmd.sourcing);
|
||||
cmd.sourcing = io.sourcing && update({}, io.sourcing);
|
||||
cmd.toString = function toString() cmd.source;
|
||||
}
|
||||
|
||||
@@ -412,6 +412,64 @@ const Commands = Module("commands", {
|
||||
return res.join(" ");
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes an Ex command script.
|
||||
*
|
||||
* @param {string} string A string containing the commands to execute.
|
||||
* @param {object} tokens An optional object containing tokens to be
|
||||
* interpolated into the command string.
|
||||
* @param {object} args Optional arguments object to be passed to
|
||||
* command actions.
|
||||
* @param {object} sourcing An object containing information about
|
||||
* the file that is being or has been sourced to obtain the
|
||||
* command string.
|
||||
*/
|
||||
execute: function (string, tokens, silent, args, sourcing) {
|
||||
io.withSavedValues(["readHeredoc", "sourcing"], function () {
|
||||
this.sourcing = update({}, sourcing);
|
||||
|
||||
args = update({ setFrom: this.file }, args || {});
|
||||
|
||||
if (tokens)
|
||||
string = commands.replaceTokens(string, tokens);
|
||||
|
||||
let lines = string.split(/\r\n|[\r\n]/);
|
||||
|
||||
this.readHeredoc = function (end) {
|
||||
let res = [];
|
||||
this.sourcing.line++;
|
||||
while (++i < lines.length) {
|
||||
if (lines[i] === end)
|
||||
return res.join("\n");
|
||||
res.push(lines[i]);
|
||||
}
|
||||
dactyl.assert(false, "Unexpected end of file waiting for " + end);
|
||||
};
|
||||
|
||||
for (var i = 0; i < lines.length && !this.sourcing.finished; i++) {
|
||||
// Deal with editors from Silly OSs.
|
||||
let line = lines[i].replace(/\r$/, "");
|
||||
|
||||
this.sourcing.line = sourcing.line + i;
|
||||
|
||||
// Process escaped new lines
|
||||
while (i < lines.length && /^\s*\\/.test(lines[i + 1]))
|
||||
line += "\n" + lines[++i].replace(/^\s*\\/, "");
|
||||
|
||||
try {
|
||||
dactyl.execute(line, args);
|
||||
}
|
||||
catch (e) {
|
||||
if (!silent) {
|
||||
dactyl.echoerr("Error detected while processing " + this.sourcing.file);
|
||||
dactyl.echomsg("line\t" + this.sourcing.line + ":");
|
||||
dactyl.reportError(e, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the command with matching <b>name</b>.
|
||||
*
|
||||
@@ -595,9 +653,11 @@ const Commands = Module("commands", {
|
||||
|
||||
outer:
|
||||
while (i < str.length || complete) {
|
||||
// skip whitespace
|
||||
while (/\s/.test(str[i]) && i < str.length)
|
||||
i++;
|
||||
var argStart = i;
|
||||
let re = /^\s*/gy;
|
||||
re.lastIndex = i;
|
||||
i += re.exec(str)[0].length;
|
||||
|
||||
if (str[i] == "|") {
|
||||
args.string = str.slice(0, i);
|
||||
args.trailing = str.slice(i + 1);
|
||||
@@ -700,14 +760,20 @@ const Commands = Module("commands", {
|
||||
complete.highlight(i, sub.length, "SPELLCHECK");
|
||||
}
|
||||
|
||||
if (args.length == literal) {
|
||||
if (args.length === literal) {
|
||||
if (complete)
|
||||
args.completeArg = args.length;
|
||||
|
||||
let re = /^(?:\s*(?=\n)|\s*)([^]*)/gy;
|
||||
re.lastIndex = argStart || 0;
|
||||
sub = re.exec(str)[1];
|
||||
|
||||
// Hack.
|
||||
if (sub.substr(0, 2) === "<<" && hereDoc)
|
||||
let ([count, arg] = getNextArg(sub)) {
|
||||
sub = arg + sub.substr(count);
|
||||
}
|
||||
|
||||
args.literalArg = sub;
|
||||
args.push(sub);
|
||||
args.quote = null;
|
||||
@@ -791,7 +857,7 @@ const Commands = Module("commands", {
|
||||
str.replace(/\s*".*$/, "");
|
||||
|
||||
// 0 - count, 1 - cmd, 2 - special, 3 - args
|
||||
let matches = str.match(/^([:\s]*(\d+|%)?([a-zA-Z]+|!)(!)?(\s*))(.*?)?$/);
|
||||
let matches = str.match(/^([:\s]*(\d+|%)?([a-zA-Z]+|!)(!)?(\s*))((?:.|\n)*?)?$/);
|
||||
//var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/);
|
||||
if (!matches)
|
||||
return [];
|
||||
@@ -997,7 +1063,7 @@ const Commands = Module("commands", {
|
||||
count: this.count && args.count
|
||||
};
|
||||
|
||||
dactyl.execute(commands.replaceTokens(this.replacementText, tokens), null, true, this.sourcing);
|
||||
commands.execute(this.replacementText, tokens, false, null, this.sourcing);
|
||||
}
|
||||
|
||||
// TODO: offer completion.ex?
|
||||
@@ -1103,21 +1169,21 @@ const Commands = Module("commands", {
|
||||
completion.ex(context);
|
||||
},
|
||||
options: [
|
||||
{ names: ["-bang"], description: "Command may be proceeded by a !" },
|
||||
{ names: ["-count"], description: "Command may be preceeded by a count" },
|
||||
{ names: ["-bang", "-b"], description: "Command may be proceeded by a !" },
|
||||
{ names: ["-count", "-c"], description: "Command may be preceeded by a count" },
|
||||
{
|
||||
names: ["-description"],
|
||||
names: ["-description", "-desc", "-d"],
|
||||
description: "A user-visible description of the command",
|
||||
type: CommandOption.STRING
|
||||
}, {
|
||||
// TODO: "E180: invalid complete value: " + arg
|
||||
names: ["-complete"],
|
||||
names: ["-complete", "-C"],
|
||||
description: "The argument completion function",
|
||||
completer: function (context) [[k, ""] for ([k, v] in Iterator(completeOptionMap))],
|
||||
type: CommandOption.STRING,
|
||||
validator: function (arg) arg in completeOptionMap || /custom,\w+/.test(arg),
|
||||
}, {
|
||||
names: ["-nargs"],
|
||||
names: ["-nargs", "-a"],
|
||||
description: "The allowed number of arguments",
|
||||
completer: [["0", "No arguments are allowed (default)"],
|
||||
["1", "One argument is allowed"],
|
||||
|
||||
@@ -153,7 +153,7 @@ const ConfigBase = Class(ModuleBase, {
|
||||
Null color: blue;
|
||||
Number color: blue;
|
||||
Object color: maroon;
|
||||
String color: green;
|
||||
String color: green; white-space: pre;
|
||||
|
||||
Key font-weight: bold;
|
||||
|
||||
|
||||
@@ -1994,7 +1994,7 @@ const Dactyl = Module("dactyl", {
|
||||
dactyl.execute(init);
|
||||
else {
|
||||
if (rcFile) {
|
||||
io.source(rcFile.path, true);
|
||||
io.source(rcFile.path, false);
|
||||
services.get("environment").set("MY_" + config.idName + "RC", rcFile.path);
|
||||
}
|
||||
else
|
||||
@@ -2022,17 +2022,7 @@ const Dactyl = Module("dactyl", {
|
||||
// all gui options to their default values, if they have not been
|
||||
// set before by any RC file
|
||||
for (let option in values(options.needInit))
|
||||
// FIXME:
|
||||
// 'encoding' option should not be set at this timing.
|
||||
// Probably a wrong value is set into the option,
|
||||
// if current page's encoding is not UTF-8.
|
||||
try {
|
||||
if (option.name != "encoding");
|
||||
option.value = option.value;
|
||||
}
|
||||
catch (e) {
|
||||
dactyl.reportError(e);
|
||||
}
|
||||
option.initValue();
|
||||
|
||||
if (dactyl.commandLineOptions.postCommands)
|
||||
dactyl.commandLineOptions.postCommands.forEach(function (cmd) {
|
||||
|
||||
@@ -319,105 +319,61 @@ lookup:
|
||||
source: function (filename, silent) {
|
||||
defineModule.loadLog.push("sourcing " + filename);
|
||||
let time = Date.now();
|
||||
this.withSavedValues(["readHeredoc", "sourcing"], function () {
|
||||
try {
|
||||
var file = io.File(filename);
|
||||
this.sourcing = {
|
||||
file: file.path,
|
||||
line: 0
|
||||
};
|
||||
try {
|
||||
var file = io.File(filename);
|
||||
|
||||
if (!file.exists() || !file.isReadable() || file.isDirectory()) {
|
||||
if (!silent)
|
||||
dactyl.echoerr("E484: Can't open file " + filename.quote());
|
||||
return;
|
||||
}
|
||||
|
||||
dactyl.echomsg("sourcing " + filename.quote(), 2);
|
||||
|
||||
let uri = services.get("io").newFileURI(file);
|
||||
|
||||
// handle pure JavaScript files specially
|
||||
if (/\.js$/.test(filename)) {
|
||||
try {
|
||||
dactyl.loadScript(uri.spec, Script(file));
|
||||
dactyl.helpInitialized = false;
|
||||
}
|
||||
catch (e) {
|
||||
if (e.fileName)
|
||||
try {
|
||||
e.fileName = e.fileName.replace(/^(chrome|resource):.*? -> /, "");
|
||||
if (e.fileName == uri.spec)
|
||||
e.fileName = filename;
|
||||
e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}</>
|
||||
}
|
||||
catch (e) {}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else if (/\.css$/.test(filename))
|
||||
storage.styles.registerSheet(uri.spec, false, true);
|
||||
else {
|
||||
let heredoc = "";
|
||||
let heredocEnd = null; // the string which ends the heredoc
|
||||
let str = file.read();
|
||||
let lines = str.split(/\r\n|[\r\n]/);
|
||||
|
||||
this.readHeredoc = function (end) {
|
||||
let res = [];
|
||||
try {
|
||||
io.sourcing.line++;
|
||||
while (true)
|
||||
let ([i, line] = iter.next()) {
|
||||
if (line === end)
|
||||
return res.join("\n");
|
||||
res.push(line);
|
||||
}
|
||||
}
|
||||
catch (e if e instanceof StopIteration) {}
|
||||
dactyl.assert(false, "Unexpected end of file waiting for " + end);
|
||||
};
|
||||
|
||||
let iter = Iterator(lines);
|
||||
for (let [i, line] in iter) {
|
||||
if (this.sourcing.finished)
|
||||
break;
|
||||
this.sourcing.line = i + 1;
|
||||
// skip line comments and blank lines
|
||||
line = line.replace(/\r$/, "");
|
||||
|
||||
if (!/^\s*(".*)?$/.test(line))
|
||||
try {
|
||||
dactyl.execute(line, { setFrom: file });
|
||||
}
|
||||
catch (e) {
|
||||
if (!silent) {
|
||||
dactyl.echoerr("Error detected while processing " + file.path);
|
||||
dactyl.echomsg("line\t" + this.sourcing.line + ":");
|
||||
dactyl.reportError(e, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._scriptNames.indexOf(file.path) == -1)
|
||||
this._scriptNames.push(file.path);
|
||||
|
||||
dactyl.echomsg("finished sourcing " + filename.quote(), 2);
|
||||
|
||||
dactyl.log("Sourced: " + filename, 3);
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof FailedAssertion))
|
||||
dactyl.reportError(e);
|
||||
let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e);
|
||||
if (!file.exists() || !file.isReadable() || file.isDirectory()) {
|
||||
if (!silent)
|
||||
dactyl.echoerr(message);
|
||||
dactyl.echoerr("E484: Can't open file " + filename.quote());
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms");
|
||||
|
||||
dactyl.echomsg("sourcing " + filename.quote(), 2);
|
||||
|
||||
let uri = services.get("io").newFileURI(file);
|
||||
|
||||
// handle pure JavaScript files specially
|
||||
if (/\.js$/.test(filename)) {
|
||||
try {
|
||||
dactyl.loadScript(uri.spec, Script(file));
|
||||
dactyl.helpInitialized = false;
|
||||
}
|
||||
catch (e) {
|
||||
if (e.fileName)
|
||||
try {
|
||||
e.fileName = e.fileName.replace(/^(chrome|resource):.*? -> /, "");
|
||||
if (e.fileName == uri.spec)
|
||||
e.fileName = filename;
|
||||
e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}</>
|
||||
}
|
||||
catch (e) {}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
else if (/\.css$/.test(filename))
|
||||
storage.styles.registerSheet(uri.spec, false, true);
|
||||
else {
|
||||
commands.execute(file.read(), null, silent, null,
|
||||
{ file: file.path, line: 1 });
|
||||
}
|
||||
|
||||
if (this._scriptNames.indexOf(file.path) == -1)
|
||||
this._scriptNames.push(file.path);
|
||||
|
||||
dactyl.echomsg("finished sourcing " + filename.quote(), 2);
|
||||
|
||||
dactyl.log("Sourced: " + filename, 3);
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof FailedAssertion))
|
||||
dactyl.reportError(e);
|
||||
let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e);
|
||||
if (!silent)
|
||||
dactyl.echoerr(message);
|
||||
}
|
||||
finally {
|
||||
defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms");
|
||||
}
|
||||
},
|
||||
|
||||
// TODO: when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is
|
||||
|
||||
@@ -384,8 +384,8 @@ const Mappings = Module("mappings", {
|
||||
}
|
||||
else if (args["-ex"]) {
|
||||
rhs = ["-ex", rhs];
|
||||
action = function action(count)
|
||||
dactyl.execute(commands.replaceTokens(rhs[1], { count: count }), null, true, action.sourcing);
|
||||
action = function action(count) commands.execute(rhs[1], { count: count },
|
||||
false, null, action.sourcing);
|
||||
action.sourcing = io.sourcing && update({}, io.sourcing);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -71,6 +71,10 @@ const Option = Class("Option", {
|
||||
this.globalValue = this.parseValues(this.defaultValue);
|
||||
},
|
||||
|
||||
initValue: function () {
|
||||
dactyl.trapErrors(function () this.values = this.values, this);
|
||||
},
|
||||
|
||||
/** @property {value} The option's global value. @see #scope */
|
||||
get globalValue() options.store.get(this.name, {}).value,
|
||||
set globalValue(val) { options.store.set(this.name, { value: val, time: Date.now() }); },
|
||||
@@ -685,8 +689,11 @@ const Options = Module("options", {
|
||||
memoize(this._optionMap, name, function () Option(names, description, type, defaultValue, extraInfo));
|
||||
for (let alias in values(names.slice(1)))
|
||||
memoize(this._optionMap, alias, closure);
|
||||
if (extraInfo.setter)
|
||||
memoize(this.needInit, this.needInit.length, closure);
|
||||
if (extraInfo.setter && (!extraInfo.scope || extraInfo.scope & Option.SCOPE_GLOBAL))
|
||||
if (dactyl.initialized)
|
||||
closure().initValue();
|
||||
else
|
||||
memoize(this.needInit, this.needInit.length, closure);
|
||||
|
||||
// quickly access options with options["wildmode"]:
|
||||
this.__defineGetter__(name, function () this._optionMap[name].values);
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
- Backtracks to the first successful match after pressing
|
||||
backspace.
|
||||
- Supports reverse incremental search.
|
||||
* Multiple Ex commands may now be separated by |
|
||||
* Ex command parsing improvements, including:
|
||||
- Multiple Ex commands may now be separated by |
|
||||
- Commands can continue over multiple lines in RC files by
|
||||
prefixing the continues lines with a \
|
||||
- The \ character is no longer treated specially within single
|
||||
quotes, i.e., 'fo\o''bar' ⇒ fo\o'bar
|
||||
* Command-line is now hidden by default. Added C and M to
|
||||
'guioptions'.
|
||||
* Hint mode improvements, including:
|
||||
@@ -41,8 +46,6 @@
|
||||
directory in 'runtimepath' rather than 'plugin/'.
|
||||
* IMPORTANT: 'loadplugins' is now a regexlist option rather than
|
||||
a boolean.
|
||||
* IMPORTANT: Single quotes no longer treat \ specially.
|
||||
I.e., 'fo\o''bar' ≡ fo\o'bar
|
||||
* IMPORTANT: 'cdpath' and 'runtimepath' no longer treat ",,"
|
||||
specially. Use "." instead.
|
||||
* IMPORTANT: Option value quoting has changed. List options will
|
||||
|
||||
Reference in New Issue
Block a user