summaryrefslogtreecommitdiffhomepage
path: root/packages/tui/internal/components/dialog/help.go
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-06-12 16:00:20 -0500
committeradamdottv <[email protected]>2025-06-12 16:00:26 -0500
commit653965ef5908a240f6038609e17bc8fa27640203 (patch)
tree439910084fdcea0c45856ad0132f916fd9038a4b /packages/tui/internal/components/dialog/help.go
parentca0ea3f94dc1929071efc93bfcf708c8cf054be8 (diff)
downloadopencode-653965ef5908a240f6038609e17bc8fa27640203.tar.gz
opencode-653965ef5908a240f6038609e17bc8fa27640203.zip
wip: refactoring tui
Diffstat (limited to 'packages/tui/internal/components/dialog/help.go')
-rw-r--r--packages/tui/internal/components/dialog/help.go239
1 files changed, 79 insertions, 160 deletions
diff --git a/packages/tui/internal/components/dialog/help.go b/packages/tui/internal/components/dialog/help.go
index 6ceeb40b2..a1508a01a 100644
--- a/packages/tui/internal/components/dialog/help.go
+++ b/packages/tui/internal/components/dialog/help.go
@@ -6,196 +6,115 @@ import (
"github.com/charmbracelet/bubbles/v2/key"
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/charmbracelet/lipgloss/v2"
+ "github.com/sst/opencode/internal/components/modal"
"github.com/sst/opencode/internal/layout"
- "github.com/sst/opencode/internal/styles"
"github.com/sst/opencode/internal/theme"
)
-type helpComponent struct {
- width int
- height int
- keys []key.Binding
+type helpDialog struct {
+ width int
+ height int
+ modal *modal.Modal
+ bindings []key.Binding
}
-func (h *helpComponent) Init() tea.Cmd {
+// func (i bindingItem) Render(selected bool, width int) string {
+// t := theme.CurrentTheme()
+// baseStyle := styles.BaseStyle().
+// Width(width - 2).
+// Background(t.BackgroundElement())
+//
+// if selected {
+// baseStyle = baseStyle.
+// Background(t.Primary()).
+// Foreground(t.BackgroundElement()).
+// Bold(true)
+// } else {
+// baseStyle = baseStyle.
+// Foreground(t.Text())
+// }
+//
+// return baseStyle.Padding(0, 1).Render(i.binding.Help().Desc)
+// }
+
+func (h *helpDialog) Init() tea.Cmd {
return nil
}
-func (h *helpComponent) SetBindings(k []key.Binding) {
- h.keys = k
-}
-
-func (h *helpComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+func (h *helpDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
- h.width = 90
+ h.width = msg.Width
h.height = msg.Height
}
return h, nil
}
-func removeDuplicateBindings(bindings []key.Binding) []key.Binding {
- seen := make(map[string]struct{})
- result := make([]key.Binding, 0, len(bindings))
-
- // Process bindings in reverse order
- for i := len(bindings) - 1; i >= 0; i-- {
- b := bindings[i]
- k := strings.Join(b.Keys(), " ")
- if _, ok := seen[k]; ok {
- // duplicate, skip
- continue
- }
- seen[k] = struct{}{}
- // Add to the beginning of result to maintain original order
- result = append([]key.Binding{b}, result...)
- }
-
- return result
-}
-
-func (h *helpComponent) render() string {
+// func removeDuplicateBindings(bindings []key.Binding) []key.Binding {
+// seen := make(map[string]struct{})
+// result := make([]key.Binding, 0, len(bindings))
+//
+// // Process bindings in reverse order
+// for i := len(bindings) - 1; i >= 0; i-- {
+// b := bindings[i]
+// k := strings.Join(b.Keys(), " ")
+// if _, ok := seen[k]; ok {
+// // duplicate, skip
+// continue
+// }
+// seen[k] = struct{}{}
+// // Add to the beginning of result to maintain original order
+// result = append([]key.Binding{b}, result...)
+// }
+//
+// return result
+// }
+
+func (h *helpDialog) View() string {
t := theme.CurrentTheme()
- baseStyle := styles.BaseStyle()
-
- helpKeyStyle := styles.Bold().
- Background(t.Background()).
+ keyStyle := lipgloss.NewStyle().
+ Background(t.BackgroundElement()).
Foreground(t.Text()).
- Padding(0, 1, 0, 0)
-
- helpDescStyle := styles.Regular().
- Background(t.Background()).
+ Bold(true)
+ descStyle := lipgloss.NewStyle().
+ Background(t.BackgroundElement()).
Foreground(t.TextMuted())
- // Compile list of bindings to render
- bindings := removeDuplicateBindings(h.keys)
-
- // Enumerate through each group of bindings, populating a series of
- // pairs of columns, one for keys, one for descriptions
- var (
- pairs []string
- width int
- rows = 12 - 2
- )
-
- for i := 0; i < len(bindings); i += rows {
- var (
- keys []string
- descs []string
- )
- for j := i; j < min(i+rows, len(bindings)); j++ {
- keys = append(keys, helpKeyStyle.Render(bindings[j].Help().Key))
- descs = append(descs, helpDescStyle.Render(bindings[j].Help().Desc))
- }
-
- // Render pair of columns; beyond the first pair, render a three space
- // left margin, in order to visually separate the pairs.
- var cols []string
- if len(pairs) > 0 {
- cols = []string{baseStyle.Render(" ")}
- }
-
- maxDescWidth := 0
- for _, desc := range descs {
- if maxDescWidth < lipgloss.Width(desc) {
- maxDescWidth = lipgloss.Width(desc)
- }
- }
- for i := range descs {
- remainingWidth := maxDescWidth - lipgloss.Width(descs[i])
- if remainingWidth > 0 {
- descs[i] = descs[i] + baseStyle.Render(strings.Repeat(" ", remainingWidth))
- }
- }
- maxKeyWidth := 0
- for _, key := range keys {
- if maxKeyWidth < lipgloss.Width(key) {
- maxKeyWidth = lipgloss.Width(key)
- }
- }
- for i := range keys {
- remainingWidth := maxKeyWidth - lipgloss.Width(keys[i])
- if remainingWidth > 0 {
- keys[i] = keys[i] + baseStyle.Render(strings.Repeat(" ", remainingWidth))
+ lines := []string{}
+ for _, b := range h.bindings {
+ content := keyStyle.Render(b.Help().Key)
+ content += descStyle.Render(" " + b.Help().Desc)
+ for i, key := range b.Keys() {
+ if i == 0 {
+ keyString := " (" + strings.ToUpper(key) + ")"
+ // space := max(h.width-lipgloss.Width(content)-lipgloss.Width(keyString), 0)
+ // spacer := strings.Repeat(" ", space)
+ // content += descStyle.Render(spacer)
+ content += descStyle.Render(keyString)
}
}
- cols = append(cols,
- strings.Join(keys, "\n"),
- strings.Join(descs, "\n"),
- )
-
- pair := baseStyle.Render(lipgloss.JoinHorizontal(lipgloss.Top, cols...))
- // check whether it exceeds the maximum width avail (the width of the
- // terminal, subtracting 2 for the borders).
- width += lipgloss.Width(pair)
- if width > h.width-2 {
- break
- }
- pairs = append(pairs, pair)
+ lines = append(lines, content)
}
- // https://github.com/charmbracelet/lipgloss/v2/issues/209
- if len(pairs) > 1 {
- prefix := pairs[:len(pairs)-1]
- lastPair := pairs[len(pairs)-1]
- prefix = append(prefix, lipgloss.Place(
- lipgloss.Width(lastPair), // width
- lipgloss.Height(prefix[0]), // height
- lipgloss.Left, // x
- lipgloss.Top, // y
- lastPair, // content
- // lipgloss.WithWhitespaceBackground(t.Background()),
- ))
- content := baseStyle.Width(h.width).Render(
- lipgloss.JoinHorizontal(
- lipgloss.Top,
- prefix...,
- ),
- )
- return content
- }
-
- // Join pairs of columns and enclose in a border
- content := baseStyle.Width(h.width).Render(
- lipgloss.JoinHorizontal(
- lipgloss.Top,
- pairs...,
- ),
- )
- return content
+ return strings.Join(lines, "\n")
}
-func (h *helpComponent) View() string {
- t := theme.CurrentTheme()
- baseStyle := styles.BaseStyle()
-
- content := h.render()
- header := baseStyle.
- Bold(true).
- Width(lipgloss.Width(content)).
- Foreground(t.Primary()).
- Render("Keyboard Shortcuts")
+func (h *helpDialog) Render(background string) string {
+ return h.modal.Render(h.View(), background)
+}
- return baseStyle.Padding(1).
- Border(lipgloss.RoundedBorder()).
- BorderForeground(t.TextMuted()).
- Width(h.width).
- BorderBackground(t.Background()).
- Render(
- lipgloss.JoinVertical(lipgloss.Center,
- header,
- baseStyle.Render(strings.Repeat(" ", lipgloss.Width(header))),
- content,
- ),
- )
+func (h *helpDialog) Close() tea.Cmd {
+ return nil
}
-type HelpComponent interface {
- layout.ModelWithView
- SetBindings([]key.Binding)
+type HelpDialog interface {
+ layout.Modal
}
-func NewHelpCmp() HelpComponent {
- return &helpComponent{}
+func NewHelpDialog(bindings ...key.Binding) HelpDialog {
+ return &helpDialog{
+ bindings: bindings,
+ modal: modal.New(),
+ }
}