-
Notifications
You must be signed in to change notification settings - Fork 12k
chore(completion) - generate shell script in a much more automated way #3981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 22 commits
99b5636
746e964
f9800b7
8045f0e
cab0460
e397ff8
293e97b
a459242
a4c299c
b249f5a
0f3c82e
3de15a5
a56a1ea
5c999a2
4e10a23
c390dab
69d1b55
6a840d6
443fbed
9f7335b
da3d31a
1739176
ed1e303
58a5646
e322284
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,176 @@ | ||
import * as path from 'path'; | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
const stringUtils = require('ember-cli-string-utils'); | ||
const Command = require('../ember-cli/lib/models/command'); | ||
const lookupCommand = require('../ember-cli/lib/cli/lookup-command'); | ||
|
||
function extractOptions(opts: any): String { | ||
const output: String[] = []; | ||
|
||
for (let index = 0; index < opts.length; index++) { | ||
const element = opts[index]; | ||
output.push('--' + element.name); | ||
if (element.aliases) { | ||
output.push('-' + element.aliases[0]); | ||
} | ||
} | ||
|
||
return output.sort().join(' '); | ||
} | ||
|
||
export interface CompletionCommandOptions { | ||
all?: boolean; | ||
bash?: boolean; | ||
zsh?: boolean; | ||
}; | ||
|
||
const commandsToIgnore = [ | ||
'easter-egg', | ||
'destroy', | ||
'github-pages-deploy' // errors because there is no base github-pages command | ||
]; | ||
|
||
const optsNg: String[] = []; | ||
|
||
const CompletionCommand = Command.extend({ | ||
name: 'completion', | ||
description: 'Adds autocomplete functionality to `ng` commands and subcommands', | ||
works: 'everywhere', | ||
run: function() { | ||
const scriptPath = path.resolve(__dirname, '..', 'utilities', 'completion.sh'); | ||
const scriptOutput = fs.readFileSync(scriptPath, 'utf8'); | ||
availableOptions: [ | ||
{ name: 'all', type: Boolean, default: true, aliases: ['a'] }, | ||
{ name: 'bash', type: Boolean, default: false, aliases: ['b'] }, | ||
{ name: 'zsh', type: Boolean, default: false, aliases: ['z'] } | ||
], | ||
|
||
run: function (commandOptions: CompletionCommandOptions) { | ||
commandOptions.all = !commandOptions.bash && !commandOptions.zsh; | ||
|
||
const commandFiles = fs.readdirSync(__dirname) | ||
.filter(file => file.match(/\.ts$/) && !file.match(/\.run.ts$/)) | ||
.map(file => path.parse(file).name) | ||
.filter(file => { | ||
return commandsToIgnore.indexOf(file) < 0; | ||
}) | ||
.map(file => file.toLowerCase()); | ||
|
||
const commandMap = commandFiles.reduce((acc: any, curr: string) => { | ||
let classifiedName = stringUtils.classify(curr); | ||
let defaultImport = require(`./${curr}`).default; | ||
|
||
acc[classifiedName] = defaultImport; | ||
|
||
return acc; | ||
}, {}); | ||
|
||
let caseBlock = ''; | ||
|
||
commandFiles.forEach(cmd => { | ||
const Command = lookupCommand(commandMap, cmd); | ||
const com: String[] = []; | ||
|
||
const command = new Command({ | ||
ui: this.ui, | ||
project: this.project, | ||
commands: this.commands, | ||
tasks: this.tasks | ||
}); | ||
|
||
optsNg.push(command.name); | ||
com.push(command.name); | ||
|
||
if (command.aliases) { | ||
command.aliases.forEach((element: String) => { | ||
optsNg.push(element); | ||
com.push(element); | ||
}); | ||
} | ||
|
||
if (command.availableOptions && command.availableOptions[0]) { | ||
let opts = extractOptions (command.availableOptions); | ||
caseBlock = caseBlock + ' ' + com.sort().join('|') + ') opts="' + opts + '" ;;\n'; | ||
} | ||
}); | ||
|
||
caseBlock = 'ng|help) opts="' + optsNg.sort().join(' ') + '" ;;\n' + | ||
caseBlock + | ||
' *) opts="" ;;'; | ||
|
||
console.log(`###-begin-ng-completion### | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
# | ||
|
||
# ng command completion script | ||
# This command supports 3 cases. | ||
# 1. (Default case) It prints a common completion initialisation for both Bash and Zsh. | ||
# It is the result of either calling "ng completion" or "ng completion -a". | ||
# 2. Produce Bash-only completion: "ng completion -b" or "ng completion --bash". | ||
# 3. Produce Zsh-only completion: "ng completion -z" or "ng completion --zsh". | ||
# | ||
# Installation: ng completion -b 1>> ~/.bashrc | ||
# or ng completion -z 1>> ~/.zshrc | ||
# | ||
`); | ||
|
||
if (commandOptions.all && !commandOptions.bash) { | ||
console.log('if test ".$(type -t complete 2>/dev/null || true)" = ".builtin"; then'); | ||
} | ||
|
||
if (commandOptions.all || commandOptions.bash) { | ||
console.log(`_ng_completion() { | ||
local cword pword opts | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here; use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, too. |
||
|
||
COMPREPLY=() | ||
cword=\${COMP_WORDS[COMP_CWORD]} | ||
pword=\${COMP_WORDS[COMP_CWORD - 1]} | ||
|
||
case \${pword} in | ||
${caseBlock} | ||
esac | ||
|
||
COMPREPLY=( $(compgen -W '\${opts}' -- $cword) ) | ||
|
||
return 0 | ||
} | ||
|
||
complete -o default -F _ng_completion ng | ||
`); | ||
} | ||
|
||
if (commandOptions.all) { | ||
console.log( | ||
'elif test ".$(type -w compctl 2>/dev/null || true)" = ".compctl: builtin" ; then'); | ||
} | ||
|
||
if (commandOptions.all || commandOptions.zsh) { | ||
console.log(`_ng_completion () { | ||
local words cword opts | ||
read -Ac words | ||
read -cn cword | ||
let cword-=1 | ||
|
||
case $words[cword] in | ||
${caseBlock} | ||
esac | ||
|
||
setopt shwordsplit | ||
reply=($opts) | ||
unset shwordsplit | ||
} | ||
|
||
compctl -K _ng_completion ng | ||
`); | ||
} | ||
|
||
if (commandOptions.all) { | ||
console.log(`else | ||
echo "Shell builtin command 'complete' or 'compctl' is redefined; cannot perform ng completion." | ||
return 1 | ||
fi | ||
`); | ||
} | ||
|
||
console.log('###-end-ng-completion###'); | ||
|
||
console.log(scriptOutput); | ||
} | ||
}); | ||
|
||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop the
1
in1>>
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, changed it in completion.ts, too.