diff --git a/package.json b/package.json
index cfc78c6bd..1a027178c 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,8 @@
"description": "Gulp based script content builder",
"main": "gulpfile.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "getcommands": "node scripts/getcommands.js"
},
"repository": {
"type": "git",
diff --git a/scripts/getcommands.js b/scripts/getcommands.js
new file mode 100644
index 000000000..72012f81f
--- /dev/null
+++ b/scripts/getcommands.js
@@ -0,0 +1,186 @@
+let fs = require('fs');
+
+let commands = [];
+let cmdindex = {};
+
+let inFile = 0;
+
+function mytrim(text){
+ text = text.trim();
+ if (text.startsWith('"')) text = text.slice(1, -1);
+ return text;
+}
+
+
+function getFolder(name, cb){
+ //console.log('dir:'+name);
+
+ let list = fs.readdirSync(name);
+ for (let i = 0; i < list.length; i++){
+ let file = name + '/' + list[i];
+ let s = fs.statSync(file);
+
+ if (s.isDirectory()){
+ getFolder(file, cb);
+ } else {
+ if (file.toLowerCase().endsWith('.c') ||
+ file.toLowerCase().endsWith('.cpp')){
+ inFile++;
+ //console.log('file:'+file);
+ let data = fs.readFileSync(file);
+ let text = data.toString('utf-8');
+ let lines = text.split('\n');
+ let newlines = [];
+ let modified = 0;
+ for (let i = 0; i < lines.length; i++){
+ let line = lines[i].trim();
+ // like CMD_RegisterCommand("SetChannel", "", CMD_SetChannel, "qqqqq0", NULL);
+ if (line.startsWith('//cmddetail:')){
+ let commentlines = [];
+ let j;
+ for (j = i; j < lines.length; j++){
+ let l = lines[j].trim();
+ if (l.startsWith('//cmddetail:')){
+ l = l.slice(12);
+ commentlines.push(l);
+ newlines.push(lines[j]);
+ } else {
+ break;
+ }
+ }
+ // move our parsing forward to skip all found
+ i = j;
+ let json = commentlines.join('\n');
+ try{
+ let cmd = JSON.parse(json);
+ if (cmdindex[cmd.name]){
+ console.error('duplicate command docs at file: '+file+' line: '+line);
+ console.error(line);
+ } else {
+ commands.push(cmd);
+ cmdindex[cmd.name] = cmd;
+ }
+ } catch(e) {
+ console.error('error in json at file: '+file+' line: '+line);
+ console.error(json);
+ }
+ }
+
+ // i may have changed...
+ line = lines[i].trim();
+
+ if (line.startsWith('CMD_RegisterCommand(')){
+ line = line.slice('CMD_RegisterCommand('.length);
+ parts = line.split(',');
+ //cmddetail:{"name":"SetChannel", "args":"TODO", "fn":"CMD_SetChannel", "descr":"qqqqq0", "example":"", "file":"");
+
+ let cmd = {
+ name: mytrim(parts[0]),
+ args: mytrim(parts[1]),
+ descr: mytrim(parts[3]),
+ fn: mytrim(parts[2]),
+ file: file.slice(6),
+ requires:"",
+ examples: "",
+ };
+
+ if (cmd.descr !== 'NULL'){
+ console.log('replace "'+cmd.descr+'" with NULL');
+ lines[i] = lines[i].replace('"'+cmd.descr+'"', 'NULL');
+ modified++;
+ }
+
+ if (!cmdindex[cmd.name]){
+ // it did not have a doc line before
+ let json = JSON.stringify(cmd);
+ // insert CR at "fn":
+ json = json.split('"descr":');
+ json = json.join('\n"descr":');
+ json = json.split('"fn":');
+ json = json.join('\n"fn":');
+ json = json.split('"examples":');
+ json = json.join('\n"examples":');
+ let jsonlines = json.split('\n');
+ for (let j = 0; j < jsonlines.length; j++){
+ jsonlines[j] = '\t//cmddetail:'+jsonlines[j];
+ }
+ newlines.push(... jsonlines);
+ modified++;
+ commands.push(cmd);
+ cmdindex[cmd.name] = cmd;
+ }
+ }
+
+ newlines.push(lines[i]);
+ }
+ if (modified){
+ let newdata = newlines.join('\n');
+ try{
+ fs.writeFileSync(file, newdata);
+ console.log('updated '+file);
+ } catch (e){
+ console.error('failed to update '+file);
+ }
+ }
+
+ inFile--;
+
+ if (!inFile){
+ //if (cb) cb();
+ }
+ }
+ }
+ }
+}
+
+
+console.log('starting');
+
+getFolder('./src');
+
+
+let mdshort =
+`# Commands
+
+| Command | Arguments | Description |
+|:------------- |:------------- | -----:|
+`;
+
+let mdlong =
+`# Commands
+
+| Command | Arguments | Description | Loc |
+|:------------- |:-------------:|:----- | ------:|
+`;
+
+for (let i = 0; i < commands.length; i++){
+
+ /* like:
+ | Command | Arguments | Description |
+ | ------------- |:-------------:| -----:|
+ | setChannel | [ChannelIndex][ChannelValue] | Sets a raw channel to given value. Relay channels are using 1 and 0 values. PWM channels are within [0,100] range. Do not use this for LED control, because there is a better and more advanced LED driver with dimming and configuration memory (remembers setting after on/off), LED driver commands has "led_" prefix. |
+ | addChannel | [ChannelIndex][ValueToAdd][ClampMin][ClampMax] | Ads a given value to the channel. Can be used to change PWM brightness. Clamp min and max arguments are optional. |
+ */
+ let cmd = commands[i];
+
+ let textshort = `| ${cmd.name} | ${cmd.args}${cmd.requires?'\nReq:'+cmd.requires:''} | ${cmd.descr}${cmd.examples?'\ne.g.:'+cmd.examples:''} |`;
+ let textlong = `| ${cmd.name} | ${cmd.args}${cmd.requires?'\nReq:'+cmd.requires:''} | ${cmd.descr}${cmd.examples?'\ne.g.:'+cmd.examples:''} | ${cmd.file}\n${cmd.fn} |`;
+
+ // allow multi-row entries in table entries.
+ textshort = textshort.replace(/\n/g, '
');
+ textlong = textlong.replace(/\n/g, '
');
+
+ mdshort += textshort;
+ mdshort += '\n';
+ mdlong += textlong;
+ mdlong += '\n';
+}
+
+mdshort += '\n';
+mdlong += '\n';
+
+fs.writeFileSync('docs/commands.md', mdshort);
+console.log('wrote commands.md');
+fs.writeFileSync('docs/commands-extended.md', mdlong);
+console.log('wrote commands-extended.md');
+