rescript
Version:
178 lines (170 loc) • 4.85 kB
JavaScript
//@ts-check
var arg = require("./rescript_arg.js");
var format_usage = `Usage: rescript format <options> [files]
rescript format -- it format the current directory
`;
var child_process = require("child_process");
var path = require("path");
var fs = require("fs");
/**
* @type {arg.stringref}
*/
var stdin = { val: undefined };
/**
* @type {arg.boolref}
*/
var format = { val: undefined };
/**
* @type{arg.specs}
*/
var specs = [
[
"-stdin",
{ kind: "String", data: { kind: "String_set", data: stdin } },
`[.res|.resi|.ml|.mli|.re|.rei] Read the format code from stdin and print the formatted code
in the stdout (in rescript syntax)`,
],
// ml|mli
[
"-all",
{ kind: "Unit", data: { kind: "Unit_set", data: format } },
"Formatting the whole project ",
],
];
var formattedStdExtensions = [".res", ".resi", ".ml", ".mli", ".re", ".rei"];
var formattedFileExtensions = [".res", ".resi"];
/**
*
* @param {string[]} extensions
*/
function hasExtension(extensions) {
/**
* @param {string} x
*/
var pred = (x) => extensions.some((ext) => x.endsWith(ext));
return pred;
}
async function readStdin() {
var stream = process.stdin;
const chunks = [];
for await (const chunk of stream) chunks.push(chunk);
return Buffer.concat(chunks).toString("utf8");
}
/**
* @param {string[]} argv
* @param {string} bsb_exe
* @param {string} bsc_exe
*/
function main(argv, bsb_exe, bsc_exe) {
var isSupportedFile = hasExtension(formattedFileExtensions);
var isSupportedStd = hasExtension(formattedStdExtensions);
try {
/**
* @type {string[]}
*/
var files = [];
arg.parse_exn(format_usage, argv, specs, (xs) => {
files = xs;
});
var format_project = format.val;
var use_stdin = stdin.val;
if (format_project) {
if (use_stdin || files.length !== 0) {
console.error("format -all can not be in use with other flags");
process.exit(2);
}
// -all
// TODO: check the rest arguments
var output = child_process.spawnSync(bsb_exe, ["info", "-list-files"], {
encoding: "utf-8",
});
if (output.status !== 0) {
console.error(output.stdout);
console.error(output.stderr);
process.exit(2);
}
files = output.stdout.split("\n").map((x) => x.trim());
for (let arg of files) {
if (isSupportedFile(arg)) {
// console.log(`processing ${arg}`);
child_process.execFile(
bsc_exe,
["-o", arg, "-format", arg],
(error, stdout, stderr) => {
if (error === null) {
// todo
} else {
// todo error handling
console.log(stderr);
}
}
);
}
}
} else if (use_stdin) {
if (isSupportedStd(use_stdin)) {
var crypto = require("crypto");
var os = require("os");
var filename = path.join(
os.tmpdir(),
"rescript_" + crypto.randomBytes(8).toString("hex") + use_stdin
);
(async function () {
var content = await readStdin();
fs.writeFileSync(filename, content, "utf8");
child_process.execFile(
bsc_exe,
["-format", filename],
(error, stdout, stderr) => {
if (error === null) {
console.log(stdout.trimEnd());
} else {
console.log(stderr);
process.exit(2);
}
}
);
})();
} else {
console.error(`Unsupported exetnsion ${use_stdin}`);
console.error(`Supported extensions: ${formattedStdExtensions} `);
process.exit(2);
}
} else {
if (files.length === 0) {
// none of argumets set
// format the current directory
files = fs.readdirSync(process.cwd()).filter(isSupportedFile);
}
for (let i = 0; i < files.length; ++i) {
let file = files[i];
if (!isSupportedStd(file)) {
console.error(`Don't know what do with ${file}`);
console.error(`Supported extensions: ${formattedFileExtensions}`);
process.exit(2);
}
}
files.forEach((file) => {
var write = isSupportedFile(file);
var flags = write ? ["-o", file, "-format", file] : ["-format", file];
child_process.execFile(bsc_exe, flags, (error, stdout, stderr) => {
if (error === null) {
if (!write) {
console.log(stdout);
}
} else {
console.log(stderr);
}
});
});
}
} catch (e) {
if (e instanceof arg.ArgError) {
console.error(e.message);
process.exit(2);
} else {
throw e;
}
}
}
exports.main = main;