From 463a3a6f56a5ca06cda890fd6fe7f16485ef70a0 Mon Sep 17 00:00:00 2001 From: Henry Date: Sun, 26 Apr 2026 19:44:34 +0200 Subject: feat: new tinywasm cli Signed-off-by: Henry --- crates/cli/src/cli.rs | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 crates/cli/src/cli.rs (limited to 'crates/cli/src/cli.rs') diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs new file mode 100644 index 0000000..8b9df2d --- /dev/null +++ b/crates/cli/src/cli.rs @@ -0,0 +1,128 @@ +use clap::{ + Args, Parser, Subcommand, ValueEnum, + builder::{ + Styles, + styling::{AnsiColor, Effects}, + }, +}; +use clap_complete::Shell; + +use crate::engine_flags::EngineFlags; + +// based on https://github.com/crate-ci/clap-cargo/blob/master/src/style.rs +const STYLES: Styles = Styles::styled() + .header(AnsiColor::BrightGreen.on_default().effects(Effects::BOLD)) + .usage(AnsiColor::BrightGreen.on_default().effects(Effects::BOLD)) + .literal(AnsiColor::BrightCyan.on_default().effects(Effects::BOLD)) + .placeholder(AnsiColor::Cyan.on_default()) + .error(AnsiColor::BrightRed.on_default().effects(Effects::BOLD)) + .valid(AnsiColor::BrightCyan.on_default().effects(Effects::BOLD)) + .invalid(AnsiColor::Yellow.on_default()); + +#[derive(Parser)] +#[command( + name = "tinywasm", + about = "TinyWasm CLI", + styles = STYLES, + version, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] +pub struct Cli { + #[arg(long, global = true, value_enum, default_value_t = LogLevel::Info)] + pub log_level: LogLevel, + + #[command(subcommand)] + pub command: Option, + + #[command(flatten)] + pub run: RunArgs, +} + +#[derive(Subcommand)] +pub enum Commands { + /// Run a module + Run(RunArgs), + /// Compile a Wasm/WAT module to a .twasm archive + Compile(CompileArgs), + /// Dump lowered TinyWasm bytecode + Dump(ModuleInputArgs), + /// Inspect imports and exports + Inspect(ModuleInputArgs), + #[cfg(feature = "wast")] + /// Execute WebAssembly spec scripts (.wast) + Wast(WastArgs), + /// Generate shell completions + Completion(CompletionArgs), +} + +#[derive(Args, Clone)] +pub struct RunArgs { + /// Module path, or `-` to read from stdin + pub module: Option, + + /// Invoke a named export instead of the default entrypoint + #[arg(long)] + pub invoke: Option, + + #[command(flatten)] + pub engine: EngineFlags, + + /// Arguments passed to the invoked Wasm function + #[arg(trailing_var_arg = true)] + pub args: Vec, +} + +#[derive(Args, Clone)] +pub struct CompileArgs { + /// Input module path, or `-` to read from stdin + pub input: String, + + /// Output path, or `-` to write to stdout + #[arg(short, long)] + pub output: Option, + + /// Overwrite the output file if it already exists + #[arg(short, long)] + pub force: bool, +} + +#[derive(Args, Clone)] +pub struct ModuleInputArgs { + /// Module path, or `-` to read from stdin + pub module: String, +} + +#[derive(Args, Clone)] +pub struct CompletionArgs { + pub shell: Shell, +} + +#[cfg(feature = "wast")] +#[derive(Args, Clone)] +pub struct WastArgs { + /// WAST files or directories containing .wast files + #[arg(required = true)] + pub paths: Vec, +} + +#[derive(Clone, Copy, ValueEnum)] +pub enum LogLevel { + Trace, + Debug, + Info, + Warn, + Error, +} + +impl From for log::LevelFilter { + fn from(value: LogLevel) -> Self { + match value { + LogLevel::Trace => log::LevelFilter::Trace, + LogLevel::Debug => log::LevelFilter::Debug, + LogLevel::Info => log::LevelFilter::Info, + LogLevel::Warn => log::LevelFilter::Warn, + LogLevel::Error => log::LevelFilter::Error, + } + } +} -- cgit v1.3.1