-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtermparse.js
More file actions
217 lines (193 loc) · 7.72 KB
/
Copy pathtermparse.js
File metadata and controls
217 lines (193 loc) · 7.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
"use strict";
const chalk = require("chalk")
//function to get defined flag property
//including values of the flag
function getflag(flg) {
//check if flags exists?
if (!this.flags.hasOwnProperty(flg)) {
console.log(chalk.red(`getFlag(): "${flg}" doesn't exists for command ${this.name}`));
process.exit();
}
return this.flags[flg];
}
//function to set flags to a specific commands
function setflags(...flagProps) {
//iterate over each provided
//flag props and set it to the command
for (let i in flagProps) {
//check for args type
if (typeof flagProps[i] !== "object") {
console.error(chalk.red(`setFlags(): invalid argument type, argument type has to be Object`));
process.exit();
}
//FIXME:
// let tmpf = { ...flagObj };
let tmpf = Object.assign({
name: "",
type: "boolean",
value: false,
usage: ""
}, flagProps[i]);
//check for same type i.e options.value should have same type as options.type
if (typeof (tmpf.value) !== tmpf.type) {
console.error(chalk.red(`setFlags(): flag ${tmpf.name} has value of invalid type. Flag takes value of type ${tmpf.type}`));
process.exit();
}
//check if flag already exists
if (this.flags.hasOwnProperty(tmpf.name)) {
console.error(chalk.red(`setFlags(): flag ${tmpf.name} already exists with the ${this.name}.`));
process.exit();
}
// console.log(`\nsetFlags::${this.name}::${tmpf.name}|\n`, cmdObj);
this.flags[tmpf.name] = { ...tmpf };
this.flags[tmpf.name]['isPresent'] = false;
}
}
function Termparse() {
//displays usage menu
this.commands = new Object();
//function used to define new commands
//takes in object property of the command
this.addCommand = function (options) {
//assigning the passed options to the tmp cmdObj
// FIXME:
// let tmp = { ...cmdObj };
options = Object.assign({
name: "",
usage: "",
run: function () { },
flags: {},
setFlags: setflags,
getFlag: getflag
}, options)
//error handling
if (options.name.length === 0) {
console.error(chalk.red("addCommand(): command name cannot be empty"));
process.exit();
}
//if command already exists
if (this.commands.hasOwnProperty(options.name)) {
console.error(chalk.red(`addCommand(): cannot have two commands with same name, ${options.name} already exists`));
process.exit();
}
if (typeof options.run !== "function") {
console.error(chalk.red(`addCommand(): no functionality added to ${cmd}. add one by passing a function to run property `));
process.exit();
}
this.commands[options.name] = { ...options };
//for chaining
return this.commands[options.name];
}
//args[0]: command
this.parse = function (args) {
if (args.length === 0) {
this.showHelp();
process.exit();
}
let cmd = args[0];//command
let cmd_args = args.slice(1);//args except command
// TODO: study this
let rxp1 = new RegExp("^\-(.*)\=([^]*)"); //for -flag=value
let rxp2 = new RegExp("^\-(.*)"); //for -flag value
this.args = new Array();
//check if `-help` flag
if (cmd === "-help") {
this.showHelp();
process.exit();
}
//check if command exists
if (!this.commands.hasOwnProperty(cmd)) {
console.log(chalk.red(`unknown command : "${cmd}"`));
this.showHelp();
process.exit();
}
for (let n in cmd_args) {
//applyting regular exp on each args
let rxp1_res = rxp1.exec(cmd_args[n]);
let rxp2_res = rxp2.exec(cmd_args[n]);
if (rxp1_res !== null) {
//for flag of type -flag=value
//if command has the flag
if (!this.commands[cmd].flags.hasOwnProperty(rxp1_res[1])) {
console.log(chalk.red(`unknown flag : "${rxp1_res[1]}"`));
this.showHelp();
process.exit();
}
let flg_obj = this.commands[cmd].flags[rxp1_res[1]];
//if flag exists and the type is boolean
if (flg_obj.type === "boolean") {
flg_obj.value = true;
flg_obj.isPresent = true;
}
//if flag exists and the type is string then next arg is it's value
if (flg_obj.type === "string") {
let flag_val_type = typeof (rxp1_res[2]);
//check if value passed?
if (flag_val_type === "undefined" || flag_val_type === "null" || rxp1_res[2].length === 0) {
console.log(chalk.red(`'-${rxp1_res[1]}' used but no value passed`));
process.exit();
}
flg_obj.value = rxp1_res[2];
flg_obj.isPresent = true;
}
} else if (rxp2_res !== null) {
//for flags of type -flag or -flag value
if (!this.commands[cmd].flags.hasOwnProperty(rxp2_res[1])) {
console.log(chalk.red(`unknown flag : "${rxp2_res[1]}"`));
this.showHelp();
process.exit();
}
let flg_obj = this.commands[cmd].flags[rxp2_res[1]];
console.log(typeof flg_obj.value)
//if flag exists and the type is boolean
if (flg_obj.type === "boolean") {
flg_obj.value = true;
flg_obj.isPresent = true;
}
//if flag exists and the type is string then next arg is it's value
if (flg_obj.type === "string") {
//error handling
//TODO: why below line?
let flag_val_type = typeof (cmd_args[parseInt(n) + 1]);
if (flag_val_type === "undefined" || flag_val_type === "null") {
console.log(chalk.red(`'-${rxp2_res[1]}' used but no value passed`));
process.exit();
}
flg_obj.value = cmd_args[parseInt(n) + 1];
flg_obj.isPresent=true;
//remove already parsed command line args
cmd_args.splice(parseInt(n) + 1, 1); //remove the next element to avoid conflict
}
} else {
//rest are arguments. store them
this.args.push(cmd_args[n]);
}
}
//executing command action
this.commands[cmd].run();
}
this.showHelp = function () {
let usage_guide = "";
for (let cmd in this.commands) {
if (this.commands[cmd].hasOwnProperty("usage")) {
usage_guide += `
${chalk.blueBright("Command:")} ${this.commands[cmd].name}
${chalk.magentaBright("Usage:")} ${this.commands[cmd].usage}
${chalk.greenBright("Flags:")}
`;
// TODO: make it clean
for (let flg in this.commands[cmd].flags) {
usage_guide += `
-${this.commands[cmd].flags[flg].name} ${this.commands[cmd].flags[flg].type} ${this.commands[cmd].flags[flg].usage}
`;
}
}
}
usage_guide += `
${chalk.yellowBright("General:")}
-help display usage guide
`;
console.log(usage_guide);
}
}
module.exports = Termparse;