Align the TUI help legend into a fixed-width column grid.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+49
-31
@@ -152,42 +152,60 @@ func (m Model) helpSep() string {
|
||||
return sep
|
||||
}
|
||||
|
||||
// wrapHelpParts packs styled help snippets into lines that fit within width.
|
||||
func wrapHelpParts(parts []string, width int, sep string) []string {
|
||||
// padHelpCell pads a styled help snippet to cellW visible columns.
|
||||
func padHelpCell(part string, cellW int) string {
|
||||
pad := cellW - lipgloss.Width(part)
|
||||
if pad < 0 {
|
||||
pad = 0
|
||||
}
|
||||
return part + strings.Repeat(" ", pad)
|
||||
}
|
||||
|
||||
// tableHelpParts lays out styled help snippets as a fixed-width column grid.
|
||||
func tableHelpParts(parts []string, width int, sep string) []string {
|
||||
if len(parts) == 0 {
|
||||
return []string{""}
|
||||
}
|
||||
if width < 1 {
|
||||
width = 1
|
||||
}
|
||||
sepW := lipgloss.Width(sep)
|
||||
var lines []string
|
||||
var cur string
|
||||
|
||||
cellW := 0
|
||||
for _, p := range parts {
|
||||
pw := lipgloss.Width(p)
|
||||
if cur == "" {
|
||||
cur = p
|
||||
// Oversized single entry still gets its own line so nothing is dropped.
|
||||
if pw > width {
|
||||
lines = append(lines, cur)
|
||||
cur = ""
|
||||
if w := lipgloss.Width(p); w > cellW {
|
||||
cellW = w
|
||||
}
|
||||
}
|
||||
if cellW < 1 {
|
||||
cellW = 1
|
||||
}
|
||||
|
||||
sepW := lipgloss.Width(sep)
|
||||
cols := 1
|
||||
if cellW <= width {
|
||||
cols = (width + sepW) / (cellW + sepW)
|
||||
if cols < 1 {
|
||||
cols = 1
|
||||
}
|
||||
}
|
||||
|
||||
var lines []string
|
||||
for i := 0; i < len(parts); i += cols {
|
||||
end := i + cols
|
||||
if end > len(parts) {
|
||||
end = len(parts)
|
||||
}
|
||||
row := parts[i:end]
|
||||
cells := make([]string, len(row))
|
||||
for j, p := range row {
|
||||
// Pad every cell except a lone oversized entry on its own row.
|
||||
if len(row) == 1 && lipgloss.Width(p) > width {
|
||||
cells[j] = p
|
||||
} else {
|
||||
cells[j] = padHelpCell(p, cellW)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if lipgloss.Width(cur)+sepW+pw <= width {
|
||||
cur = cur + sep + p
|
||||
continue
|
||||
}
|
||||
lines = append(lines, cur)
|
||||
cur = p
|
||||
if pw > width {
|
||||
lines = append(lines, cur)
|
||||
cur = ""
|
||||
}
|
||||
}
|
||||
if cur != "" {
|
||||
lines = append(lines, cur)
|
||||
}
|
||||
if len(lines) == 0 {
|
||||
return []string{""}
|
||||
lines = append(lines, strings.Join(cells, sep))
|
||||
}
|
||||
return lines
|
||||
}
|
||||
@@ -203,8 +221,8 @@ func (m Model) renderFooter() string {
|
||||
sep := m.helpSep()
|
||||
parts := m.helpParts()
|
||||
|
||||
// Wrap help across the full width so all bindings stay visible.
|
||||
lines := wrapHelpParts(parts, width, sep)
|
||||
// Table layout so key/desc columns stay aligned across rows.
|
||||
lines := tableHelpParts(parts, width, sep)
|
||||
|
||||
// Place version on the last line to the right when it fits; otherwise
|
||||
// put it on an extra right-aligned line.
|
||||
|
||||
Reference in New Issue
Block a user