Documentation
//! Tools for working with command line arguments

#[cfg(feature = "unstable-cli-parse-args")]
pub use unstable_parse_args::*;

#[cfg(feature = "unstable-cli-parse-args")]
#[expect(missing_docs)]
mod unstable_parse_args {
  use crate::{BTreeMap, String, Vec};

  pub type ParseArgsResult = Result<ParsedArgs, ParseArgsError>;

  #[derive(Debug, Default)]
  pub struct ParseArgsConfig {
    pub flags: Vec<String>,
  }

  #[derive(Debug, Default)]
  pub struct ParsedArgs {
    pub flags: BTreeMap<String, usize>,
    pub named: BTreeMap<String, Vec<String>>,
    pub positional: Vec<String>,
  }

  pub enum ParseArgsError {
    None,
  }

  pub fn parse_args(args: &[&str]) -> ParsedArgs {
    parse_args_with_config(args, None)
  }

  pub fn parse_args_with_config(args: &[&str], config: Option<&ParseArgsConfig>) -> ParsedArgs {
    let mut parsed = ParsedArgs::default();

    let mut key: Option<&str> = None;

    for &arg in args {
      if let Some(k) = key.take() {
        parsed.named.entry(k.into()).or_default().push(arg.into());
        continue;
      }

      if arg.starts_with("--") {
        if let Some((k, v)) = arg.split_once('=') {
          parsed.named.entry(k.into()).or_default().push(v.into());
        } else if let Some(c) = config
          && c.flags.iter().any(|f| f == arg)
        {
          *parsed.flags.entry(arg.into()).or_default() += 1;
        } else {
          key = Some(arg);
        }

        continue;
      }

      parsed.positional.push(arg.into());
    }

    if let Some(k) = key {
      parsed
        .named
        .entry(k.into())
        .or_default()
        .push(String::new());
    }

    parsed
  }
}