Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding CLI Streams #52

Merged
merged 14 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### ✨ Enhancements

- Changed the `filePath` argument in the MemoryViz CLI to be optional and added `--output` option.

### 🐛 Bug fixes

- Fixed issue where object boxes would be drawn on top of stack frames in diagrams with large left margins.
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ For more information, check out the project [documentation website](https://www.

### MemoryViz CLI

To run MemoryViz from your terminal, run:
To use the MemoryViz CLI, run:

```console
$ npx memory-viz <path-to-file>
```

replacing `<path-to-file>` with the path to a file containing MemoryViz-compatible JSON. The output is an SVG image generated by MemoryViz and the image is saved in the current working directory. For more information, check out the project [documentation website](https://www.cs.toronto.edu/~david/memory-viz/docs/cli).
where `<path-to-file>` is the path to a file containing MemoryViz-compatible JSON. If a file path is not provided, the CLI will take input from standard input.

You may also specify an output path using the `--output` option (see documentation). If no output path is provided, the CLI will print to standard output.

For more information, check out the project [documentation website](https://www.cs.toronto.edu/~david/memory-viz/docs/cli).

## Developers

Expand Down
46 changes: 30 additions & 16 deletions docs/docs/06-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,62 @@ title: MemoryViz CLI

# MemoryViz CLI

You can run MemoryViz straight from your terminal!
Run MemoryViz straight from your terminal!

## Input
The MemoryViz CLI takes in MemoryViz-compatible JSON and returns an SVG of the memory model.

To run the MemoryViz CLI, run:
## Usage

To use the MemoryViz CLI, run:

```console
$ npx memory-viz <path-to-file>
```

replacing `<path-to-file>` with the path to a file containing MemoryViz-compatible JSON. If the file content is not compatible with MemoryViz, an error will be thrown.
where `<path-to-file>` is the path to a file containing MemoryViz-compatible JSON. If a file path is not provided, the CLI will take input from standard input.

## Output
You may also specify an output path using the `--output` option (see below). If no output path is provided, the CLI will print to standard output.

The output is an SVG image generated by MemoryViz and the image is saved in the current working directory. The name of the SVG will be the same as that of the inputted file (i.e., if the inputted file is `david-is-cool.json`, the output will be `david-is-cool.svg`).
NOTE: If you are typing JSON directly into the terminal, you need to use `Ctrl + D` to signal the end of your input.

## Options

Below are optional arguments used to specify the way in which the SVG image is generated.
Below are optional arguments used to specify the way in which the SVG is outputed and generated.

### `--output=<path>`

Writes generated SVG to specified path.

### `--width`

Specifies the width of the generated SVG.

```console
$ npx memory-viz <path-to-file> --width=700
```

### `--height`

Specifies the height of the generated SVG.

### `--roughjs_config<arg>`

Specifies the style of the generated SVG. Please refer to the [Rough.js documentation](https://github.com/rough-stuff/rough/wiki#options) for available options.

The argument is a comma-separated list of key-value pairs in the form `<key1=value1,key2=value2,...>`.

## Examples

File path input and default output.

```console
$ npx memory-viz <path-to-file> --height=700
$ npx memory-viz <path-to-file>
```

### `--roughjs_config`
Standard input, standard output, with a width of 200.

Specifies the style of the generated SVG. Please refer to the [Rough.js documentation](https://github.com/rough-stuff/rough/wiki#options) for available options.
```console
$ npx memory-viz --stdout --width=200
sarahsonder marked this conversation as resolved.
Show resolved Hide resolved
```

The argument is a comma-separated list of key-value pairs in the form `<key1=value1,key2=value2,...>`.
File path input, output path, and solid red fill.

```console
$ npx memory-viz <path-to-file> --roughjs-config fill=red,fillStyle=solid
$ npx memory-viz <path-to-file> --output=<path> --roughjs-config fill=red,fillStyle=solid
```
8 changes: 6 additions & 2 deletions memory-viz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ For more information, check out the project [documentation website](https://www.

### MemoryViz CLI

To run MemoryViz from your terminal, run:
To use the MemoryViz CLI, run:

```console
$ npx memory-viz <path-to-file>
```

replacing `<path-to-file>` with the path to a file containing MemoryViz-compatible JSON. The output is an SVG image generated by MemoryViz and the image is saved in the current working directory. For more information, check out the project [documentation website](https://www.cs.toronto.edu/~david/memory-viz/docs/cli).
where `<path-to-file>` is the path to a file containing MemoryViz-compatible JSON. If a file path is not provided, the CLI will take input from standard input.

You may also specify an output path using the `--output` option (see documentation). If no output path is provided, the CLI will print to standard output.

For more information, check out the project [documentation website](https://www.cs.toronto.edu/~david/memory-viz/docs/cli).

## Developers

Expand Down
146 changes: 112 additions & 34 deletions memory-viz/bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ const fs = require("fs");
const path = require("path");
const { draw } = require("memory-viz");
const { program } = require("commander");
const readline = require("readline");

function parseFilePath(input) {
if (input) {
return pathExists(input, `File`);
} else {
return undefined;
}
}

function parseOutputPath(input) {
return pathExists(input, `Output path`);
}

// helper function for parsing paths
function pathExists(inputPath, errMsg) {
const fullPath = path.resolve(process.cwd(), inputPath);
if (!fs.existsSync(fullPath)) {
console.error(`Error: ${errMsg} ${fullPath} does not exist.`);
process.exit(1);
} else {
return fullPath;
}
}

function parseRoughjsConfig(input) {
const pairs = input.split(",");
Expand All @@ -16,8 +40,14 @@ program
"Command line interface for generating memory model diagrams with MemoryViz"
)
.argument(
"<filepath>",
"path to a file containing MemoryViz-compatible JSON"
"[filePath]",
"path to a file containing MemoryViz-compatible JSON",
parseFilePath
)
.option(
"--output <path>",
"writes generated SVG to specified path",
parseOutputPath
)
.option("--width <value>", "width of generated SVG", "1300")
.option("--height <value>", "height of generated SVG")
Expand All @@ -29,43 +59,91 @@ program
);

program.parse();
const filePath = program.processedArgs[0];
const options = program.opts();

const filePath = program.args[0];
const absolutePath = path.resolve(process.cwd(), filePath);
let jsonContent = "";

// Checks if absolutePath exists
let fileContent;
if (!fs.existsSync(absolutePath)) {
console.error(`Error: File ${absolutePath} does not exist.`);
process.exit(1);
if (filePath) {
// rl.close();
jsonContent = fs.readFileSync(filePath, "utf8");
runMemoryViz(jsonContent);
} else {
fileContent = fs.readFileSync(absolutePath, "utf8");
}
// const rl = readline.createInterface({
// input: process.stdin,
// output: process.stdin.isTTY ? process.stdout : null,
// });

let data;
try {
data = JSON.parse(fileContent);
} catch (err) {
console.error(`Error: Invalid JSON\n${err.message}.`);
process.exit(1);
}
// rl.on("line", (line) => {
// jsonContent += line;
// });

// rl.on("close", () => {
// runMemoryViz(jsonContent);
// });

// Option 1
// process.stdin.on("data", (chunk) => {
// if (chunk.includes("\u0004")) {
// process.stdin.emit("end");
// } else {
// jsonContent += chunk;
// }
// });

// process.stdin.on("end", () => {
// process.stdin.pause();
// runMemoryViz(jsonContent);
// });
// End of option 1

let m;
try {
m = draw(data, true, {
width: program.opts().width,
height: program.opts().height,
roughjs_config: { options: program.opts().roughjsConfig },
});
} catch (err) {
console.error(`Error: ${err.message}`);
process.exit(1);
// Option 2 (Currently cannot signal EOF from terminal)
async function read(stream) {
const chunks = [];
for await (const chunk of stream) chunks.push(chunk);
return Buffer.concat(chunks).toString("utf8");
}

async function run() {
const input = await read(process.stdin);
runMemoryViz(input);
}

run();
// End of option 2
}

const outputName = path.parse(filePath).name + ".svg";
try {
m.save(outputName);
} catch (err) {
console.error(`Error: ${err.message}`);
process.exit(1);
function runMemoryViz(jsonContent) {
let data;
try {
data = JSON.parse(jsonContent);
} catch (err) {
console.error(`Error: Invalid JSON\n${err.message}.`);
process.exit(1);
}

let m;
try {
m = draw(data, true, {
width: options.width,
height: options.height,
roughjs_config: { options: options.roughjsConfig },
});
} catch (err) {
console.error(`Error: ${err.message}`);
process.exit(1);
}

try {
if (options.output) {
const outputName = path.parse(options.output).name + ".svg";
const outputPath = path.join(options.output, outputName);
m.save(outputPath);
} else {
m.save();
}
} catch (err) {
console.error(`Error: ${err.message}`);
process.exit(1);
}
}
Loading
Loading