commit e6e639ecbdb0737bbf5966eff51475014670afc4
parent 42df0a819e98268548aca5b6e0cab29e7421909c
Author: William Casarin <jb55@jb55.com>
Date: Wed, 28 Jan 2026 20:32:26 -0800
dave: show cwd in session list and scene view
Display the working directory below the title in both views using
monospace font with weak/dimmed styling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat:
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/crates/notedeck_dave/src/ui/scene.rs b/crates/notedeck_dave/src/ui/scene.rs
@@ -1,3 +1,5 @@
+use std::path::Path;
+
use crate::agent_status::AgentStatus;
use crate::focus_queue::{FocusPriority, FocusQueue};
use crate::session::{SessionId, SessionManager};
@@ -168,6 +170,7 @@ impl AgentScene {
position,
status,
title,
+ session.cwd.as_deref(),
is_selected,
ctrl_held,
queue_priority,
@@ -303,6 +306,7 @@ impl AgentScene {
position: Vec2,
status: AgentStatus,
title: &str,
+ cwd: Option<&Path>,
is_selected: bool,
show_keybinding: bool,
queue_priority: Option<FocusPriority>,
@@ -383,6 +387,19 @@ impl AgentScene {
status_color.gamma_multiply(0.9),
);
+ // Cwd label (monospace, weak+small)
+ if let Some(cwd_path) = cwd {
+ let cwd_text = cwd_path.to_string_lossy();
+ let cwd_pos = center + Vec2::new(0.0, agent_radius + 38.0);
+ painter.text(
+ cwd_pos,
+ egui::Align2::CENTER_TOP,
+ &cwd_text,
+ egui::FontId::monospace(8.0),
+ ui.visuals().weak_text_color(),
+ );
+ }
+
response
}
}
diff --git a/crates/notedeck_dave/src/ui/session_list.rs b/crates/notedeck_dave/src/ui/session_list.rs
@@ -1,3 +1,5 @@
+use std::path::Path;
+
use egui::{Align, Color32, Layout, Sense};
use notedeck_ui::app_images;
@@ -102,6 +104,7 @@ impl<'a> SessionListUi<'a> {
let response = self.session_item_ui(
ui,
&session.title,
+ session.cwd.as_deref(),
is_active,
shortcut_hint,
session.status(),
@@ -128,12 +131,15 @@ impl<'a> SessionListUi<'a> {
&self,
ui: &mut egui::Ui,
title: &str,
+ cwd: Option<&Path>,
is_active: bool,
shortcut_hint: Option<usize>,
status: AgentStatus,
queue_priority: Option<FocusPriority>,
) -> egui::Response {
- let desired_size = egui::vec2(ui.available_width(), 36.0);
+ // Taller height when cwd is present to fit both lines
+ let item_height = if cwd.is_some() { 48.0 } else { 36.0 };
+ let desired_size = egui::vec2(ui.available_width(), item_height);
let (rect, response) = ui.allocate_exact_size(desired_size, Sense::click());
let hover_text = format!("Ctrl+{} to switch", shortcut_hint.unwrap_or(0));
let response = response
@@ -185,11 +191,12 @@ impl<'a> SessionListUi<'a> {
right_offset
};
- // Draw title text (with clipping to avoid overlapping the dot)
- let text_pos = rect.left_center() + egui::vec2(text_start_x, 0.0);
+ // Calculate text position - offset title upward when cwd is present
+ let title_y_offset = if cwd.is_some() { -7.0 } else { 0.0 };
+ let text_pos = rect.left_center() + egui::vec2(text_start_x, title_y_offset);
let max_text_width = rect.width() - text_start_x - text_end_x;
- // Clip title if needed
+ // Draw title text (with clipping to avoid overlapping the dot)
let font_id = egui::FontId::proportional(14.0);
let text_color = ui.visuals().text_color();
let galley = ui
@@ -217,6 +224,43 @@ impl<'a> SessionListUi<'a> {
);
}
+ // Draw cwd below title
+ if let Some(cwd_path) = cwd {
+ let cwd_pos = rect.left_center() + egui::vec2(text_start_x, 7.0);
+ cwd_ui(ui, cwd_path, cwd_pos, max_text_width);
+ }
+
response
}
}
+
+/// Draw cwd text (monospace, weak+small) with clipping
+fn cwd_ui(ui: &mut egui::Ui, cwd_path: &Path, pos: egui::Pos2, max_width: f32) {
+ let cwd_text = cwd_path.to_string_lossy();
+ let cwd_font = egui::FontId::monospace(10.0);
+ let cwd_color = ui.visuals().weak_text_color();
+
+ let cwd_galley = ui
+ .painter()
+ .layout_no_wrap(cwd_text.to_string(), cwd_font.clone(), cwd_color);
+
+ if cwd_galley.size().x > max_width {
+ let clip_rect = egui::Rect::from_min_size(
+ pos - egui::vec2(0.0, cwd_galley.size().y / 2.0),
+ egui::vec2(max_width, cwd_galley.size().y),
+ );
+ ui.painter().with_clip_rect(clip_rect).galley(
+ pos - egui::vec2(0.0, cwd_galley.size().y / 2.0),
+ cwd_galley,
+ cwd_color,
+ );
+ } else {
+ ui.painter().text(
+ pos,
+ egui::Align2::LEFT_CENTER,
+ &cwd_text,
+ cwd_font,
+ cwd_color,
+ );
+ }
+}