arcature-cli 2026.1.1

Developer lifecycle CLI for Arcature applications.
Documentation
use std::fmt;
use std::path::PathBuf;

use crate::process::ProcessError;

#[derive(Debug)]
pub(crate) enum ScriptError {
    InvalidName(String),
    InvalidWorkingDirectory(PathBuf),
    MissingProgram(String),
    Parse {
        path: PathBuf,
        source: toml::de::Error,
    },
    Process(ProcessError),
    Read {
        path: PathBuf,
        source: std::io::Error,
    },
    ResolveWorkingDirectory {
        path: PathBuf,
        source: std::io::Error,
    },
    Unknown {
        name: String,
        available: Vec<String>,
    },
}

impl fmt::Display for ScriptError {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::InvalidName(name) => write!(
                formatter,
                "invalid script name `{name}`; use alphanumeric namespace segments separated by `:`"
            ),
            Self::InvalidWorkingDirectory(path) => write!(
                formatter,
                "script working directory `{}` must be a relative path contained in the project",
                path.display()
            ),
            Self::MissingProgram(name) => write!(formatter, "script `{name}` has an empty program"),
            Self::Parse { path, source } => write!(
                formatter,
                "invalid script file {}: {source}",
                path.display()
            ),
            Self::Process(error) => error.fmt(formatter),
            Self::Read { path, source } => write!(
                formatter,
                "cannot read script file {}: {source}",
                path.display()
            ),
            Self::ResolveWorkingDirectory { path, source } => write!(
                formatter,
                "cannot resolve script working directory {}: {source}",
                path.display()
            ),
            Self::Unknown { name, available } => write!(
                formatter,
                "unknown script `{name}`; available scripts: {}",
                available.join(", ")
            ),
        }
    }
}

impl std::error::Error for ScriptError {}
impl From<ProcessError> for ScriptError {
    fn from(value: ProcessError) -> Self {
        Self::Process(value)
    }
}