knave 0.14.17

A Lisp programming language for humans and agents that infers types and ownership and compiles to readable Rust
Documentation
use clap::Subcommand;

use super::add::AddCommand;
use super::crate_section::CrateSection;
use super::exit_status::ExitStatus;
use super::new::NewCommand;
use super::release_flag::ReleaseFlag;
use super::remove::RemoveCommand;
use super::task::TaskCommand;
use super::terminal::Terminal;

const DEV_HELP: &str = "Edit `dev-dependencies`, which only `test` builds with";

#[derive(Subcommand)]
pub enum ProjectCommand {
    #[command(about = "Add a crate to the project's dependencies, at the version Cargo picks")]
    Add {
        #[arg(help = "The crate's name, as crates.io writes it")]
        name: String,
        #[arg(
            long,
            value_delimiter = ',',
            help = "Features to turn on, separated by commas"
        )]
        features: Vec<String>,
        #[arg(long = CrateSection::DEV_FLAG_NAME, help = DEV_HELP)]
        dev: bool,
    },
    #[command(about = "Remove a crate from the project's dependencies")]
    Remove {
        #[arg(help = "The crate's name, as the project file writes it")]
        name: String,
        #[arg(long = CrateSection::DEV_FLAG_NAME, help = DEV_HELP)]
        dev: bool,
    },
    #[command(
        name = TaskCommand::NAME,
        about = "Run a task from the project's `tasks` directory, or list the tasks"
    )]
    Task {
        #[arg(
            trailing_var_arg = true,
            allow_hyphen_values = true,
            value_name = "NAME [ARGUMENTS]",
            help = "The task's name, then the arguments it takes [default: list the tasks]"
        )]
        command: Vec<String>,
        #[command(flatten)]
        release: ReleaseFlag,
    },
    #[command(about = "Create a project in a new directory of its name")]
    New {
        #[arg(
            help = "The project's name, in kebab-case",
            value_parser = clap::builder::NonEmptyStringValueParser::new()
        )]
        name: String,
    },
}

impl ProjectCommand {
    pub fn execute(self, terminal: &mut Terminal) -> ExitStatus {
        match self {
            Self::New { name } => NewCommand::new(name).run(terminal),
            Self::Add {
                name,
                features,
                dev,
            } => AddCommand::new(name, features, CrateSection::of(dev)).run(terminal),
            Self::Remove { name, dev } => {
                RemoveCommand::new(name, CrateSection::of(dev)).run(terminal)
            }
            Self::Task { command, release } => {
                TaskCommand::new(command, release.profile()).run(terminal)
            }
        }
    }
}