Skip to main content

romm_cli/commands/
mod.rs

1//! Top-level CLI command handling.
2//!
3//! The `Cli` type (derived from `clap`) describes the public command-line
4//! interface. Each subcommand lives in its own module and is free to use
5//! `RommClient` directly. The TUI is just another subcommand.
6
7use anyhow::Result;
8use clap::{Parser, Subcommand};
9
10use crate::client::RommClient;
11use crate::config::Config;
12
13pub mod api;
14pub mod download;
15pub mod init;
16pub mod platforms;
17pub mod print;
18pub mod roms;
19pub mod update;
20
21/// How a command should format its output.
22#[derive(Clone, Copy, Debug)]
23pub enum OutputFormat {
24    /// Human-readable text (tables, aligned columns, etc.).
25    Text,
26    /// Machine-friendly JSON (pretty-printed by default).
27    Json,
28}
29
30impl OutputFormat {
31    /// Resolve the effective output format from global and per-command flags.
32    pub fn from_flags(global_json: bool, local_json: bool) -> Self {
33        if global_json || local_json {
34            OutputFormat::Json
35        } else {
36            OutputFormat::Text
37        }
38    }
39}
40
41/// Top-level CLI entrypoint for `romm-cli`.
42///
43/// This binary can be used both as:
44/// - a **TUI launcher** (`romm-cli tui`), and
45/// - a **scripting-friendly CLI** for platforms/ROMs/API calls.
46#[derive(Parser, Debug)]
47#[command(
48    name = "romm-cli",
49    version,
50    about = "Rust CLI and TUI for the ROMM API"
51)]
52pub struct Cli {
53    /// Increase output verbosity
54    #[arg(short, long, global = true)]
55    pub verbose: bool,
56
57    /// Output JSON instead of human-readable text where supported.
58    #[arg(long, global = true)]
59    pub json: bool,
60
61    #[command(subcommand)]
62    pub command: Commands,
63}
64
65/// All top-level commands supported by the CLI.
66#[derive(Subcommand, Debug)]
67pub enum Commands {
68    /// Create or update user config (~/.config/romm-cli/.env or %APPDATA%\\romm-cli\\.env)
69    #[command(visible_alias = "setup")]
70    Init(init::InitCommand),
71    /// Launch interactive TUI for exploring API endpoints
72    #[cfg(feature = "tui")]
73    Tui,
74    /// Launch interactive TUI (stub for disabled feature)
75    #[cfg(not(feature = "tui"))]
76    Tui,
77    /// Low-level access to any ROMM API endpoint
78    Api(api::ApiCommand),
79    /// Platform-related commands
80    Platforms(platforms::PlatformsCommand),
81    /// ROM-related commands
82    Roms(roms::RomsCommand),
83    /// Download a ROM
84    Download(download::DownloadCommand),
85    /// Check for and install updates for romm-cli
86    Update,
87}
88
89pub async fn run(cli: Cli, config: Config) -> Result<()> {
90    let client = RommClient::new(&config, cli.verbose)?;
91
92    match cli.command {
93        Commands::Init(_) => {
94            anyhow::bail!("internal error: init must be handled before load_config");
95        }
96        #[cfg(feature = "tui")]
97        Commands::Tui => crate::frontend::tui::run(client, config).await?,
98        #[cfg(not(feature = "tui"))]
99        Commands::Tui => anyhow::bail!("this feature requires the tui"),
100        command => crate::frontend::cli::run(command, &client, cli.json).await?,
101    }
102
103    Ok(())
104}