Skip to main content

CliParser

Struct CliParser 

Source
pub struct CliParser<'a> { /* private fields */ }
Expand description

CLI argument parser

Parses command-line arguments according to a CommandDefinition. The parser handles both positional arguments and named options with type conversion and validation.

§Lifetime

The parser holds a reference to a CommandDefinition and therefore has a lifetime parameter 'a that must outlive the parser.

§Example

use dynamic_cli::parser::cli_parser::CliParser;
use dynamic_cli::config::schema::{
    CommandDefinition, OptionDefinition, ArgumentType
};
use std::collections::HashMap;

let definition = CommandDefinition {
    name: "test".to_string(),
    aliases: vec![],
    description: "Test command".to_string(),
    required: false,
    arguments: vec![],
    options: vec![
        OptionDefinition {
            name: "verbose".to_string(),
            short: Some("v".to_string()),
            long: Some("verbose".to_string()),
            option_type: ArgumentType::Bool,
            required: false,
            default: Some("false".to_string()),
            description: "Verbose output".to_string(),
            choices: vec![],
            repeatable: false,
            option_parameters: HashMap::new(),
        }
    ],
    implementation: "handler".to_string(),
    continue_on_failure: false,
    requires_success: false,
};

let parser = CliParser::new(&definition);
let args = vec!["-v".to_string()];
let parsed = parser.parse(&args).unwrap();

assert_eq!(parsed.get("verbose"), Some(&"true".to_string()));

Implementations§

Source§

impl<'a> CliParser<'a>

Source

pub fn new(definition: &'a CommandDefinition) -> Self

Create a new CLI parser for the given command definition

§Arguments
  • definition - The command definition specifying expected arguments
§Example
use dynamic_cli::parser::cli_parser::CliParser;
use dynamic_cli::config::schema::CommandDefinition;

let parser = CliParser::new(&definition);
Source

pub fn parse(&self, args: &[String]) -> Result<HashMap<String, String>>

Parse command-line arguments into a HashMap of strings

Thin, non-breaking wrapper around Self::parse_typed for callers that only deal in scalar values. Any ParsedValue::Repeated entry (i.e. any repeatable: true option) is silently dropped from the result — no command definition predating DD-024 can have one, so existing callers see no behaviour change. Once the dispatch layer is migrated to consume crate::parser::ParsedArgs directly (#39, in progress — the type exists but interface/cli.rs and interface/repl.rs still call this method, not parse_typed), this method can be removed.

§Arguments
  • args - Slice of argument strings (excluding the command name)
§Returns

A HashMap mapping argument/option names to their string values. All values are stored as strings after type validation.

§Errors
§Example
use dynamic_cli::parser::cli_parser::CliParser;
use dynamic_cli::config::schema::{
    CommandDefinition, ArgumentDefinition, ArgumentType
};

let definition = CommandDefinition {
    name: "greet".to_string(),
    aliases: vec![],
    description: "Greet someone".to_string(),
    required: false,
    arguments: vec![
        ArgumentDefinition {
            name: "name".to_string(),
            arg_type: ArgumentType::String,
            required: true,
            description: "Name".to_string(),
            validation: vec![],
            secure: false,
        }
    ],
    options: vec![],
    implementation: "handler".to_string(),
    continue_on_failure: false,
    requires_success: false,
};

let parser = CliParser::new(&definition);
let result = parser.parse(&["Alice".to_string()]).unwrap();
assert_eq!(result.get("name"), Some(&"Alice".to_string()));
Source

pub fn parse_typed( &self, args: &[String], ) -> Result<HashMap<String, ParsedValue>>

Parse command-line arguments into a HashMap of ParsedValue

Like Self::parse, but preserves repeatable options as ParsedValue::Repeated instead of dropping them. This is the method that actually implements DD-024 parsing; parse() is a filtering wrapper around it.

§Arguments
  • args - Slice of argument strings (excluding the command name)
§Errors

In addition to the errors documented on Self::parse:

Source

pub fn parse_typed_segment( &self, args: &[String], ) -> Result<(HashMap<String, ParsedValue>, usize)>

Parse command-line arguments, stopping cleanly at a segment boundary instead of erroring on positional-arity overflow (DD-026, #52).

Shares Self::parse_typed’s token loop and every option-parsing helper it calls (Self::parse_long_option, Self::parse_short_option, Self::parse_repeatable_occurrence) unchanged. The only difference is what happens when a bare (non-flag) token is reached once positional_index has already reached self.definition.arguments.len(): where Self::parse_typed calls Self::parse_positional_argument and gets back crate::error::ParseError::too_many_arguments, this method stops the loop immediately instead — without consuming that token, without erroring — then runs the same finishing steps (apply_defaults / validate_required_arguments / validate_required_options) on whatever was accumulated so far.

Self::parse_typed itself is not modified by this method’s existence: it keeps calling Self::parse_positional_argument directly and erroring immediately on overflow, so Self::parse and any existing caller keep today’s exact behaviour.

§Returns

(parsed, consumed), where consumed is the number of tokens of args that belong to this command. When the loop reaches the end of args with no leftover boundary token (the single-command, non-chained case), consumed == args.len() and parsed is identical to what Self::parse_typed would return for the same input.

§Errors

Same as Self::parse_typed for every case other than positional-arity overflow, which this method never raises — an overflowing bare token is reported to the caller via consumed instead, for crate::registry::CommandRegistry::resolve_name to resolve as the next chain segment.

§Example
use dynamic_cli::parser::cli_parser::{CliParser, ParsedValue};
use dynamic_cli::config::schema::{
    CommandDefinition, ArgumentDefinition, ArgumentType
};

let definition = CommandDefinition {
    name: "config".to_string(),
    aliases: vec![],
    description: "Configure a source".to_string(),
    required: false,
    arguments: vec![
        ArgumentDefinition {
            name: "source".to_string(),
            arg_type: ArgumentType::Path,
            required: true,
            description: "Source file".to_string(),
            validation: vec![],
            secure: false,
        }
    ],
    options: vec![],
    implementation: "config_handler".to_string(),
    continue_on_failure: false,
    requires_success: false,
};

let parser = CliParser::new(&definition);
// "solve" is the next chained command's name — arity for "config"
// (one positional) is already satisfied by "model.yml".
let args = vec!["model.yml".to_string(), "solve".to_string()];
let (parsed, consumed) = parser.parse_typed_segment(&args).unwrap();

assert_eq!(consumed, 1);
assert_eq!(
    parsed.get("source"),
    Some(&ParsedValue::Scalar("model.yml".to_string()))
);

Auto Trait Implementations§

§

impl<'a> Freeze for CliParser<'a>

§

impl<'a> RefUnwindSafe for CliParser<'a>

§

impl<'a> Send for CliParser<'a>

§

impl<'a> Sync for CliParser<'a>

§

impl<'a> Unpin for CliParser<'a>

§

impl<'a> UnsafeUnpin for CliParser<'a>

§

impl<'a> UnwindSafe for CliParser<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.