use core::fmt;
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
use clap::builder::{Styles, TypedValueParser};
use clap::{Args, Parser, Subcommand, ValueEnum, ValueHint};
use crate::style::{CLI_STYLING, after_help};
const STYLES: Styles = CLI_STYLING;
#[derive(Debug, Clone, Parser)]
#[clap(
name = "cnvx",
about = "A CLI for modeling and solving optimization problems",
disable_help_flag = true,
disable_help_subcommand = false,
after_help = after_help(),
max_term_width = 80,
styles = STYLES,
)]
pub struct CliArguments {
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Clone, Subcommand)]
#[command()]
pub enum Command {
#[command(visible_alias = "s")]
Solve(SolveCommand),
#[command(visible_alias = "v")]
Version(VersionCommand),
}
#[derive(Debug, Clone, Parser)]
pub struct SolveCommand {
#[clap(flatten)]
pub args: SolveArgs,
}
#[derive(Debug, Clone, Parser)]
pub struct VersionCommand {}
#[derive(Debug, Clone, Args)]
pub struct SolveArgs {
#[clap(
required=true,
value_parser = input_value_parser(),
value_hint = ValueHint::FilePath,
)]
pub input: Input,
#[clap(
required_if_eq("input", "-"),
value_hint = ValueHint::FilePath,
)]
pub language_type: Option<LanguageType>,
}
#[derive(Debug, Clone)]
pub enum Input {
Stdin,
Path(PathBuf),
}
impl Display for Input {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Input::Stdin => f.pad("stdin"),
Input::Path(path) => path.display().fmt(f),
}
}
}
fn input_value_parser() -> impl TypedValueParser<Value = Input> {
clap::builder::OsStringValueParser::new().try_map(|value| {
if value.is_empty() {
Err(clap::Error::new(clap::error::ErrorKind::InvalidValue))
} else if value == "-" {
Ok(Input::Stdin)
} else {
Ok(Input::Path(value.into()))
}
})
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, ValueEnum)]
#[allow(clippy::upper_case_acronyms)]
pub enum LanguageType {
#[value(name = "gmpl")]
GMPL,
#[value(name = "mps")]
MPS,
}
impl Display for LanguageType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
LanguageType::GMPL => f.write_str("gmpl"),
LanguageType::MPS => f.write_str("mps"),
}
}
}