Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hand written user documentation overhaul (part 1) #242

Merged
merged 5 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ bpaf = { path = ".", features = ["derive", "extradocs", "autocomplete", "docgen
[package.metadata.docs.rs]
features = ["derive", "extradocs", "autocomplete", "batteries"]
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
rustdoc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--generate-link-to-definition"]


[features]
Expand Down
6 changes: 5 additions & 1 deletion docs2/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ fn import_example(example: &Path, name: &str) -> Result<String> {
let test_source = std::fs::read_to_string(&example)?;
let mut cases = String::new();

for line in std::fs::read_to_string(PathBuf::from("src").join(name).join("cases.md"))?.lines() {
let file = PathBuf::from("src").join(name).join("cases.md");
if !file.exists() {
return Err(format!("File does not exist: {file:?}").into());
}
for line in std::fs::read_to_string(file)?.lines() {
if let Some(all_args) = line.strip_prefix("> ") {
let args = shell_words::split(all_args)?;
write_scenario(&mut cases, &args, all_args, None)?;
Expand Down
1 change: 1 addition & 0 deletions docs2/src/command_enum/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub enum Options {
Build {
/// Name of a binary to build
bin: String,

/// Compile the binary in release mode
release: bool,
},
Expand Down
1 change: 1 addition & 0 deletions docs2/src/command_enum/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub enum Options {
#[bpaf(argument("BIN"))]
/// Name of a binary to build
bin: String,

/// Compile the binary in release mode
release: bool,
},
Expand Down
20 changes: 20 additions & 0 deletions docs2/src/compose_basic_argument/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
By default all arguments are required so running with no arguments produces an error

>

Bpaf accepts various combinations of names and adjacencies:

> -s100
> --size 300
> -s=42
> --size=14

Since not every string is a valid number - bpaf would report any parsing failures to the user
directly

> --size fifty

In addition to the switch you defined `bpaf` generates switch for user help which will include
the description from the `help` method

> --help
9 changes: 9 additions & 0 deletions docs2/src/compose_basic_argument/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use bpaf::*;

pub fn options() -> OptionParser<usize> {
short('s')
.long("size")
.help("Defines size of an object")
.argument::<usize>("SIZE")
.to_options()
}
14 changes: 14 additions & 0 deletions docs2/src/compose_basic_choice/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Help message describes all the parser combined
> --help

Users can pass value that satisfy either parser

> --miles 42
> --kilo 15

But not both at once or not at all:

> --miles 53 --kilo 10
>

If those cases are valid you can handle them with `optional` and `many`
7 changes: 7 additions & 0 deletions docs2/src/compose_basic_choice/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use bpaf::*;

pub fn options() -> OptionParser<f64> {
let miles = long("miles").help("Distance in miles").argument("MI");
let km = long("kilo").help("Distance in kilometers").argument("KM");
construct!([miles, km]).to_options()
}
13 changes: 13 additions & 0 deletions docs2/src/compose_basic_command/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Help contains both commands, bpaf takes short command description from the inner command
description

> --help

Same as before each command gets its own help message

> run --help

And can be executed separately

> run --bin basic
> build --bin demo --release
49 changes: 49 additions & 0 deletions docs2/src/compose_basic_command/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
use bpaf::*;
#[derive(Debug, Clone)]
pub enum Options {
/// Run a binary
Run {
/// Name of a binary to run
bin: String,

/// Arguments to pass to a binary
args: Vec<String>,
},
/// Compile a binary
Build {
/// Name of a binary to build
bin: String,

/// Compile the binary in release mode
release: bool,
},
}

// combine mode gives more flexibility to share the same code across multiple parsers
fn run() -> impl Parser<Options> {
let bin = long("bin").help("Name of a binary to run").argument("BIN");
let args = positional("ARG")
.strict()
.help("Arguments to pass to a binary")
.many();

construct!(Options::Run { bin, args })
}

pub fn options() -> OptionParser<Options> {
let run = run().to_options().descr("Run a binary").command("run");

let bin = long("bin")
.help("Name of a binary to build ")
.argument("BIN");
let release = long("release")
.help("Compile the binary in release mode")
.switch();
let build = construct!(Options::Build { bin, release })
.to_options()
.descr("Compile a binary")
.command("build");

construct!([run, build]).to_options()
}
8 changes: 8 additions & 0 deletions docs2/src/compose_basic_construct/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Help message describes all the parser combined
> --help

And users can pass any combinations of options, resulting parser will handle them as long as they are valid

> --argument 10 --argument 20
> --switch
> --switch --switch --argument 20
16 changes: 16 additions & 0 deletions docs2/src/compose_basic_construct/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use bpaf::*;

#[derive(Debug, Clone)]
pub struct Options {
argument: Vec<u32>,
switches: Vec<bool>,
}

pub fn options() -> OptionParser<Options> {
let argument = long("argument")
.help("important argument")
.argument("ARG")
.many();
let switches = long("switch").help("some switch").switch().many();
construct!(Options { argument, switches }).to_options()
}
9 changes: 9 additions & 0 deletions docs2/src/compose_basic_many/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Run inner parser as many times as possible collecting all the new results
First `false` is collected from a switch even if it is not consuming anything
> --argument 10 --argument 20

If there's no matching parameters - it would produce an empty vector.
>

In usage lines `many` items are indicated with `...`
> --help
9 changes: 9 additions & 0 deletions docs2/src/compose_basic_many/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use bpaf::*;

pub fn options() -> OptionParser<Vec<u32>> {
let argument = long("argument")
.help("important argument")
.argument("ARG")
.many();
argument.to_options()
}
14 changes: 14 additions & 0 deletions docs2/src/compose_basic_positional/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Same as with argument by default there's no fallback so with no arguments parser fails

>

Other than that any name that does not start with a dash or explicitly converted to positional
parameter gets parsed:

> https://lemmyrs.org
> "strange url"
> -- --can-start-with-dash-too

And as usual there's help message

> --help
6 changes: 6 additions & 0 deletions docs2/src/compose_basic_positional/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use bpaf::*;

pub fn options() -> OptionParser<String> {
let simple = positional("URL").help("Url to open");
simple.to_options()
}
12 changes: 12 additions & 0 deletions docs2/src/compose_basic_switch/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
If you run the app with no parameters - switch will parse as `false`

>

Both short and long names produce true

> -s
> --simple

In addition to the switch you defined `bpaf` generates switch for user help

> --help
6 changes: 6 additions & 0 deletions docs2/src/compose_basic_switch/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use bpaf::*;

pub fn options() -> OptionParser<bool> {
let simple = short('s').long("simple").switch();
simple.to_options()
}
17 changes: 17 additions & 0 deletions docs2/src/compose_basic_to_options/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
In addition to all the arguments specified by user `bpaf` adds a few more. One of them is
`--help`:

> --help

The other one is `--version` - passing a string literal or something like
`env!("CARGO_PKG_VERSION")` to get version from `cargo` directly usually works

> --version

Other than that `bpaf` tries its best to provide a helpful error messages

>

And if all parsers are satisfied [`run`](OptionParser::run) produces the result

> -i 10
16 changes: 16 additions & 0 deletions docs2/src/compose_basic_to_options/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
use bpaf::*;
#[derive(Debug, Clone)]
pub struct Options {
argument: u32,
}

pub fn options() -> OptionParser<Options> {
let argument = short('i').argument::<u32>("ARG");
construct!(Options { argument })
.to_options()
.version("3.1415")
.descr("This is a short description")
.header("It can contain multiple blocks, this block goes before options")
.footer("This one goes after")
}
7 changes: 7 additions & 0 deletions docs2/src/intro/cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
With everything in place users should be able to pass their arguments

> "Hello world"

As well as read the help message generated by the library

> --help
11 changes: 11 additions & 0 deletions docs2/src/intro/combine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use bpaf::*;

#[derive(Debug, Clone)]
pub struct Options {
message: String,
}

pub fn options() -> OptionParser<Options> {
let message = positional("MESSAGE").help("Message to print in a big friendly letters");
construct!(Options { message }).to_options()
}
9 changes: 9 additions & 0 deletions docs2/src/intro/derive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use bpaf::*;

#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
/// Message to print in a big friendly letters
#[bpaf(positional("MESSAGE"))]
message: String,
}
5 changes: 5 additions & 0 deletions docs2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ fn import_escaped_source(res: &mut String, path: impl AsRef<std::path::Path>, ti
writeln!(res, "{}", line).unwrap();
}
}
writeln!(
res,
"\nfn main() {{\n println!(\"{{:?}}\", options().run())\n}}"
)
.unwrap();
writeln!(res, "```\n").unwrap();
writeln!(res, "</details>").unwrap();
}
Expand Down
Loading
Loading