diff --git a/common/content/commands.js b/common/content/commands.js index eb10a156..b860fbaa 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -1264,19 +1264,7 @@ var Commands = Module("commands", { }, commands: function () { - // TODO: offer completion.ex? - // : make this config specific - var completeOptionMap = { - abbreviation: "abbreviation", altstyle: "alternateStyleSheet", - bookmark: "bookmark", buffer: "buffer", color: "colorScheme", - command: "command", dialog: "dialog", dir: "directory", - environment: "environment", event: "autocmdEvent", file: "file", - help: "help", highlight: "highlightGroup", history: "history", - javascript: "javascript", macro: "macro", mapping: "userMapping", - menu: "menuItem", option: "option", preference: "preference", - search: "search", shellcmd: "shellCommand", sidebar: "sidebar", - url: "url", usercommand: "userCommand" - }; + let completerMap = config.completers; // TODO: Vim allows commands to be defined without {rep} if there are {attr}s // specified - useful? @@ -1288,22 +1276,22 @@ var Commands = Module("commands", { dactyl.assert(!cmd || commands.validName.test(cmd), "E182: Invalid command name"); if (args.literalArg) { - let completeOpt = args["-complete"]; - let completeFunc = null; // default to no completion for user commands + let completer = args["-complete"]; + let completerFunc = null; // default to no completion for user commands - if (completeOpt) { - if (/^custom,/.test(completeOpt)) { - completeOpt = completeOpt.substr(7); - completeFunc = function () { + if (completer) { + if (/^custom,/.test(completer)) { + completer = completer.substr(7); + completerFunc = function () { try { - var completer = dactyl.userEval(completeOpt); + var completer = dactyl.userEval(completer); if (!callable(completer)) - throw new TypeError("User-defined custom completer " + completeOpt.quote() + " is not a function"); + throw new TypeError("User-defined custom completer " + completer.quote() + " is not a function"); } catch (e) { dactyl.echo(":" + this.name + " ..."); - dactyl.echoerr("E117: Unknown function: " + completeOpt); + dactyl.echoerr("E117: Unknown function: " + completer); dactyl.log(e); return undefined; } @@ -1311,7 +1299,7 @@ var Commands = Module("commands", { }; } else - completeFunc = completion.closure[completeOptionMap[completeOpt]]; + completerFunc = function (context) completion.closure[completerMap[completer]](context); } let added = commands.addUserCommand([cmd], @@ -1326,7 +1314,7 @@ var Commands = Module("commands", { argCount: args["-nargs"], bang: args["-bang"], count: args["-count"], - completer: function (context) completeFunc(context), + completer: completerFunc, persist: !args["-nopersist"], replacementText: args.literalArg, sourcing: io.sourcing && update({}, io.sourcing) @@ -1338,13 +1326,11 @@ var Commands = Module("commands", { else { function completerToString(completer) { if (completer) - return [k for ([k, v] in Iterator(completeOptionMap)) if (completer == completion.closure[v])][0] || "custom"; + return [k for ([k, v] in Iterator(completerMap)) if (completer == completion.closure[v])][0] || "custom"; return ""; } - // TODO: using an array comprehension here generates flakey results across repeated calls - // : perhaps we shouldn't allow options in a list call but just ignore them for now - // : No, array comprehensions are fine, generator statements aren't. --Kris + // TODO: perhaps we shouldn't allow options in a list call but just ignore them for now let cmds = commands._exCommands.filter(function (c) c.user && (!cmd || c.name.match("^" + cmd))); if (cmds.length > 0) @@ -1376,9 +1362,9 @@ var Commands = Module("commands", { // TODO: "E180: invalid complete value: " + arg names: ["-complete", "-C"], description: "The argument completion function", - completer: function (context) [[k, ""] for ([k, v] in Iterator(completeOptionMap))], + completer: function (context) [[k, ""] for ([k, v] in Iterator(completerMap))], type: CommandOption.STRING, - validator: function (arg) arg in completeOptionMap || /custom,\w+/.test(arg), + validator: function (arg) arg in completerMap || /custom,\w+/.test(arg), }, { names: ["-description", "-desc", "-d"], description: "A user-visible description of the command", diff --git a/common/locale/en-US/map.xml b/common/locale/en-US/map.xml index 298c74e6..9bab524a 100644 --- a/common/locale/en-US/map.xml +++ b/common/locale/en-US/map.xml @@ -610,32 +610,7 @@ -complete option when defining the command.

-
-
altstyle
alternate author style sheets
-
bookmark
bookmarks
-
buffer
buffers
-
color
color schemes
-
command
Ex commands
-
dialog
&dactyl.host; dialogs
-
dir
directories
-
environment
environment variables
-
event
autocommand events
-
file
files
-
help
help tags
-
highlight
highlight groups
-
javascript
JavaScript expressions
-
macro
named macros
-
mapping
user mappings
-
menu
menu items
-
option
&dactyl.appName; options
-
preference
&dactyl.host; preferences
-
search
search engines and keywords
-
shellcmd
shell commands
-
sidebar
sidebar panels
-
url
URLs
-
usercommand
user commands
-
custom,func
custom completion, provided by func
-
+

Custom completion

diff --git a/common/modules/config.jsm b/common/modules/config.jsm index 1137e993..d2cbdff4 100644 --- a/common/modules/config.jsm +++ b/common/modules/config.jsm @@ -98,6 +98,43 @@ var ConfigBase = Class("ConfigBase", { commandContainer: "browser-bottombox", + /** + * @property {Object} A map of :command-complete option values to completer + * function names. + */ + completers: { + abbreviation: "abbreviation", + altstyle: "alternateStyleSheet", + bookmark: "bookmark", + buffer: "buffer", + charset: "charset", + color: "colorScheme", + command: "command", + dialog: "dialog", + dir: "directory", + environment: "environment", + event: "autocmdEvent", + extension: "extension", + file: "file", + help: "help", + highlight: "highlightGroup", + history: "history", + javascript: "javascript", + macro: "macro", + mapping: "userMapping", + mark: "mark", + menu: "menuItem", + option: "option", + preference: "preference", + qmark: "quickmark", + runtime: "runtime", + search: "search", + shellcmd: "shellCommand", + toolbar: "toolbar", + url: "url", + usercommand: "userCommand" + }, + /** * @property {Object} Application specific defaults for option values. The * property names must be the options' canonical names, and the values diff --git a/melodactyl/content/config.js b/melodactyl/content/config.js index c5a1a4bd..e6c1c8f0 100644 --- a/melodactyl/content/config.js +++ b/melodactyl/content/config.js @@ -63,6 +63,14 @@ const Config = Module("config", ConfigBase, { Leave: "Triggered before exiting Songbird" }, + completers: Class.memoize(function () update({ + displaypane: "displayPane", + playlist: "playlist", + mediaview: "mediaView", + mediasort: "mediaListSort", + song: "song" + }, this.__proto__.completers)), + dialogs: { about: ["About Songbird", function () { window.openDialog("chrome://songbird/content/xul/about.xul", "_blank", "chrome,dialog,modal,centerscreen"); }], diff --git a/pentadactyl/content/config.js b/pentadactyl/content/config.js index 211969f0..0b04627e 100644 --- a/pentadactyl/content/config.js +++ b/pentadactyl/content/config.js @@ -126,6 +126,8 @@ var Config = Module("config", ConfigBase, { Leave: "Triggered before exiting Firefox" }, + completers: Class.memoize(function () update({ sidebar: "sidebar", window: "window" }, this.__proto__.completers)), + defaults: { complete: "slf", guioptions: "bCrs", diff --git a/teledactyl/content/config.js b/teledactyl/content/config.js index 3aa4f198..4ba2900c 100644 --- a/teledactyl/content/config.js +++ b/teledactyl/content/config.js @@ -23,6 +23,8 @@ const Config = Module("config", ConfigBase, { get browser() getBrowser(), + completers: Class.memoize(function () update({ mailfolder: "mailFolder" }, this.__proto__.completers)), + dialogs: { about: ["About Thunderbird", function () { window.openAboutDialog(); }],