mirror of
https://github.com/elkowar/eww.git
synced 2024-10-26 21:34:19 +03:00
gen-docs.js ~ widget argument type support (#148)
* Clumsy typescript / deno rewrite * Requested Changes
This commit is contained in:
parent
661c29f1d2
commit
8c5143653c
92
gen-docs.js
92
gen-docs.js
@ -1,92 +0,0 @@
|
||||
const fs = require("fs");
|
||||
fs.readFile(process.argv[process.argv.length - 1], "utf8", (err, data) => {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
} else {
|
||||
const vars = parseVars(data);
|
||||
printDocs(vars, parseDocs(data));
|
||||
}
|
||||
});
|
||||
|
||||
function parseVars(code) {
|
||||
const VAR_PATTERN = /^.*\/\/+ *@var +(.*?) +- +(.*)$/;
|
||||
const vars = {};
|
||||
for (let line of code.split("\n")) {
|
||||
const match = line.match(VAR_PATTERN);
|
||||
if (match && match.length == 3) {
|
||||
const name = match[1];
|
||||
const value = match[2];
|
||||
vars[name] = value;
|
||||
}
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
function parseDocs(code) {
|
||||
const NEW_WIDGET_PATTERN = /^.*\/\/+ *@widget +(!?)(.*?)(?: +extends +(.*))?$/;
|
||||
const DESC_PATTERN = /^.*\/\/+ *@desc +(.*)$/;
|
||||
const PROP_PATTERN = /^.*\/\/+ *@prop +(.*?) +- +(.*)$/;
|
||||
|
||||
const widgets = {};
|
||||
let currentWidget = "";
|
||||
for (let line of code.split("\n")) {
|
||||
const newWidgetMatch = line.match(NEW_WIDGET_PATTERN);
|
||||
if (newWidgetMatch && newWidgetMatch.length >= 3) {
|
||||
const name = newWidgetMatch[2];
|
||||
/** @type string[] */
|
||||
const exts = newWidgetMatch[3]
|
||||
? newWidgetMatch[3].split(/, */)
|
||||
: [];
|
||||
currentWidget = name;
|
||||
widgets[currentWidget] = {
|
||||
name,
|
||||
exts,
|
||||
props: [],
|
||||
isVisible: newWidgetMatch[1] !== "!",
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
const descMatch = line.match(DESC_PATTERN);
|
||||
if (descMatch && descMatch.length == 2) {
|
||||
widgets[currentWidget].desc = descMatch[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
const propMatch = line.match(PROP_PATTERN);
|
||||
if (propMatch && propMatch.length == 3) {
|
||||
widgets[currentWidget].props.push({
|
||||
name: propMatch[1],
|
||||
desc: propMatch[2],
|
||||
});
|
||||
}
|
||||
}
|
||||
return widgets;
|
||||
}
|
||||
|
||||
function printDocs(vars, docs) {
|
||||
let output = Object.values(docs)
|
||||
.filter((x) => x.isVisible)
|
||||
.map((x) => {
|
||||
x.props = [
|
||||
...x.props,
|
||||
...x.exts.map((w) => docs[w]).flatMap((w) => w.props),
|
||||
];
|
||||
return x;
|
||||
})
|
||||
.map((x) => printWidget(x))
|
||||
.map((x) => x.replace(/\$\w+/g, (x) => vars[x.replace("$", "")]))
|
||||
.join("\n\n");
|
||||
console.log(output);
|
||||
}
|
||||
|
||||
function printWidget(widget) {
|
||||
return `
|
||||
## \`${widget.name}\` ${widget.desc ? `\n${widget.desc}` : ""}
|
||||
|
||||
**Properties**
|
||||
${widget.props.map((prop) => `- **\`${prop.name}\`**: ${prop.desc}`).join("\n")}
|
||||
`;
|
||||
}
|
||||
|
||||
// vim:ft=javascript
|
144
gen-docs.ts
Normal file
144
gen-docs.ts
Normal file
@ -0,0 +1,144 @@
|
||||
interface WidgetData {
|
||||
name: string;
|
||||
desc: string;
|
||||
type: string; // this should be an enum.. maybe
|
||||
}
|
||||
|
||||
interface Widget {
|
||||
name: string;
|
||||
exts: string[];
|
||||
desc: string;
|
||||
props: WidgetData[];
|
||||
isVisible: boolean;
|
||||
}
|
||||
|
||||
function parseVars(code: string): Record<string, string> {
|
||||
const VAR_PATTERN = /^.*\/\/+ *@var +(.*?) +- +(.*)$/;
|
||||
const vars: Record<string, string> = {};
|
||||
|
||||
for (const line of code.split("\n")) {
|
||||
|
||||
const match = line.match(VAR_PATTERN);
|
||||
if (match && match.length == 3) {
|
||||
const name = match[1];
|
||||
const value = match[2];
|
||||
vars[name] = value;
|
||||
}
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
function replaceTypeNames(type: string) {
|
||||
|
||||
switch (type) {
|
||||
case "f64":
|
||||
case "f32":
|
||||
return "float"
|
||||
case "i32":
|
||||
case "i64":
|
||||
return "int"
|
||||
default:
|
||||
return type
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function parseDocs(code: string) {
|
||||
const NEW_WIDGET_PATTERN = /^.*\/\/+ *@widget +(!?)(.*?)(?: +extends +(.*))?$/;
|
||||
const DESC_PATTERN = /^.*\/\/+ *@desc +(.*)$/;
|
||||
const PROP_PATTERN = /^.*\/\/+ *@prop +(.*?) +- +(.*)$/;
|
||||
const ARG_TYPE_PATTERN = /(\w+):\s+as_(\w+)/g;
|
||||
|
||||
const widgets: Record<string, Widget> = {};
|
||||
const lines = code.split("\n")
|
||||
|
||||
let currentWidget = "";
|
||||
|
||||
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
||||
|
||||
const line = lines[lineIndex]
|
||||
const newWidgetMatch = NEW_WIDGET_PATTERN.exec(line);
|
||||
|
||||
if (newWidgetMatch && newWidgetMatch.length >= 3) {
|
||||
const name = newWidgetMatch[2];
|
||||
/** @type string[] */
|
||||
const exts = newWidgetMatch[3]
|
||||
? newWidgetMatch[3].split(/, */)
|
||||
: [];
|
||||
currentWidget = name;
|
||||
widgets[currentWidget] = {
|
||||
name,
|
||||
exts,
|
||||
desc: "",
|
||||
props: [],
|
||||
isVisible: newWidgetMatch[1] !== "!",
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
const descMatch = line.match(DESC_PATTERN);
|
||||
if (descMatch && descMatch.length == 2) {
|
||||
widgets[currentWidget].desc = descMatch[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
const propMatch = line.match(PROP_PATTERN);
|
||||
if (propMatch && propMatch.length == 3) {
|
||||
let no = lineIndex + 1
|
||||
|
||||
while (/\s*\/\//.test(lines[no])) {
|
||||
no += 1
|
||||
} // continue till you find the line with actual code
|
||||
|
||||
const matches = [...lines[no].matchAll(ARG_TYPE_PATTERN)].map(z => { z.shift(); return z }).flat() // try to use the iterator directly
|
||||
|
||||
const possibleMatch = matches.findIndex(x => x == propMatch[1].replaceAll("-", "_"))
|
||||
if (possibleMatch == -1) {
|
||||
console.log(`Failed to find a match for "${propMatch[1].replace("-", "_")}" ~ ${JSON.stringify(matches, null, 2)} ~ ${lines[no]}`)
|
||||
}
|
||||
const type = replaceTypeNames(matches[possibleMatch + 1])
|
||||
|
||||
widgets[currentWidget].props.push({
|
||||
name: propMatch[1],
|
||||
desc: propMatch[2],
|
||||
type: type ?? "no-type-found"
|
||||
});
|
||||
}
|
||||
}
|
||||
return widgets;
|
||||
}
|
||||
|
||||
function printDocs(vars: Record<string, string>, docs: Record<string, Widget>) {
|
||||
const output = Object.values(docs)
|
||||
.filter((x) => x.isVisible)
|
||||
.map((x) => {
|
||||
x.props = [
|
||||
...x.props,
|
||||
...x.exts.map((w) => docs[w]).flatMap((w) => w.props),
|
||||
];
|
||||
return x;
|
||||
})
|
||||
.map((x) => printWidget(x))
|
||||
.map((x) => x.replace(/\$\w+/g, (x) => vars[x.replace("$", "")]))
|
||||
.join("\n\n");
|
||||
console.log(output);
|
||||
}
|
||||
|
||||
function printWidget(widget: Widget) {
|
||||
return `
|
||||
## \`${widget.name}\` ${widget.desc ? `\n${widget.desc}` : ""}
|
||||
|
||||
**Properties**
|
||||
${widget.props.map((prop) => `- **\`${prop.name}\`**: *\`${prop.type}\`* ${prop.desc}`).join("\n")}
|
||||
`;
|
||||
}
|
||||
|
||||
// Deno args start from actual args
|
||||
// Redirect stderr to ignore deno checking messages so:
|
||||
// deno run --allow-read gen-docs.ts ./src/widgets/widget_definitions.ts 2> /dev/null
|
||||
Deno.readTextFile(Deno.args[0]).then(data => {
|
||||
const vars = parseVars(data);
|
||||
printDocs(vars, parseDocs(data));
|
||||
}).catch(err => {
|
||||
return console.error(err);
|
||||
})
|
Loading…
Reference in New Issue
Block a user