feat: add interactive pick project flow

This commit is contained in:
2026-08-23 08:08:21 +05:00
parent de9b6ad0dd
commit 31bbeca941
5 changed files with 152 additions and 8 deletions
+36 -7
View File
@@ -7,7 +7,7 @@ mod sync;
use std::process::ExitCode;
use anyhow::{Context, Result};
use anyhow::{Context, Result, bail};
use clap::Parser;
use colored::Colorize;
@@ -56,14 +56,43 @@ fn run(cli: &cli::Cli) -> Result<()> {
return Ok(());
}
let name = cli
.project
.as_deref()
.expect("clap guarantees <PROJECT> or --list");
let name = if cli.pick {
match pick_project(&cfg)? {
Some(name) => name,
None => return Ok(()),
}
} else {
cli.project
.clone()
.expect("clap guarantees <PROJECT> or a mode flag")
};
let project = cfg
.projects
.get(name)
.get(&name)
.with_context(|| format!("project '{name}' not found in {}", path.display()))?;
deploy::deploy(name, project, cli.dry_run)
deploy::deploy(&name, project, cli.dry_run)
}
fn pick_project(cfg: &config::Config) -> Result<Option<String>> {
use dialoguer::FuzzySelect;
use std::io::IsTerminal;
if !std::io::stdout().is_terminal() {
bail!("interactive picker needs a real terminal; use --list instead");
}
let names: Vec<&str> = cfg.projects.keys().map(String::as_str).collect();
match FuzzySelect::new()
.with_prompt("Pick a project")
.items(&names)
.default(0)
.interact()
{
Ok(idx) => Ok(Some(names[idx].to_string())),
Err(dialoguer::Error::IO(err)) if err.kind() == std::io::ErrorKind::Interrupted => {
println!("cancelled.");
Ok(None)
}
Err(err) => Err(err).context("project selection failed"),
}
}