diff --git a/NEWS b/NEWS index 81eff239..8f0b886e 100644 --- a/NEWS +++ b/NEWS @@ -27,7 +27,7 @@ * add . mapping * add N% normal mode command * add interpolation for items such as to autocommands - * add -nargs, -bang, and -count attribute support to :command + * add -nargs, -complete, -bang, and -count attribute support to :command * much improved completion support, including javascript, option, and search keyword * add / and / command-line mappings for selecting the previous and next history items diff --git a/content/commands.js b/content/commands.js index 9946bbb3..f5076bce 100644 --- a/content/commands.js +++ b/content/commands.js @@ -668,6 +668,11 @@ function Commands() //{{{ liberator.execute(commands.replaceTokens(this.replacementText, tokens)); } + // TODO: add dir, highlight, menu, option completers + var completeOptionMap = { url: "url", buffer: "buffer", bookmark: "bookmark", command: "ex", + environment: "environment", event: "autocmdEvent", file: "file", shellcmd: "shellCommand", + javascript: "javascript", help: "help", mapping: "userMapping" }; + // TODO: Vim allows commands to be defined without {rep} if there are {attr}s // specified - useful? commandManager.add(["com[mand]"], @@ -684,9 +689,24 @@ function Commands() //{{{ if (args.literalArg) { - let nargsOpt = args["-nargs"] || "0"; - let bangOpt = "-bang" in args; - let countOpt = "-count" in args; + let nargsOpt = args["-nargs"] || "0"; + let bangOpt = "-bang" in args; + let countOpt = "-count" in args; + let completeOpt = args["-complete"]; + + let completeFunc = null; // default to no completion for user commands + + if (completeOpt) + { + let func; + + if (/^custom,/.test(completeOpt)) + func = completeOpt.replace("custom,", ""); + else + func = "completion." + completeOptionMap[completeOpt]; + + completeFunc = eval(func); + } if (!commands.addUserCommand( [cmd], @@ -696,6 +716,7 @@ function Commands() //{{{ argCount: nargsOpt, bang: bangOpt, count: countOpt, + completer: completeFunc, replacementText: args.literalArg }, special) @@ -706,17 +727,27 @@ function Commands() //{{{ } else { + function completerToString(completer) + { + if (completer) + return [k for ([k, v] in Iterator(completeOptionMap)) + if (v == completer.name)][0] || "custom"; + else + 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 let cmds = exCommands.filter(function (c) c.isUserCommand && (!cmd || c.name.match("^" + cmd))); if (cmds.length > 0) { - let str = template.tabular(["", "Name", "Args", "Range", "Definition"], ["padding-right: 2em;"], + let str = template.tabular(["", "Name", "Args", "Range", "Complete", "Definition"], ["padding-right: 2em;"], ([cmd.bang ? "!" : " ", cmd.name, cmd.argCount, cmd.count ? "0c" : "", + completerToString(cmd.completer), cmd.replacementText || "function () { ... }"] for each (cmd in cmds))); commandline.echo(str, commandline.HL_NORMAL, commandline.FORCE_MULTILINE); @@ -732,9 +763,12 @@ function Commands() //{{{ bang: true, completer: function (filter) completion.userCommand(filter), options: [ - [["-nargs"], commandManager.OPTION_STRING, function (arg) /^[01*?+]$/.test(arg), ["0", "1", "*", "?", "+"]], - [["-bang"], commandManager.OPTION_NOARG], + [["-nargs"], commandManager.OPTION_STRING, + function (arg) /^[01*?+]$/.test(arg), ["0", "1", "*", "?", "+"]], + [["-bang"], commandManager.OPTION_NOARG], [["-count"], commandManager.OPTION_NOARG], + [["-complete"], commandManager.OPTION_STRING, + function (arg) arg in completeOptionMap || /custom,\w+/.test(arg)] ], literal: true, serial: function () [ diff --git a/content/completion.js b/content/completion.js index 24c8846a..2bc0b08b 100644 --- a/content/completion.js +++ b/content/completion.js @@ -923,7 +923,7 @@ function Completion() //{{{ return [0, this.filter(vars, filter)]; }, - event: function event(filter) [0, this.filter(config.autocommands, filter)], + autocmdEvent: function autocmdEvent(filter) [0, this.filter(config.autocommands, filter)], // provides completions for ex commands, including their arguments ex: function ex(str) diff --git a/content/events.js b/content/events.js index f0962044..bb113aef 100644 --- a/content/events.js +++ b/content/events.js @@ -53,6 +53,7 @@ function AutoCommands() //{{{ { let values = value.split(","); let events = config.autocommands.map(function (event) event[0]); + events.push("all"); return values.every(function (event) events.indexOf(event) >= 0); @@ -113,7 +114,7 @@ function AutoCommands() //{{{ { argCount: "3", bang: true, - completer: function (filter) completion.event(filter), + completer: function (filter) completion.autocmdEvent(filter), literal: true }); @@ -126,7 +127,7 @@ function AutoCommands() //{{{ }, { argCount: "+", - completer: function (filter) completion.event(filter) + completer: function (filter) completion.autocmdEvent(filter) } ); @@ -163,7 +164,7 @@ function AutoCommands() //{{{ { // TODO: Vim actually just displays "No matching autocommands" when no arg is specified argCount: "+", - completer: function (filter) completion.event(filter) + completer: function (filter) completion.autocmdEvent(filter) } ); diff --git a/locale/en-US/map.txt b/locale/en-US/map.txt index 1c80fa2e..e67378e3 100644 --- a/locale/en-US/map.txt +++ b/locale/en-US/map.txt @@ -286,6 +286,40 @@ The valid values are: *-nargs=+* One or more argument is allowd -------------------------------------------------------------------------------- +|E180| |E181| |:command-complete| + +Argument completion + +Completion for arguments to user defined commands is not available by default. +Completion can be enabled by specifying one of the following arguments to the +-complete option when defining the command. +`----------------`-------------------------------------------------------------- +*bookmark* bookmarks +*buffer* buffers +*command* Ex commands +*environment* environment variables +*event* autocommand events +*file* files +*help* help tags +*javascript* javascript +*mapping* user mappings +*shellcmd* shell commands +*url* URLs +*custom,{func}* custom completion, provided by {func} +-------------------------------------------------------------------------------- + +|E467| |E468| |:command-completion-custom| + +Custom completion + +Custom completion can be provided by specifying the "custom,{func}" argument to +-complete. The {func} is called with one argument, the word being completed, +and should return an array [start, completions]. + +*start* is the index into the word being completed at which the returned values +should be applied and *completions* is a two dimensional array of the form: +\[[arg1, description1], [arg2, description2], ...] + +// TODO: add examples + |E177| |E178| |:command-count| + Count handling