diff options
Diffstat (limited to 'crates/dinggerd/src/main.rs')
| -rw-r--r-- | crates/dinggerd/src/main.rs | 67 |
1 files changed, 65 insertions, 2 deletions
diff --git a/crates/dinggerd/src/main.rs b/crates/dinggerd/src/main.rs index b97471c..c50fb80 100644 --- a/crates/dinggerd/src/main.rs +++ b/crates/dinggerd/src/main.rs @@ -1,6 +1,7 @@ //! dingger: agent state watching for tmux panes. mod hooks; +mod importance; mod integrations; mod manifest_update; mod names; @@ -71,6 +72,16 @@ enum Command { }, /// Wake the watcher so focus changes show up immediately (tmux hooks). Poke, + /// Set an agent's importance: it orders agents within a status (the + /// list, and the jump), and a low agent makes no sound. In pi, use + /// /importance instead: pi saves it with the session. + Importance { + /// `high`, `normal`, or `low`; without it, print the current one. + level: Option<String>, + /// The agent's pane (default: the pane this runs in). + #[arg(long)] + pane: Option<String>, + }, /// Restore tmux sessions saved before tmux last stopped (a crash, /// shutdown, or kill-server): windows, panes, layouts, directories. /// Only adds what is missing; a bare session of the same name (what a @@ -177,6 +188,12 @@ fn main() { std::process::exit(1); } } + Command::Importance { level, pane } => { + if let Err(err) = set_importance(level.as_deref(), pane) { + eprintln!("dingger: {err}"); + std::process::exit(1); + } + } Command::Poke => { // Best effort: a stopped watcher just means nothing to wake. let _ = hooks::poke(); @@ -284,6 +301,46 @@ fn raise(client: &terminals::Client) { } } +/// `dingger importance`: report the pane's agent importance to the daemon, +/// which writes it (the daemon is the one writer of pane state). +fn set_importance(level: Option<&str>, pane: Option<String>) -> Result<(), String> { + let target = pane + .or_else(|| std::env::var("TMUX_PANE").ok()) + .ok_or("not in a tmux pane; pass --pane")?; + let info = tmux::run(&[ + "display-message", + "-p", + "-t", + &target, + "#{pane_id}\t#{@agent}\t#{@dingger_hook}\t#{@dingger_importance}", + ]) + .map_err(|_| format!("no pane {target}"))?; + let fields: Vec<&str> = info.trim_end_matches('\n').split('\t').collect(); + let [pane_id, agent, hook, written] = fields[..] else { + return Err(format!("no pane {target}")); + }; + if agent.is_empty() { + return Err(format!("no agent in pane {target}")); + } + let Some(level) = level else { + println!("{}", importance::Importance::from_option(written).label()); + return Ok(()); + }; + let level = importance::Importance::parse(level).ok_or("importance is high, normal, or low")?; + // pi's extension reports the importance saved in the session; a value + // set here would last only until its next report. + if agent == "pi" && !hook.is_empty() { + return Err("this pi reports to dingger: use /importance in it (pi saves it with the session)".into()); + } + let message = serde_json::json!({ + "method": "pane.report_agent", + "params": { "pane_id": pane_id, "importance": level.label() }, + }); + hooks::send(&message.to_string())?; + println!("importance: {}", level.label()); + Ok(()) +} + /// Every agent pane in herdr's priority order (blocked, done, working, /// idle), oldest-waiting first within a status. fn status() -> Result<(), String> { @@ -297,7 +354,8 @@ fn status() -> Result<(), String> { } panes.sort_by_key(|pane| { let status = watcher::Status::from_label(&pane.written_state); - (watcher::list_order(status, pane.written_since.parse().ok()), pane.display_target.clone()) + let importance = importance::Importance::from_option(&pane.written_importance); + (watcher::list_order(status, importance, pane.written_since.parse().ok()), pane.display_target.clone()) }); let place = |pane: &tmux::Pane| pane.display_target.replacen(':', " ยท ", 1); let width = panes.iter().map(|pane| place(pane).chars().count()).max().unwrap_or(5).max(5); @@ -305,7 +363,12 @@ fn status() -> Result<(), String> { for pane in &panes { let state = if pane.written_state.is_empty() { "-" } else { &pane.written_state }; let agent = pane.agent.map(detect_core::agent_label).unwrap_or("-"); - println!("{state:<8} {:<width$} {agent:<7} {}", place(pane), pane.written_name); + let name = match importance::Importance::from_option(&pane.written_importance) { + importance::Importance::High => format!("! {}", pane.written_name), + importance::Importance::Low => format!("{} (low)", pane.written_name), + importance::Importance::Normal => pane.written_name.clone(), + }; + println!("{state:<8} {:<width$} {agent:<7} {}", place(pane), name.trim()); } Ok(()) } |
