1use clap::{Parser, Subcommand};
8
9use crate::client::RommClient;
10use crate::config::Config;
11use crate::error::RommError;
12
13pub mod api;
14pub mod auth;
15pub mod cache;
16pub mod completions;
17pub mod download;
18pub mod init;
19pub mod library_scan;
20pub mod platforms;
21pub mod print;
22pub mod roms;
23pub mod scan;
24pub mod sync;
25pub mod update;
26
27#[derive(Clone, Copy, Debug)]
29pub enum OutputFormat {
30 Text,
32 Json,
34}
35
36impl OutputFormat {
37 pub fn from_flags(global_json: bool, local_json: bool) -> Self {
42 if global_json || local_json {
43 OutputFormat::Json
44 } else {
45 OutputFormat::Text
46 }
47 }
48}
49
50#[derive(Parser, Debug)]
55#[command(
56 name = "romm-cli",
57 version,
58 about = "Rust CLI and TUI for the ROMM API",
59 infer_subcommands = true,
60 arg_required_else_help = true,
61 after_help = "Exit codes: 0 success, 1 general failure, 2 usage, 3 config/auth, 4 API/network.\n\
62 See README \"Exit codes\" for scripting examples.\n\
63 JSON output shapes: docs/json-output.md"
64)]
65pub struct Cli {
66 #[arg(short, long, global = true)]
68 pub verbose: bool,
69
70 #[arg(long, global = true)]
72 pub json: bool,
73
74 #[command(subcommand)]
76 pub command: Commands,
77}
78
79#[derive(Subcommand, Debug)]
81pub enum Commands {
82 #[command(visible_alias = "setup")]
84 Init(init::InitCommand),
85 #[cfg(feature = "tui")]
87 Tui {
88 #[arg(long)]
90 mock_update: bool,
91 },
92 #[cfg(not(feature = "tui"))]
94 Tui {
95 #[arg(long)]
96 mock_update: bool,
97 },
98 #[command(visible_alias = "call")]
100 Api(api::ApiCommand),
101 #[command(visible_aliases = ["platform", "p", "plats"])]
103 Platforms(platforms::PlatformsCommand),
104 #[command(visible_aliases = ["rom", "r"])]
106 Roms(Box<roms::RomsCommand>),
107 Scan(scan::ScanCommand),
109 Sync(sync::SyncCommand),
111 #[command(visible_aliases = ["dl", "get"])]
113 Download(download::DownloadCommand),
114 Cache(cache::CacheCommand),
116 Auth(auth::AuthCommand),
118 Update,
120 Completions(completions::CompletionsCommand),
122}
123
124pub async fn run(cli: Cli, config: Config) -> Result<(), RommError> {
129 let client = RommClient::new(&config, cli.verbose)?;
130
131 match cli.command {
132 Commands::Completions(_) => Err(RommError::Other(
133 "internal error: completions must be handled in main".into(),
134 )),
135 Commands::Init(_) => Err(RommError::Other(
136 "internal error: init must be handled before load_config".into(),
137 )),
138 #[cfg(feature = "tui")]
139 Commands::Tui { .. } => Err(RommError::Other(
140 "internal error: TUI must be started via run_interactive from main".into(),
141 )),
142 #[cfg(not(feature = "tui"))]
143 Commands::Tui { .. } => Err(RommError::Other("this feature requires the tui".into())),
144 command => crate::frontend::cli::run(command, &client, cli.json, cli.verbose).await,
145 }
146}