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

A new playground #71

Merged
merged 16 commits into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ stdlib/**/*.js
tools/**/native/*.js
_build
*.lingua.crochet
*:Zone.Identifier
*:Zone.Identifier
!stdlib/**/vendor-native/**/*.js
33 changes: 18 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,28 +39,20 @@ $ node make build

See `crochet --help` (or `./node_modules/.bin/crochet --help` if you've installed it locally) for usage information.

## REPL
## Playground

There's a basic command-line based REPL currently which you can run with:
You can try programming interactively with the Playground. You can run with:

```shell
$ crochet repl <path/to/your/crochet.json>
$ crochet playground <path/to/your/crochet.json>
```

You do need to specify a package currently because that's how Crochet tracks
dependencies and capabilities. All code you type in the REPL will be executed
in the context of the given package. And all dependencies of that package
will be loaded first.
dependencies and capabilities. All code you type in the Playground will
be executed in the context of the given package. And all dependencies of
that package will be loaded first.

The REPL accepts both declarations and statements/expressions. Multi-line
input currently works by allowing the reporting of a parser error to be
delayed until an empty line is entered.

E.g.: if you type `define hello =` and press return, you'll get a "continuation
input" (marked with `...`), since that piece of text is not a complete `define`
declaration. Typing the rest of it, e.g.: `"hello";` will then allow the
declaration to be executed. Entering an empty line by just pressing return
will accept the partial declaration and present the parser error on the screen.
The Playground accepts both declarations and statements/expressions.

## API Reference

Expand All @@ -87,6 +79,17 @@ Anything after `--` is passed as the invocation arguments as-is to your
package. You must provide a command called `main: _`, where the only
parameter will be this list of command line arguments.

Web packages are currently run with the `run-web` command. This does not
accept any invocation arguments:

```shell
$ crochet run-web <path/to/your/crochet.json>
```

You can provide a different port with `--port 12345`. Currently the server
is started on port 8000, and Crochet does not try to find an available
port if that one is taken.

## Licence

Copyright (c) 2021 Q.
Expand Down
2 changes: 2 additions & 0 deletions examples/agata/todo-list/source/ui/frame.crochet
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ command todo-ui with-frame: (Content is widget) do
Content
| with-padding: { P in P all: (2 as rem) }
| with-background: (agata-theme-colors bg-muted)
| with-box-overflow: #overflow-style hidden
),
]
| fill-screen-vertically
end
6 changes: 5 additions & 1 deletion examples/agata/todo-list/source/ui/lists-panel.crochet
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ open crochet.ui.agata;

command todo-ui render-lists do
#widget flex-column: [
#flex-child fluid: (self render-all-lists),
#flex-child fluid: (
#widget container: [self render-all-lists]
| with-box-overflow: #overflow-style auto
),
#widget space | vertical: (1 as rem),
#widget divider: "full",
self render-new-list-widget
]
| with-box-overflow: #overflow-style hidden
| fill-container-vertically;
end

Expand Down
8 changes: 5 additions & 3 deletions examples/agata/todo-list/source/ui/todo-list.crochet
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ command todo-ui render-list: (List is todo-list) do

#widget space | vertical: (2 as rem),

#flex-child fluid: [
self render-list-items: Items
],
#flex-child fluid: (
#widget container: [self render-list-items: Items]
| with-box-overflow: #overflow-style auto
| fill-container-vertically
),

#widget space | vertical: (2 as rem),

Expand Down
11 changes: 8 additions & 3 deletions examples/web-apis/ws-chat/source/main.crochet
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,13 @@ command screen-chat as widget do

#widget flex-column: [
#flex-child fluid: (
Received map: { Xs in
#widget flex-column: Xs
}
#widget container: [
Received map: { Xs in
#widget flex-column: Xs
}
]
| with-size: { S in S height: (1 as pixels) }
| with-box-overflow: { S in S style: #overflow-style auto | scroll-pin: #scroll-pin at-end }
),

#widget divider: "full",
Expand All @@ -202,6 +206,7 @@ command screen-chat as widget do
| key-up: Key-events
]
| with-background: (agata-theme-colors bg-muted)
| with-box-overflow: #overflow-style hidden
| fill-container;
end

Expand Down
41 changes: 35 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"benchmark": "node make.js benchmark"
},
"dependencies": {
"@types/codemirror": "^5.60.5",
"express": "^4.17.1",
"immutable": "^4.0.0-rc.14",
"ohm-js": "^15.3.0",
Expand Down
26 changes: 24 additions & 2 deletions source/node-cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ async function repl([file0]: string[], options: Options) {
await REPL.repl(crochet, pkg.meta.name);
}

async function run_web([file]: string[], options: Options) {
async function setup_web_capabilities(file: string, options: Options) {
const crochet = new CrochetForNode(
{ universe: random_uuid(), packages: new Map() },
options.disclose_debug,
Expand Down Expand Up @@ -346,8 +346,27 @@ async function run_web([file]: string[], options: Options) {
);
}
}
}

await Server(file, options.web.port, options.web.www_root);
async function run_web([file]: string[], options: Options) {
setup_web_capabilities(file, options);
await build([file], options);
await Server(file, options.web.port, options.web.www_root, "/");
}

async function playground([file]: string[], options: Options) {
setup_web_capabilities(file, options);
await build([file], options);
await build(
[Path.join(__dirname, "../../stdlib/crochet.debug.ui/crochet.json")],
options
);
await Server(
file,
options.web.port,
Path.join(__dirname, "../../www"),
"/playground"
);
}

async function show_docs([file]: string[], options: Options) {
Expand Down Expand Up @@ -485,6 +504,7 @@ function help(command?: string) {
"Usage:\n",
" crochet run <crochet.json> [-- <app-args...>]\n",
" crochet run-web <crochet.json> [--port PORT --www-root DIR]\n",
" crochet playground <crochet.json> [--port PORT]\n",
" crochet docs <crochet.json> [--port PORT --target ('node' | 'browser' | '*')]\n",
" crochet package <crochet.json> [--package-to OUT_DIR]\n",
" crochet repl <crochet.json>\n",
Expand Down Expand Up @@ -541,6 +561,8 @@ void (async function main() {
return await run(args, options);
case "run-web":
return await run_web(args, options);
case "playground":
return await playground(args, options);
case "docs":
return await show_docs(args, options);
case "test":
Expand Down
29 changes: 25 additions & 4 deletions source/node-cli/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import { random_uuid } from "../utils/uuid";

const repo_root = Path.resolve(__dirname, "../../");

export default async (root: string, port: number, www: string) => {
const template = (config: unknown) => {
export default async (
root: string,
port: number,
www: string,
start_page: string
) => {
const template = (filename: string) => (config: unknown) => {
const config_str = JSON.stringify(config).replace(/</g, "\\u003c");
const source = FS.readFileSync(Path.join(www, "index.html"), "utf-8");
const source = FS.readFileSync(Path.join(www, filename), "utf-8");
return source.replace(/{{crochet_config}}/g, (_) => config_str);
};
const index_template = template("index.html");
const playground_template = template("playground.html");

console.log("Building all dependencies...");
const crochet = new CrochetForNode(
Expand Down Expand Up @@ -76,7 +83,20 @@ export default async (root: string, port: number, www: string) => {
capabilities: [...pkg.meta.capabilities.requires.values()],
package_tokens: Object.fromEntries([...pkg_tokens.entries()]),
};
res.send(template(config));
res.send(index_template(config));
});

app.get("/playground", (req, res) => {
const config = {
token: random_uuid(),
library_root: "/library",
app_root: "/app/crochet.json",
playground_root: "/library/crochet.debug.ui/crochet.json",
asset_root: "/assets",
capabilities: [...pkg.meta.capabilities.requires.values()],
package_tokens: Object.fromEntries([...pkg_tokens.entries()]),
};
res.send(playground_template(config));
});

app.use("/", express.static(www));
Expand All @@ -96,6 +116,7 @@ export default async (root: string, port: number, www: string) => {
app.listen(port, () => {
const url = new URL("http://localhost");
url.port = String(port);
url.pathname = start_page;
console.log(`Server started at ${url.toString()}`);
});
};
7 changes: 6 additions & 1 deletion source/targets/browser/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import * as IR from "../../ir";
import * as Compiler from "../../compiler";
import * as Binary from "../../binary";
import * as VM from "../../vm";
import * as Package from "../../pkg";
import * as AST from "../../generated/crochet-grammar";

export * from "./browser";

export { Package };
export { Package, IR, Compiler, Binary, VM, AST };
2 changes: 1 addition & 1 deletion stdlib/crochet.core/source/debug/constructors.crochet
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
% crochet

/// Represents a secret value
command #document secret: Value seal: (Seal is secret-seal) =
command #document secret: (Value is document) seal: (Seal is document) =
new doc-secret(Value, Seal);

/// Represents nothing
Expand Down
5 changes: 3 additions & 2 deletions stdlib/crochet.core/source/debug/representations.crochet
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ command debug-representation for: (X is secret) perspective: (P is default-persp
end

command debug-representation for: (X is secret-seal) perspective: (P is default-perspective) =
#document text: X.description
#document crochet-text: X.description
| typed: #secret-seal;

command debug-representation for: (X is record) perspective: default-perspective do
let Rows = (#map from: X) pairs
let Rows = (#map from: X)
| entries
| map: { P in #document table-row: [
self for: P key perspective: default-perspective,
self for: P value perspective: default-perspective,
Expand Down
Loading