argh_shared-0.1.13/.cargo_vcs_info.json0000644000000001510000000000100133620ustar { "git": { "sha1": "f08a5db26b964b53e33112def6f2cab9c56b66cc" }, "path_in_vcs": "argh_shared" }argh_shared-0.1.13/Cargo.toml0000644000000020560000000000100113660ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "argh_shared" version = "0.1.13" authors = [ "Taylor Cramer ", "Benjamin Brittain ", "Erick Tryzelaar ", ] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Derive-based argument parsing optimized for code size" readme = "README.md" license = "BSD-3-Clause" repository = "https://github.com/google/argh" [lib] name = "argh_shared" path = "src/lib.rs" [dependencies.serde] version = "1" features = ["derive"] optional = true argh_shared-0.1.13/Cargo.toml.orig000064400000000000000000000004431046102023000150450ustar 00000000000000[package] name = "argh_shared" version.workspace = true authors.workspace = true edition.workspace = true license.workspace = true description.workspace = true repository.workspace = true readme = "README.md" [dependencies] serde = { version = "1", optional = true, features = ["derive"] } argh_shared-0.1.13/LICENSE000064400000000000000000000027101046102023000131620ustar 00000000000000Copyright 2019 The Fuchsia Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. argh_shared-0.1.13/README.md000064400000000000000000000116311046102023000134360ustar 00000000000000# Argh **Argh is an opinionated Derive-based argument parser optimized for code size** [![crates.io](https://img.shields.io/crates/v/argh.svg)](https://crates.io/crates/argh) [![license](https://img.shields.io/badge/license-BSD3.0-blue.svg)](https://github.com/google/argh/LICENSE) [![docs.rs](https://docs.rs/argh/badge.svg)](https://docs.rs/crate/argh/) ![Argh](https://github.com/google/argh/workflows/Argh/badge.svg) 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 ```rust,no_run 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, } fn main() { let up: GoUp = argh::from_env(); } ``` `./some_bin --help` will then output the following: ``` Usage: cmdname [-j] --height [--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 = "")]` attribute, and in this case an option is treated as optional. ```rust 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, /// 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` using the `from_str_fn` attribute: ```rust 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 { Ok(5) } ``` Positional arguments can be declared using `#[argh(positional)]`. These arguments will be parsed in order of their declaration in the structure: ```rust 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: ```rust 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](https://crates.io/crates/cargo-expand) crate. ### Expand the derive macro in `examples/simple_example.rs` See [argh/examples/simple_example.rs](./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_shared-0.1.13/src/lib.rs000064400000000000000000000141621046102023000140640ustar 00000000000000// Copyright (c) 2020 Google LLC All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //! Shared functionality between argh_derive and the argh runtime. //! //! This library is intended only for internal use by these two crates. /// Information about a particular command used for output. pub struct CommandInfo<'a> { /// The name of the command. pub name: &'a str, /// A short description of the command's functionality. pub description: &'a str, } /// Information about the command line arguments for a given command. #[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct CommandInfoWithArgs<'a> { /// The name of the command. pub name: &'a str, /// A short description of the command's functionality. pub description: &'a str, /// Examples of usage pub examples: &'a [&'a str], /// Flags pub flags: &'a [FlagInfo<'a>], /// Notes about usage pub notes: &'a [&'a str], /// The subcommands. pub commands: Vec>, /// Positional args pub positionals: &'a [PositionalInfo<'a>], /// Error code information pub error_codes: &'a [ErrorCodeInfo<'a>], } /// Information about a documented error code. #[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct ErrorCodeInfo<'a> { /// The code value. pub code: i32, /// Short description about what this code indicates. pub description: &'a str, } /// Information about positional arguments #[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct PositionalInfo<'a> { /// Name of the argument. pub name: &'a str, /// Description of the argument. pub description: &'a str, /// Optionality of the argument. pub optionality: Optionality, /// Visibility in the help for this argument. /// `false` indicates this argument will not appear /// in the help message. pub hidden: bool, } /// Information about a subcommand. /// Dynamic subcommands do not implement /// get_args_info(), so the command field /// only contains the name and description. #[derive(Debug, Default, PartialEq, Eq, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct SubCommandInfo<'a> { /// The subcommand name. pub name: &'a str, /// The information about the subcommand. pub command: CommandInfoWithArgs<'a>, } /// Information about a flag or option. #[derive(Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct FlagInfo<'a> { /// The kind of flag. pub kind: FlagInfoKind<'a>, /// The optionality of the flag. pub optionality: Optionality, /// The long string of the flag. pub long: &'a str, /// The single character short indicator /// for this flag. pub short: Option, /// The description of the flag. pub description: &'a str, /// Visibility in the help for this argument. /// `false` indicates this argument will not appear /// in the help message. pub hidden: bool, } /// The kind of flags. #[derive(Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub enum FlagInfoKind<'a> { /// switch represents a boolean flag, #[default] Switch, /// option is a flag that also has an associated /// value. This value is named `arg_name`. Option { arg_name: &'a str }, } /// The optionality defines the requirements related /// to the presence of the argument on the command line. #[derive(Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub enum Optionality { /// Required indicates the argument is required /// exactly once. #[default] Required, /// Optional indicates the argument may or may not /// be present. Optional, /// Repeating indicates the argument may appear zero /// or more times. Repeating, /// Greedy is used for positional arguments which /// capture the all command line input up to the next flag or /// the end of the input. Greedy, } pub const INDENT: &str = " "; const DESCRIPTION_INDENT: usize = 20; const WRAP_WIDTH: usize = 80; /// Write command names and descriptions to an output string. pub fn write_description(out: &mut String, cmd: &CommandInfo<'_>) { let mut current_line = INDENT.to_string(); current_line.push_str(cmd.name); if cmd.description.is_empty() { new_line(&mut current_line, out); return; } if !indent_description(&mut current_line) { // Start the description on a new line if the flag names already // add up to more than DESCRIPTION_INDENT. new_line(&mut current_line, out); } let mut words = cmd.description.split(' ').peekable(); while let Some(first_word) = words.next() { indent_description(&mut current_line); current_line.push_str(first_word); 'inner: while let Some(&word) = words.peek() { if (char_len(¤t_line) + char_len(word) + 1) > WRAP_WIDTH { new_line(&mut current_line, out); break 'inner; } else { // advance the iterator let _ = words.next(); current_line.push(' '); current_line.push_str(word); } } } new_line(&mut current_line, out); } // Indent the current line in to DESCRIPTION_INDENT chars. // Returns a boolean indicating whether or not spacing was added. fn indent_description(line: &mut String) -> bool { let cur_len = char_len(line); if cur_len < DESCRIPTION_INDENT { let num_spaces = DESCRIPTION_INDENT - cur_len; line.extend(std::iter::repeat(' ').take(num_spaces)); true } else { false } } fn char_len(s: &str) -> usize { s.chars().count() } // Append a newline and the current line to the output, // clearing the current line. fn new_line(current_line: &mut String, out: &mut String) { out.push('\n'); out.push_str(current_line); current_line.truncate(0); }