2 releases

new 0.1.1 Feb 20, 2025
0.1.0 Feb 20, 2025

#201 in Game dev

MIT OR Apache-2.0 OR GPL-2.0-or-later

43KB
324 lines

Command line in web.

Clap in web. Pronounced "Clue" as in "Get a cliw."

Command line arguments for native and the web.
Also provide output for the web.

The goal is to be flexible, write your command line code once and it should be able to run anywhere!

Screencast of an egui app running in web page with popup alerts showing a variety of clap help messages.
we-clap_egui_demo

Why use cliw?

You probably don't want to use cliw directly. This crate was designed so clap can be used in the web. You normaly use cliw indirectly with a web enabled clap, we-clap.

Find cliw at crates.io, or the cliw repository. Also check out the examples and docs.

Why not use cliw?

  • If you are writing only for the web, you may not be wanting to use command line arguments.
  • You might have another use of the url query string.
  • You might be compiling to wasm but the framework you use provides std::env::args_os and/or standard output.

Cliw was designed to enable clap to be used in the web. The best way to use cliw is to use a web enable clap we-clap and pretend like you are just using clap. we-clap_demo.

Cliw can also be used with a regular clap. You just need to do a little more work. cliw_clap_demo

Of course cliw can be also used for getting args without using clap. cliw_demo

we-clap_demo

Web enabled clap features

The patches to clap, we-clap, are minimal and try to be non-invasive.
The wasm/web enabled we-clap functionality is gated by features.

  • unstable-web-alert
    • Enable we-clap to use an alert for its output on the web.
    • we-clap will have cliw as a dependency with the "alert" feature set
  • unstable-web-console
    • Enable we-clap to use the browser console for its output on the web.
    • we-clap will have cliw as a dependency with the "console" feature set
  • unstable-web-urlargs
    • Enable we-clap to use urlargs on the web.
    • we-clap will have cliw as a dependency with the "urlargs" feature set

Cargo.toml

[package]
name = "we-clap_demo"
version = "0.1.0"
edition = "2021"

[dependencies]
# use a web enabled version of clap
clap = { git = "https://github.com/stonerfish/clap", branch = "we-clap",  features = [
    "derive",               #normal clap derive feature
    "unstable-web-alert",   #enable clap to use an alert for its output on the web
    "unstable-web-urlargs"  #enable clap to use urlargs on the web 
] }

main.rs

use clap::Parser;

#[derive(Parser, Debug, Default)]
#[command(author, version, about, long_about)]
pub struct Opts {
    /// A required string 
    #[arg(short, long)]
    pub words: String,

    /// An optional value 
    #[arg(short, long)]
    pub value: Option<f32>,
}

fn main() {
    // Like magic, this will work on native parsing the command line arguments,
    // or on the web parsing the url query string as if it were command line arguments,
    // providing clap help and error messages to stdout/stderr on native or a popup alert on web/wasm.

    let opts = Opts::parse();

    // this app doesn't do anything, except parse arguments and demonstrate clap powers in the web.
}

Running with wasm-server-runner.

cargo r --target wasm32-unknown-unknown
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
     Running `wasm-server-runner /path/to/target/wasm32-unknown-unknown/debug/we-clap_demo.wasm`
 INFO wasm_server_runner: uncompressed wasm output is 2.10mb in size
 INFO wasm_server_runner: starting webserver at http://127.0.0.1:1334

Screencast of the we-clap_demo program running in web page with popup alerts showing a variety of clap help messages.
we-clap_demo

cliw_clap_demo

If you don't want to use a web-enabled clap you can use cliw with regular clap, but it is a little bit more work. You use the clap functions "try_get_matches_from()" or "try_parse_from()" passing in cliw::args_os() as the iterator. For output we use cliw, but for the clap error output on native we use the clap error print() method so that colors and stdout/stderr work properly.

Cargo.toml

[package]
name = "cliw_clap_demo"
version = "0.1.0"
edition = "2021"

[dependencies]
# use a regular (non-web enabled) version of clap
clap = { version = "what",  features = [
    "derive",
] }

cliw = { version = "0.1.0" , features = [
    "alert",
    "urlargs",
] }

src/main.rs

use clap::Parser;

#[derive(Parser, Debug, Default)]
#[command(author, version, about, long_about)]
pub struct Opts {
    /// A required string 
    #[arg(short, long)]
    pub words: String,

    /// An optional value 
    #[arg(short, long)]
    pub value: Option<f32>,
}

fn main() {
    // Try parsing ArgsOs on native or UrlArgs on wasm/web
    let opts = Opts::try_parse_from(cliw::args_os());

    // Handle the result
    match opts {
        Ok(opts) => {
            let msg = format!("{opts:?}");
            println!("{msg}");
            cliw::output::print(&msg);
        }
        Err(err) => {
            // jump through some hoops to get proper color and error direction on native
            #[cfg(not(target_arch = "wasm32"))]
            {
                err.print().unwrap();
            }
            // and this hoop to get output for web/wasm
            #[cfg(target_arch = "wasm32")]
            {
                let msg = format!("{err}");
                cliw::output::eprint(&msg);
            }
        }
    };
}

Running with wasm-server-runner.

cargo r --target wasm32-unknown-unknown
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
     Running `wasm-server-runner /path/to/target/wasm32-unknown-unknown/debug/cliw_clap_demo.wasm`
 INFO wasm_server_runner: uncompressed wasm output is 2.10mb in size
 INFO wasm_server_runner: starting webserver at http://127.0.0.1:1334

Screencast of the cliw_clap_demo program running in web page with popup alerts showing a variety of clap help messages.
cliw_clap_demo

cliw_demo

If you don't want to use clap you can use cliw and just process the args yourself.

Cargo.toml

[package]
name = "cliw_demo"
version = "0.1.0"
edition = "2021"

[dependencies]
cliw = { version = "0.1.0", features = [
    "alert",
    "urlargs",
] }

main.rs

fn main() {
    //  This is an example using raw cliw without using clap
    let args = cliw::args_os();
    let args: Vec<_> = args.collect();
    let msg = format!("{:?}", args);
    cliw::output::print(&msg);
}

Running with wasm-server-runner.

cargo r --target wasm32-unknown-unknown
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
     Running `wasm-server-runner /path/to/target/wasm32-unknown-unknown/debug/cliw_demo.wasm`
 INFO wasm_server_runner: uncompressed wasm output is 2.10mb in size
 INFO wasm_server_runner: starting webserver at http://127.0.0.1:1334

Screencast of the cliw_demo program running in web page with popup alerts showing a variety of clap help messages.
cliw_demo

Cliw Features

The functionality of the cliw crate is gated by features.

  • alert
    • Enable output to browser popup alert.
  • console
    • Enable output to browser console.
  • web-std-output
    • Enable standard output on the web.
    • You can use this if your web framework provides standard output.
    • You always get standard output on native.
  • urlarg

For simplicity just set the "urlargs" and "console" or "alert" features in you Cargo.toml for both native and wasm. Under native you always get standard args and output.

cliw = { "0.1.0", features = [
    "alert",
    "urlargs",
]}

License

Copyright 2025 Richard Gould

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~0–2.4MB
~44K SLoC