summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdotdevin <[email protected]>2025-07-14 11:56:25 -0500
committeradamdotdevin <[email protected]>2025-07-14 12:15:47 -0500
commita1c8e5af454fb5db562334fa66efe3f4d5d014f1 (patch)
tree89d5ac1d67f314abf9317a191338c275c4d7ce10
parentf1e7e7c1383075c87859cdbb1d08d510398302a9 (diff)
downloadopencode-a1c8e5af454fb5db562334fa66efe3f4d5d014f1.tar.gz
opencode-a1c8e5af454fb5db562334fa66efe3f4d5d014f1.zip
chore: use new search component in find dialog
-rw-r--r--packages/tui/internal/components/dialog/find.go172
1 files changed, 37 insertions, 135 deletions
diff --git a/packages/tui/internal/components/dialog/find.go b/packages/tui/internal/components/dialog/find.go
index 1f716c892..40909b6f0 100644
--- a/packages/tui/internal/components/dialog/find.go
+++ b/packages/tui/internal/components/dialog/find.go
@@ -3,14 +3,10 @@ package dialog
import (
"log/slog"
- "github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/bubbles/v2/textinput"
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/sst/opencode/internal/components/list"
"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"
"github.com/sst/opencode/internal/util"
)
@@ -30,120 +26,61 @@ type FindDialog interface {
}
type findDialogComponent struct {
- query string
completionProvider CompletionProvider
width, height int
modal *modal.Modal
- textInput textinput.Model
- list list.List[CompletionItemI]
-}
-
-type findDialogKeyMap struct {
- Select key.Binding
- Cancel key.Binding
-}
-
-var findDialogKeys = findDialogKeyMap{
- Select: key.NewBinding(
- key.WithKeys("enter"),
- ),
- Cancel: key.NewBinding(
- key.WithKeys("esc"),
- ),
+ searchDialog *SearchDialog
}
func (f *findDialogComponent) Init() tea.Cmd {
- return textinput.Blink
+ return f.searchDialog.Init()
}
func (f *findDialogComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
- var cmd tea.Cmd
- var cmds []tea.Cmd
-
switch msg := msg.(type) {
case []CompletionItemI:
- f.list.SetItems(msg)
- case tea.KeyMsg:
- switch msg.String() {
- case "ctrl+c":
- if f.textInput.Value() == "" {
- return f, nil
- }
- f.textInput.SetValue("")
- return f.update(msg)
+ // Convert CompletionItemI to list.ListItem
+ items := make([]list.ListItem, len(msg))
+ for i, item := range msg {
+ items[i] = item
}
+ f.searchDialog.SetItems(items)
+ return f, nil
- switch {
- case key.Matches(msg, findDialogKeys.Select):
- item, i := f.list.GetSelectedItem()
- if i == -1 {
- return f, nil
- }
+ case SearchSelectionMsg:
+ // Handle selection from search dialog
+ if item, ok := msg.Item.(CompletionItemI); ok {
return f, f.selectFile(item)
- case key.Matches(msg, findDialogKeys.Cancel):
- return f, f.Close()
- default:
- f.textInput, cmd = f.textInput.Update(msg)
- cmds = append(cmds, cmd)
-
- f, cmd = f.update(msg)
- cmds = append(cmds, cmd)
}
- }
-
- return f, tea.Batch(cmds...)
-}
+ return f, nil
-func (f *findDialogComponent) update(msg tea.Msg) (*findDialogComponent, tea.Cmd) {
- var cmd tea.Cmd
- var cmds []tea.Cmd
+ case SearchCancelledMsg:
+ return f, f.Close()
- query := f.textInput.Value()
- if query != f.query {
- f.query = query
- cmd = func() tea.Msg {
- items, err := f.completionProvider.GetChildEntries(query)
+ case SearchQueryChangedMsg:
+ // Update completion items based on search query
+ return f, func() tea.Msg {
+ items, err := f.completionProvider.GetChildEntries(msg.Query)
if err != nil {
slog.Error("Failed to get completion items", "error", err)
}
return items
}
- cmds = append(cmds, cmd)
}
- u, cmd := f.list.Update(msg)
- f.list = u.(list.List[CompletionItemI])
- cmds = append(cmds, cmd)
-
- return f, tea.Batch(cmds...)
+ // Forward all other messages to the search dialog
+ updatedDialog, cmd := f.searchDialog.Update(msg)
+ f.searchDialog = updatedDialog.(*SearchDialog)
+ return f, cmd
}
func (f *findDialogComponent) View() string {
- t := theme.CurrentTheme()
- f.textInput.SetWidth(f.width - 8)
- f.list.SetMaxWidth(f.width - 4)
- inputView := f.textInput.View()
- inputView = styles.NewStyle().
- Background(t.BackgroundElement()).
- Height(1).
- Width(f.width-4).
- Padding(0, 0).
- Render(inputView)
-
- listView := f.list.View()
- return styles.NewStyle().
- Height(12).
- Background(t.BackgroundPanel()).
- Width(f.width - 4).
- Render(inputView + "\n" + listView)
+ return f.searchDialog.View()
}
func (f *findDialogComponent) SetWidth(width int) {
f.width = width
- if width > 4 {
- f.textInput.SetWidth(width - 4)
- f.list.SetMaxWidth(width - 4)
- }
+ f.searchDialog.SetWidth(width - 4)
}
func (f *findDialogComponent) SetHeight(height int) {
@@ -151,7 +88,7 @@ func (f *findDialogComponent) SetHeight(height int) {
}
func (f *findDialogComponent) IsEmpty() bool {
- return f.list.IsEmpty()
+ return f.searchDialog.GetQuery() == ""
}
func (f *findDialogComponent) selectFile(item CompletionItemI) tea.Cmd {
@@ -168,67 +105,32 @@ func (f *findDialogComponent) Render(background string) string {
}
func (f *findDialogComponent) Close() tea.Cmd {
- f.textInput.Reset()
- f.textInput.Blur()
+ f.searchDialog.SetQuery("")
+ f.searchDialog.Blur()
return util.CmdHandler(modal.CloseModalMsg{})
}
-func createTextInput(existing *textinput.Model) textinput.Model {
- t := theme.CurrentTheme()
- bgColor := t.BackgroundElement()
- textColor := t.Text()
- textMutedColor := t.TextMuted()
-
- ti := textinput.New()
-
- ti.Styles.Blurred.Placeholder = styles.NewStyle().
- Foreground(textMutedColor).
- Background(bgColor).
- Lipgloss()
- ti.Styles.Blurred.Text = styles.NewStyle().Foreground(textColor).Background(bgColor).Lipgloss()
- ti.Styles.Focused.Placeholder = styles.NewStyle().
- Foreground(textMutedColor).
- Background(bgColor).
- Lipgloss()
- ti.Styles.Focused.Text = styles.NewStyle().Foreground(textColor).Background(bgColor).Lipgloss()
- ti.Styles.Cursor.Color = t.Primary()
- ti.VirtualCursor = true
-
- ti.Prompt = " "
- ti.CharLimit = -1
- ti.Focus()
-
- if existing != nil {
- ti.SetValue(existing.Value())
- ti.SetWidth(existing.Width())
- }
-
- return ti
-}
-
func NewFindDialog(completionProvider CompletionProvider) FindDialog {
- ti := createTextInput(nil)
-
- li := list.NewListComponent(
- []CompletionItemI{},
- 10, // max visible items
- completionProvider.GetEmptyMessage(),
- false,
- )
+ searchDialog := NewSearchDialog("Search files...", 10)
+ // Initialize with empty query to get initial items
go func() {
items, err := completionProvider.GetChildEntries("")
if err != nil {
slog.Error("Failed to get completion items", "error", err)
+ return
+ }
+ // Convert CompletionItemI to list.ListItem
+ listItems := make([]list.ListItem, len(items))
+ for i, item := range items {
+ listItems[i] = item
}
- li.SetItems(items)
+ searchDialog.SetItems(listItems)
}()
return &findDialogComponent{
- query: "",
completionProvider: completionProvider,
- textInput: ti,
- list: li,
+ searchDialog: searchDialog,
modal: modal.New(
modal.WithTitle("Find Files"),
modal.WithMaxWidth(80),