rdice-tui 0.1.0

Terminal UI for persistent dice trays powered by rdice-core
Documentation
use rdice_core::error::{DiceError, Result};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Command {
    ManagerDice,
    ManagerTrays,
    Overview,
    OpenTray(String),
    DiceNew { name: String, faces: Vec<String> },
    DiceDelete(String),
    DiceEdit { name: String, faces: Vec<String> },
    TrayNew(String),
    TrayDelete(String),
    TrayRename { old_name: String, new_name: String },
    Quit,
}

pub fn parse_command(input: &str) -> Result<Command> {
    let parts = input.split_whitespace().collect::<Vec<_>>();
    if parts.is_empty() {
        return invalid_command(input);
    }

    match parts.as_slice() {
        ["manager", "dice"] => Ok(Command::ManagerDice),
        ["manager", "trays"] => Ok(Command::ManagerTrays),
        ["overview"] => Ok(Command::Overview),
        ["tray", name] => Ok(Command::OpenTray((*name).to_string())),
        ["dice", "new", name, faces @ ..] if !faces.is_empty() => Ok(Command::DiceNew {
            name: (*name).to_string(),
            faces: faces.iter().map(|face| (*face).to_string()).collect(),
        }),
        ["dice", "delete", name] => Ok(Command::DiceDelete((*name).to_string())),
        ["dice", "edit", name, faces @ ..] if !faces.is_empty() => Ok(Command::DiceEdit {
            name: (*name).to_string(),
            faces: faces.iter().map(|face| (*face).to_string()).collect(),
        }),
        ["tray", "new", name] => Ok(Command::TrayNew((*name).to_string())),
        ["tray", "delete", name] => Ok(Command::TrayDelete((*name).to_string())),
        ["tray", "rename", old_name, new_name] => Ok(Command::TrayRename {
            old_name: (*old_name).to_string(),
            new_name: (*new_name).to_string(),
        }),
        ["quit"] | ["q"] => Ok(Command::Quit),
        _ => invalid_command(input),
    }
}

fn invalid_command<T>(input: &str) -> Result<T> {
    Err(DiceError::InvalidArguments(format!(
        "invalid command: {input}"
    )))
}