-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprogram.js
More file actions
137 lines (123 loc) · 3.5 KB
/
program.js
File metadata and controls
137 lines (123 loc) · 3.5 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
import * as std from 'std';
import * as os from 'os';
import arg from 'ext/arg.js';
import * as path from 'ext/path.js';
const VERSION = '0.1.0';
const mySelf = path.getScriptName(true);
/*
generate usage message
*/
const getUsage = () => {
const message = `
Usage: ${mySelf} [option]...
-f, --first (*) : first number
-s, --second (*) : second number
-o, --operation (*) : operation to perform (+,x)
-v, --verbose : display extra informations on stderr
-h, --help : print help
`.trim();
return message;
}
/*
generate help message (displayed when using --help)
*/
const getHelp = () => {
// program purpose
const message = `
Sample command-line program
https://github.com/ctn-malone/cli-example
Version ${VERSION}
`.trimStart();
// some examples to display
const examples = `
Examples:
${mySelf} -f 1 -s 1 -o + (result = 2)
${mySelf} -f 2 -s 2 -o x (result = 4)
`.trimStart();
return `${message}\n${getUsage()}\n\n${examples}`;
}
/*
arguments parsing
*/
let args;
try {
args = arg({
// first number
'--first': (val, name, prev, index) => {
const value = val.trim();
const num = parseInt(value);
if (isNaN(num)) {
const err = new Error(`Invalid option value: ${n} ${value} (should be an integer)`);
err.code = 'ARG_INVALID_OPTION';
throw err;
}
return num;
},
// second number
'--second': (val, name, prev, index) => {
const value = val.trim();
const num = parseInt(value);
if (isNaN(num)) {
const err = new Error(`Invalid option value: ${n} ${value} (should be an integer)`);
err.code = 'ARG_INVALID_OPTION';
throw err;
}
return num;
},
// operation
'--operation': (val, name, prev, index) => {
const operations = ['+', 'x'];
if (!operations.includes(val)) {
const err = new Error(`Invalid option value: ${n} ${value} (should be one of [${operations.join(',')}])`);
err.code = 'ARG_INVALID_OPTION';
throw err;
}
return val;
},
'--verbose': Boolean,
'--help': Boolean,
// aliases
'-h': '--help',
'-f': '--first',
'-s': '--second',
'-o': '--operation',
'-v': '--verbose'
});
}
catch (e) {
switch (e.code) {
case 'ARG_UNKNOWN_OPTION':
case 'ARG_INVALID_OPTION':
case 'ARG_MISSING_REQUIRED_SHORTARG':
case 'ARG_MISSING_REQUIRED_LONGARG':
std.err.printf(`${e.message.trim()}\n`);
std.err.printf(`${getUsage()}\n`);
std.exit(2);
}
throw e;
}
if (args['--help']) {
std.err.printf(`${getHelp()}\n`);
std.exit(2);
}
// ensure all required arguments were provided
['--first', '--second', '--operation'].forEach((n) => {
if (undefined === args[n]) {
std.err.printf(`Option ${n} is required\n`);
std.err.printf(`${getUsage()}\n`);
std.exit(2);
}
});
// display extra information on stderr
if (args['--verbose']) {
std.err.puts(`${args['--first']} ${args['--operation']} ${args['--second']}\n`)
}
// compute result
let result;
if ('+' == args['--operation']) {
result = args['--first'] + args['--second'];
}
else {
result = args['--first'] * args['--second'];
}
std.out.puts(`${result}\n`);