use crate::ui;
const COMMANDS: &[(&str, &str, &[&str])] = &[
(
"🚀",
"rproj new <name>",
&[
"Scaffold a project. Sets your machine up first if it",
"hasn't been, then asks only about this project's packages.",
"--like <setup> reuses a saved selection, --save-setup saves one",
],
),
(
"🔧",
"rproj setup",
&["Install or change the machine-wide tools: system apps, CLI", "tools, Studio plugins, editor extensions"],
),
(
"🔩",
"rproj configure [tool]",
&[
"Walk through a tool's settings one at a time - StyLua,",
"Selene, luau-lsp - explaining each, then write them out",
],
),
(
"🔄",
"rproj upgrade",
&[
"Re-apply rproj's generated config to a project you already made,",
"so it picks up fixes shipped since it was scaffolded",
],
),
("👀", "rproj watch", &["Resume the dev loop: install what's missing, watch the sourcemap"]),
("📋", "rproj copy", &["Copy every file under src/ to the clipboard, with path headers"]),
("📖", "rproj info [key]", &["Look up what a tool or package does, and how to use it"]),
];
pub fn run() {
let version = env!("CARGO_PKG_VERSION");
let (rocket, book, sparkle) = match ui::emoji_enabled() {
true => ("🎮 ", "📚 ", "✨ "),
false => ("", "", ""),
};
println!("\n{rocket}rproj {version} - guided bootstrap-to-game-dev CLI for Roblox\n");
println!(" Takes a fresh PC all the way to a working Roblox dev setup, then");
println!(" scaffolds projects on top of it. Explains every tool and package");
println!(" as it goes, so you end up knowing why your setup looks like it does.\n");
println!("{book}Commands\n");
let width = COMMANDS.iter().map(|(_, name, _)| name.len()).max().unwrap_or(0);
let icon_columns = if ui::emoji_enabled() { 4 } else { 0 };
for (icon, name, lines) in COMMANDS {
for (i, line) in lines.iter().enumerate() {
let lead = match (i, ui::emoji_enabled()) {
(0, true) => format!("{icon} "),
_ => " ".repeat(icon_columns),
};
let name = if i == 0 { *name } else { "" };
println!(" {lead}{name:<width$} {line}");
}
println!();
}
println!("{sparkle}New here? rproj new my-first-game sets your machine up and");
println!(" scaffolds your first project in one go.\n");
crate::steps::update_check::nudge_if_outdated();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_icon_is_a_single_char() {
for (icon, name, _) in COMMANDS {
assert_eq!(icon.chars().count(), 1, "{name}'s icon {icon} is not a single char");
}
}
#[test]
fn every_command_is_listed() {
for command in ["new", "setup", "configure", "upgrade", "watch", "copy", "info"] {
assert!(
COMMANDS.iter().any(|(_, name, _)| name.starts_with(&format!("rproj {command}"))),
"`{command}` is missing from the welcome screen"
);
}
}
#[test]
fn every_command_explains_itself() {
for (_, name, lines) in COMMANDS {
assert!(!lines.is_empty(), "{name} has no description");
assert!(lines.iter().all(|l| !l.trim().is_empty()), "{name} has a blank line");
}
}
}