aboutsummaryrefslogtreecommitdiff
path: root/crates/dinggerd/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/dinggerd/src/main.rs')
-rw-r--r--crates/dinggerd/src/main.rs67
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(())
}