From c540250a695d887ba4e74b41dc3eaa6bcba433ae Mon Sep 17 00:00:00 2001 From: yongcheng Date: Fri, 29 May 2026 02:22:49 +0000 Subject: [PATCH] fix(help): style full help column padding --- help/help.go | 17 +++++++++------ help/help_test.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/help/help.go b/help/help.go index b6523bc49..826c54d05 100644 --- a/help/help.go +++ b/help/help.go @@ -179,7 +179,6 @@ func (m Model) FullHelpView(groups [][]key.Binding) string { out []string totalWidth int - separator = m.Styles.FullSeparator.Inline(true).Render(m.FullSeparator) ) // Iterate over groups to build columns @@ -193,11 +192,6 @@ func (m Model) FullHelpView(groups [][]key.Binding) string { descriptions []string ) - // Sep - if totalWidth > 0 && i < len(groups) { - sep = separator - } - // Separate keys and descriptions into different slices for _, kb := range group { if !kb.Enabled() { @@ -207,6 +201,17 @@ func (m Model) FullHelpView(groups [][]key.Binding) string { descriptions = append(descriptions, kb.Help().Desc) } + // Sep + if totalWidth > 0 && i < len(groups) { + separatorWidth := lipgloss.Width(m.FullSeparator) + separatorLines := make([]string, len(keys)) + separatorLines[0] = m.FullSeparator + for i := 1; i < len(separatorLines); i++ { + separatorLines[i] = strings.Repeat(" ", separatorWidth) + } + sep = m.Styles.FullSeparator.Render(strings.Join(separatorLines, "\n")) + } + // Column col := lipgloss.JoinHorizontal(lipgloss.Top, sep, diff --git a/help/help_test.go b/help/help_test.go index fbb5e26a1..15bf65f9a 100644 --- a/help/help_test.go +++ b/help/help_test.go @@ -2,9 +2,11 @@ package help import ( "fmt" + "strings" "testing" "charm.land/bubbles/v2/key" + "charm.land/lipgloss/v2" "github.com/charmbracelet/x/ansi" "github.com/charmbracelet/x/exp/golden" ) @@ -37,3 +39,56 @@ func TestFullHelp(t *testing.T) { }) } } + +func TestFullHelpStylesColumnPadding(t *testing.T) { + m := New() + m.FullSeparator = " | " + m.SetWidth(80) + m.Styles.FullSeparator = lipgloss.NewStyle().Background(lipgloss.Color("2")).Foreground(lipgloss.Color("0")) + m.Styles.FullKey = lipgloss.NewStyle().Background(lipgloss.Color("1")).Foreground(lipgloss.Color("0")) + m.Styles.FullDesc = lipgloss.NewStyle().Background(lipgloss.Color("4")).Foreground(lipgloss.Color("0")) + + k := key.WithKeys("x") + kb := [][]key.Binding{ + { + key.NewBinding(k, key.WithHelp("a", "alpha")), + key.NewBinding(k, key.WithHelp("b", "beta")), + }, + { + key.NewBinding(k, key.WithHelp("c", "gamma")), + key.NewBinding(k, key.WithHelp("d", "delta")), + }, + } + + rendered := m.FullHelpView(kb) + if !strings.Contains(rendered, "\x1b[30;42m ") { + t.Fatalf("expected separator style to cover column padding, got %q", rendered) + } +} + +func TestFullHelpStylesColumnPaddingSkipsDisabledBindings(t *testing.T) { + m := New() + m.FullSeparator = " | " + m.SetWidth(80) + m.Styles.FullSeparator = lipgloss.NewStyle().Background(lipgloss.Color("2")).Foreground(lipgloss.Color("0")) + + k := key.WithKeys("x") + disabled := key.NewBinding(k, key.WithHelp("z", "zeta")) + disabled.SetEnabled(false) + kb := [][]key.Binding{ + { + key.NewBinding(k, key.WithHelp("a", "alpha")), + key.NewBinding(k, key.WithHelp("b", "beta")), + }, + { + key.NewBinding(k, key.WithHelp("c", "gamma")), + disabled, + key.NewBinding(k, key.WithHelp("d", "delta")), + }, + } + + rendered := ansi.Strip(m.FullHelpView(kb)) + if strings.Count(rendered, "\n") != 1 { + t.Fatalf("expected exactly two rendered rows when one binding is disabled, got %q", rendered) + } +}