UNPKG

4.15 kBJavaScriptView Raw
1//
2// Copyright (c) Microsoft and contributors. All rights reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17var _ = require('underscore');
18var fs = require('fs');
19var path = require('path');
20
21var CmdLoader = require('./cmdLoader');
22var utilsCore = require('./util/utilsCore');
23
24function AutoComplete() {
25 this.mode = utilsCore.getMode();
26 this.cmdMetadataFile = path.join(__dirname, 'plugins.' + this.mode + '.json');
27 this.cmdBasePath = __dirname;
28 var loader = new CmdLoader(this, this.mode);
29 if (loader.cmdMetadataExists()) {
30 this.initFromCmdMetadata();
31 }
32
33 this.enableAutoComplete();
34}
35
36_.extend(AutoComplete.prototype, {
37 initFromCmdMetadata: function () {
38 var data = fs.readFileSync(this.cmdMetadataFile);
39 var cachedPlugins = JSON.parse(data);
40 this.commands = cachedPlugins.commands;
41 this.categories = cachedPlugins.categories;
42 },
43
44 enableAutoComplete: function () {
45 var root = this;
46 var omelette = require('omelette');
47 root.autoComplete = omelette('azure');
48
49 function handleAutocomplete(fragment, word, line) {
50 var args = line.trim().split(' ')
51 .filter(function (a) {
52 return a !== '';
53 }).map(function (c) {
54 return c.trim();
55 });
56
57 var currentCommand;
58 var arg;
59 var index;
60 var parentCategory;
61 var currentCategory;
62
63 // start from 1, so to discard "azure" word
64 for (index = 1, currentCategory = root; index < args.length; index++) {
65 arg = args[index];
66 parentCategory = currentCategory;
67 currentCategory = currentCategory.categories[arg];
68 if (!currentCategory) {
69 break;
70 }
71 }
72
73 var tempCategory = currentCategory ? currentCategory : parentCategory;
74 var allSubCategoriesAndCommands = Object.keys(tempCategory.categories)
75 .concat(tempCategory.commands.map(function (c) { return c.name; }));
76
77 currentCommand = tempCategory.commands
78 .filter(function (c) {return c.name === arg;})[0];
79
80 //run out argument while have a valid category?
81 if (currentCategory) {
82 //return sub categories and command combind
83 return this.reply(allSubCategoriesAndCommands);
84 }
85
86 var allCommandOptions;
87 if (currentCommand) {
88 allCommandOptions = currentCommand.options.map(function (o) { return o.long; })
89 .concat(currentCommand.options.map(function (o) { return o.short; }));
90 }
91 //we are at the last arg, try match both categories and commands
92 if (index === args.length - 1) {
93 if (currentCommand) {
94 return this.reply(allCommandOptions);
95 } else {
96 return this.reply(allSubCategoriesAndCommands.filter(function (c) {
97 return utilsCore.stringStartsWith(c, arg);
98 }));
99 }
100 }
101
102 // try to match a command's options
103 var lastArg = args[args.length - 1];
104 if (currentCommand && utilsCore.stringStartsWith(lastArg, '-')) {
105 var option = currentCommand.options
106 .filter(function (c) {
107 return c.fileRelatedOption && (c.short === lastArg || c.long === lastArg);
108 })[0];
109
110 if (option) {
111 return this.reply(fs.readdirSync(process.cwd()));
112 } else {
113 return this.reply(
114 allCommandOptions.filter(function (c) { return c && utilsCore.stringStartsWith(c, lastArg);}));
115 }
116 }
117 return this.reply([]);
118 }
119
120 root.autoComplete.on('complete', handleAutocomplete);
121 root.autoComplete.init();
122 }
123});
124
125module.exports = AutoComplete;
\No newline at end of file