diff options
author | Kris Maglione <maglione.k@gmail.com> | 2010-12-18 11:54:31 -0500 |
---|---|---|
committer | Kris Maglione <maglione.k@gmail.com> | 2010-12-18 11:54:31 -0500 |
commit | f1e4ef93dfefe9c06e011c8c53f6d09aa1cec5a5 (patch) | |
tree | 0eda4a26ee5494ee84460a6ac3ca4225493e26cf /common/content | |
parent | 3f343d0d983f0e6c67a8515a4dcc6622531a7ae5 (diff) | |
download | pentadactyl-f1e4ef93dfefe9c06e011c8c53f6d09aa1cec5a5.tar.gz |
Add :list* commands, linkify help tags in certain output, and augment :yank to accept JavaScript directly.
Diffstat (limited to 'common/content')
-rw-r--r-- | common/content/commandline.js | 16 | ||||
-rw-r--r-- | common/content/commands.js | 14 | ||||
-rw-r--r-- | common/content/dactyl.js | 39 | ||||
-rw-r--r-- | common/content/mappings.js | 80 | ||||
-rw-r--r-- | common/content/options.js | 30 |
5 files changed, 150 insertions, 29 deletions
diff --git a/common/content/commandline.js b/common/content/commandline.js index b9e2147d..cd7f8c22 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -940,14 +940,18 @@ const CommandLine = Module("commandline", { dactyl.open(event.target.href, where); } + let command = event.originalTarget.getAttributeNS(NS.uri, "command"); + if (command && dactyl.commands[command]) { + return dactyl.withSavedValues(["forceNewTab"], function () { + dactyl.forceNewTab = event.ctrlKey || event.shiftKey || event.button == 1; + dactyl.commands[command](event); + }); + } + switch (key) { case "<LeftMouse>": event.preventDefault(); - let command = event.originalTarget.getAttributeNS(NS.uri, "command"); - if (command && dactyl.commands[command]) - return dactyl.commands[command](event); - else - openLink(dactyl.CURRENT_TAB); + openLink(dactyl.CURRENT_TAB); return false; case "<MiddleMouse>": case "<C-LeftMouse>": @@ -1708,7 +1712,7 @@ const CommandLine = Module("commandline", { { validator: function (value) value >= 1 }); options.add(["messages", "msgs"], - "Number of messages to store in the :message history", + "Number of messages to store in the :messages history", "number", 100, { validator: function (value) value >= 0 }); diff --git a/common/content/commands.js b/common/content/commands.js index 46f9a4fb..5c16bc8e 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -1395,6 +1395,15 @@ const Commands = Module("commands", { completer: function (context) completion.userCommand(context) }); + dactyl.addUsageCommand({ + name: ["listc[ommands]", "lc"], + description: "List all Ex commands along with their short descriptions", + iterate: function (args) commands, + format: { + description: function (cmd) template.linkifyHelp(cmd.description + (cmd.replacementText ? ": " + cmd.action : "")) + } + }); + function checkStack(cmd) { util.assert(io.sourcing && io.sourcing.stack && io.sourcing.stack[cmd] && io.sourcing.stack[cmd].length, @@ -1454,13 +1463,14 @@ const Commands = Module("commands", { commands.add(["y[ank]"], "Yanks the output of the given command to the clipboard", function (args) { - let res = commandline.withOutputToString(commands.execute, commands, args[0]); + let cmd = /^:/.test(args[0]) ? args[0] : ":echo " + args[0]; + let res = commandline.withOutputToString(commands.execute, commands, cmd); dactyl.clipboardWrite(res); let lines = res.split("\n").length; dactyl.echomsg("Yanked " + lines + " line" + (lines == 1 ? "" : "s")); }, { - completer: function (context) completion.ex(context), + completer: function (context) completion[/^:/.test(context.filter) ? "ex" : "javascript"](context), literal: 0 }); }, diff --git a/common/content/dactyl.js b/common/content/dactyl.js index 84731c65..bf2b0bdc 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -48,6 +48,10 @@ const Dactyl = Module("dactyl", { this.commands = {}; this.modules = modules; this.observers = {}; + + this.commands["dactyl.help"] = function (event) { + dactyl.help(event.originalTarget.textContent); + }; }, /** @property {string} The name of the current user profile. */ @@ -139,6 +143,35 @@ const Dactyl = Module("dactyl", { }); }, + addUsageCommand: function (params) { + commands.add(params.name, params.description, + function (args) { + let results = array(params.iterate(args)) + .sort(function (a, b) String.localeCompare(a.name, b.name)); + if (args.length) + results = results.filter(function (item) args.map(String.toLowerCase) + .every(function (arg) (item.name + item.description).toLowerCase().indexOf(arg) >= 0)); + commandline.commandOutput( + template.usage(results, params.format)); + }, + { + argCount: "*", + completer: function (context, args) { + context.keys.text = util.identity; + context.keys.description = function () seen[this.text] + " matching items"; + let seen = {}; + context.completions = array(item.description.toLowerCase().split(/[()\s]+/) + for (item in params.iterate(args))) + .flatten().filter(function (w) /^\w[\w-_']+$/.test(w)) + .map(function (k) { + seen[k] = (seen[k] || 0) + 1; + return k; + }).uniq() + }, + options: params.options || [] + }); + }, + /** * Triggers the application bell to notify the user of an error. The * bell may be either audible or visual depending on the value of the @@ -257,8 +290,7 @@ const Dactyl = Module("dactyl", { if (typeof str == "object" && "echoerr" in str) str = str.echoerr; else if (isinstance(str, ["Error"])) - str = str.fileName.replace(/^.*? -> /, "") - + ":" + str.lineNumber + ": " + str; + str = <>{str.fileName.replace(/^.*? -> /, "")}: {str.lineNumber}: {str}</>; if (options["errorbells"]) dactyl.beep(); @@ -1044,7 +1076,7 @@ const Dactyl = Module("dactyl", { reportError: function reportError(error, echo) { if (error instanceof FailedAssertion || error.message === "Interrupted") { if (error.message) - dactyl.echoerr(error.message); + dactyl.echoerr(template.linkifyHelp(error.message)); else dactyl.beep(); return; @@ -1935,7 +1967,6 @@ const Dactyl = Module("dactyl", { argCount: "0", bang: true }); - }, completion: function () { diff --git a/common/content/mappings.js b/common/content/mappings.js index 08c71404..db256085 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -185,16 +185,17 @@ const Mappings = Module("mappings", { some(function (m) m.rhs && m.rhs === map.rhs && m.name === map.name)))) }, - // NOTE: just normal mode for now - /** @property {Iterator(Map)} @private */ - __iterator__: function () { - let mode = modes.NORMAL; + iterate: function (mode) { let seen = {}; for (let map in iterAll(values(this._user[mode]), values(this._main[mode]))) if (!set.add(seen, map.name)) yield map; }, + // NOTE: just normal mode for now + /** @property {Iterator(Map)} */ + __iterator__: function () this.iterate(modes.NORMAL), + // used by :mkpentadactylrc to save mappings /** * Returns a user-defined mappings iterator for the specified *mode*. @@ -381,19 +382,6 @@ const Mappings = Module("mappings", { } } - function findMode(name) { - for (let mode in modes.mainModes) - if (name == mode || name == mode.char || String.toLowerCase(name).replace(/-/g, "_") == mode.name.toLowerCase()) - return mode.mask; - return null; - } - function uniqueModes(modes) { - modes = modes.map(modules.modes.closure.getMode); - let chars = [k for ([k, v] in Iterator(modules.modes.modeChars)) - if (v.every(function (mode) modes.indexOf(mode) >= 0))]; - return array.uniq(modes.filter(function (m) chars.indexOf(m.char) < 0).concat(chars)); - } - const opts = { completer: function (context, args) { if (args.length == 1) @@ -511,8 +499,66 @@ const Mappings = Module("mappings", { }); } + function findMode(name) { + for (let mode in modes.mainModes) + if (name == mode || name == mode.char || String.toLowerCase(name).replace(/-/g, "_") == mode.name.toLowerCase()) + return mode.mask; + return null; + } + function uniqueModes(modes) { + modes = modes.map(modules.modes.closure.getMode); + let chars = [k for ([k, v] in Iterator(modules.modes.modeChars)) + if (v.every(function (mode) modes.indexOf(mode) >= 0))]; + return array.uniq(modes.filter(function (m) chars.indexOf(m.char) < 0).concat(chars)); + } + addMapCommands("", [modes.NORMAL, modes.VISUAL], ""); + let args = { + getMode: function (args) findMode(args["-mode"]), + iterate: function (args) { + for (let map in mappings.iterate(this.getMode(args))) + for (let name in values(map.names)) + yield { name: name, __proto__: map }; + }, + format: { + description: function (map) (XML.ignoreWhitespace = false, XML.prettyPrinting = false, <> + {options.get("passkeys").has(map.name) + ? <span highlight="URLExtra">(passed by {template.helpLink("'passkeys'")})</span> + : <></>} + {template.linkifyHelp(map.description + (map.rhs ? ": " + map.rhs : ""))} + </>) + } + } + + dactyl.addUsageCommand({ + __proto__: args, + name: ["listk[eys]", "lk"], + description: "List all mappings along with their short descriptions", + options: [ + { + names: ["-mode", "-m"], + type: CommandOption.STRING, + description: "The mode for which to list mappings", + default: "n", + completer: function () [[array.compact([mode.name.toLowerCase().replace(/_/g, "-"), mode.char]), mode.disp] + for (mode in modes.mainModes)], + validator: function (m) findMode(m) + } + ] + }); + + forEach(modes.mainModes, function (mode) { + if (mode.char && !commands.get(mode.char + "listkeys", true)) + dactyl.addUsageCommand({ + __proto__: args, + name: [mode.char + "listk[eys]", mode.char + "lk"], + description: "List all " + mode.name + " mode mappings along with their short descriptions", + getMode: function (args) mode, + options: [] + }); + }); + for (let mode in modes.mainModes) if (mode.char && !commands.get(mode.char + "map", true)) addMapCommands(mode.char, diff --git a/common/content/options.js b/common/content/options.js index 99e6d51f..5454ec62 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -817,6 +817,36 @@ const Options = Module("options", { }, { }, { commands: function () { + let args = { + getMode: function (args) findMode(args["-mode"]), + iterate: function (args) { + for (let map in mappings.iterate(this.getMode(args))) + for (let name in values(map.names)) + yield { name: name, __proto__: map }; + }, + format: { + description: function (map) (XML.ignoreWhitespace = false, XML.prettyPrinting = false, <> + {options.get("passkeys").has(map.name) + ? <span highlight="URLExtra">(passed by {template.helpLink("'passkeys'")})</span> + : <></>} + {template.linkifyHelp(map.description)} + </>) + } + } + + dactyl.addUsageCommand({ + name: ["listo[ptions]", "lo"], + description: "List all options along with their short descriptions", + iterate: function (args) options, + format: { + description: function (opt) (XML.ignoreWhitespace = false, XML.prettyPrinting = false, <> + {opt.scope == Option.SCOPE_LOCAL + ? <span highlight="URLExtra">(buffer local)</span> : ""} + {template.linkifyHelp(opt.description)} + </>) + } + }); + function setAction(args, modifiers) { let bang = args.bang; if (!args.length) |