mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-18 11:44:05 +08:00
feat(@angular/cli): Generate completion.sh automatically.
It requires little tweaking in the case-block. Now the completion shell script is generated out of TypeScript code entirely. The options and aliases are generated dynamically. There are options to only produce bash- or zsh-specific code. Closes #3981.
This commit is contained in:
parent
3b62a93a6d
commit
d2f8ca7215
@ -285,19 +285,19 @@ To turn on auto completion use the following commands:
|
||||
|
||||
For bash:
|
||||
```bash
|
||||
ng completion 1>> ~/.bashrc 2>>&1
|
||||
ng completion --bash >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
For zsh:
|
||||
```bash
|
||||
ng completion 1>> ~/.zshrc 2>>&1
|
||||
ng completion --zsh >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
Windows users using gitbash:
|
||||
```bash
|
||||
ng completion 1>> ~/.bash_profile 2>>&1
|
||||
ng completion --bash >> ~/.bash_profile
|
||||
source ~/.bash_profile
|
||||
```
|
||||
|
||||
|
@ -1,17 +1,181 @@
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import { oneLine, stripIndent } from 'common-tags';
|
||||
|
||||
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(stripIndent`
|
||||
###-begin-ng-completion###
|
||||
#
|
||||
|
||||
# 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 >> ~/.bashrc
|
||||
# or ng completion -z >> ~/.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(stripIndent`
|
||||
_ng_completion() {
|
||||
local cword pword opts
|
||||
|
||||
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(stripIndent`
|
||||
elif test ".$(type -w compctl 2>/dev/null || true)" = ".compctl: builtin" ; then
|
||||
`);
|
||||
}
|
||||
|
||||
if (commandOptions.all || commandOptions.zsh) {
|
||||
console.log(stripIndent`
|
||||
_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(stripIndent`
|
||||
else
|
||||
echo "Builtin command 'complete' or 'compctl' is redefined; cannot produce completion."
|
||||
return 1
|
||||
fi`);
|
||||
}
|
||||
|
||||
console.log('###-end-ng-completion###');
|
||||
|
||||
console.log(scriptOutput);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,85 +0,0 @@
|
||||
###-begin-ng-completion###
|
||||
#
|
||||
# ng command completion script
|
||||
#
|
||||
# Installation: ng completion 1>> ~/.bashrc 2>>&1
|
||||
# or ng completion 1>> ~/.zshrc 2>>&1
|
||||
#
|
||||
|
||||
ng_opts='b build completion doc e2e g generate get github-pages:deploy gh-pages:deploy h help i init install lint make-this-awesome new s serve server set t test v version'
|
||||
|
||||
build_opts='--aot --base-href --environment --i18n-file --i18n-format --locale --output-path --progress --sourcemap --suppress-sizes --target --vendor-chunk --verbose --watch --watcher -bh -dev -e -o -prod -sm -t -w'
|
||||
generate_opts='class component directive enum module pipe route service c cl d e m p r s --help'
|
||||
github_pages_deploy_opts='--base-href --environment --gh-token --gh-username --message --skip-build --target --user-page --custom-domain -cd -bh -e -t'
|
||||
help_opts='--json --verbose -v'
|
||||
init_opts='--dry-run inline-style inline-template --link-cli --name --prefix --routing --skip-npm --source-dir --style --verbose -d -is -it -lc -n -p -sb -sd -sn -v'
|
||||
new_opts='--directory --dry-run inline-style inline-template --link-cli --prefix --routing --skip-git --skip-npm --source-dir --style --verbose -d -dir -is -it -lc -p -sb -sd -sg -sn -v'
|
||||
serve_opts='--aot --environment --hmr --host --i18n-file --i18n-format --live-reload --live-reload-base-url --live-reload-host --live-reload-live-css --live-reload-port --locale --open --port --proxy-config --sourcemap --ssl --ssl-cert --ssl-key --target --watcher -H -e -lr -lrbu -lrh -lrp -o -p -pc -sm -t -w'
|
||||
set_opts='--global -g'
|
||||
test_opts='--browsers --build --code-coverage --colors --lint --log-level --port --reporters --single-run --sourcemap --watch -cc -l -sm -sr -w'
|
||||
|
||||
version_opts='--verbose'
|
||||
|
||||
if test ".$(type -t complete 2>/dev/null || true)" = ".builtin"; then
|
||||
_ng_completion() {
|
||||
local cword pword opts
|
||||
|
||||
COMPREPLY=()
|
||||
cword=${COMP_WORDS[COMP_CWORD]}
|
||||
pword=${COMP_WORDS[COMP_CWORD - 1]}
|
||||
|
||||
case ${pword} in
|
||||
ng) opts=$ng_opts ;;
|
||||
b|build) opts=$build_opts ;;
|
||||
g|generate) opts=$generate_opts ;;
|
||||
gh-pages:deploy|github-pages:deploy) opts=$github_pages_deploy_opts ;;
|
||||
h|help|-h|--help) opts=$help_opts ;;
|
||||
init) opts=$init_opts ;;
|
||||
new) opts=$new_opts ;;
|
||||
s|serve|server) opts=$serve_opts ;;
|
||||
set) opts=$set_opts ;;
|
||||
t|test) opts=$test_opts ;;
|
||||
v|version) opts=$version_opts ;;
|
||||
*) opts='' ;;
|
||||
esac
|
||||
|
||||
COMPREPLY=( $(compgen -W '${opts}' -- $cword) )
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o default -F _ng_completion ng
|
||||
elif test ".$(type -w compctl 2>/dev/null || true)" = ".compctl: builtin" ; then
|
||||
_ng_completion () {
|
||||
local words cword opts
|
||||
read -Ac words
|
||||
read -cn cword
|
||||
let cword-=1
|
||||
|
||||
case $words[cword] in
|
||||
ng) opts=$ng_opts ;;
|
||||
b|build) opts=$build_opts ;;
|
||||
g|generate) opts=$generate_opts ;;
|
||||
gh-pages:deploy|github-pages:deploy) opts=$github_pages_deploy_opts ;;
|
||||
h|help|-h|--help) opts=$help_opts ;;
|
||||
init) opts=$init_opts ;;
|
||||
new) opts=$new_opts ;;
|
||||
s|serve|server) opts=$serve_opts ;;
|
||||
set) opts=$set_opts ;;
|
||||
t|test) opts=$test_opts ;;
|
||||
v|version) opts=$version_opts ;;
|
||||
*) opts='' ;;
|
||||
esac
|
||||
|
||||
setopt shwordsplit
|
||||
reply=($opts)
|
||||
unset shwordsplit
|
||||
}
|
||||
|
||||
compctl -K _ng_completion ng
|
||||
else
|
||||
echo "Shell builtin command 'complete' or 'compctl' is redefined; cannot perform ng completion."
|
||||
return 1
|
||||
fi
|
||||
|
||||
###-end-ng-completion###
|
Loading…
x
Reference in New Issue
Block a user