diff --git a/common/content/commandline.js b/common/content/commandline.js index 67f85d01..c79945b1 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -1165,7 +1165,7 @@ const CommandLine = Module("commandline", { dactyl.registerObserver("echoLine", observe, true); dactyl.registerObserver("echoMultiline", observe, true); function observe(str, highlight, dom) { - buffer.push(dom ? util.domToString(dom) : str) + buffer.push(dom && !isString(str) ? util.domToString(dom) : str) } dactyl.trapErrors.apply(dactyl, [fn, self].concat(Array.slice(arguments, 2))); return buffer.join("\n"); diff --git a/common/content/commands.js b/common/content/commands.js index 6c760c3c..92b1626b 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -145,8 +145,12 @@ const Command = Class("Command", { if (args.bang && !this.bang) throw FailedAssertion("E477: No ! allowed"); + dactyl.trapErrors(function exec(command) { - this.action(args, modifiers); + if (this.always) + this.always(args, modifiers); + if (!io.sourcing || !io.sourcing.noExecute) + this.action(args, modifiers); }, this); }, @@ -1245,6 +1249,62 @@ const Commands = Module("commands", { completer: function (context) completion.userCommand(context) }); + function checkStack(cmd) { + util.assert(io.sourcing && io.sourcing.stack && + io.sourcing.stack[cmd] && io.sourcing.stack[cmd].length, + "Invalid use of conditional"); + } + function pop(cmd) { + checkStack(cmd); + return io.sourcing.stack[cmd].pop(); + } + function push(cmd, value) { + util.assert(io.sourcing, "Invalid use of conditional"); + if (arguments.length < 2) + value = io.sourcing.noExecute; + io.sourcing.stack = io.sourcing.stack || {}; + io.sourcing.stack[cmd] = (io.sourcing.stack[cmd] || []).concat([value]) + } + + commands.add(["if"], + "Execute commands until the next :elseif, :else, or :endif only if the argument returns true", + function (args) { io.sourcing.noExecute = !dactyl.userEval(args[0]); }, + { + always: function (args) { push("if") }, + argCount: "1", + literal: 0 + }); + commands.add(["elsei[f]", "elif"], + "Execute commands until the next :elseif, :else, or :endif only if the argument returns true", + function (args) {}, + { + always: function (args) { + checkStack("if"); + io.sourcing.noExecute = io.sourcing.stack.if.slice(-1)[0] || + !io.sourcing.noExecute || !dactyl.userEval(args[0]); + }, + argCount: "1", + literal: 0 + }); + commands.add(["el[se]"], + "Execute commands until the next :endif only if the previous conditionals were not executed", + function (args) {}, + { + always: function (args) { + checkStack("if"); + io.sourcing.noExecute = io.sourcing.stack.if.slice(-1)[0] || + !io.sourcing.noExecute; + }, + argCount: "0" + }); + commands.add(["en[dif]", "fi"], + "Ends a string of :if/:elseif/:else conditionals", + function (args) {}, + { + always: function (args) { io.sourcing.noExecute = pop("if") }, + argCount: "0" + }); + commands.add(["y[ank]"], "Yanks the output of the given command to the clipboard", function (args) { diff --git a/common/locale/en-US/eval.xml b/common/locale/en-US/eval.xml index b6c0912e..3ff5216b 100644 --- a/common/locale/en-US/eval.xml +++ b/common/locale/en-US/eval.xml @@ -24,6 +24,8 @@ along with paren matching and syntax error highlighting.
+
+ Execute commands until the next
+ Ends a string of
+ Execute commands until the next
+ Execute commands until the next
See also
:js <<EOF
var hello = function () {
alert(Hello world );
@@ -228,6 +230,54 @@
+Ex Command Scripts
+
+
+ Ex command scripts are similar to both entering commands on the
+ command line and to Vim
+ scripts, but with some notable differences.
+
+
+
+ Commands in Ex command scripts can span multiple lines by
+ prefixing the second and further lines with a \
+ character. For instance, the following all define commands whose
+ definitions span multiple lines.
+
+
+:command! foo
+ \ -description A command that frobs bars
+ \ :javascript frob(content.bar)
+
+:style -name foo
+ \ foobar.com
+ \ p:first-line { font-variant: small-caps ; }
+ \ div#side-bar > :first-child { display: none ; }
+
+:command do-some-stuff
+ \ -description A command does some stuff in JavaScript
+ \ :javascript <<EOF
+ \ window.do(some );
+ \ window.do(stuff );
+ \EOF
+
+:command do-some-stuff
+ \ -description A command does some stuff in JavaScript
+ \ :javascript
+ \\ window.do(some );
+ \\ window.do(stuff );
+
+
+ Lines may be commented out by prefixing them with a "
+ character.
+
+
+ " This is a comment
+ foo bar " This is a comment
+ This is not a comment
+ foo bar This is not a cumment
+
+
Profiling
-
diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS
index f9aace11..2d3bbd98 100644
--- a/pentadactyl/NEWS
+++ b/pentadactyl/NEWS
@@ -78,6 +78,7 @@
* Added "passwords" and "venkman" dialogs to :dialog.
* Added :extupdate command.
* Replaced 'focuscontent' with 'strictfocus'.
+ * Add :if/:elseif/:else/:endif conditionals.
* Changed 'urlseparator' default value to '|'.
* Added 'wildanchor' option.
* Added -javascript option to :abbrev and :map.