feat(tui): configurable keybinds and mouse scroll

This commit is contained in:
adamdottv 2025-06-18 13:56:46 -05:00
parent d4157d9a96
commit bd46cf0f86
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75
19 changed files with 1276 additions and 853 deletions

View file

@ -1,6 +1,8 @@
package dialog
import (
"log/slog"
"github.com/charmbracelet/bubbles/v2/key"
"github.com/charmbracelet/bubbles/v2/textarea"
tea "github.com/charmbracelet/bubbletea/v2"
@ -144,6 +146,7 @@ func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
c.list.SetItems(msg)
case tea.KeyMsg:
if c.pseudoSearchTextArea.Focused() {
slog.Info("CompletionDialog", "key", msg.String(), "focused", true)
if !key.Matches(msg, completionDialogKeys.Complete) {
var cmd tea.Cmd
c.pseudoSearchTextArea, cmd = c.pseudoSearchTextArea.Update(msg)
@ -159,10 +162,10 @@ func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
c.query = query
cmd = func() tea.Msg {
items, err := c.completionProvider.GetChildEntries(query)
slog.Info("CompletionDialog", "query", query, "items", len(items))
if err != nil {
// status.Error(err.Error())
slog.Error("Failed to get completion items", "error", err)
}
// c.list.SetItems(items)
return items
}
cmds = append(cmds, cmd)
@ -189,9 +192,11 @@ func (c *completionDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return c, tea.Batch(cmds...)
} else {
slog.Info("CompletionDialog", "key", msg.String(), "focused", false)
cmd := func() tea.Msg {
items, err := c.completionProvider.GetChildEntries("")
if err != nil {
slog.Error("Failed to get completion items", "error", err)
// status.Error(err.Error())
}
return items

View file

@ -3,9 +3,9 @@ package dialog
import (
"strings"
"github.com/charmbracelet/bubbles/v2/key"
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/charmbracelet/lipgloss/v2"
"github.com/sst/opencode/internal/commands"
"github.com/sst/opencode/internal/components/modal"
"github.com/sst/opencode/internal/layout"
"github.com/sst/opencode/internal/theme"
@ -15,28 +15,9 @@ type helpDialog struct {
width int
height int
modal *modal.Modal
bindings []key.Binding
commands commands.CommandRegistry
}
// 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
}
@ -63,19 +44,24 @@ func (h *helpDialog) View() string {
PaddingLeft(1).Background(t.BackgroundElement())
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)
}
for _, b := range h.commands {
// Only interested in slash commands
if b.Trigger == "" {
continue
}
content := keyStyle.Render("/" + b.Trigger)
content += descStyle.Render(" " + b.Description)
// for i, key := range b.Keybindings {
// if i == 0 {
// keyString := " (" + key.Key + ")"
// space := max(h.width-lipgloss.Width(content)-lipgloss.Width(keyString), 0)
// spacer := strings.Repeat(" ", space)
// content += descStyle.Render(spacer)
// content += descStyle.Render(keyString)
// }
// }
lines = append(lines, contentStyle.Render(content))
}
@ -94,9 +80,9 @@ type HelpDialog interface {
layout.Modal
}
func NewHelpDialog(bindings ...key.Binding) HelpDialog {
func NewHelpDialog(commands commands.CommandRegistry) HelpDialog {
return &helpDialog{
bindings: bindings,
commands: commands,
modal: modal.New(),
}
}