1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const fs = require("fs");
|
4 | const path = require("path");
|
5 | const common_tags_1 = require("common-tags");
|
6 | const stringUtils = require('ember-cli-string-utils');
|
7 | const Command = require('../ember-cli/lib/models/command');
|
8 | const lookupCommand = require('../ember-cli/lib/cli/lookup-command');
|
9 | function extractOptions(opts) {
|
10 | const output = [];
|
11 | for (let index = 0; index < opts.length; index++) {
|
12 | const element = opts[index];
|
13 | output.push('--' + element.name);
|
14 | if (element.aliases) {
|
15 | output.push('-' + element.aliases[0]);
|
16 | }
|
17 | }
|
18 | return output.sort().join(' ');
|
19 | }
|
20 | function extractBlueprints(opts) {
|
21 | const output = [];
|
22 | for (let index = 0; index < opts.length; index++) {
|
23 | const element = opts[index];
|
24 | output.push(element.name);
|
25 | }
|
26 | return output.sort().join(' ');
|
27 | }
|
28 | const commandsToIgnore = [
|
29 | 'destroy',
|
30 | 'easter-egg',
|
31 | 'init'
|
32 | ];
|
33 | const optsNg = [];
|
34 | const CompletionCommand = Command.extend({
|
35 | name: 'completion',
|
36 | description: 'Adds autocomplete functionality to `ng` commands and subcommands.',
|
37 | works: 'everywhere',
|
38 | availableOptions: [
|
39 | {
|
40 | name: 'all',
|
41 | type: Boolean,
|
42 | default: true,
|
43 | aliases: ['a'],
|
44 | description: 'Generate a completion script compatible with both bash and zsh.'
|
45 | },
|
46 | {
|
47 | name: 'bash',
|
48 | type: Boolean,
|
49 | default: false,
|
50 | aliases: ['b'],
|
51 | description: 'Generate a completion script for bash.'
|
52 | },
|
53 | {
|
54 | name: 'zsh',
|
55 | type: Boolean,
|
56 | default: false,
|
57 | aliases: ['z'],
|
58 | description: 'Generate a completion script for zsh.'
|
59 | }
|
60 | ],
|
61 | run: function (commandOptions) {
|
62 | commandOptions.all = !commandOptions.bash && !commandOptions.zsh;
|
63 | const commandFiles = fs.readdirSync(__dirname)
|
64 | .filter(file => file.match(/\.ts$/) && !file.match(/\.run.ts$/))
|
65 | .map(file => path.parse(file).name)
|
66 | .filter(file => {
|
67 | return commandsToIgnore.indexOf(file) < 0;
|
68 | })
|
69 | .map(file => file.toLowerCase());
|
70 | const commandMap = commandFiles.reduce((acc, curr) => {
|
71 | let classifiedName = stringUtils.classify(curr);
|
72 | let defaultImport = require(`./${curr}`).default;
|
73 | acc[classifiedName] = defaultImport;
|
74 | return acc;
|
75 | }, {});
|
76 | let caseBlock = '';
|
77 | commandFiles.forEach(cmd => {
|
78 | const Command = lookupCommand(commandMap, cmd);
|
79 | const com = [];
|
80 | const command = new Command({
|
81 | ui: this.ui,
|
82 | project: this.project,
|
83 | commands: this.commands,
|
84 | tasks: this.tasks
|
85 | });
|
86 | optsNg.push(command.name);
|
87 | com.push(command.name);
|
88 | if (command.aliases) {
|
89 | command.aliases.forEach((element) => {
|
90 | optsNg.push(element);
|
91 | com.push(element);
|
92 | });
|
93 | }
|
94 | let opts = '';
|
95 | if (command.blueprints && command.blueprints[0]) {
|
96 | opts += extractBlueprints(command.blueprints);
|
97 | }
|
98 | if (command.availableOptions && command.availableOptions[0]) {
|
99 | opts += extractOptions(command.availableOptions);
|
100 | caseBlock = caseBlock + ' ' + com.sort().join('|') + ') opts="' + opts + '" ;;\n';
|
101 | }
|
102 | });
|
103 | caseBlock = 'ng|help) opts="' + optsNg.sort().join(' ') + '" ;;\n' +
|
104 | caseBlock +
|
105 | ' *) opts="" ;;';
|
106 | console.log(common_tags_1.stripIndent `
|
107 | ###-begin-ng-completion###
|
108 | #
|
109 |
|
110 | # ng command completion script
|
111 | # This command supports 3 cases.
|
112 | # 1. (Default case) It prints a common completion initialisation for both Bash and Zsh.
|
113 | # It is the result of either calling "ng completion" or "ng completion -a".
|
114 | # 2. Produce Bash-only completion: "ng completion -b" or "ng completion --bash".
|
115 | # 3. Produce Zsh-only completion: "ng completion -z" or "ng completion --zsh".
|
116 | #
|
117 | # Installation: ng completion -b >> ~/.bashrc
|
118 | # or ng completion -z >> ~/.zshrc
|
119 | #`);
|
120 | if (commandOptions.all && !commandOptions.bash) {
|
121 | console.log('if test ".$(type -t complete 2>/dev/null || true)" = ".builtin"; then');
|
122 | }
|
123 | if (commandOptions.all || commandOptions.bash) {
|
124 | console.log(common_tags_1.stripIndent `
|
125 | _ng_completion() {
|
126 | local cword pword opts
|
127 |
|
128 | COMPREPLY=()
|
129 | cword=\${COMP_WORDS[COMP_CWORD]}
|
130 | pword=\${COMP_WORDS[COMP_CWORD - 1]}
|
131 |
|
132 | case \${pword} in
|
133 | ${caseBlock}
|
134 | esac
|
135 |
|
136 | COMPREPLY=( $(compgen -W '\${opts}' -- $cword) )
|
137 |
|
138 | return 0
|
139 | }
|
140 |
|
141 | complete -o default -F _ng_completion ng
|
142 | `);
|
143 | }
|
144 | if (commandOptions.all) {
|
145 | console.log(common_tags_1.stripIndent `
|
146 | elif test ".$(type -w compctl 2>/dev/null || true)" = ".compctl: builtin" ; then
|
147 | `);
|
148 | }
|
149 | if (commandOptions.all || commandOptions.zsh) {
|
150 | console.log(common_tags_1.stripIndent `
|
151 | _ng_completion () {
|
152 | local words cword opts
|
153 | read -Ac words
|
154 | read -cn cword
|
155 | let cword-=1
|
156 |
|
157 | case $words[cword] in
|
158 | ${caseBlock}
|
159 | esac
|
160 |
|
161 | setopt shwordsplit
|
162 | reply=($opts)
|
163 | unset shwordsplit
|
164 | }
|
165 |
|
166 | compctl -K _ng_completion ng
|
167 | `);
|
168 | }
|
169 | if (commandOptions.all) {
|
170 | console.log(common_tags_1.stripIndent `
|
171 | else
|
172 | echo "Builtin command 'complete' or 'compctl' is redefined; cannot produce completion."
|
173 | return 1
|
174 | fi`);
|
175 | }
|
176 | console.log('###-end-ng-completion###');
|
177 | }
|
178 | });
|
179 | exports.default = CompletionCommand;
|
180 |
|
\ | No newline at end of file |