cliw 0.1.0

Command Line In Web
Documentation
# 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!

<a href="https://github.com/stonerfish/cliw_examples/we-clap_demos/we-clap_egui_demo"><figure><img alt="Screencast of an egui app running in web page with popup alerts showing a variety of clap help messages." src="https://github.com/stonerfish/cliw_examples/blob/master/we-clap_demos/we-clap_egui_demo/we-clap_egui_demo.gif?raw=true" width="50%"><figcaption>we-clap_egui_demo</figcaption></figure></a>

## 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.

## Recommended usage 
  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
``` 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
``` rust
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.
``` console
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
```

<a href="https://github.com/stonerfish/cliw_examples/we-clap_demos/we-clap_demo"><figure><img alt="Screencast of the we-clap_demo program running in web page with popup alerts showing a variety of clap help messages." src="https://github.com/stonerfish/cliw_examples/blob/master/we-clap_demos/we-clap_demo/we-clap_demo.gif?raw=true" width="50%"><figcaption>we-clap_demo</figcaption></figure></a>

### 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
``` 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
``` rust
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.
``` console
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
```

<a href="https://github.com/stonerfish/cliw_examples/cliw_clap_demos/cliw_clap_demo"><figure><img alt="Screencast of the cliw_clap_demo program running in web page with popup alerts showing a variety of clap help messages." src="https://github.com/stonerfish/cliw_examples/blob/master/cliw_clap_demos/cliw_clap_demo/cliw_clap_demo.gif?raw=true" width="50%"><figcaption>we-clap_demo</figcaption></figure></a>

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

#### Cargo.toml
``` toml
[package]
name = "cliw_demo"
version = "0.1.0"
edition = "2021"

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

#### main.rs
``` rust
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.
``` console
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
```

<a href="https://github.com/stonerfish/cliw_examples/cliw_demo"><figure><img alt="Screencast of the cliw_demo program running in web page with popup alerts showing a variety of clap help messages." src="https://github.com/stonerfish/cliw_examples/blob/master/cliw_demo/cliw_demo.gif?raw=true" width="50%"><figcaption>we-clap_demo</figcaption></figure></a>

## 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
    - Enable getting args from [`UrlArgs`] on the web.
    - Do not use this if your web framework provides [`std::env::args_os`].

 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.
 ```toml
 cliw = { "0.1.0", features = [
     "alert",
     "urlargs",
 ]}
 ```

## License

Copyright 2025 Richard Gould

Licensed under either of

 * Apache License, Version 2.0
   ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license
   ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

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.


[`clap`]: https://crates.io/crates/clap
[`cliw`]: https://crates.io/crates/cliw
[`cliw_clap_demo`]: https://github.com/stonerfish/cliw_examples/cliw_clap_demos/cliw_clap_demo
[`cliw_demo`]: https://github.com/stonerfish/cliw_examples/cliw_demo
[`cliw repository`]: https://github.com/stonerfish/cliw
[`crates.io`]: http://crates.io/crates/cliw
[`docs`]: https://docs.rs/cliw
[`examples`]: https://github.com/stonerfish/cliw_examples
[`std::env::args_os`]: https://doc.rust-lang.org/std/env/fn.args_os.html
[`UrlArgs`]: https://docs.rs/cliw/latest/cliw/urlargs/struct.UrlArgs.html
[`use cliw indirectly`]: https://github.com/stonerfish/cliw_examples/we-clap_demos/we-clap_demo
[`we-clap`]: https://github.com/stonerfish/clap/tree/we-clap
[`we-clap_demo`]: https://github.com/stonerfish/cliw_examples/we-clap_demos/we-clap_demo