mirror of
https://github.com/aduros/wasm4.git
synced 2026-10-17 13:54:47 +00:00
217 lines
8.7 KiB
JavaScript
Executable File
217 lines
8.7 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
const { program, Option } = require("commander");
|
|
const pkg = require('./package.json');
|
|
const { supportedIconExtensions } = require('./lib/utils/icon');
|
|
|
|
const LANGS = ["assemblyscript", "c", "c3", "cpp", "d", "go", "grain", "nelua", "nim", "odin", "penne", "porth", "roc", "roland", "rust", "wat", "zig"];
|
|
const langOption = new Option("--lang <lang>", "Use the given language")
|
|
.env("W4_LANG")
|
|
.choices(LANGS);
|
|
|
|
function requireLang (opts) {
|
|
if (opts.lang) {
|
|
return opts.lang;
|
|
}
|
|
if (opts.surpriseMe) {
|
|
return LANGS[(Math.random()*LANGS.length) >>> 0];
|
|
}
|
|
|
|
if (opts.assemblyscript) {
|
|
return "assemblyscript";
|
|
} else if (opts.c) {
|
|
return "c";
|
|
} else if (opts.c3) {
|
|
return "c3";
|
|
} else if (opts.cpp) {
|
|
return "cpp";
|
|
} else if (opts.d) {
|
|
return "d";
|
|
} else if (opts.go) {
|
|
return "go";
|
|
} else if (opts.grain) {
|
|
return "grain";
|
|
} else if (opts.nelua) {
|
|
return "nelua";
|
|
} else if (opts.nim) {
|
|
return "nim";
|
|
} else if (opts.odin) {
|
|
return "odin";
|
|
} else if (opts.penne) {
|
|
return "penne";
|
|
} else if (opts.porth) {
|
|
return "porth";
|
|
} else if (opts.roc) {
|
|
return "roc";
|
|
} else if (opts.roland) {
|
|
return "roland";
|
|
} else if (opts.rust) {
|
|
return "rust";
|
|
} else if (opts.wat) {
|
|
return "wat";
|
|
} else if (opts.zig) {
|
|
return "zig";
|
|
}
|
|
|
|
console.error("You must specify a programming language, for example by passing --c or --rust.");
|
|
process.exit(1);
|
|
}
|
|
|
|
const blankProject = (cmd) =>
|
|
cmd
|
|
.option("--as, --assemblyscript", "Create AssemblyScript project (Shorthand for --lang assemblyscript)")
|
|
.option("--c", "Create C project (Shorthand for --lang c)")
|
|
.option("--c3", "Create C3 project (Shorthand for --lang c3)")
|
|
.option("--cpp", "Create C++ project (Shorthand for --lang cpp)")
|
|
.option("--d", "Create D project (Shorthand for --lang d)")
|
|
.option("--go", "Create Go project (Shorthand for --lang go)")
|
|
.option("--grain", "Create Grain project (Shorthand for --lang grain)")
|
|
.option("--nelua", "Create Nelua project (Shorthand for --lang nelua)")
|
|
.option("--nim", "Create Nim project (Shorthand for --lang nim)")
|
|
.option("--odin", "Create Odin project (Shorthand for --lang odin)")
|
|
.option("--penne", "Create Penne project (Shorthand for --lang penne)")
|
|
.option("--porth", "Create Porth project (Shorthand for --lang porth)")
|
|
.option("--roland", "Create Roland project (Shorthand for --lang roland)")
|
|
.option("--rs, --rust", "Create Rust project (Shorthand for --lang rust)")
|
|
.option("--wat", "Create WebAssembly Text project (Shorthand for --lang wat)")
|
|
.option("--zig", "Create Zig project (Shorthand for --lang zig)")
|
|
.addOption(langOption)
|
|
.option("--surprise-me", "Create a project in a random language");
|
|
|
|
|
|
blankProject(
|
|
program.command("new <directory>")
|
|
.alias("create")
|
|
.description("Create a new blank project")
|
|
)
|
|
.action((dir, opts) => {
|
|
const newCmd = require("./lib/new");
|
|
opts.lang = requireLang(opts);
|
|
newCmd.run(dir, opts);
|
|
});
|
|
|
|
blankProject(
|
|
program.command("init")
|
|
.description("Create a new blank project in current folder")
|
|
)
|
|
.action(opts => {
|
|
const newCmd = require("./lib/new");
|
|
opts.lang = requireLang(opts);
|
|
newCmd.run(".", opts);
|
|
});
|
|
|
|
function withCommonRunOptions (cmd) {
|
|
return cmd.option("--open", "Open the browser", true)
|
|
.addOption(
|
|
new Option("--port <port>", "Binds the runtime to a specific port")
|
|
.env("W4_PORT")
|
|
.default("4444")
|
|
)
|
|
.addOption(
|
|
new Option("-n, --no-open", "Don't open the browser")
|
|
.env("W4_NO_OPEN")
|
|
.default(false)
|
|
)
|
|
.option("--qr", "Displays a QR code", true)
|
|
.addOption(
|
|
new Option("--no-qr", "Don't display a QR code")
|
|
.env("W4_NO_QR")
|
|
.default(false)
|
|
)
|
|
.option("--hot", "Enable hot swapping. When the cart is reloaded, the console memory will be preserved, allowing code changes to the cart without resetting.", false);
|
|
}
|
|
|
|
withCommonRunOptions(program.command("watch"))
|
|
.description("Rebuild and refresh when source code changes")
|
|
.action(opts => {
|
|
const watch = require("./lib/watch");
|
|
watch.start(opts);
|
|
});
|
|
|
|
withCommonRunOptions(program.command("run <cart>"))
|
|
.description("Open a cartridge in the web runtime")
|
|
.addOption(
|
|
new Option("--settle-time <time>", "Changes to the cart must have stopped for at least this long before a reload happens. Increase this if you're getting erroneous double-reloads and cart corruption, decrease it if you want snappier reloads. In milliseconds.")
|
|
.env("W4_SETTLE_TIME")
|
|
.default(300)
|
|
)
|
|
.action((cart, opts) => {
|
|
const server = require("./lib/server");
|
|
server.start(cart, opts);
|
|
});
|
|
|
|
program.command("run-native <cart>")
|
|
.description("Open a cartridge in the native desktop runtime")
|
|
.action((cart, opts) => {
|
|
const runNative = require("./lib/run-native");
|
|
runNative.run(cart, opts);
|
|
});
|
|
|
|
program.command("png2src <images...>")
|
|
.description("Convert images to source code")
|
|
.option("--as, --assemblyscript", "Generate AssemblyScript source (Shorthand for --lang assemblyscript)")
|
|
.option("--c, --cpp", "Generate C/C++ source (Shorthand for --lang c)")
|
|
.option("--c3", "Generate C3 source (Shorthand for --lang c3)")
|
|
.option("--d", "Generate D source (Shorthand for --lang d)")
|
|
.option("--go", "Generate Go source (Shorthand for --lang go)")
|
|
.option("--grain", "Generate Grain source (Shorthand for --lang grain)")
|
|
.option("--nelua", "Generate Nelua source (Shorthand for --lang nelua)")
|
|
.option("--nim", "Generate Nim source (Shorthand for --lang nim)")
|
|
.option("--odin", "Generate Odin source (Shorthand for --lang odin)")
|
|
.option("--penne", "Generate Penne source (Shorthand for --lang penne)")
|
|
.option("--porth", "Generate Porth source (Shorthand for --lang porth)")
|
|
.option("--roc", "Generate Roc source (Shorthand for --lang roc)")
|
|
.option("--roland", "Generate Roland source (Shorthand for --lang roland)")
|
|
.option("--rs, --rust", "Generate Rust source (Shorthand for --lang rust)")
|
|
.option("--wat", "Generate WebAssembly Text source (Shorthand for --lang wat)")
|
|
.option("--zig", "Generate Zig source (Shorthand for --lang zig)")
|
|
.option("-t, --template <file>", "Template file with a custom output format")
|
|
.option("-o, --output <file>", "File to write the result to", "-")
|
|
.addOption(langOption)
|
|
.action((images, opts) => {
|
|
const png2src = require("./lib/png2src");
|
|
if (!opts.template) {
|
|
opts.lang = requireLang(opts);
|
|
}
|
|
try {
|
|
png2src.runAll(images, opts);
|
|
} catch (error) {
|
|
console.error(error.message);
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
program.command("bundle <cart>")
|
|
.description("Bundle a cartridge for final distribution")
|
|
.option("--html <output>", "Bundle standalone HTML")
|
|
.option("--windows <output>", "Bundle a native Windows executable")
|
|
.option("--mac <output>", "Bundle a native Mac executable")
|
|
.option("--linux <output>", "Bundle a native Linux executable")
|
|
.option("--title <title>", "Game title", "WASM-4 Game")
|
|
.option("--description <description>", "Game description")
|
|
.option("--icon-file <file>", `Game icon image. Supported types: ${supportedIconExtensions().join(', ')}.\nTakes precedence over --icon-url`)
|
|
.option("--icon-url <url>", 'Favicon icon url')
|
|
.option("--timestamp", 'Adds build timestamp to output', false)
|
|
.option("--html-disk-prefix <prefix>", "Specify a prefix for the disk localStorage key. Defaults to game title")
|
|
.option("--html-template <file>", "Mustache HTML template file for standalone HTML. Defaults to a built-in template.")
|
|
.action((cart, opts) => {
|
|
const bundle = require("./lib/bundle");
|
|
bundle.run(cart, opts);
|
|
});
|
|
|
|
program
|
|
.name("w4")
|
|
.description("WASM-4: Build retro games using WebAssembly for a fantasy console.\n\nLearn more: https://wasm4.org")
|
|
.version(pkg.version)
|
|
.parse();
|
|
|
|
// Manages unhandled rejections:
|
|
// conforms behavior between node versions:
|
|
// node 15+ throw on `unhandledRejection`.
|
|
// @see https://nodejs.org/api/process.html#process_event_unhandledrejection
|
|
process.on('unhandledRejection', unhandledRejectionError => {
|
|
console.error(unhandledRejectionError.message);
|
|
process.exit(1);
|
|
// throw unhandledRejectionError;
|
|
});
|