use std::path::PathBuf;
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
#[derive(Debug, Parser)]
#[command(
name = "fgk",
about = "Scaffold and package Foglet door games.",
version
)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
New {
path: PathBuf,
},
EmitManifest {
#[arg(long, value_name = "ABSOLUTE_PATH")]
install_dir: String,
#[arg(long, default_value = ".", value_name = "DIR")]
project: PathBuf,
},
Package {
#[arg(long, value_name = "DIR")]
out: PathBuf,
#[arg(long, default_value = ".", value_name = "DIR")]
project: PathBuf,
#[arg(long, value_name = "ABSOLUTE_PATH")]
install_dir: Option<String>,
#[arg(long, value_name = "PATH")]
binary: Option<PathBuf>,
},
Tick {
#[arg(long, default_value = ".", value_name = "DIR")]
project: PathBuf,
},
}
fn main() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Command::New { path } => run_new(path),
Command::EmitManifest {
install_dir,
project,
} => run_emit_manifest(&project, &install_dir),
Command::Package {
out,
project,
install_dir,
binary,
} => run_package(&project, &out, install_dir.as_deref(), binary.as_deref()),
Command::Tick { project } => run_tick(&project),
}
}
fn run_new(path: PathBuf) -> Result<()> {
fgk::scaffold::scaffold_project(&path)
.with_context(|| format!("failed to scaffold new project at `{}`", path.display()))?;
println!(
"Created new Foglet game project at {}\n\
Next steps:\n cd {}\n cargo run",
path.display(),
path.display()
);
Ok(())
}
fn run_emit_manifest(project: &std::path::Path, install_dir: &str) -> Result<()> {
let json = fgk::emit_manifest::emit_manifest_json(project, install_dir).with_context(|| {
format!(
"failed to emit manifest for project `{}` (install_dir = `{}`)",
project.display(),
install_dir
)
})?;
print!("{json}");
Ok(())
}
fn run_package(
project: &std::path::Path,
out: &std::path::Path,
install_dir: Option<&str>,
binary: Option<&std::path::Path>,
) -> Result<()> {
let inputs = fgk::package::PackageInputs {
project_dir: project,
out_dir: out,
install_dir,
};
let outputs = match binary {
Some(path) => fgk::package::assemble_bundle(inputs, path),
None => fgk::package::package_project(inputs),
}
.with_context(|| {
format!(
"failed to package project `{}` into `{}`",
project.display(),
out.display()
)
})?;
println!(
"Packaged `{}` at {}\n binary: {}\n run.sh: {}\n manifest: {}\n assets: {}",
outputs.slug,
outputs.out_dir.display(),
outputs.binary.display(),
outputs.run_sh.display(),
outputs.manifest.display(),
outputs.assets.display(),
);
Ok(())
}
fn run_tick(project: &std::path::Path) -> Result<()> {
let summary = fgk::tick::run_tick(project)
.with_context(|| format!("failed to run scheduled tasks for `{}`", project.display()))?;
println!(
"Ran {tasks_run} task(s), skipped {tasks_skipped} task(s)",
tasks_run = summary.tasks_run,
tasks_skipped = summary.tasks_skipped
);
Ok(())
}