aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-11 23:31:36 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-11 23:34:20 +0300
commitfe693f613a23452e68589a4337863f217cc57930 (patch)
tree8d60f6c5b0d8b31426c6623cc8b0c2415d481000 /src/ui
parent84c0d003ddb19a8e95e7ad5206771a663913605b (diff)
feat: add optional pane border labels
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/dialogs.rs1
-rw-r--r--src/ui/keybind_help.rs1
-rw-r--r--src/ui/panes.rs44
-rw-r--r--src/ui/settings.rs11
-rw-r--r--src/ui/sidebar.rs1
5 files changed, 57 insertions, 1 deletions
diff --git a/src/ui/dialogs.rs b/src/ui/dialogs.rs
index 78f1d1cb..3c481a97 100644
--- a/src/ui/dialogs.rs
+++ b/src/ui/dialogs.rs
@@ -42,6 +42,7 @@ pub(super) fn render_rename_overlay(app: &AppState, frame: &mut Frame, area: Rec
Mode::RenameWorkspace => "rename workspace",
Mode::RenameTab if app.creating_new_tab => "new tab",
Mode::RenameTab => "rename tab",
+ Mode::RenamePane => "rename pane",
_ => return,
};
diff --git a/src/ui/keybind_help.rs b/src/ui/keybind_help.rs
index 2bb05c50..fdc600c4 100644
--- a/src/ui/keybind_help.rs
+++ b/src/ui/keybind_help.rs
@@ -82,6 +82,7 @@ pub(super) fn keybind_help_groups(
(kb.split_vertical_label.clone(), "split vertical"),
(kb.split_horizontal_label.clone(), "split horizontal"),
(kb.close_pane_label.clone(), "close pane"),
+ (optional_keybind_label(&kb.rename_pane_label), "rename pane"),
(kb.fullscreen_label.clone(), "fullscreen"),
(kb.resize_mode_label.clone(), "resize mode"),
(kb.toggle_sidebar_label.clone(), "toggle sidebar"),
diff --git a/src/ui/panes.rs b/src/ui/panes.rs
index 818ee9fd..72a5c30c 100644
--- a/src/ui/panes.rs
+++ b/src/ui/panes.rs
@@ -18,6 +18,30 @@ pub(crate) fn pane_is_scrolled_back(rt: &PaneRuntime) -> bool {
.is_some_and(|metrics| metrics.offset_from_bottom > 0)
}
+fn truncate_label(text: &str, max_width: usize) -> String {
+ let len = text.chars().count();
+ if len <= max_width {
+ return text.to_string();
+ }
+ if max_width == 0 {
+ return String::new();
+ }
+ if max_width == 1 {
+ return "…".to_string();
+ }
+ let prefix: String = text.chars().take(max_width.saturating_sub(1)).collect();
+ format!("{prefix}…")
+}
+
+fn pane_border_title(label: &str, pane_width: u16) -> Option<String> {
+ let label = label.trim();
+ if label.is_empty() || pane_width <= 4 {
+ return None;
+ }
+ let max_label_width = pane_width.saturating_sub(4) as usize;
+ Some(format!(" {} ", truncate_label(label, max_label_width)))
+}
+
fn stable_terminal_inner_rect(pane_inner: Rect) -> Rect {
if pane_inner.width <= 4 {
return pane_inner;
@@ -174,10 +198,17 @@ pub(super) fn render_panes(app: &AppState, frame: &mut Frame, area: Rect) {
)
};
- let block = Block::default()
+ let mut block = Block::default()
.borders(Borders::ALL)
.border_style(border_style)
.border_set(border_set);
+ if let Some(title) = ws
+ .pane_state(info.id)
+ .and_then(|pane| pane.border_label(app.show_agent_labels_on_pane_borders))
+ .and_then(|label| pane_border_title(label, info.rect.width))
+ {
+ block = block.title(Line::from(Span::styled(title, border_style)));
+ }
frame.render_widget(block, info.rect);
}
@@ -303,6 +334,17 @@ mod tests {
use crate::pane::PaneRuntime;
use crate::workspace::Workspace;
+ #[test]
+ fn pane_border_title_trims_and_truncates() {
+ assert_eq!(
+ pane_border_title(" claude ", 20).as_deref(),
+ Some(" claude ")
+ );
+ assert_eq!(pane_border_title("", 20), None);
+ assert_eq!(pane_border_title("abcdef", 8).as_deref(), Some(" abc… "));
+ assert_eq!(pane_border_title("abcdef", 4), None);
+ }
+
#[tokio::test]
async fn pane_scrollbar_gutter_is_reserved_before_scrollback_exists() {
let mut app = AppState::test_new();
diff --git a/src/ui/settings.rs b/src/ui/settings.rs
index 5269f380..ef80d85a 100644
--- a/src/ui/settings.rs
+++ b/src/ui/settings.rs
@@ -106,6 +106,17 @@ pub(super) fn render_settings_overlay(app: &AppState, frame: &mut Frame, area: R
2,
);
}
+ SettingsSection::PaneLabels => {
+ render_settings_toggle(
+ frame,
+ content_area,
+ p,
+ "agent border labels",
+ "show detected agent names in split pane borders",
+ app.agent_border_labels_enabled(),
+ app.settings.list.selected,
+ );
+ }
}
if let Some(footer_area) = stack.footer {
diff --git a/src/ui/sidebar.rs b/src/ui/sidebar.rs
index 83ceebe0..8a104dba 100644
--- a/src/ui/sidebar.rs
+++ b/src/ui/sidebar.rs
@@ -70,6 +70,7 @@ fn agent_panel_current_workspace_idx(app: &AppState) -> Option<usize> {
app.mode,
Mode::Navigate
| Mode::RenameWorkspace
+ | Mode::RenamePane
| Mode::Resize
| Mode::ConfirmClose
| Mode::ContextMenu