josie / alder-tools

Graphs: axis labels on border rows, full-width boxes

- Dropped the left axis gutter (was KEY_RESERVE=8 cols); max/min labels
  now overlay the top/bottom BORDER rows just inside the ┌/└ corners
  (e.g. ┌─1.5───┐ / └─0.5───┘)
- Box spans the full width; trace gained ~8 cols of sub-pixel resolution
- KEY_RESERVE still reserves the key row left so the peak line stays
  clear of the label text
- 15 tests, clippy clean; pty-verified 40x120, 24x70 narrow

be5b81e85ffd54d2a1a45df431a39ed06fe147fc
josie <administrator@josie-c.com> · 2026-09-01T22:58 · browse files at this commit

parents: 6bcf0be

diff --git a/src/ui.rs b/src/ui.rs
index bad6301..a144841 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -746,14 +746,14 @@ pub fn draw(f: &mut Frame, app: &App) {
             } else {
                 plot::fmt_axis(min / axis_div)
             };
-            // Axis gutter: max label top, min label bottom, right-aligned to
-            // the box. Sized to the labels (6 chars max) but at least
-            // KEY_RESERVE so the peak line stays clear of the key text.
-            let axis_w = (axis_max.chars().count().max(axis_min.chars().count()) as u16)
-                .clamp(3, 6)
-                .max(KEY_RESERVE);
-            let box_x = area.x + axis_w.max(KEY_RESERVE);
-            let box_w = w.saturating_sub(box_x - area.x);
+            // Box spans the full width — no left gutter. Axis labels
+            // overlay the top/bottom BORDER rows, just inside the ┌/└
+            // corners (the braille trace lives in the interior, so the
+            // border rows are free for labels). KEY_RESERVE still reserves
+            // the left of the key row so the peak line stays clear of the
+            // label text.
+            let box_x = area.x;
+            let box_w = w;
             let inner_w = box_w.saturating_sub(2);
 
             // Key row ABOVE the box (label + live value left-aligned at
@@ -777,25 +777,24 @@ pub fn draw(f: &mut Frame, app: &App) {
                 box_rect,
             );
             let axis_st = Style::default().fg(Color::DarkGray);
-            let gutter_w = box_x - area.x;
-            let right_fit = |s: &str| -> String {
-                let n = s.chars().count();
-                if n > gutter_w as usize {
-                    s.chars().skip(n - gutter_w as usize).collect()
-                } else {
-                    format!("{}{}", " ".repeat(gutter_w as usize - n), s)
-                }
-            };
-            // max: top border row, right-aligned against the box
-            f.render_widget(
-                ratatui::text::Text::from(Line::from(Span::styled(right_fit(&axis_max), axis_st))),
-                Rect { x: area.x, y: box_rect.y, width: gutter_w, height: 1 },
-            );
-            // min: bottom border row, right-aligned against the box
-            f.render_widget(
-                ratatui::text::Text::from(Line::from(Span::styled(right_fit(&axis_min), axis_st))),
-                Rect { x: area.x, y: box_rect.y + box_h - 1, width: gutter_w, height: 1 },
-            );
+            // Overlay max/min labels on the border rows, just inside the
+            // left corner (after ┌ / └). First-blank-wins: border glyphs
+            // are already rendered, so we overwrite the first few cells
+            // inside the border with the label text.
+            let max_w = axis_max.chars().count() as u16;
+            let min_w = axis_min.chars().count() as u16;
+            if max_w + 2 <= box_w {
+                f.render_widget(
+                    ratatui::text::Text::from(Line::from(Span::styled(axis_max.clone(), axis_st))),
+                    Rect { x: box_x + 2, y: box_rect.y, width: max_w, height: 1 },
+                );
+            }
+            if min_w + 2 <= box_w {
+                f.render_widget(
+                    ratatui::text::Text::from(Line::from(Span::styled(axis_min.clone(), axis_st))),
+                    Rect { x: box_x + 2, y: box_rect.y + box_h - 1, width: min_w, height: 1 },
+                );
+            }
             let used = plot::render(
                 f,
                 Rect { x: box_rect.x + 1, y: box_rect.y + 1, width: inner_w, height: graph_rows },