history : reexecution (issues #27 #28) - expansion !! !N !prefix ^old^new dans le REPL + am history --rerun N avec confirmation (shell ou commande am)

This commit is contained in:
2026-08-17 08:05:58 -04:00
parent 4ef89cde72
commit 81c69db17b
6 changed files with 126 additions and 1 deletions
+42
View File
@@ -3,6 +3,44 @@
use super::*;
use crate::history::{self, HistoryEntry};
use crate::output::print_json;
use anyhow::{anyhow, Result};
use clap::Parser;
/// Re-run the Nth most recent entry: shell commands go through the
/// active shell, am commands are parsed and dispatched like the REPL does.
fn rerun_entry(app: &App, n: usize) -> Result<i32> {
if n == 0 {
return Err(anyhow!("invalid entry number 0 — am history numbers start at 1"));
}
let entries = history::read_all(app, n);
let entry = entries.get(n - 1).cloned().ok_or_else(|| {
anyhow!("history entry {n} not found — 'am history' lists them")
})?;
let question = format!("re-run: {} [y/N]", entry.cmd);
if !app.confirm(&question)? {
app.log.info("cancelled");
return Ok(0);
}
let cmd = entry.cmd.strip_prefix('!').unwrap_or(&entry.cmd);
if entry.kind == "shell" {
let session = crate::shell::ShellSession::start(&app.config);
return Ok(session.run(cmd)?);
}
let tokens = shell_words::split(cmd)
.map_err(|e| anyhow!("cannot parse '{cmd}': {e}"))?;
if tokens.is_empty() {
return Ok(0);
}
let cli = crate::cli::Cli::try_parse_from(std::iter::once("am".to_string()).chain(tokens))
.map_err(|e| anyhow!("cannot parse '{cmd}': {e}"))?;
match &cli.command {
Some(cmd) => execute_command(app, cmd),
None => {
app.log.info("nothing to re-run (no subcommand)");
Ok(0)
}
}
}
/// Filter history entries; returns them most recent first.
pub fn filter(
@@ -57,8 +95,12 @@ pub fn run(
failed: bool,
session: Option<&str>,
limit: usize,
rerun: Option<usize>,
) -> Result<i32> {
history::migrate(app)?;
if let Some(n) = rerun {
return rerun_entry(app, n);
}
let rows = filter(app, kind, cwd, search, failed, session, limit);
if app.json() {
let payload: Vec<serde_json::Value> = rows
+2
View File
@@ -102,6 +102,7 @@ pub fn execute_command(app: &App, cmd: &Command) -> Result<i32> {
failed,
session,
limit,
rerun,
} => history_cmd::run(
app,
kind.as_deref(),
@@ -110,6 +111,7 @@ pub fn execute_command(app: &App, cmd: &Command) -> Result<i32> {
*failed,
session.as_deref(),
*limit,
*rerun,
),
Command::Info { agent } => info_cmd::run(app, agent),
Command::Init { force } => init_cmd::run(app, *force),