Giter Club home page Giter Club logo

argh's Introduction

Argh

Argh is an opinionated Derive-based argument parser optimized for code size

crates.io license docs.rs Argh

Derive-based argument parsing optimized for code size and conformance to the Fuchsia commandline tools specification

The public API of this library consists primarily of the FromArgs derive and the from_env function, which can be used to produce a top-level FromArgs type from the current program's commandline arguments.

Basic Example

use argh::FromArgs;

#[derive(FromArgs)]
/// Reach new heights.
struct GoUp {
    /// whether or not to jump
    #[argh(switch, short = 'j')]
    jump: bool,

    /// how high to go
    #[argh(option)]
    height: usize,

    /// an optional nickname for the pilot
    #[argh(option)]
    pilot_nickname: Option<String>,
}

fn main() {
    let up: GoUp = argh::from_env();
}

./some_bin --help will then output the following:

Usage: cmdname [-j] --height <height> [--pilot-nickname <pilot-nickname>]

Reach new heights.

Options:
  -j, --jump        whether or not to jump
  --height          how high to go
  --pilot-nickname  an optional nickname for the pilot
  --help, help      display usage information

The resulting program can then be used in any of these ways:

  • ./some_bin --height 5
  • ./some_bin -j --height 5
  • ./some_bin --jump --height 5 --pilot-nickname Wes

Switches, like jump, are optional and will be set to true if provided.

Options, like height and pilot_nickname, can be either required, optional, or repeating, depending on whether they are contained in an Option or a Vec. Default values can be provided using the #[argh(default = "<your_code_here>")] attribute, and in this case an option is treated as optional.

use argh::FromArgs;

fn default_height() -> usize {
    5
}

#[derive(FromArgs)]
/// Reach new heights.
struct GoUp {
    /// an optional nickname for the pilot
    #[argh(option)]
    pilot_nickname: Option<String>,

    /// an optional height
    #[argh(option, default = "default_height()")]
    height: usize,

    /// an optional direction which is "up" by default
    #[argh(option, default = "String::from(\"only up\")")]
    direction: String,
}

fn main() {
    let up: GoUp = argh::from_env();
}

Custom option types can be deserialized so long as they implement the FromArgValue trait (automatically implemented for all FromStr types). If more customized parsing is required, you can supply a custom fn(&str) -> Result<T, String> using the from_str_fn attribute:

use argh::FromArgs;

#[derive(FromArgs)]
/// Goofy thing.
struct FiveStruct {
    /// always five
    #[argh(option, from_str_fn(always_five))]
    five: usize,
}

fn always_five(_value: &str) -> Result<usize, String> {
    Ok(5)
}

Positional arguments can be declared using #[argh(positional)]. These arguments will be parsed in order of their declaration in the structure:

use argh::FromArgs;

#[derive(FromArgs, PartialEq, Debug)]
/// A command with positional arguments.
struct WithPositional {
    #[argh(positional)]
    first: String,
}

The last positional argument may include a default, or be wrapped in Option or Vec to indicate an optional or repeating positional argument.

Subcommands are also supported. To use a subcommand, declare a separate FromArgs type for each subcommand as well as an enum that cases over each command:

use argh::FromArgs;

#[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
struct TopLevel {
    #[argh(subcommand)]
    nested: MySubCommandEnum,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum MySubCommandEnum {
    One(SubCommandOne),
    Two(SubCommandTwo),
}

#[derive(FromArgs, PartialEq, Debug)]
/// First subcommand.
#[argh(subcommand, name = "one")]
struct SubCommandOne {
    #[argh(option)]
    /// how many x
    x: usize,
}

#[derive(FromArgs, PartialEq, Debug)]
/// Second subcommand.
#[argh(subcommand, name = "two")]
struct SubCommandTwo {
    #[argh(switch)]
    /// whether to fooey
    fooey: bool,
}

NOTE: This is not an officially supported Google product.

How to debug the expanded derive macro for argh

The argh::FromArgs derive macro can be debugged with the cargo-expand crate.

Expand the derive macro in examples/simple_example.rs

See argh/examples/simple_example.rs for the example struct we wish to expand.

First, install cargo-expand by running cargo install cargo-expand. Note this requires the nightly build of Rust.

Once installed, run cargo expand with in the argh package and you can see the expanded code.

argh's People

Contributors

aminya avatar atul9 avatar bastidood avatar benbrittain avatar carbocarde avatar claywilkinson avatar elipsitz avatar erickt avatar foresterre avatar kafji avatar katemorley avatar lassipulkkinen avatar lioness100 avatar lrazovic avatar matklad avatar maurer avatar mboetger avatar mkatychev avatar mredies avatar novacrazy avatar omertuc avatar otavio avatar qhua948 avatar richkadel avatar sadmac7000 avatar stormbrew avatar theli-ua avatar tshepang avatar xzfc avatar yujincheng08 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

argh's Issues

Add a chart comparing Argh to existing parsers

If Argh is "optimized for code size", then it only makes sense to show a comparison with other existing parsers, similar to the chart in the README for pico-args.

(Though, ideally, also with a quick run-down of how the features and APIs compare.)

The pico-args chart covers bare Clap, Clap+structopt, pico-args, and gumdrop, though argparse also shows up reasonably high in search results.

Interleaved positional arguments and switches/options are parsed in unexpected ways

I have a command that ends up running another program with some CLI arguments. I have a struct like:

#[derive(Debug, FromArgs)]
struct Args {
    #[argh(switch, short = 'v')]
    verbose: bool,

    #[argh(positional)]
    program: String,

    #[argh(positional)]
    args: Vec<String>,
}

argh allows options and switches to be parsed even after position arguments are found, which leads the following behavior:

Examples

Correct

-v program arg1 arg2 arg3 is parsed as {verbose: true, program: "program", args: ["arg1", "arg2", "arg3"]}

Not correct

program --option-for-the-program doesn't parse, because --option-for-the-program isn't a valid argument for Args.

I would expect it to parse as {verbose: false, program: "program", args: ["--option-for-the-program"]}.

Not correct

program arg1 arg2 -v arg3 bizarrely parses as {verbose: true, program: "Program", args: ["arg1", "arg2", "arg3"]}.

I would expect it to parse args as ["arg1", "arg2", "-v", "arg3"].

Not correct

Similar to above, program arg1 arg2 -p arg3 fails to parse because -p is treated as a switch for the top level command.

Fix

A fix for all of this would be to stop parsing options/switches once we hit a positional argument, and definitely don't allow options/switches to come in the middle of a Vec positional argument.

The issue with this fix is that some people might want to run their commands like tar my_dir/ -f output.tar instead of tar -f output.tar my_dir/ -- this would break that.

One could definitely argue that my use case is weird and not particularly suited for argh. However, consider a more reasonable (albeit slightly contrived) example:

#[derive(Debug, FromArgs)]
/// Sums some numbers.
struct Sum {
    /// the numbers
    #[argh(positional)]
    numbers: Vec<i64>,
}

This returns the correct results for sum 1 2 3 4 5, but breaks if you give it sum 4 7 -8 3 5 (erroring with "Unrecognized argument: -8"), because of the same issue.

Support for completion scripts generation

A convenient feature of clap is the support for generating shell completion scripts from build.rs (i.e. during build of the application, thus without overhead on the application).

I don't know if there's already something available and I didn't find it or if it's still something which should be added.

If an addition is needed, would you welcome some PR ?

Examples

An example directory of common usage patterns

[Request] better raw identifier support

#[derive(FromArgs, Debug)]
/// tool
pub struct Config {
    #[argh(option)]
    /// run forever. Exit with Ctrl-C.
    pub r#loop: bool,
}
$ tool --loop
Required options not provided:
    --r-loop

Obviously, here the flag should be loop not r-loop :)

Wrong output in terminal

use argh::FromArgs;

use std::path::PathBuf;

#[derive(FromArgs, Debug)]
#[argh(description = "Prints xrefs to specified string address")]
struct Arguments {
    /// path to target binary file
    #[argh(positional)]
    filename: PathBuf,

    /// todo
    #[argh(option, from_str_fn(always_five))]
    offset: usize,

    /// todo
    #[argh(option, from_str_fn(always_five))]
    length: usize,
}

fn always_five(_value: &str) -> Result<usize, String> {
    Ok(5)
}

fn main() {
    let p: Arguments = argh::from_env();
    dbg!(p);
}
$ cargo run

    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/xstrings`
Required positional arguments not provided:
    filenameRequired options not provided:
    --offset
    --length

Allow multiple subcommands

I would really like to be able to do the following:

prog <general_args..> cmd1 <cmd1_args..> cmd2 <cmd2_args..>

Because my program needs to have a CLI to run commands seq sequentially, without duplicating all the fields in each subcommand: Currently the cli for that looks like:

prog <general_args..> cmd1 <cmd1_args..> --cmd2 <cmd2_args..>

Which makes everything really awkward, especially because I have to duplicate the fields and support chaining and calling of cmd2 directly. And now I want to be able to chain arbitrary number of commands, this gets very hairy!
So please, can we allow multiple subcommands? :)

Use the Default trait for enums used as options

It should be possible to use an enum as the possible value of an option, without wrapping it in an Option when and if the enum implements Default.

Current example :

#[derive(argh::FromArgs)]
struct Args {
    /// output format
    #[argh(option)]
    format: Option<OutputFormat>,
}

let args: Args = argh::from_env();
let format = args.format.unwrap_or_default();

Using the Default trait :

#[derive(argh::FromArgs)]
struct Args {
    /// output format
    #[argh(option)]
    format: OutputFormat, // enum should implement Default
}

Case in my own code, just for context.

Establish some written governance

This will need to evolve, this proposal is just a starting point based on history and practical concerns for invested stakeholders.

  • For the time being, one of the stated project goals is to support the fuchsia command specification. This may change over time, but is a nod to our heritage and acknowledging this stakeholder helps us to make shared decisions. It's important to note that the Fuchsia command spec is not immovable, but it has its own governance model.
  • We can support non-conflicting features beyond the aforementioned specification, and the library can enable users to write code that violates the aforementioned specification.
  • We want to constrain the feature set in the library such that we maintain sight on several key goals:
    • small object code
    • low cost of ownership implementation
    • a balanced simple and easy to use public api surface

We should identify some key stakeholders to take part in decision making with regard to the above, and at a later time establish how that group membership evolves over time. The first implementation of the group will be discretionary.

Practical matters:

  • There are a number of issues in the tracker, both open and closed the implementations of which have as yet been avoided due to apparent conflicts with the fuchsia command specification. We would like to respond to these thoughtfully, so the goal is to enable a mechanism by which we can make a project-local decision about which to accept and which to reject, while being considerate as discussed above. For now we'll label those issues as specification change issues, so that we can collate them for focused discussion at a dedicated time.
  • Where applicable we will take back some of the suggestions to Fuchsia API council as change proposals for the fuchsia specification, as minimizing the deviation between available features in this library, and the specification to which the (current) largest user group is useful for both sides, as well as outside users who aren't clear on the relationship between the two. I'll take ownership of executing this process, but I'll also make sure to coordinate here so that all voices are heard - the process will be open.
  • Some decisions have already been made by maintainers / stakeholders, but are not yet documented (particular those where the decision was not to support something). We will start to respond to issues requesting such features by adding documentation that explains the motivations behind the choice, even if that choice is just arbitrary. Requests to revisit those decisions will remain open, but the requester should bring new use cases / examples / motivations to the discussion.

[Question] What is a feasibility of automatic help about default options?

Hi!

I was thinking about automatic print of the defaults to the help message, like kingpin and clap do ("-f, --file file [default: ~/path/to]"). After messing around argh code I realized that it would be not really trivial to make a PR... or trivial? What is your ideology about printing defaults to help?

Of course, the easy way is just to manually add them to the description, still...

Thank you!

Garbles help text when subcommand follows a positional argument

/// ...
#[derive(argh::FromArgs)]
struct Opts {
    #[argh(positional)]
    dbpath: PathBuf,

    #[argh(subcommand)]
    cmd: Cmd,
}

/// Outout entire content of the database to text file, stdout (suitable for migrations)
#[derive(argh::FromArgs)]
#[argh(subcommand, name = "export")]
struct Export {}

/// Import entire content of the database from text file, stdin (suitable for migrations)
#[derive(argh::FromArgs)]
#[argh(subcommand, name = "import")]
struct Import {}

#[derive(argh::FromArgs)]
#[argh(subcommand)]
enum Cmd {
    Export(Export),
    Import(Import),
}
Required positional arguments not provided:
    dbpathOne of the following subcommands must be present:
    help
    export
    import

Suggestion: `#[argh(rename = "name")]`

Problem: Often, fields that are option members have long (descriptive) names that make sense in the source code, but are too long to type for cli options.
The attribute short = 'x' can only take single chars, so that can't be used to shorten them.

Solution: Adding a way to rename cli option members using #[argh(rename = "name")].
Similar to #[serde(rename = "name")].

Default subcommand

Is it possible to make a default subcommand with argh? I want something like this:

#[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
struct TopLevel {
    #[argh(subcommand)]
    nested: Sub,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum Sub {
    #[argh(default)] // <-----
    One(SubCommandOne),
    Two(SubCommandTwo),
}

/* one and two subcommands*/

With

  • cmd one ... resulting in Sub::One(..)
  • cmd two ... resulting in Sub::Two(..)
  • cmd ... resulting in Sub::One(..) (the default)

Use basename not full path in help

When the help shows the usage, it shows the full path of a command. Instead, show the basename of the command (just the actually command's name).

Arbitrarily nested subcommands

Is it possible to have arbitrarily nested subcommands? I have an example where it doesn't seem to be working, but maybe I'm holding it wrong :)

The example is like:

#[derive(Debug, FromArgs)]
pub struct Args {
    #[argh(subcommand)]
    command: Command,
}

#[derive(Debug, FromArgs)]
#[argh(subcommand)]
pub enum Command {
    Foo(Foo),
    Bar(Bar),
}

#[derive(Debug, FromArgs)]
#[argh(subcommand, name = "foo")]
pub enum Foo {
    Baz(Baz),
    Quux(Quux),
}

#[derive(Debug, FromArgs)]
#[argh(subcommand, name = "baz")]
pub struct Baz {
    /// the baz
    #[argh(option)]
    baz: String,
}

#[derive(Debug, FromArgs)]
#[argh(subcommand, name = "quux")]
pub struct Quux {
    /// the quux
    #[argh(option)]
    quux: String,
}

#[derive(Debug, FromArgs)]
#[argh(subcommand, name = "bar")]
pub enum Bar {
    Who(Who),
    What(What),
}

pub struct Who {
    /// the Who
    #[argh(option]
    who: String,
}

#[derive(Debug, FromArgs)]
#[argh(subcommand, name = "what")]
pub struct What {
    /// the What
    #[argh(option)]
    what: String,
}

The error I get is along the lines:

error: Unused `argh` attribute on `#![derive(FromArgs)]` enum. Such `enum`s can only be used to dispatch to subcommands, and should only contain the #[argh(subcommand)] attribute.
  --> copy/src/bin/main.rs:43:27
   |
43 | #[argh(subcommand, name = "foo")]
   |                           ^^^^^^^^^

error: Unused `argh` attribute on `#![derive(FromArgs)]` enum. Such `enum`s can only be used to dispatch to subcommands, and should only contain the #[argh(subcommand)] attribute.
  --> copy/src/bin/main.rs:69:27
   |
69 | #[argh(subcommand, name = "bar")]
   |                           ^^^^^^^^

error[E0277]: the trait bound `Bar: SubCommand` is not satisfied
  --> copy/src/bin/main.rs:34:17
   |
34 | #[derive(Debug, FromArgs)]
   |                 ^^^^^^^^ the trait `SubCommand` is not implemented for `Bar`
   |
   = note: required by `COMMAND`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Foo: SubCommand` is not satisfied
  --> copy/src/bin/main.rs:34:17
   |
34 | #[derive(Debug, FromArgs)]
   |                 ^^^^^^^^ the trait `SubCommand` is not implemented for `Foo`
   |
   = note: required by `COMMAND`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

Thanks for the help :)

Allow positional arguments to be omitted from the help text

I have been using argh to develop a new cargo command. Cargo passes the actual command being executed as the first command line argument. In order to capture (and ignore) that argument, I have an extra positional argument in the structure, followed by the real positional arguments. However, this first argument shows up in the command line help and is quite confusing as users should not actually enter it. It would be good to have a flag that omits a positional argument (and possibly others) from the generated help text.

Support option delimiter in argh

Two dashes ('--') will indicate the end of argument options. All subsequent values are given to the tool as-is. For example, with "Usage: foo [-a] ", the command line "foo -- -a" may interpret -a as a file name rather than a switch. Further, "foo -a -- -a" enables the switch -a (the first -a, before the --) and passes the literal text -a (the second -a).

This option is supported in various tools. Would be useful to support here too.

Probably incorrect error message about default values for subcommands

default may only be specified on #[argh(option)] or #[argh(subcommand)] fields"

But the code checks for positional or option. Error message should be fixed to include #[argh(positional)]. Preferrably default subcommands should be implemented as well (with effect similar to optional subcommands).

Only display name of binary

I'm having a weird issue with the generated help message: the command is with it's absolute path when I run ./target/debug/mycmd --help

What am I doing wrong?

./target/debug/mycmd --help
Usage: ./target/debug/mycmd [<test_file...>] -a <address> [-p <port>]

MyCMD

Options:
  -a, --address     address
  -p, --port        port
  --help            display usage information
#[derive(FromArgs)]
/// MyCMD
struct Opt {
    #[argh(option, short = 'a')]
    /// address
    address: String,
    #[argh(option, short = 'p')]
    /// port
    port: Option<u32>,
    #[argh(positional)]
    /// script files to run
    test_file: Vec<PathBuf>,
}

Bot tracking binary size

There are some changes to the library (as well as increasing usage!) and I'd like to prevent size regressions. We should check binary output on a slew of targets/configs on every commit

A single quote is missing in the "Error parsing positional argument" message

I tried:

#[derive(argh::FromArgs)]
#[argh(description = "...")]
struct Args {
    #[argh(positional)]
    n: usize,
}

When I ran cargo run invalid-argument, it printed:

Error parsing positional argument 'n' with value 'invalid-argument: invalid digit found in string

A single quote was missing. It should be Error parsing positional argument 'n' with value 'invalid-argument': invalid digit found in string, just like error messages for non-positional arguments:

argh/src/lib.rs

Line 429 in 8d9a82f

["Error parsing option '", arg, "' with value '", value, "': ", &s, "\n"].concat()

Corresponding source code:

argh/src/lib.rs

Line 448 in 8d9a82f

["Error parsing positional argument '", name, "' with value '", arg, ": ", &s].concat()

A single quote should be inserted after arg.

Offer ability to short circuit help output (Ex: -h)

Currently, passing -h doesn't work:

Unrecognized argument: -h

Passing -h should work the same as --help, unless one of the options/switches uses short = 'h'.


And in the Usage output, it would then show

-h, --help display usage information

instead of just

--help display usage information

[Question] `positional` argument with at least one value mandatory

Is there a way to specify that a positional arg need at least one value?

#[derive(FromArgs)]
/// MyCMD
struct Opt {
    #[argh(positional)]
    /// script files to run
    test_file: Vec<PathBuf>,
}

gives me:

Usage: mycmd.exe [<test_file...>]

Which suggests the tool can work without any input when it needs at least one.

Errors should go to stderr

Most command line tools send --help and --version output to stdout, but send parsing failures to stderr. argh now sends both of these 'early exits' to stdout.

Switch chaining like `-vv` for verbosity?

Is it possible to allow switch chaining like -vv for verbosity?

With this

	/// verbosity level
	#[argh(switch, short = 'v')]
	verbosity: u8,

it only allows -v -v, not -v 2 or -vv.

It'd be nice to manually print usage

In some cases (i.e. if an argument is the correct type but maybe isn't exactly desirable), it'd be nice to short-circuit the app and manually print the usage. I didn't see a way to do this in the docs.

I'm using 0.1.3.

Argh fails to remove newlines from within /** */ style doc block comments on struct fields.

Hello,
I was working on a crate and found inconsistent newlines when argh prints help for a binary when using different forms of doc comments.

When fields within a FromArgs struct are documented using /// style doc comments, and consecutive lines also begin with /// every newline and break in the doc comment is ignored when the --help string is printed. If instead the fields are documented using /** */ style doc block comments, newlines within that block are preserved into the output of --help.

I have provided some sample code which manages to reproduce it (at least on my end) and should provide help with triaging this.

OS Cargo Version Rustup default
Windows 10 cargo 1.43.0-nightly (bda50510d 2020-03-02) nightly-x86_64-pc-windows-msvc (default)

Example Code

#[derive(Debug, argh::FromArgs)]
/// Demonstrating the disparity between /** */ doc comments
/// and /// doc comments
struct FailToDocument {
	#[argh(switch)]
	/// this doc comment will print itself correctly
	/// when wrapped using multiple newlines + ///
	/// at the begining
	working_example: bool,

	#[argh(switch)]
	/** this doc comment will fail to print itself correctly
	when wrapped using multiple newlines + /** */ at the
	begining */
	failing_example: bool,
}

fn main() {
	dbg!(argh::from_env::<FailToDocument>());
}
Shell Fish Shell on Windows Subsystem for Linux
/mnt/z/dev/stf-rs$ cargo.exe run -- --help
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target\debug\stf.exe --help`
Usage: target\debug\stf.exe [--working-example] [--failing-example]

Demonstrating the disparity between /** */ doc comments and /// doc comments

Options:
  --working-example this doc comment will print itself correctly when wrapped
                    using multiple newlines + /// at the begining
  --failing-example this doc comment will fail to print itself correctly
        when
                    wrapped using multiple newlines + /** */ at the
        begining
  --help            display usage information
Shell Powershell
PS Z:\dev\stf-rs> cargo run -- --help
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target\debug\stf.exe --help`
Usage: target\debug\stf.exe [--working-example] [--failing-example]

Demonstrating the disparity between /** */ doc comments and /// doc comments

Options:
  --working-example this doc comment will print itself correctly when wrapped
                    using multiple newlines + /// at the begining
  --failing-example this doc comment will fail to print itself correctly
        when
                    wrapped using multiple newlines + /** */ at the
        begining
  --help            display usage information

Distinguish between `x` and `-- x`

#60 marks all options following -- as positional arguments, but there's no way to tell the difference between arguments before and after the dashes.

My use case is that I have a cargo wrapper, and I want to pass all arguments after -- verbatim to cargo, but parse arguments before -- differently.

Supporting non-UTF-8 paths

I love argh for its simplicity, compile performance and leanness, and I find myself migrating more and more projects to it.

Just now it became evident that despite supporting PathBuf in struct fields, it will always assume valid UTF-8 in the arguments it parses. This might be an assumption that holds in Fuchsia, but may make it impossible to use for general purpose linux tools that consume paths in arguments.

I wonder if there is any chance to allow parsing PathBuf fields without making assumptions about their encoding?

Thank you

PS: This question was triggered by this post on reddit/r/rust.

from_env is not from environment variables?

It's not obvious from the readme that from_env() does not take input from environment variables. This may be confusing for first time readers of this documentation. Note that the 'env' term has popular usage to mean environment variables in the 'env', env_logger, and dotenv crates.

I think the documentation is great, so this isn't intended as critical, but rather an attempt to highlight the challenge for newcomers to rust, who may struggle to understand the meaning of various documentation.

Positional arguments do not have a help

Running `/work/pump --help`
Usage: /work/pump <topic> [<fields...>] [-w]

pump

Options:
  -w, --wait-for-reply
                    wait for reply
  --help            display usage information
/// pump
#[derive(Debug, FromArgs)]
struct Args {
    /// topic of message to send
    #[argh(positional)]
    topic: String,
    ...
}

Shouldn't positional arguments like topic and fields also have their description displayed in a section such as Options? If not, how would the user know the meaning of topic and fields? Thanks

[Breaking change] Accept raw expression for default values

There might be a reason why default requires an expression-as-a-string, but I can't think of one. The reference has examples of macros doing lots of funky things inside attributes.

It would be nice if someone could write, for example,

#[derive(FromArgs)]
struct GoUp {
    #[argh(option, default = default_height())]
    height: usize,

    #[argh(option, default = String::from("only up"))]
    direction: String,
}

The second example in particular is much nicer than what we have to write today,

    #[argh(option, default = "String::from(\"only up\")")]
    direction: String,

We could even wrap the expression with Into::into() in the expansion so it gets even shorter..

    #[argh(option, default = "only up")]
    direction: String,

The only problem is that this is definitely a breaking change.

One possible soft migration is to add a new attribute default_expr which has these semantics.

Access subcommand from Base Command.

 #[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
struct TopLevel {
  #[argh(subcommand)]
  nested: MySubCommandEnum,
  /// number of connections
  #[argh(option, short = 'c', default = "1")]
  connections: usize,
}

 #[derive(FromArgs, PartialEq, Debug)]
 #[argh(subcommand)]
 enum MySubCommandEnum {
   Pub(PublishConfig),
   Sub(SubConfig),
 }

Here in we have 2 sub commands for a base command.

in main.rs

 let base = argh::from_env()

After that I want to filter out he nested command and use one appropriately.

 let sub_command = tt.nested;
println!("{:?}", sub_command);

match sub_command {
    MySubCommandEnum::Pub => {
        println!("We have to do Publish");
    },
    MySubCommandEnum::Sub => {
        println!("We have to subs");
    },
}

When I try to do something like this, I get following error expected unit struct, unit variant or constant, found tuple variant MySubCommandEnum::Pubdid you meanMySubCommandEnum::Pub`

What am I missing? Thanks in advance.

Newline is missing in error output

I tried this:

#[derive(Clone, argh::FromArgs)]
#[argh(description = "...")]
struct Options {
    #[argh(option, description = "...")]
    bind_to: SocketAddr,
    #[argh(positional)]
    dir: PathBuf,
}

When I ran the program with no argument, it printed:

Required positional arguments not provided:
    dirRequired options not provided:
    --bind-to

The second line of the output was unreadable. I expected the output to be:

Required positional arguments not provided:
    dir
Required options not provided:
    --bind-to

It seems that

argh/src/lib.rs

Lines 536 to 538 in 507087f

if !self.options.is_empty() {
output.push_str("\n");
}

is missing in

argh/src/lib.rs

Lines 527 to 529 in 507087f

if !self.options.is_empty() {
output.push_str("Required options not provided:");
for option in &self.options {
.

Flag with optional value?

Hi,

is there a way to express a flag that might have a value?
This doesn't work:

#[derive(FromArgs)]
struct Opt {
  #[argh(option, short='f')]
  /// my flag
  flag: Option<Option<u32>>
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.