-
Notifications
You must be signed in to change notification settings - Fork 0
/
cli.js
130 lines (113 loc) · 2.9 KB
/
cli.js
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
/**
* This module enables commands to be entered into the STDIN of the server.
* Also closing the server should be done through this rather than through
* Ctrl+C as some cleaning takes place when the server is shut down.
*
* N.B. If two modules use the same main command name, the action will NOT be
* overridden. Both 'subscribed' actions will be executed (like in C# - function
* subscription).
*
* @module cli
* @author Luka Kralj
* @version 1.0
*/
module.exports = {
registerCommand
};
const readline = require('readline');
const logger = require('./util/logger');
const commands = {};
registerCommand("help", printHelp);
registerCommand("exit", onExit);
const cli = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
cli.setPrompt("stdin@gpioManager >> ");
// Print initial help
setTimeout(() => {
console.log("====Hello!====");
console.log("Communicate with the server via this CLI.")
console.log("N.B. To properly stop the server execute 'stop' first and then call 'exit'.");
console.log("==============");
cli.prompt();
}, 5000)
cli.on('line', async (line) => {
processLine(line);
});
/**
* Resolves command action.
*
* @param {string} line Line read.
*/
async function processLine(line) {
line = line.trim();
if (line.length == 0) {
cli.prompt();
return;
}
// parse main command
const all = line.split(" ");
const main = all[0];
const params = (all.length > 1) ? all.slice(1) : [];
if (commands.hasOwnProperty(main)) {
// valid command
executeAll(commands[main], params, "exit" != main);
}
else {
console.log("Invalid command. Type 'help' for available commands.");
cli.prompt();
}
}
async function executeAll(actions, params, prompt) {
const total = actions.length;
let executed = 0;
for (const i in actions) {
actions[i](params).then(() => {
executed++;
});
}
while (executed < total) {
await sleep(2);
}
if (prompt) {
cli.prompt();
}
}
/**
* Register a new command.
*
* @param {string} command Main command without parameters.
* @param {function} action Will receive a list of optional parameters.
*/
async function registerCommand(command, action) {
if (commands.hasOwnProperty(command)) {
commands[command].push(action);
}
else {
commands[command] = [action];
}
}
/**
* Displays valid commands.
*/
async function printHelp() {
console.log("Valid commands are:");
console.log(Object.keys(commands));
}
async function onExit() {
cli.close();
logger.info("CLI closed.")
}
/**
* Await for this function to pause execution for a certain time.
*
* @param {number} ms Time in milliseconds
* @returns {Promise}
*/
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}