refactor(simulation): split atlas.rs subcommands into modules
Extract 2119-line monolithic atlas.rs into 8 focused modules under src/bin/atlas/: main.rs (thin dispatch), common.rs (shared types and DB helpers), show.rs, mutate.rs, stats.rs, systems.rs, author.rs, and sync_wiki.rs. Commands enum stays in main.rs; each match arm delegates to module::cmd_fn(&conn, args). No behavior change. Closes #776. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
//! Atlas CLI — query and manage celestial bodies and stations in systems.db.
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! ```sh
|
||||
//! # Via wrapper script (recommended):
|
||||
//! tooling/atlas list-bodies --system "GJ 15A"
|
||||
//! tooling/atlas list-bodies --type planet --inhabited
|
||||
//! tooling/atlas show-system "GJ 15A"
|
||||
//! tooling/atlas show-body "GJ 15Ab"
|
||||
//! tooling/atlas add-body --system "GJ 15A" --type planet --orbit 1 --id "GJ 15Ab"
|
||||
//! tooling/atlas stats
|
||||
//! tooling/atlas corridor-status # remaining systems by corridor/hop
|
||||
//! tooling/atlas populate # bulk classifier pass
|
||||
//!
|
||||
//! # Direct:
|
||||
//! cargo run --bin atlas -- <subcommand> [args]
|
||||
//! ```
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
mod author;
|
||||
mod common;
|
||||
mod mutate;
|
||||
mod show;
|
||||
mod stats;
|
||||
mod sync_wiki;
|
||||
mod systems;
|
||||
|
||||
use common::{open_db, resolve_db_path};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CLI structure
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
name = "atlas",
|
||||
about = "Query and manage celestial bodies and stations in systems.db"
|
||||
)]
|
||||
struct Cli {
|
||||
/// Path to the SQLite database (default: auto-detect from worktree)
|
||||
#[arg(long, global = true)]
|
||||
db: Option<PathBuf>,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Show full system hierarchy (star → bodies → stations)
|
||||
ShowSystem {
|
||||
/// System ID (e.g., "GJ 15A")
|
||||
system_id: String,
|
||||
},
|
||||
/// Show a single body's details
|
||||
ShowBody {
|
||||
/// Body ID (e.g., "GJ 15Ab")
|
||||
body_id: String,
|
||||
},
|
||||
/// Show a single station's details
|
||||
ShowStation {
|
||||
/// Station ID (e.g., "GJ 15Ab-S1")
|
||||
station_id: String,
|
||||
},
|
||||
/// List bodies with optional filters
|
||||
ListBodies {
|
||||
#[arg(long)]
|
||||
system: Option<String>,
|
||||
#[arg(long, value_name = "TYPE")]
|
||||
r#type: Option<String>,
|
||||
#[arg(long)]
|
||||
inhabited: bool,
|
||||
#[arg(long)]
|
||||
unnamed: bool,
|
||||
},
|
||||
/// List stations with optional filters
|
||||
ListStations {
|
||||
#[arg(long)]
|
||||
system: Option<String>,
|
||||
#[arg(long, value_name = "TYPE")]
|
||||
r#type: Option<String>,
|
||||
},
|
||||
/// Add a body record
|
||||
AddBody {
|
||||
#[arg(long)]
|
||||
id: String,
|
||||
#[arg(long)]
|
||||
system: String,
|
||||
#[arg(long, value_name = "TYPE")]
|
||||
r#type: String,
|
||||
#[arg(long)]
|
||||
orbit: Option<i32>,
|
||||
#[arg(long)]
|
||||
name: Option<String>,
|
||||
#[arg(long)]
|
||||
parent: Option<String>,
|
||||
#[arg(long)]
|
||||
mass_class: Option<String>,
|
||||
#[arg(long)]
|
||||
atmosphere: Option<String>,
|
||||
#[arg(long)]
|
||||
gravity: Option<f64>,
|
||||
#[arg(long)]
|
||||
biome: Option<String>,
|
||||
#[arg(long)]
|
||||
inhabited: bool,
|
||||
#[arg(long)]
|
||||
population: Option<i64>,
|
||||
},
|
||||
/// Add a station record
|
||||
AddStation {
|
||||
#[arg(long)]
|
||||
id: String,
|
||||
#[arg(long)]
|
||||
system: String,
|
||||
#[arg(long)]
|
||||
orbits: Option<String>,
|
||||
#[arg(long, value_name = "TYPE")]
|
||||
r#type: String,
|
||||
#[arg(long)]
|
||||
name: Option<String>,
|
||||
#[arg(long)]
|
||||
population: Option<i64>,
|
||||
#[arg(long)]
|
||||
docking: Option<String>,
|
||||
#[arg(long)]
|
||||
gate: bool,
|
||||
},
|
||||
/// Database statistics
|
||||
Stats,
|
||||
/// Generate a body/station proposal for a single system (writes JSON file for review)
|
||||
Author {
|
||||
/// System ID (e.g., "GJ 71")
|
||||
system_id: String,
|
||||
/// Output directory for proposal JSON (default: docs/atlas/proposals/)
|
||||
#[arg(long, default_value = "docs/atlas/proposals")]
|
||||
outdir: String,
|
||||
/// Path to wiki directory (default: wiki/star-systems/)
|
||||
#[arg(long, default_value = "wiki/star-systems")]
|
||||
wiki: String,
|
||||
},
|
||||
/// Commit an approved proposal JSON to the database
|
||||
CommitSystem {
|
||||
/// Path to the proposal JSON file
|
||||
path: String,
|
||||
},
|
||||
/// Wipe all bodies and stations for a single system
|
||||
WipeSystem {
|
||||
/// System ID
|
||||
system_id: String,
|
||||
},
|
||||
/// List systems with optional filters
|
||||
ListSystems {
|
||||
/// Filter by geographic sector (e.g., "west_reach", "east_reach")
|
||||
#[arg(long)]
|
||||
sector: Option<String>,
|
||||
/// Filter by hop distance
|
||||
#[arg(long)]
|
||||
hop: Option<i32>,
|
||||
/// Only show systems that have bodies authored
|
||||
#[arg(long)]
|
||||
finished: bool,
|
||||
/// Only show systems that have NO bodies yet
|
||||
#[arg(long)]
|
||||
unfinished: bool,
|
||||
},
|
||||
/// List systems that have no bodies yet
|
||||
Unfinished {
|
||||
/// Filter by geographic sector
|
||||
#[arg(long)]
|
||||
sector: Option<String>,
|
||||
},
|
||||
/// List unfinished systems at a specific hop distance (or next available hop)
|
||||
Next {
|
||||
/// Hop distance (omit to find the lowest hop with unfinished systems)
|
||||
hop: Option<i32>,
|
||||
/// Filter by geographic sector
|
||||
#[arg(long)]
|
||||
sector: Option<String>,
|
||||
},
|
||||
/// Sync body/station data into wiki page for a system (or all systems)
|
||||
SyncWiki {
|
||||
/// System ID (omit for all systems with bodies)
|
||||
system_id: Option<String>,
|
||||
/// Path to wiki directory (default: wiki/star-systems/)
|
||||
#[arg(long, default_value = "wiki/star-systems")]
|
||||
wiki: String,
|
||||
},
|
||||
/// Show remaining unfinished systems grouped by geographic sector and hop distance
|
||||
CorridorStatus,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
let db_path = resolve_db_path(cli.db);
|
||||
let conn = open_db(&db_path);
|
||||
|
||||
match &cli.command {
|
||||
Commands::ShowSystem { system_id } => show::cmd_show_system(&conn, system_id),
|
||||
Commands::ShowBody { body_id } => show::cmd_show_body(&conn, body_id),
|
||||
Commands::ShowStation { station_id } => show::cmd_show_station(&conn, station_id),
|
||||
Commands::ListBodies {
|
||||
system,
|
||||
r#type,
|
||||
inhabited,
|
||||
unnamed,
|
||||
} => systems::cmd_list_bodies(
|
||||
&conn,
|
||||
system.as_deref(),
|
||||
r#type.as_deref(),
|
||||
*inhabited,
|
||||
*unnamed,
|
||||
),
|
||||
Commands::ListStations { system, r#type } => {
|
||||
systems::cmd_list_stations(&conn, system.as_deref(), r#type.as_deref())
|
||||
}
|
||||
Commands::AddBody {
|
||||
id,
|
||||
system,
|
||||
r#type,
|
||||
orbit,
|
||||
name,
|
||||
parent,
|
||||
mass_class,
|
||||
atmosphere,
|
||||
gravity,
|
||||
biome,
|
||||
inhabited,
|
||||
population,
|
||||
} => mutate::cmd_add_body(
|
||||
&conn, id, system, r#type, *orbit, name, parent, mass_class, atmosphere, *gravity,
|
||||
biome, *inhabited, *population,
|
||||
),
|
||||
Commands::AddStation {
|
||||
id,
|
||||
system,
|
||||
orbits,
|
||||
r#type,
|
||||
name,
|
||||
population,
|
||||
docking,
|
||||
gate,
|
||||
} => mutate::cmd_add_station(
|
||||
&conn, id, system, orbits, r#type, name, *population, docking, *gate,
|
||||
),
|
||||
Commands::Stats => stats::cmd_stats(&conn),
|
||||
Commands::Author {
|
||||
system_id,
|
||||
outdir,
|
||||
wiki,
|
||||
} => author::cmd_author(&conn, system_id, outdir, wiki),
|
||||
Commands::CommitSystem { path } => author::cmd_commit_system(&conn, path),
|
||||
Commands::WipeSystem { system_id } => mutate::cmd_wipe_system(&conn, system_id),
|
||||
Commands::ListSystems {
|
||||
sector,
|
||||
hop,
|
||||
finished,
|
||||
unfinished,
|
||||
} => systems::cmd_list_systems(&conn, sector.as_deref(), *hop, *finished, *unfinished),
|
||||
Commands::Unfinished { sector } => systems::cmd_unfinished(&conn, sector.as_deref()),
|
||||
Commands::Next { hop, sector } => systems::cmd_next(&conn, *hop, sector.as_deref()),
|
||||
Commands::SyncWiki { system_id, wiki } => {
|
||||
sync_wiki::cmd_sync_wiki(&conn, system_id.as_deref(), wiki)
|
||||
}
|
||||
Commands::CorridorStatus => systems::cmd_corridor_status(&conn),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user