Merge pull request #707 from quantified-uncertainty/cli
Simple CLI for compiling @import statements
This commit is contained in:
commit
02af4393b0
4
packages/cli/.gitignore
vendored
Normal file
4
packages/cli/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
## Artifacts
|
||||
*.swp
|
||||
/node_modules/
|
||||
yarn-error.log
|
20
packages/cli/README.md
Normal file
20
packages/cli/README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
## Squiggle CLI
|
||||
|
||||
This package can be used to incorporate a very simple `import` system into Squiggle.
|
||||
|
||||
To use, write special files with a ``.squiggleU`` file type. In these files, you can write lines like,
|
||||
|
||||
```
|
||||
@import(models/gdp_over_time.squiggle, gdpOverTime)
|
||||
gdpOverTime(2.5)
|
||||
```
|
||||
|
||||
The imports will be replaced with the contents of the file in `models/gdp_over_time.squiggle` upon compilation. The ``.squiggleU`` file will be converted into a ``.squiggle`` file with the ``import`` statement having this replacement.
|
||||
|
||||
## Running
|
||||
|
||||
### `npx squiggle-cli-experimental compile`
|
||||
Runs compilation in the current directory and all of its subdirectories.
|
||||
|
||||
### `npx squiggle-cli-experimental watch`
|
||||
Watches ``.squiggleU`` files in the current directory (and subdirectories) and rebuilds them when they are saved. Note that this will *not* rebuild files when their dependencies are changed, just when they are changed directly.
|
96
packages/cli/index.js
Normal file
96
packages/cli/index.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import indentString from "indent-string";
|
||||
import chokidar from "chokidar";
|
||||
import chalk from "chalk";
|
||||
import { Command } from "commander";
|
||||
import glob from "glob";
|
||||
|
||||
const processFile = (fileName, seen = []) => {
|
||||
const normalizedFileName = path.resolve(fileName);
|
||||
if (seen.includes(normalizedFileName)) {
|
||||
throw new Error(`Recursive dependency for file ${fileName}`);
|
||||
}
|
||||
|
||||
const fileContents = fs.readFileSync(fileName, "utf-8");
|
||||
if (!fileName.endsWith(".squiggleU")) {
|
||||
return fileContents;
|
||||
}
|
||||
|
||||
const regex = /\@import\(\s*([^)]+?)\s*\)/g;
|
||||
const matches = Array.from(fileContents.matchAll(regex)).map((r) =>
|
||||
r[1].split(/\s*,\s*/)
|
||||
);
|
||||
const newContent = fileContents.replaceAll(regex, "");
|
||||
const appendings = [];
|
||||
|
||||
matches.forEach((r) => {
|
||||
const importFileName = r[0];
|
||||
const rename = r[1];
|
||||
const item = fs.statSync(importFileName);
|
||||
if (item.isFile()) {
|
||||
const data = processFile(importFileName, [...seen, normalizedFileName]);
|
||||
if (data) {
|
||||
const importString = `${rename} = {\n${indentString(data, 2)}\n}\n`;
|
||||
appendings.push(importString);
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
chalk.red(`Import Error`) +
|
||||
`: ` +
|
||||
chalk.cyan(importFileName) +
|
||||
` not found in file ` +
|
||||
chalk.cyan(fileName) +
|
||||
`. Make sure the @import file names all exist in this repo.`
|
||||
);
|
||||
}
|
||||
});
|
||||
const imports = appendings.join("\n");
|
||||
|
||||
const newerContent = imports.concat(newContent);
|
||||
return newerContent;
|
||||
};
|
||||
|
||||
const run = (fileName) => {
|
||||
const content = processFile(fileName);
|
||||
const parsedPath = path.parse(path.resolve(fileName));
|
||||
const newFilename = `${parsedPath.dir}/${parsedPath.name}.squiggle`;
|
||||
fs.writeFileSync(newFilename, content);
|
||||
console.log(chalk.cyan(`Updated ${fileName} -> ${newFilename}`));
|
||||
};
|
||||
|
||||
const compile = () => {
|
||||
glob("**/*.squiggleU", (_err, files) => {
|
||||
files.forEach(run);
|
||||
});
|
||||
};
|
||||
|
||||
const watch = () => {
|
||||
chokidar
|
||||
.watch("**.squiggleU")
|
||||
.on("ready", () => console.log(chalk.green("Ready!")))
|
||||
.on("change", (event, _) => {
|
||||
run(event);
|
||||
});
|
||||
};
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name("squiggle-utils")
|
||||
.description("CLI to transform squiggle files with @imports")
|
||||
.version("0.0.1");
|
||||
|
||||
program
|
||||
.command("watch")
|
||||
.description("watch files and compile on the fly")
|
||||
.action(watch);
|
||||
|
||||
program
|
||||
.command("compile")
|
||||
.description("compile all .squiggleU files into .squiggle files")
|
||||
.action(compile);
|
||||
|
||||
program.parse();
|
22
packages/cli/package.json
Normal file
22
packages/cli/package.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "squiggle-cli-experimental",
|
||||
"version": "0.0.1",
|
||||
"main": "index.js",
|
||||
"homepage": "https://squiggle-language.com",
|
||||
"author": "Quantified Uncertainty Research Institute",
|
||||
"bin": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node ."
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^5.0.1",
|
||||
"chokidar": "^3.5.3",
|
||||
"commander": "^9.3.0",
|
||||
"fs": "^0.0.1-security",
|
||||
"glob": "^8.0.3",
|
||||
"indent-string": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
10
yarn.lock
10
yarn.lock
|
@ -9292,6 +9292,11 @@ fs.realpath@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fs@^0.0.1-security:
|
||||
version "0.0.1-security"
|
||||
resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4"
|
||||
integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==
|
||||
|
||||
fsevents@^1.2.7:
|
||||
version "1.2.13"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
|
||||
|
@ -10268,6 +10273,11 @@ indent-string@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
||||
|
||||
indent-string@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5"
|
||||
integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==
|
||||
|
||||
infer-owner@^1.0.3, infer-owner@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||
|
|
Loading…
Reference in New Issue
Block a user