quick wins (issues #9 #10 #11 #12 #13 #16) : am logs (tail+follow), am list --running/--sort, am config set, am alias add/remove/list, dedup historique, am open
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
//! alias: manage command aliases (cc -> claude-code) in the user config.
|
||||
|
||||
use super::*;
|
||||
use crate::cli::AliasCmd;
|
||||
use crate::output::print_json;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Ensure the user config file exists and return its path.
|
||||
fn user_config(app: &App) -> Result<PathBuf> {
|
||||
let dir = app
|
||||
.paths
|
||||
.config_dir
|
||||
.clone()
|
||||
.ok_or_else(|| anyhow!("cannot determine the user config directory (no HOME set)"))?;
|
||||
std::fs::create_dir_all(&dir)?;
|
||||
let path = dir.join(crate::config::CONFIG_FILE_NAME);
|
||||
if !path.exists() {
|
||||
std::fs::write(&path, concat!("version: \"1.0\"\n", "agents: []\n"))
|
||||
.with_context(|| format!("cannot create {}", path.display()))?;
|
||||
}
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// Read the aliases map from the user config file.
|
||||
fn read_aliases(app: &App) -> Result<(PathBuf, serde_yaml::Mapping)> {
|
||||
let path = user_config(app)?;
|
||||
let text = std::fs::read_to_string(&path)
|
||||
.with_context(|| format!("cannot read {}", path.display()))?;
|
||||
let mut value: serde_yaml::Value = serde_yaml::from_str(&text)
|
||||
.with_context(|| format!("{} is not valid YAML", path.display()))?;
|
||||
let mapping = value
|
||||
.as_mapping_mut()
|
||||
.ok_or_else(|| anyhow!("{} must contain a YAML mapping", path.display()))?;
|
||||
let aliases = mapping
|
||||
.entry(serde_yaml::Value::String("aliases".to_string()))
|
||||
.or_insert_with(|| serde_yaml::Value::Mapping(Default::default()))
|
||||
.as_mapping()
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
Ok((path, aliases))
|
||||
}
|
||||
|
||||
fn write_aliases(app: &App, path: &std::path::Path, aliases: serde_yaml::Mapping) -> Result<()> {
|
||||
let text = std::fs::read_to_string(path)
|
||||
.with_context(|| format!("cannot read {}", path.display()))?;
|
||||
let mut value: serde_yaml::Value = serde_yaml::from_str(&text)
|
||||
.with_context(|| format!("{} is not valid YAML", path.display()))?;
|
||||
if let Some(mapping) = value.as_mapping_mut() {
|
||||
mapping.insert(
|
||||
serde_yaml::Value::String("aliases".to_string()),
|
||||
serde_yaml::Value::Mapping(aliases),
|
||||
);
|
||||
}
|
||||
std::fs::write(path, serde_yaml::to_string(&value)?)
|
||||
.with_context(|| format!("cannot write {}", path.display()))
|
||||
}
|
||||
|
||||
pub fn run(app: &App, sub: &AliasCmd) -> Result<i32> {
|
||||
match sub {
|
||||
AliasCmd::Add { name, target } => {
|
||||
// The target must be a known agent (or another alias).
|
||||
require_agent(app, target)?;
|
||||
let (path, mut aliases) = read_aliases(app)?;
|
||||
aliases.insert(
|
||||
serde_yaml::Value::String(name.clone()),
|
||||
serde_yaml::Value::String(target.clone()),
|
||||
);
|
||||
write_aliases(app, &path, aliases)?;
|
||||
app.log.success(&format!("alias '{name}' -> '{target}'"));
|
||||
Ok(0)
|
||||
}
|
||||
AliasCmd::Remove { name } => {
|
||||
let (path, mut aliases) = read_aliases(app)?;
|
||||
let removed = aliases
|
||||
.remove(&serde_yaml::Value::String(name.clone()))
|
||||
.is_some();
|
||||
if removed {
|
||||
write_aliases(app, &path, aliases)?;
|
||||
app.log.success(&format!("alias '{name}' removed"));
|
||||
} else {
|
||||
app.log.info(&format!("alias '{name}' does not exist"));
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
AliasCmd::List => {
|
||||
if app.json() {
|
||||
print_json(&app.config.aliases);
|
||||
return Ok(0);
|
||||
}
|
||||
if app.config.aliases.is_empty() {
|
||||
app.log.info("no aliases defined — 'am alias add cc claude-code'");
|
||||
return Ok(0);
|
||||
}
|
||||
let mut table = crate::output::Table::new(vec!["ALIAS", "TARGET"]);
|
||||
for (k, v) in &app.config.aliases {
|
||||
table.row(vec![k.clone(), v.clone()]);
|
||||
}
|
||||
print!("{}", table.render());
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user