Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/thepacketgeek/clap-stdin


https://github.com/thepacketgeek/clap-stdin

clap cli

Last synced: 6 days ago
JSON representation

Awesome Lists containing this project

README

        

# clap-stdin [![Build](https://img.shields.io/github/actions/workflow/status/thepacketgeek/clap-stdin/ci-build.yml?branch=main)](https://github.com/thepacketgeek/clap-stdin/actions/workflows/ci-build.yml)

This library offers two wrapper types for [`clap`](https://docs.rs/clap) `Arg`s that help
for cases where values may be passed in via `stdin`. When an `Arg` value is to be read
from `stdin`, the user will pass the commonly used `stdin` alias: `-`

- `MaybeStdin`: Used when a value can be passed in via args OR `stdin`
- `FileOrStdin`: Used when a value can be read in from a file OR `stdin`

## `MaybeStdin`

Example usage with `clap`'s `derive` feature for a positional argument:
```rust,no_run
use clap::Parser;

use clap_stdin::MaybeStdin;

#[derive(Debug, Parser)]
struct Args {
value: MaybeStdin,
}

let args = Args::parse();
println!("value={}", args.value);
```

Calling this CLI:
```sh
# using stdin for positional arg value
$ echo "testing" | cargo run -- -
value=testing
```

## Compatible Types
[`MaybeStdin`] can wrap any type that matches the trait bounds for `Arg`: `FromStr` and `Clone`
```rust
use std::path::PathBuf;
use clap::Parser;
use clap_stdin::MaybeStdin;

#[derive(Debug, Parser)]
struct Args {
path: MaybeStdin,
}
```

```sh
$ pwd | ./example -
```

## `FileOrStdin`

Example usage with `clap`'s `derive` feature for a positional argument:
```rust,no_run
use clap::Parser;

use clap_stdin::FileOrStdin;

#[derive(Debug, Parser)]
struct Args {
input: FileOrStdin,
}

# fn main() -> anyhow::Result<()> {
let args = Args::parse();
println!("input={}", args.input.contents()?);
# Ok(())
# }
```

Calling this CLI:
```sh
# using stdin for positional arg value
$ echo "testing" | cargo run -- -
input=testing

# using filename for positional arg value
$ echo "testing" > input.txt
$ cargo run -- input.txt
input=testing
```

## Compatible Types
[`FileOrStdin`] can wrap any type that matches the trait bounds for `Arg`: `FromStr` and `Clone`
```rust
use clap::Parser;
use clap_stdin::FileOrStdin;

#[derive(Debug, Parser)]
struct Args {
path: FileOrStdin,
}
```

```sh
# Value from stdin
$ wc ~/myfile.txt -l | ./example -

# Value from file
$ cat myfile.txt
42
$ .example myfile.txt
```

## Reading from Stdin without special characters
When using [`MaybeStdin`] or [`FileOrStdin`], you can allow your users to omit the "-" character to read from `stdin` by providing a `default_value` to clap. This works with positional and optional args:

```rust,no_run
use clap::Parser;

use clap_stdin::FileOrStdin;

#[derive(Debug, Parser)]
struct Args {
#[clap(default_value = "-")]
input: FileOrStdin,
}

# fn main() -> anyhow::Result<()> {
let args = Args::parse();
println!("input={}", args.input.contents()?);
# Ok(())
# }
```

Calling this CLI:
```sh
# using stdin for positional arg value
$ echo "testing" | cargo run
input=testing

# using filename for positional arg value
$ echo "testing" > input.txt
$ cargo run -- input.txt
input=testing
```

## Async Support
`FileOrStdin` can also be used with [`tokio::io::AsyncRead`](https://docs.rs/tokio/latest/tokio/io/trait.AsyncRead.html) using the `tokio` feature. See [`FileOrStdin::contents_async`] and [`FileOrStdin::into_async_reader`] for examples.

# Using `MaybeStdin` or `FileOrStdin` multiple times
Both [`MaybeStdin`] and [`FileOrStdin`] will check at runtime if `stdin` is being read from multiple times. You can use this
as a feature if you have mutually exclusive args that should both be able to read from stdin, but know
that the user will receive an error if 2+ `MaybeStdin` args receive the "-" value.

For example, this compiles:
```rust
use clap_stdin::{FileOrStdin, MaybeStdin};

#[derive(Debug, clap::Parser)]
struct Args {
first: FileOrStdin,
second: MaybeStdin,
}
```

and it will work fine if the stdin alias `-` is only passed for one of the arguments:
```sh
$ echo "2" | ./example FIRST -
```

But if `stdin` is attempted to be used for both arguments, there will be no value for the `second` arg
```sh
$ echo "2" | ./example - -
error: invalid value '-' for '': stdin argument used more than once
```

# License

`clap-stdin` is both MIT and Apache License, Version 2.0 licensed, as found
in the LICENSE-MIT and LICENSE-APACHE files.