From b4f45632debe6b8dc2f44ca6cc1b003d9093ad33 Mon Sep 17 00:00:00 2001 From: Igor Soarez Date: Fri, 23 Oct 2026 18:45:06 +0300 Subject: session groups: list each pane once, save each group once a pane in several sessions (a session group, `new-session -t`, or a linked window) was listed once per session: every agent of a group showed twice in the menu, panel, search, `dingger status`, and the counts. and snapshots saved each session of a group with its own copy of the windows, so restore would have rebuilt them twice and resumed each agent twice on one session file. - a pane keeps its first listing (tmux lists sessions by name) and is attended if the user looks at it through any session of the group. - snapshots keep the first session of each group; the others are not restored. e2e step 19 covers both; the previous binaries fail it. two checks (step 11's and this one) waited for idle after a turn that started from idle, which passed before the turn was even processed: they now wait for working first, and the negative control for group attendance fails as it should. step 18 now waits for the snapshot it later restores from. --- crates/dinggerd/src/tmux.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'crates/dinggerd/src/tmux.rs') diff --git a/crates/dinggerd/src/tmux.rs b/crates/dinggerd/src/tmux.rs index 182d62f..6610161 100644 --- a/crates/dinggerd/src/tmux.rs +++ b/crates/dinggerd/src/tmux.rs @@ -15,10 +15,10 @@ pub struct Pane { /// Working directory of the pane's foreground process. pub cwd: String, pub dead: bool, - /// The pane's window is the current window of its session. - pub window_active: bool, - /// The pane's session has at least one attached client. - pub session_attached: bool, + /// The user is looking at this pane's window: it is the current window + /// of a session with an attached client. herdr marks every pane of the + /// active tab seen (`mark_active_tab_seen`); a tmux window is a tab. + pub attended: bool, pub agent: Option, /// Pane options written by dingger (see the watcher module docs). pub written_state: String, @@ -30,13 +30,6 @@ pub struct Pane { pub written_session: String, } -impl Pane { - /// The user is looking at this pane's window. herdr marks every pane of - /// the active tab seen (`mark_active_tab_seen`); a tmux window is a tab. - pub fn attended(&self) -> bool { - self.window_active && self.session_attached - } -} /// The tmux binary. launchd starts dingger, and the menu bar app that runs /// `dingger focus`, with PATH=/usr/bin:/bin:/usr/sbin:/sbin, where Homebrew's @@ -92,6 +85,9 @@ fn run_tmux(args: &[&str]) -> Result { Ok(String::from_utf8_lossy(&output.stdout).into_owned()) } +/// Every pane, once. A pane in several sessions (a session group, or a +/// linked window) keeps its first listing (tmux lists sessions by name), +/// and is attended if the user looks at it in any of them. pub fn list_panes() -> Result, String> { let format = concat!( "#{pane_id}\t", @@ -115,13 +111,18 @@ pub fn list_panes() -> Result, String> { "#{@agent_session}", ); let out = run_tmux(&["list-panes", "-a", "-F", format])?; - let mut panes = Vec::new(); + let mut panes: Vec = Vec::new(); let mut process_tree = None; for line in out.lines() { let fields: Vec<&str> = line.split('\t').collect(); if fields.len() < 19 { continue; } + let attended = fields[4] == "1" && fields[5] != "0"; + if let Some(listed) = panes.iter_mut().find(|pane| pane.pane_id == fields[0]) { + listed.attended |= attended; + continue; + } let current_command = fields[1]; let start_command = fields[6]; let pane_pid: Option = fields[7].trim().parse().ok(); @@ -147,8 +148,7 @@ pub fn list_panes() -> Result, String> { pane_title: fields[2].to_string(), cwd: fields[16].to_string(), dead: fields[3] == "1", - window_active: fields[4] == "1", - session_attached: fields[5] != "0", + attended, agent, written_state: fields[8].to_string(), written_agent: fields[9].to_string(), -- cgit v1.2.3