| import { isCommandBuilderCallback } from './command.js'; | 
| import { assertNotStrictEqual } from './typings/common-types.js'; | 
| import * as templates from './completion-templates.js'; | 
| import { isPromise } from './utils/is-promise.js'; | 
| import { parseCommand } from './parse-command.js'; | 
| export function completion(yargs, usage, command, shim) { | 
|     const self = { | 
|         completionKey: 'get-yargs-completions', | 
|     }; | 
|     let aliases; | 
|     self.setParsed = function setParsed(parsed) { | 
|         aliases = parsed.aliases; | 
|     }; | 
|     const zshShell = (shim.getEnv('SHELL') && shim.getEnv('SHELL').indexOf('zsh') !== -1) || | 
|         (shim.getEnv('ZSH_NAME') && shim.getEnv('ZSH_NAME').indexOf('zsh') !== -1); | 
|     self.getCompletion = function getCompletion(args, done) { | 
|         const completions = []; | 
|         const current = args.length ? args[args.length - 1] : ''; | 
|         const argv = yargs.parse(args, true); | 
|         const parentCommands = yargs.getContext().commands; | 
|         function runCompletionFunction(argv) { | 
|             assertNotStrictEqual(completionFunction, null, shim); | 
|             if (isSyncCompletionFunction(completionFunction)) { | 
|                 const result = completionFunction(current, argv); | 
|                 if (isPromise(result)) { | 
|                     return result | 
|                         .then(list => { | 
|                         shim.process.nextTick(() => { | 
|                             done(list); | 
|                         }); | 
|                     }) | 
|                         .catch(err => { | 
|                         shim.process.nextTick(() => { | 
|                             throw err; | 
|                         }); | 
|                     }); | 
|                 } | 
|                 return done(result); | 
|             } | 
|             else { | 
|                 return completionFunction(current, argv, completions => { | 
|                     done(completions); | 
|                 }); | 
|             } | 
|         } | 
|         if (completionFunction) { | 
|             return isPromise(argv) | 
|                 ? argv.then(runCompletionFunction) | 
|                 : runCompletionFunction(argv); | 
|         } | 
|         const handlers = command.getCommandHandlers(); | 
|         for (let i = 0, ii = args.length; i < ii; ++i) { | 
|             if (handlers[args[i]] && handlers[args[i]].builder) { | 
|                 const builder = handlers[args[i]].builder; | 
|                 if (isCommandBuilderCallback(builder)) { | 
|                     const y = yargs.reset(); | 
|                     builder(y); | 
|                     return y.argv; | 
|                 } | 
|             } | 
|         } | 
|         if (!current.match(/^-/) && | 
|             parentCommands[parentCommands.length - 1] !== current) { | 
|             usage.getCommands().forEach(usageCommand => { | 
|                 const commandName = parseCommand(usageCommand[0]).cmd; | 
|                 if (args.indexOf(commandName) === -1) { | 
|                     if (!zshShell) { | 
|                         completions.push(commandName); | 
|                     } | 
|                     else { | 
|                         const desc = usageCommand[1] || ''; | 
|                         completions.push(commandName.replace(/:/g, '\\:') + ':' + desc); | 
|                     } | 
|                 } | 
|             }); | 
|         } | 
|         if (current.match(/^-/) || (current === '' && completions.length === 0)) { | 
|             const descs = usage.getDescriptions(); | 
|             const options = yargs.getOptions(); | 
|             Object.keys(options.key).forEach(key => { | 
|                 const negable = !!options.configuration['boolean-negation'] && | 
|                     options.boolean.includes(key); | 
|                 let keyAndAliases = [key].concat(aliases[key] || []); | 
|                 if (negable) | 
|                     keyAndAliases = keyAndAliases.concat(keyAndAliases.map(key => `no-${key}`)); | 
|                 function completeOptionKey(key) { | 
|                     const notInArgs = keyAndAliases.every(val => args.indexOf(`--${val}`) === -1); | 
|                     if (notInArgs) { | 
|                         const startsByTwoDashes = (s) => /^--/.test(s); | 
|                         const isShortOption = (s) => /^[^0-9]$/.test(s); | 
|                         const dashes = !startsByTwoDashes(current) && isShortOption(key) ? '-' : '--'; | 
|                         if (!zshShell) { | 
|                             completions.push(dashes + key); | 
|                         } | 
|                         else { | 
|                             const desc = descs[key] || ''; | 
|                             completions.push(dashes + | 
|                                 `${key.replace(/:/g, '\\:')}:${desc.replace('__yargsString__:', '')}`); | 
|                         } | 
|                     } | 
|                 } | 
|                 completeOptionKey(key); | 
|                 if (negable && !!options.default[key]) | 
|                     completeOptionKey(`no-${key}`); | 
|             }); | 
|         } | 
|         done(completions); | 
|     }; | 
|     self.generateCompletionScript = function generateCompletionScript($0, cmd) { | 
|         let script = zshShell | 
|             ? templates.completionZshTemplate | 
|             : templates.completionShTemplate; | 
|         const name = shim.path.basename($0); | 
|         if ($0.match(/\.js$/)) | 
|             $0 = `./${$0}`; | 
|         script = script.replace(/{{app_name}}/g, name); | 
|         script = script.replace(/{{completion_command}}/g, cmd); | 
|         return script.replace(/{{app_path}}/g, $0); | 
|     }; | 
|     let completionFunction = null; | 
|     self.registerFunction = fn => { | 
|         completionFunction = fn; | 
|     }; | 
|     return self; | 
| } | 
| function isSyncCompletionFunction(completionFunction) { | 
|     return completionFunction.length < 3; | 
| } |