mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 16:17:59 +01:00
Preserve file/line information with saved ex commands (:au, :com, :map -ex).
This commit is contained in:
@@ -128,16 +128,7 @@ const AutoCommands = Module("autocommands", {
|
|||||||
lastPattern = autoCmd.pattern;
|
lastPattern = autoCmd.pattern;
|
||||||
dactyl.echomsg("autocommand " + autoCmd.command, 9);
|
dactyl.echomsg("autocommand " + autoCmd.command, 9);
|
||||||
|
|
||||||
if (typeof autoCmd.command == "function") {
|
autoCmd.command(args);
|
||||||
try {
|
|
||||||
autoCmd.command.call(autoCmd, args);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
dactyl.echoerr(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dactyl.execute(commands.replaceTokens(autoCmd.command, args), null, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,8 +164,16 @@ const AutoCommands = Module("autocommands", {
|
|||||||
if (args.length > 2) { // add new command, possibly removing all others with the same event/pattern
|
if (args.length > 2) { // add new command, possibly removing all others with the same event/pattern
|
||||||
if (args.bang)
|
if (args.bang)
|
||||||
autocommands.remove(event, regex);
|
autocommands.remove(event, regex);
|
||||||
if (args["-javascript"])
|
if (args["-javascript"]) {
|
||||||
cmd = dactyl.userFunc("args", "with(args) {" + cmd + "}");
|
cmd = dactyl.userFunc("args", "with(args) {" + cmd + "}");
|
||||||
|
cmd.toString = function toString() "-javascript " + cmd.source;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmd = function cmd(args) dactyl.execute(commands.replaceTokens(cmd.source, args), null, true, cmd.sourcing);
|
||||||
|
cmd.sourcing = io.sourcing && update({}, io.sourcing);
|
||||||
|
cmd.toString = function toString() cmd.source;
|
||||||
|
}
|
||||||
|
cmd.source = args[2];
|
||||||
autocommands.add(events, regex, cmd);
|
autocommands.add(events, regex, cmd);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -404,14 +404,10 @@ const CommandLine = Module("commandline", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
runSilently: function (func, self) {
|
runSilently: function (func, self) {
|
||||||
let wasSilent = this._silent;
|
this.withSavedValues(["_silent"], function () {
|
||||||
this._silent = true;
|
this._silent = true;
|
||||||
try {
|
|
||||||
func.call(self);
|
func.call(self);
|
||||||
}
|
});
|
||||||
finally {
|
|
||||||
this._silent = wasSilent;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
hideCompletions: function () {
|
hideCompletions: function () {
|
||||||
|
|||||||
@@ -997,7 +997,7 @@ const Commands = Module("commands", {
|
|||||||
count: this.count && args.count
|
count: this.count && args.count
|
||||||
};
|
};
|
||||||
|
|
||||||
dactyl.execute(commands.replaceTokens(this.replacementText, tokens));
|
dactyl.execute(commands.replaceTokens(this.replacementText, tokens), null, true, this.sourcing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: offer completion.ex?
|
// TODO: offer completion.ex?
|
||||||
@@ -1062,7 +1062,8 @@ const Commands = Module("commands", {
|
|||||||
bang: bangOpt,
|
bang: bangOpt,
|
||||||
count: countOpt,
|
count: countOpt,
|
||||||
completer: completeFunc,
|
completer: completeFunc,
|
||||||
replacementText: args.literalArg
|
replacementText: args.literalArg,
|
||||||
|
sourcing: io.sourcing && update({}, io.sourcing)
|
||||||
}, args.bang);
|
}, args.bang);
|
||||||
|
|
||||||
if (!added)
|
if (!added)
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
*/
|
*/
|
||||||
userFunc: function () {
|
userFunc: function () {
|
||||||
return this.userEval(
|
return this.userEval(
|
||||||
"(function (" +
|
"(function userFunction(" +
|
||||||
Array.slice(arguments, 0, -1).join(", ") +
|
Array.slice(arguments, 0, -1).join(", ") +
|
||||||
") { " + arguments[arguments.length - 1] + " })");
|
") { " + arguments[arguments.length - 1] + " })");
|
||||||
},
|
},
|
||||||
@@ -344,7 +344,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
* @param {boolean} silent Whether the command should be echoed on the
|
* @param {boolean} silent Whether the command should be echoed on the
|
||||||
* command line.
|
* command line.
|
||||||
*/
|
*/
|
||||||
execute: function (str, modifiers, silent) {
|
execute: function (str, modifiers, silent, sourcing) {
|
||||||
// skip comments and blank lines
|
// skip comments and blank lines
|
||||||
if (/^\s*("|$)/.test(str))
|
if (/^\s*("|$)/.test(str))
|
||||||
return;
|
return;
|
||||||
@@ -359,7 +359,10 @@ const Dactyl = Module("dactyl", {
|
|||||||
if (!silent)
|
if (!silent)
|
||||||
commandline.command = str.replace(/^\s*:\s*/, "");
|
commandline.command = str.replace(/^\s*:\s*/, "");
|
||||||
|
|
||||||
command.execute(args, modifiers);
|
io.withSavedValues(["sourcing"], function () {
|
||||||
|
io.sourcing = sourcing || io.sourcing;
|
||||||
|
command.execute(args, modifiers);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ const RangeFind = Class("RangeFind", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
iter: function (word) {
|
iter: function (word) {
|
||||||
let saved = ["range", "lastRange", "lastString"].map(function (s) [s, this[s]], this);
|
let saved = ["lastRange", "lastString", "range"].map(function (s) [s, this[s]], this);
|
||||||
try {
|
try {
|
||||||
this.range = this.ranges[0];
|
this.range = this.ranges[0];
|
||||||
this.lastRange = null;
|
this.lastRange = null;
|
||||||
|
|||||||
@@ -317,104 +317,102 @@ lookup:
|
|||||||
* @param {boolean} silent Whether errors should be reported.
|
* @param {boolean} silent Whether errors should be reported.
|
||||||
*/
|
*/
|
||||||
source: function (filename, silent) {
|
source: function (filename, silent) {
|
||||||
let wasSourcing = this.sourcing;
|
|
||||||
let readHeredoc = this.readHeredoc;
|
|
||||||
defineModule.loadLog.push("sourcing " + filename);
|
defineModule.loadLog.push("sourcing " + filename);
|
||||||
let time = Date.now();
|
let time = Date.now();
|
||||||
try {
|
this.withSavedValues(["readHeredoc", "sourcing"], function () {
|
||||||
var file = io.File(filename);
|
try {
|
||||||
this.sourcing = {
|
var file = io.File(filename);
|
||||||
file: file.path,
|
this.sourcing = {
|
||||||
line: 0
|
file: file.path,
|
||||||
};
|
line: 0
|
||||||
|
|
||||||
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 (isString(e))
|
|
||||||
e = { message: e };
|
|
||||||
let err = new Error();
|
|
||||||
for (let [k, v] in Iterator(e))
|
|
||||||
err[k] = v;
|
|
||||||
err.echoerr = <>{file.path}:{e.lineNumber}: {e}</>;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
if (!file.exists() || !file.isReadable() || file.isDirectory()) {
|
||||||
for (let [i, line] in iter) {
|
if (!silent)
|
||||||
if (this.sourcing.finished)
|
dactyl.echoerr("E484: Can't open file " + filename.quote());
|
||||||
break;
|
return;
|
||||||
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 }, true);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
dactyl.echoerr("Error detected while processing " + file.path);
|
|
||||||
dactyl.echomsg("line\t" + this.sourcing.line + ":");
|
|
||||||
dactyl.reportError(e, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (isString(e))
|
||||||
|
e = { message: e };
|
||||||
|
let err = new Error();
|
||||||
|
for (let [k, v] in Iterator(e))
|
||||||
|
err[k] = v;
|
||||||
|
err.echoerr = <>{file.path}:{e.lineNumber}: {e}</>;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 }, true);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
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 (this._scriptNames.indexOf(file.path) == -1)
|
dactyl.reportError(e);
|
||||||
this._scriptNames.push(file.path);
|
let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e);
|
||||||
|
if (!silent)
|
||||||
dactyl.echomsg("finished sourcing " + filename.quote(), 2);
|
dactyl.echoerr(message);
|
||||||
|
}
|
||||||
dactyl.log("Sourced: " + filename, 3);
|
finally {
|
||||||
}
|
defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms");
|
||||||
catch (e) {
|
}
|
||||||
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");
|
|
||||||
this.sourcing = wasSourcing;
|
|
||||||
this.readHeredoc = readHeredoc;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is
|
// TODO: when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is
|
||||||
|
|||||||
@@ -384,9 +384,9 @@ const Mappings = Module("mappings", {
|
|||||||
}
|
}
|
||||||
else if (args["-ex"]) {
|
else if (args["-ex"]) {
|
||||||
rhs = ["-ex", rhs];
|
rhs = ["-ex", rhs];
|
||||||
action = function (count) {
|
action = function action(count)
|
||||||
dactyl.execute(commands.replaceTokens(rhs[1], { count: count }));
|
dactyl.execute(commands.replaceTokens(rhs[1], { count: count }), null, true, action.sourcing);
|
||||||
};
|
action.sourcing = io.sourcing && update({}, io.sourcing);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rhs = [events.canonicalKeys(rhs)];
|
rhs = [events.canonicalKeys(rhs)];
|
||||||
|
|||||||
@@ -764,6 +764,16 @@ Class.prototype = {
|
|||||||
*/
|
*/
|
||||||
init: function () {},
|
init: function () {},
|
||||||
|
|
||||||
|
withSavedValues: function (names, callback, self) {
|
||||||
|
let vals = names.map(function (name) this[name], this);
|
||||||
|
try {
|
||||||
|
return callback.call(self || this);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
names.forEach(function (name, i) this[name] = vals[i], this);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
toString: function () "[instance " + this.constructor.className + "]",
|
toString: function () "[instance " + this.constructor.className + "]",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user