use dirs::home_dir;
use lumer::run;
use miette::Result;
use std::process::{Command, ExitCode};
use std::{
env::var_os,
fs::{copy, create_dir_all, read_dir},
io,
path::Path,
};
#[tokio::main]
async fn main() -> Result<ExitCode> {
ensure_lumic_installed().expect("failed to install lumic");
ensure_stdlib().expect("failed to install lumi-std");
run().await
}
fn ensure_lumic_installed() -> Result<(), io::Error> {
if var_os("LUMER_SKIP_LUMIC").is_some() {
return Ok(());
}
if Command::new("lumic")
.arg("--version")
.status()
.is_ok_and(|status| status.success())
{
return Ok(());
}
println!("Installing lumic");
let output = Command::new("cargo")
.args(["install", "lumic"])
.output()
.map_err(|e| io::Error::other(format!("cargo failed: {}", e)))?;
if !output.status.success() {
eprintln!("lumic install failed - run: cargo install lumic");
return Ok(());
}
println!("lumic ready");
Ok(())
}
fn ensure_stdlib() -> Result<(), io::Error> {
let home_dir =
home_dir().ok_or(io::Error::new(io::ErrorKind::NotFound, "no home directory"))?;
let stdlib_dir = home_dir
.join(".local")
.join("lib")
.join("lumi")
.join("lumi-std");
if stdlib_dir.exists() {
return Ok(());
}
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let source_stdlib = manifest_dir.join("lumi-std");
if !source_stdlib.exists() {
eprintln!(
"Warning: lumi-std not found at {}, skipping",
source_stdlib.display()
);
return Ok(());
}
create_dir_all(&stdlib_dir)
.map_err(|e| io::Error::other(format!("failed to create stdlib dir: {}", e)))?;
for entry in read_dir(&source_stdlib)? {
let entry = entry?;
let src = entry.path();
let dest = stdlib_dir.join(src.file_name().ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, "invalid file name in lumi-std")
})?);
if src.is_file() {
copy(&src, &dest).map_err(|e| {
io::Error::other(format!("failed to copy {}: {}", src.display(), e))
})?;
}
}
println!("Installed lumi-std to {}", stdlib_dir.display());
Ok(())
}