1 const fs = require('fs')
2 const path = require('path')
4 // add bash completions to your
5 // yargs-powered applications.
6 module.exports = function (yargs, usage, command) {
8 completionKey: 'get-yargs-completions'
11 // get a list of completion commands.
12 // 'args' is the array of strings from the line to be completed
13 self.getCompletion = function (args, done) {
14 const completions = []
15 const current = args.length ? args[args.length - 1] : ''
16 const argv = yargs.parse(args, true)
17 const aliases = yargs.parsed.aliases
19 // a custom completion function can be provided
21 if (completionFunction) {
22 if (completionFunction.length < 3) {
23 var result = completionFunction(current, argv)
25 // promise based completion function.
26 if (typeof result.then === 'function') {
27 return result.then(function (list) {
28 process.nextTick(function () { done(list) })
29 }).catch(function (err) {
30 process.nextTick(function () { throw err })
34 // synchronous completion function.
37 // asynchronous completion function
38 return completionFunction(current, argv, function (completions) {
44 var handlers = command.getCommandHandlers()
45 for (var i = 0, ii = args.length; i < ii; ++i) {
46 if (handlers[args[i]] && handlers[args[i]].builder) {
47 return handlers[args[i]].builder(yargs.reset()).argv
51 if (!current.match(/^-/)) {
52 usage.getCommands().forEach(function (command) {
53 if (args.indexOf(command[0]) === -1) {
54 completions.push(command[0])
59 if (current.match(/^-/)) {
60 Object.keys(yargs.getOptions().key).forEach(function (key) {
61 // If the key and its aliases aren't in 'args', add the key to 'completions'
62 var keyAndAliases = [key].concat(aliases[key] || [])
63 var notInArgs = keyAndAliases.every(function (val) {
64 return args.indexOf('--' + val) === -1
67 completions.push('--' + key)
75 // generate the completion script to add to your .bashrc.
76 self.generateCompletionScript = function ($0) {
77 var script = fs.readFileSync(
78 path.resolve(__dirname, '../completion.sh.hbs'),
81 var name = path.basename($0)
83 // add ./to applications not yet installed as bin.
84 if ($0.match(/\.js$/)) $0 = './' + $0
86 script = script.replace(/{{app_name}}/g, name)
87 return script.replace(/{{app_path}}/g, $0)
90 // register a function to perform your own custom
91 // completions., this function can be either
92 // synchrnous or asynchronous.
93 var completionFunction = null
94 self.registerFunction = function (fn) {
95 completionFunction = fn