Skip to content

Instantly share code, notes, and snippets.

@nikeee
Last active October 10, 2023 18:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikeee/748301705d3ed53b6b8776fba8748a9b to your computer and use it in GitHub Desktop.
Save nikeee/748301705d3ed53b6b8776fba8748a9b to your computer and use it in GitHub Desktop.
replaces `#include filename` with the contents of the file
#!/usr/bin/env node
// @ts-check
import { createReadStream } from "node:fs";
import { realpath } from "node:fs/promises";
import * as rl from "node:readline/promises";
import * as path from "node:path";
const fileToProcess = process.argv[2];
if (!fileToProcess) {
console.error("No file specified");
process.exit(1);
}
emitFile(await realpath(path.resolve(fileToProcess)), []);
/**
* @param {import("fs").PathLike} file
* @param {import("fs").PathLike[]} alreadyIncluded
*/
async function emitFile(file, alreadyIncluded) {
const lines = rl.createInterface({
input: createReadStream(file),
});
for await (const line of lines) {
if (line.startsWith("#")) {
const includeStatement = /^#include\s+([\w\./-]+)$/gi.exec(line);
if (includeStatement) {
const includedFile = includeStatement[1];
let includedFileFullPath = path.resolve(path.dirname(file), includedFile);
if (file === includedFileFullPath) {
console.error(`Circular dependency detected: ${file} -> ${includedFile}, skipping include`);
continue;
}
includedFileFullPath = await realpath(includedFileFullPath);
if (file === includedFileFullPath || alreadyIncluded.includes(includedFileFullPath)) {
console.error(`Circular dependency detected: ${file} -> ${includedFile}, skipping include`);
} else {
await emitFile(includedFileFullPath, [...alreadyIncluded, file]);
}
continue;
}
}
process.stdout.write(line + "\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment