mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 16:17:59 +01:00
Allow :set foo=bar | echo baz.
This commit is contained in:
@@ -138,7 +138,7 @@ const CommandLine = Module("commandline", {
|
|||||||
this._currentCommand = null;
|
this._currentCommand = null;
|
||||||
|
|
||||||
// save the arguments for the inputMultiline method which are needed in the event handler
|
// save the arguments for the inputMultiline method which are needed in the event handler
|
||||||
this._multilineRegexp = null;
|
this._multilineEnd = null;
|
||||||
this._multilineCallback = null;
|
this._multilineCallback = null;
|
||||||
|
|
||||||
this._input = {};
|
this._input = {};
|
||||||
@@ -581,11 +581,11 @@ const CommandLine = Module("commandline", {
|
|||||||
* which matches the given regular expression. Then execute the
|
* which matches the given regular expression. Then execute the
|
||||||
* callback with that string as a parameter.
|
* callback with that string as a parameter.
|
||||||
*
|
*
|
||||||
* @param {RegExp} untilRegexp
|
* @param {string} end
|
||||||
* @param {function(string)} callbackFunc
|
* @param {function(string)} callbackFunc
|
||||||
*/
|
*/
|
||||||
// FIXME: Buggy, especially when pasting. Shouldn't use a RegExp.
|
// FIXME: Buggy, especially when pasting. Shouldn't use a RegExp.
|
||||||
inputMultiline: function inputMultiline(untilRegexp, callbackFunc) {
|
inputMultiline: function inputMultiline(end, callbackFunc) {
|
||||||
// Kludge.
|
// Kludge.
|
||||||
let cmd = !this.widgets.command.collapsed && this.command;
|
let cmd = !this.widgets.command.collapsed && this.command;
|
||||||
modes.push(modes.COMMAND_LINE, modes.INPUT_MULTILINE);
|
modes.push(modes.COMMAND_LINE, modes.INPUT_MULTILINE);
|
||||||
@@ -593,7 +593,7 @@ const CommandLine = Module("commandline", {
|
|||||||
this._echoLine(cmd, this.HL_NORMAL);
|
this._echoLine(cmd, this.HL_NORMAL);
|
||||||
|
|
||||||
// save the arguments, they are needed in the event handler onEvent
|
// save the arguments, they are needed in the event handler onEvent
|
||||||
this._multilineRegexp = untilRegexp;
|
this._multilineEnd = "\n" + end + "\n";
|
||||||
this._multilineCallback = callbackFunc;
|
this._multilineCallback = callbackFunc;
|
||||||
|
|
||||||
this.widgets.multilineInput.collapsed = false;
|
this.widgets.multilineInput.collapsed = false;
|
||||||
@@ -702,9 +702,10 @@ const CommandLine = Module("commandline", {
|
|||||||
if (event.type == "keypress") {
|
if (event.type == "keypress") {
|
||||||
let key = events.toString(event);
|
let key = events.toString(event);
|
||||||
if (events.isAcceptKey(key)) {
|
if (events.isAcceptKey(key)) {
|
||||||
let text = this.widgets.multilineInput.value.substr(0, this.widgets.multilineInput.selectionStart);
|
let text = "\n" + this.widgets.multilineInput.value.substr(0, this.widgets.multilineInput.selectionStart);
|
||||||
if (text.match(this._multilineRegexp)) {
|
let index = text.indexOf(this._multilineEnd);
|
||||||
text = text.replace(this._multilineRegexp, "");
|
if (index >= 0) {
|
||||||
|
text = text.substring(1, index);
|
||||||
modes.pop();
|
modes.pop();
|
||||||
this.widgets.multilineInput.collapsed = true;
|
this.widgets.multilineInput.collapsed = true;
|
||||||
this._multilineCallback.call(this, text);
|
this._multilineCallback.call(this, text);
|
||||||
|
|||||||
@@ -137,31 +137,13 @@ const Command = Class("Command", {
|
|||||||
* @deprecated
|
* @deprecated
|
||||||
* @param {Object} modifiers Any modifiers to be passed to {@link #action}.
|
* @param {Object} modifiers Any modifiers to be passed to {@link #action}.
|
||||||
*/
|
*/
|
||||||
execute: function (args, bang, count, modifiers) {
|
execute: function (args, modifiers) {
|
||||||
// XXX
|
let self = this;
|
||||||
bang = !!bang;
|
|
||||||
count = (count === undefined) ? null : count;
|
|
||||||
modifiers = modifiers || {};
|
modifiers = modifiers || {};
|
||||||
|
|
||||||
let self = this;
|
dactyl.trapErrors(function exec(command) {
|
||||||
function exec(command) {
|
|
||||||
// FIXME: Move to parseCommand?
|
|
||||||
args = this.parseArgs(command);
|
|
||||||
args.count = count;
|
|
||||||
args.bang = bang;
|
|
||||||
this.action(args, modifiers);
|
this.action(args, modifiers);
|
||||||
}
|
}, this);
|
||||||
|
|
||||||
if (this.hereDoc) {
|
|
||||||
let matches = args.match(/(.*)<<\s*(\S+)$/);
|
|
||||||
if (matches && matches[2]) {
|
|
||||||
commandline.inputMultiline(RegExp("^" + matches[2] + "$", "m"),
|
|
||||||
function (args) { dactyl.trapErrors(exec, self, matches[1] + "\n" + args); });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dactyl.trapErrors(exec, this, args);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,6 +176,7 @@ const Command = Class("Command", {
|
|||||||
argCount: this.argCount,
|
argCount: this.argCount,
|
||||||
complete: complete,
|
complete: complete,
|
||||||
extra: extra,
|
extra: extra,
|
||||||
|
hereDoc: this.hereDoc,
|
||||||
keepQuotes: !!this.keepQuotes,
|
keepQuotes: !!this.keepQuotes,
|
||||||
literal: this.literal,
|
literal: this.literal,
|
||||||
options: this.options
|
options: this.options
|
||||||
@@ -460,26 +443,6 @@ const Commands = Module("commands", {
|
|||||||
return this._exCommands.filter(function (cmd) cmd.user);
|
return this._exCommands.filter(function (cmd) cmd.user);
|
||||||
},
|
},
|
||||||
|
|
||||||
_subCommands: function (command) {
|
|
||||||
while (command) {
|
|
||||||
// FIXME: This parseCommand/commands.get/parseArgs is duplicated too often.
|
|
||||||
let [count, cmd, bang, args] = commands.parseCommand(command);
|
|
||||||
command = commands.get(cmd);
|
|
||||||
if (command) {
|
|
||||||
try {
|
|
||||||
args = command.parseArgs(args, null, { count: count, bang: bang });
|
|
||||||
yield [command, args];
|
|
||||||
if (commands.subCommand == null)
|
|
||||||
break;
|
|
||||||
command = args[command.subCommand];
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a command invocation contains a URL referring to the
|
* Returns true if a command invocation contains a URL referring to the
|
||||||
* domain 'host'.
|
* domain 'host'.
|
||||||
@@ -563,6 +526,13 @@ const Commands = Module("commands", {
|
|||||||
*/
|
*/
|
||||||
parseArgs: function (str, params) {
|
parseArgs: function (str, params) {
|
||||||
function getNextArg(str) {
|
function getNextArg(str) {
|
||||||
|
if (str.substr(0, 2) === "<<" && hereDoc) {
|
||||||
|
let arg = /^<<(\S*)/.exec(str)[1];
|
||||||
|
let count = arg.length + 2;
|
||||||
|
if (complete)
|
||||||
|
return [count, "", ""]
|
||||||
|
return [count, io.readHeredoc(arg), ""];
|
||||||
|
}
|
||||||
let [count, arg, quote] = Commands.parseArg(str, null, keepQuotes);
|
let [count, arg, quote] = Commands.parseArg(str, null, keepQuotes);
|
||||||
if (quote == "\\" && !complete)
|
if (quote == "\\" && !complete)
|
||||||
return [,,,"Trailing \\"];
|
return [,,,"Trailing \\"];
|
||||||
@@ -571,7 +541,7 @@ const Commands = Module("commands", {
|
|||||||
return [count, arg, quote];
|
return [count, arg, quote];
|
||||||
}
|
}
|
||||||
|
|
||||||
var { allowUnknownOptions, argCount, complete, extra, literal, options, keepQuotes } = params;
|
var { allowUnknownOptions, argCount, complete, extra, hereDoc, literal, options, keepQuotes } = params || {};
|
||||||
|
|
||||||
if (!options)
|
if (!options)
|
||||||
options = [];
|
options = [];
|
||||||
@@ -628,6 +598,11 @@ const Commands = Module("commands", {
|
|||||||
// skip whitespace
|
// skip whitespace
|
||||||
while (/\s/.test(str[i]) && i < str.length)
|
while (/\s/.test(str[i]) && i < str.length)
|
||||||
i++;
|
i++;
|
||||||
|
if (str[i] == "|") {
|
||||||
|
args.string = str.slice(0, i);
|
||||||
|
args.trailing = str.slice(i + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (i == str.length && !complete)
|
if (i == str.length && !complete)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -728,6 +703,11 @@ const Commands = Module("commands", {
|
|||||||
if (args.length == literal) {
|
if (args.length == literal) {
|
||||||
if (complete)
|
if (complete)
|
||||||
args.completeArg = args.length;
|
args.completeArg = args.length;
|
||||||
|
// Hack.
|
||||||
|
if (sub.substr(0, 2) === "<<" && hereDoc)
|
||||||
|
let ([count, arg] = getNextArg(sub)) {
|
||||||
|
sub = arg + sub.substr(count);
|
||||||
|
}
|
||||||
args.literalArg = sub;
|
args.literalArg = sub;
|
||||||
args.push(sub);
|
args.push(sub);
|
||||||
args.quote = null;
|
args.quote = null;
|
||||||
@@ -757,7 +737,7 @@ const Commands = Module("commands", {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (complete) {
|
if (complete && args.trailing == null) {
|
||||||
if (args.completeOpt) {
|
if (args.completeOpt) {
|
||||||
let opt = args.completeOpt;
|
let opt = args.completeOpt;
|
||||||
let context = complete.fork(opt.names[0], args.completeStart);
|
let context = complete.fork(opt.names[0], args.completeStart);
|
||||||
@@ -811,12 +791,12 @@ const Commands = Module("commands", {
|
|||||||
str.replace(/\s*".*$/, "");
|
str.replace(/\s*".*$/, "");
|
||||||
|
|
||||||
// 0 - count, 1 - cmd, 2 - special, 3 - args
|
// 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*)(.*?)?$/);
|
||||||
//var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/);
|
//var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/);
|
||||||
if (!matches)
|
if (!matches)
|
||||||
return [null, null, null, null];
|
return [null, null, null, null];
|
||||||
|
|
||||||
let [, count, cmd, special, args] = matches;
|
let [, spec, count, cmd, special, args] = matches;
|
||||||
|
|
||||||
// parse count
|
// parse count
|
||||||
if (count)
|
if (count)
|
||||||
@@ -824,7 +804,42 @@ const Commands = Module("commands", {
|
|||||||
else
|
else
|
||||||
count = this.COUNT_NONE;
|
count = this.COUNT_NONE;
|
||||||
|
|
||||||
return [count, cmd, !!special, args || ""];
|
return [count, cmd, !!special, args || "", spec.length];
|
||||||
|
},
|
||||||
|
|
||||||
|
parseCommands: function (str, complete) {
|
||||||
|
do {
|
||||||
|
let [count, cmd, bang, args, len] = commands.parseCommand(str);
|
||||||
|
if (cmd == null)
|
||||||
|
return;
|
||||||
|
let command = commands.get(cmd);
|
||||||
|
if (command && complete) {
|
||||||
|
complete.fork(command.name);
|
||||||
|
var context = complete.fork("args", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command && /\w[!\s]/.test(str))
|
||||||
|
args = command.parseArgs(args, context, { count: count, bang: bang });
|
||||||
|
else
|
||||||
|
args = commands.parseArgs(args, { extra: { count: count, bang: bang } });
|
||||||
|
args.commandName = cmd;
|
||||||
|
args.commandString = str.substr(0, len) + args.string;
|
||||||
|
str = args.trailing;
|
||||||
|
yield [command, args];
|
||||||
|
}
|
||||||
|
while (str);
|
||||||
|
},
|
||||||
|
|
||||||
|
_subCommands: function (command) {
|
||||||
|
let commands = [command];
|
||||||
|
while (command = commands.shift())
|
||||||
|
for (let [command, args] in this.parseCommands(command)) {
|
||||||
|
if (command) {
|
||||||
|
yield [command, args];
|
||||||
|
if (command.subCommand && args[command.subCommand])
|
||||||
|
commands.push(args[command.subCommand]);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/** @property */
|
/** @property */
|
||||||
@@ -921,8 +936,13 @@ const Commands = Module("commands", {
|
|||||||
completion.ex = function ex(context) {
|
completion.ex = function ex(context) {
|
||||||
// if there is no space between the command name and the cursor
|
// if there is no space between the command name and the cursor
|
||||||
// then get completions of the command name
|
// then get completions of the command name
|
||||||
let [count, cmd, bang, args] = commands.parseCommand(context.filter);
|
for (var [command, args] in commands.parseCommands(context.filter, context))
|
||||||
let [, prefix, junk] = context.filter.match(/^(:*\d*)\w*(.?)/) || [];
|
if (args.trailing)
|
||||||
|
context.advance(args.commandString.length + 1);
|
||||||
|
if (!args)
|
||||||
|
args = { commandString: context.filter };
|
||||||
|
|
||||||
|
let [, prefix, junk] = args.commandString.match(/^(:*\s*\d*\s*)\w*(.?)/) || [];
|
||||||
context.advance(prefix.length);
|
context.advance(prefix.length);
|
||||||
if (!junk) {
|
if (!junk) {
|
||||||
context.fork("", 0, this, "command");
|
context.fork("", 0, this, "command");
|
||||||
@@ -931,40 +951,26 @@ const Commands = Module("commands", {
|
|||||||
|
|
||||||
// dynamically get completions as specified with the command's completer function
|
// dynamically get completions as specified with the command's completer function
|
||||||
context.highlight();
|
context.highlight();
|
||||||
let command = cmd && commands.get(cmd);
|
|
||||||
if (!command) {
|
if (!command) {
|
||||||
context.highlight(0, cmd && cmd.length, "SPELLCHECK");
|
context.highlight(0, args.commandName && args.commandName.length, "SPELLCHECK");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[prefix] = context.filter.match(/^(?:\w*[\s!])?\s*/);
|
[prefix] = args.commandString.match(/^(?:\w*[\s!])?\s*/);
|
||||||
let cmdContext = context.fork(command.name, prefix.length);
|
let cmdContext = context.fork(command.name, prefix.length);
|
||||||
let argContext = context.fork("args", prefix.length);
|
try {
|
||||||
args = command.parseArgs(cmdContext.filter, argContext, { count: count, bang: bang });
|
if (!cmdContext.waitingForTab) {
|
||||||
if (args && !cmdContext.waitingForTab) {
|
if (!args.completeOpt && command.completer) {
|
||||||
// FIXME: Move to parseCommand
|
cmdContext.advance(args.completeStart);
|
||||||
args.count = count;
|
cmdContext.quote = args.quote;
|
||||||
args.bang = bang;
|
cmdContext.filter = args.completeFilter;
|
||||||
if (!args.completeOpt && command.completer) {
|
command.completer.call(command, cmdContext, args);
|
||||||
cmdContext.advance(args.completeStart);
|
|
||||||
cmdContext.quote = args.quote;
|
|
||||||
cmdContext.filter = args.completeFilter;
|
|
||||||
try {
|
|
||||||
let compObject = command.completer.call(command, cmdContext, args);
|
|
||||||
|
|
||||||
if (isArray(compObject)) // for now at least, let completion functions return arrays instead of objects
|
|
||||||
compObject = { start: compObject[0], items: compObject[1] };
|
|
||||||
if (compObject != null) {
|
|
||||||
cmdContext.advance(compObject.start);
|
|
||||||
cmdContext.filterFunc = null;
|
|
||||||
cmdContext.completions = compObject.items;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
dactyl.reportError(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (e) {
|
||||||
|
dactyl.reportError(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
completion.userCommand = function userCommand(context) {
|
completion.userCommand = function userCommand(context) {
|
||||||
@@ -1183,16 +1189,16 @@ const Commands = Module("commands", {
|
|||||||
res.list = list;
|
res.list = list;
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
Commands.complQuote = {
|
|
||||||
'"': ['"', quote("", '\n\t"\\\\'), '"'],
|
|
||||||
"'": ["'", quote("", "'", { "'": "''" }), "'"],
|
|
||||||
"": ["", quote("", "\\\\ '\""), ""]
|
|
||||||
};
|
|
||||||
|
|
||||||
Commands.quoteArg = {
|
Commands.quoteArg = {
|
||||||
'"': quote('"', '\n\t"\\\\'),
|
'"': quote('"', '\n\t"\\\\'),
|
||||||
"'": quote("'", "'", { "'": "''" }),
|
"'": quote("'", "'", { "'": "''" }),
|
||||||
"": quote("", "\\\\\\s'\"")
|
"": quote("", "|\\\\\\s'\"")
|
||||||
|
};
|
||||||
|
Commands.complQuote = {
|
||||||
|
'"': ['"', Commands.quoteArg['"'], '"'],
|
||||||
|
"'": ["'", Commands.quoteArg["'"], "'"],
|
||||||
|
"": ["", Commands.quoteArg[""], ""]
|
||||||
};
|
};
|
||||||
|
|
||||||
Commands.parseBool = function (arg) {
|
Commands.parseBool = function (arg) {
|
||||||
|
|||||||
@@ -576,7 +576,8 @@ const CompletionContext = Class("CompletionContext", {
|
|||||||
if (typeof completer == "string")
|
if (typeof completer == "string")
|
||||||
completer = self[completer];
|
completer = self[completer];
|
||||||
let context = CompletionContext(this, name, offset);
|
let context = CompletionContext(this, name, offset);
|
||||||
this.contextList.push(context);
|
if (this.contextList.indexOf(context) < 0)
|
||||||
|
this.contextList.push(context);
|
||||||
|
|
||||||
if (!context.autoComplete && !context.tabPressed && context.editor)
|
if (!context.autoComplete && !context.tabPressed && context.editor)
|
||||||
context.waitingForTab = true;
|
context.waitingForTab = true;
|
||||||
|
|||||||
@@ -392,25 +392,24 @@ const Dactyl = Module("dactyl", {
|
|||||||
modifiers = modifiers || {};
|
modifiers = modifiers || {};
|
||||||
|
|
||||||
let err = null;
|
let err = null;
|
||||||
let [count, cmd, special, args] = commands.parseCommand(str.replace(/^'(.*)'$/, "$1"));
|
for (let [command, args] in commands.parseCommands(str.replace(/^'(.*)'$/, "$1"))) {
|
||||||
let command = commands.get(cmd);
|
if (command === null) {
|
||||||
|
err = "E492: Not a " + config.name + " command: " + str;
|
||||||
|
dactyl.focusContent();
|
||||||
|
}
|
||||||
|
else if (command.action === null)
|
||||||
|
err = "E666: Internal error: command.action === null"; // TODO: need to perform this test? -- djk
|
||||||
|
else if (args.count != null && !command.count)
|
||||||
|
err = "E481: No range allowed";
|
||||||
|
else if (args.bang && !command.bang)
|
||||||
|
err = "E477: No ! allowed";
|
||||||
|
|
||||||
if (command === null) {
|
dactyl.assert(!err, err);
|
||||||
err = "E492: Not a " + config.name + " command: " + str;
|
if (!silent)
|
||||||
dactyl.focusContent();
|
commandline.command = str.replace(/^\s*:\s*/, "");
|
||||||
|
|
||||||
|
command.execute(args, modifiers);
|
||||||
}
|
}
|
||||||
else if (command.action === null)
|
|
||||||
err = "E666: Internal error: command.action === null"; // TODO: need to perform this test? -- djk
|
|
||||||
else if (count != null && !command.count)
|
|
||||||
err = "E481: No range allowed";
|
|
||||||
else if (special && !command.bang)
|
|
||||||
err = "E477: No ! allowed";
|
|
||||||
|
|
||||||
dactyl.assert(!err, err);
|
|
||||||
if (!silent)
|
|
||||||
commandline.command = str.replace(/^\s*:\s*/, "");
|
|
||||||
|
|
||||||
command.execute(args, special, count, modifiers);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1717,7 +1716,7 @@ const Dactyl = Module("dactyl", {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
dactyl.userEval(args.string);
|
dactyl.userEval(args[0]);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
dactyl.echoerr(e);
|
dactyl.echoerr(e);
|
||||||
|
|||||||
@@ -207,6 +207,15 @@ const IO = Module("io", {
|
|||||||
return io.File(file);
|
return io.File(file);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
readHeredoc: function (end) {
|
||||||
|
let args;
|
||||||
|
commandline.inputMultiline(end,
|
||||||
|
function (res) { args = res; });
|
||||||
|
while (args === undefined)
|
||||||
|
dactyl.threadYield(true);
|
||||||
|
return args;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs an external program.
|
* Runs an external program.
|
||||||
*
|
*
|
||||||
@@ -312,6 +321,7 @@ lookup:
|
|||||||
*/
|
*/
|
||||||
source: function (filename, silent) {
|
source: function (filename, silent) {
|
||||||
let wasSourcing = this.sourcing;
|
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 {
|
try {
|
||||||
@@ -355,61 +365,27 @@ lookup:
|
|||||||
let str = file.read();
|
let str = file.read();
|
||||||
let lines = str.split(/\r\n|[\r\n]/);
|
let lines = str.split(/\r\n|[\r\n]/);
|
||||||
|
|
||||||
|
this.readHeredoc = function (end) {
|
||||||
|
let res = [];
|
||||||
|
for (let [i, line] in iter)
|
||||||
|
if (line === end)
|
||||||
|
return res.join("\n");
|
||||||
|
else
|
||||||
|
res.push(line);
|
||||||
|
dactyl.assert(false, "Unexpected end of file waiting for " + end);
|
||||||
|
};
|
||||||
|
|
||||||
function execute(args) { command.execute(args, special, count, { setFrom: file }); }
|
function execute(args) { command.execute(args, special, count, { setFrom: file }); }
|
||||||
|
|
||||||
for (let [i, line] in Iterator(lines)) {
|
let iter = Iterator(lines);
|
||||||
if (heredocEnd) { // we already are in a heredoc
|
for (let [i, line] in iter) {
|
||||||
if (heredocEnd.test(line)) {
|
this.sourcing.line = i + 1;
|
||||||
execute(heredoc);
|
// skip line comments and blank lines
|
||||||
heredoc = "";
|
line = line.replace(/\r$/, "");
|
||||||
heredocEnd = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
heredoc += line + "\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.sourcing.line = i + 1;
|
|
||||||
// skip line comments and blank lines
|
|
||||||
line = line.replace(/\r$/, "");
|
|
||||||
|
|
||||||
if (/^\s*(".*)?$/.test(line))
|
if (!/^\s*(".*)?$/.test(line))
|
||||||
continue;
|
dactyl.execute(line, null, true);
|
||||||
|
|
||||||
var [count, cmd, special, args] = commands.parseCommand(line);
|
|
||||||
var command = commands.get(cmd);
|
|
||||||
|
|
||||||
if (!command) {
|
|
||||||
let lineNumber = i + 1;
|
|
||||||
|
|
||||||
dactyl.echoerr("Error detected while processing " + file.path, commandline.FORCE_MULTILINE);
|
|
||||||
commandline.echo("line " + lineNumber + ":", commandline.HL_LINENR, commandline.APPEND_TO_MESSAGES);
|
|
||||||
dactyl.echoerr("E492: Not an editor command: " + line);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (command.name == "finish")
|
|
||||||
break;
|
|
||||||
else if (command.hereDoc) {
|
|
||||||
// check for a heredoc
|
|
||||||
let matches = args.match(/(.*)<<\s*(\S+)$/);
|
|
||||||
|
|
||||||
if (matches) {
|
|
||||||
args = matches[1];
|
|
||||||
heredocEnd = RegExp("^" + matches[2] + "$", "m");
|
|
||||||
if (matches[1])
|
|
||||||
heredoc = matches[1] + "\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
execute(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no heredoc-end delimiter is found before EOF then
|
|
||||||
// process the heredoc anyway - Vim compatible ;-)
|
|
||||||
if (heredocEnd)
|
|
||||||
execute(heredoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._scriptNames.indexOf(file.path) == -1)
|
if (this._scriptNames.indexOf(file.path) == -1)
|
||||||
@@ -428,6 +404,7 @@ lookup:
|
|||||||
finally {
|
finally {
|
||||||
defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms");
|
defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms");
|
||||||
this.sourcing = wasSourcing;
|
this.sourcing = wasSourcing;
|
||||||
|
this.readHeredoc = readHeredoc;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ const Option = Class("Option", {
|
|||||||
} while (value.length);
|
} while (value.length);
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
quote: function quote(str) Commands.quoteArg[/[\s"'\\,]|^$/.test(str) ? "'" : ""](str),
|
quote: function quote(str) Commands.quoteArg[/[\s|"'\\,]|^$/.test(str) ? "'" : ""](str),
|
||||||
|
|
||||||
ops: {
|
ops: {
|
||||||
boolean: function (operator, values, scope, invert) {
|
boolean: function (operator, values, scope, invert) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
- Backtracks to the first successful match after pressing
|
- Backtracks to the first successful match after pressing
|
||||||
backspace.
|
backspace.
|
||||||
- Supports reverse incremental search.
|
- Supports reverse incremental search.
|
||||||
|
* Multiple ex commands may now be separated by |
|
||||||
* IMPORTANT: Plugins are now loaded from the 'plugins/'
|
* IMPORTANT: Plugins are now loaded from the 'plugins/'
|
||||||
directory in 'runtimepath' rather than 'plugin/'.
|
directory in 'runtimepath' rather than 'plugin/'.
|
||||||
* IMPORTANT: 'loadplugins' is not a regexlist option rather than
|
* IMPORTANT: 'loadplugins' is not a regexlist option rather than
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ FEATURES:
|
|||||||
8 :redir and 'verbosefile'
|
8 :redir and 'verbosefile'
|
||||||
8 middleclick in content == p, and if command line is open, paste there the clipboard buffer
|
8 middleclick in content == p, and if command line is open, paste there the clipboard buffer
|
||||||
8 all search commands should start searching from the top of the visible viewport
|
8 all search commands should start searching from the top of the visible viewport
|
||||||
8 allow for multiple ex commands separated with | (see #24)
|
|
||||||
8 <C-o>/<C-i> should work as in vim (i.e., save page positions as well as
|
8 <C-o>/<C-i> should work as in vim (i.e., save page positions as well as
|
||||||
locations in the history list).
|
locations in the history list).
|
||||||
8 jump to the next heading with ]h, next image ]i, previous textbox [t and so on
|
8 jump to the next heading with ]h, next image ]i, previous textbox [t and so on
|
||||||
|
|||||||
Reference in New Issue
Block a user