mirror of
https://github.com/gay-pizza/jaarg.git
synced 2025-12-19 07:20:18 +00:00
Add an option to generalise parsing to a BTreeMap when using std
This commit is contained in:
29
examples/btreemap.rs
Normal file
29
examples/btreemap.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* btreemap - jaarg example program using BTreeMap
|
||||||
|
* SPDX-FileCopyrightText: (C) 2025 Gay Pizza Specifications
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
use jaarg::{std::ParseMapResult, Opt, Opts};
|
||||||
|
use std::process::ExitCode;
|
||||||
|
|
||||||
|
fn main() -> ExitCode {
|
||||||
|
const OPTIONS: Opts<&'static str> = Opts::new(&[
|
||||||
|
Opt::flag("help", &["--help"], "Show this help"),
|
||||||
|
Opt::positional("positional", "positional", "Positional argument"),
|
||||||
|
Opt::value("value", &["-v", "--value"], "path", "Value option"),
|
||||||
|
Opt::flag("flag", &["-f", "--flag"], "Flag option"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let map = match OPTIONS.parse_map_easy() {
|
||||||
|
// TODO: There should probably be a more efficient way to make jaarg handle help for us
|
||||||
|
ParseMapResult::Map(map) if map.contains_key("help") => {
|
||||||
|
OPTIONS.print_full_help("btreemap");
|
||||||
|
return ExitCode::SUCCESS;
|
||||||
|
}
|
||||||
|
ParseMapResult::Map(map) => map,
|
||||||
|
ParseMapResult::Exit(code) => { return code; }
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{:?}", map);
|
||||||
|
ExitCode::SUCCESS
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ impl<ID: 'static> Opts<ID> {
|
|||||||
pub const fn new(options: &'static[Opt<ID>]) -> Self {
|
pub const fn new(options: &'static[Opt<ID>]) -> Self {
|
||||||
Self { flag_chars: "-", options }
|
Self { flag_chars: "-", options }
|
||||||
}
|
}
|
||||||
|
// TODO: Replace with a parser options construct
|
||||||
pub const fn new_flag(flag_chars: &'static str, options: &'static[Opt<ID>]) -> Self {
|
pub const fn new_flag(flag_chars: &'static str, options: &'static[Opt<ID>]) -> Self {
|
||||||
Self { flag_chars, options }
|
Self { flag_chars, options }
|
||||||
}
|
}
|
||||||
|
|||||||
63
src/std.rs
63
src/std.rs
@@ -5,9 +5,12 @@
|
|||||||
|
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
use std::{env, eprintln, println};
|
use crate::{HandlerResult, HelpWriter, HelpWriterContext, Opt, Opts, ParseControl, ParseError, ParseResult, StandardFullHelpWriter, StandardShortUsageWriter};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::{HandlerResult, Opt, Opts, ParseControl, ParseResult, StandardShortUsageWriter, HelpWriterContext, StandardFullHelpWriter, HelpWriter};
|
use std::rc::Rc;
|
||||||
|
use std::string::String;
|
||||||
|
use std::{env, eprintln, println};
|
||||||
|
|
||||||
impl<ID: 'static> Opts<ID> {
|
impl<ID: 'static> Opts<ID> {
|
||||||
/// Wrapper around `jaarg::parse` that gathers arguments from the command line and prints errors to stderr.
|
/// Wrapper around `jaarg::parse` that gathers arguments from the command line and prints errors to stderr.
|
||||||
@@ -16,14 +19,8 @@ impl<ID: 'static> Opts<ID> {
|
|||||||
/// Requires features = [std]
|
/// Requires features = [std]
|
||||||
pub fn parse_easy<'a>(&self, handler: impl FnMut(&str, &ID, &Opt<ID>, &str, &str) -> HandlerResult<'a, ParseControl>
|
pub fn parse_easy<'a>(&self, handler: impl FnMut(&str, &ID, &Opt<ID>, &str, &str) -> HandlerResult<'a, ParseControl>
|
||||||
) -> ParseResult {
|
) -> ParseResult {
|
||||||
let mut argv = env::args();
|
let (program_name, argv) = Self::easy_args();
|
||||||
let argv0 = argv.next().unwrap();
|
self.parse(&program_name, argv, handler, |name, e| self.easy_error(name, e))
|
||||||
let program_name = Path::new(&argv0).file_name().unwrap().to_string_lossy();
|
|
||||||
self.parse(&program_name, argv, handler, |program_name, e| {
|
|
||||||
eprintln!("{program_name}: {e}");
|
|
||||||
self.eprint_help::<StandardShortUsageWriter<'_, ID>>(program_name);
|
|
||||||
eprintln!("Run '{program_name} --help' to view all available options.");
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints full help text for the options using the standard full
|
/// Prints full help text for the options using the standard full
|
||||||
@@ -48,4 +45,50 @@ impl<ID: 'static> Opts<ID> {
|
|||||||
let ctx = HelpWriterContext { options: self, program_name };
|
let ctx = HelpWriterContext { options: self, program_name };
|
||||||
eprintln!("{}", W::new(ctx));
|
eprintln!("{}", W::new(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn easy_args<'a>() -> (Rc<str>, env::Args) {
|
||||||
|
let mut argv = env::args();
|
||||||
|
let argv0 = argv.next().unwrap();
|
||||||
|
let program_name = Path::new(&argv0).file_name().unwrap().to_string_lossy();
|
||||||
|
(program_name.into(), argv)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn easy_error(&self, program_name: &str, err: ParseError) {
|
||||||
|
eprintln!("{program_name}: {err}");
|
||||||
|
self.eprint_help::<StandardShortUsageWriter<'_, ID>>(program_name);
|
||||||
|
// TODO: only show when an option is marked help
|
||||||
|
eprintln!("Run '{program_name} --help' to view all available options.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The result of parsing commands using `jaarg::Opts::parse_map`.
|
||||||
|
pub enum ParseMapResult {
|
||||||
|
Map(BTreeMap<&'static str, String>),
|
||||||
|
Exit(std::process::ExitCode),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Opts<&'static str> {
|
||||||
|
/// Parse an iterator of strings as arguments and return the results in a BTreeMap.
|
||||||
|
///
|
||||||
|
/// Requires features = [std]
|
||||||
|
pub fn parse_map<'a, S: AsRef<str> + 'a, I: Iterator<Item = S>>(&self, program_name: &str, args: I,
|
||||||
|
error: impl FnOnce(&str, ParseError)) -> ParseMapResult {
|
||||||
|
let mut out: BTreeMap<&'static str, String> = BTreeMap::new();
|
||||||
|
match self.parse(&program_name, args, |program_name, id, _opt, _name, arg| {
|
||||||
|
out.insert(id, arg.into());
|
||||||
|
Ok(ParseControl::Continue)
|
||||||
|
}, error) {
|
||||||
|
ParseResult::ContinueSuccess => ParseMapResult::Map(out),
|
||||||
|
ParseResult::ExitSuccess => ParseMapResult::Exit(std::process::ExitCode::SUCCESS),
|
||||||
|
ParseResult::ExitError => ParseMapResult::Exit(std::process::ExitCode::FAILURE),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse arguments from the command line and return the results in a BTreeMap.
|
||||||
|
///
|
||||||
|
/// Requires features = [std]
|
||||||
|
pub fn parse_map_easy(&self) -> ParseMapResult {
|
||||||
|
let (program_name, argv) = Self::easy_args();
|
||||||
|
self.parse_map(&program_name, argv, |name, e| self.easy_error(name, e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user