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"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
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:
|
fsevents@^1.2.7:
|
||||||
version "1.2.13"
|
version "1.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
|
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"
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||||
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
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:
|
infer-owner@^1.0.3, infer-owner@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user