Skip to content

Commit

Permalink
Merge pull request #1 from Broderick-Westrope/fix/get-search-working
Browse files Browse the repository at this point in the history
fix: searching list
  • Loading branch information
SaltySpaghetti authored Jan 9, 2025
2 parents 2a6be6e + def464d commit 9291a12
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 64 deletions.
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug TUI interactively",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}",
"console": "integratedTerminal"
},
]
}
10 changes: 8 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ go 1.23.4
require github.com/charmbracelet/bubbletea v1.2.4

require (
github.com/Broderick-Westrope/charmutils v0.0.0-20241115050827-f328b6667400 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/catppuccin/go v0.2.0 // indirect
github.com/charmbracelet/huh v0.6.0 // indirect
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/sahilm/fuzzy v0.1.1 // indirect
)

Expand All @@ -22,9 +28,9 @@ require (
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.3.8 // indirect
golang.org/x/text v0.18.0 // indirect
)
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
github.com/Broderick-Westrope/charmutils v0.0.0-20241115050827-f328b6667400 h1:cb9Y/X/7+JemuYjw/Fv2ELVgtd6BwIiB82EMbmm7wGs=
github.com/Broderick-Westrope/charmutils v0.0.0-20241115050827-f328b6667400/go.mod h1:oh2FSHkUk/5karkxreTzft6smriW821P7puhvnrOMtw=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
github.com/charmbracelet/huh v0.6.0 h1:mZM8VvZGuE0hoDXq6XLxRtgfWyTI3b2jZNKh0xWmax8=
github.com/charmbracelet/huh v0.6.0/go.mod h1:GGNKeWCeNzKpEOh/OJD8WBwTQjV3prFAtQPpLv+AVwU=
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4=
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
Expand All @@ -24,12 +34,16 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
Expand All @@ -43,3 +57,5 @@ golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
97 changes: 35 additions & 62 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,62 @@ package main
import (
"fmt"
"os"
"time"
"tui/test/models"
"tui/test/views"

"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/textinput"
"github.com/Broderick-Westrope/charmutils"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

type app struct {
step models.Step
searchModel views.SearchModel
downloadModel views.DownloadModel
}

func (app app) Init() tea.Cmd {
return nil
}

var appStyle = lipgloss.NewStyle().Padding(1, 2)

func (app app) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd

switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c":
return app, tea.Quit
default:
if len(msg.Runes) == 1 && msg.Type == tea.KeyRunes {
return app, app.handleSearch()
}
}
case tea.WindowSizeMsg:
h, v := appStyle.GetFrameSize()
app.resultsList.SetSize(msg.Width-h, msg.Height-v)
}

// Update the components
updateSearchInput, searchCmd := app.searchInput.Update(msg)
app.searchInput = updateSearchInput
cmds = append(cmds, searchCmd)
updatedResultsList, listCmd := app.resultsList.Update(msg)
app.resultsList = updatedResultsList
cmds = append(cmds, listCmd)

return app, tea.Batch(cmds...)
}
switch app.step {
case models.Searching:
cmd, err := charmutils.UpdateTypedModel(&app.searchModel, msg)
if err != nil {
panic(err)
}
return app, cmd

func (app app) handleSearch() tea.Cmd {
return tea.Tick(time.Millisecond*300, func(t time.Time) tea.Msg {
app.state.ApiState.Status = models.Loading
characters, _ := models.FetchCharacters(app.searchInput.Value())
return app.resultsList.SetItems(characters)
// if err != nil {
// app.state.ApiState.Status = models.Error
// app.state.ApiState.Error = err
// return err
// } else {
// return characters
// }
})
case models.Downloading:
cmd, err := charmutils.UpdateTypedModel(&app.downloadModel, msg)
if err != nil {
panic(err)
}
return app, cmd
}
return app, nil
}

func (app app) View() string {
return fmt.Sprintf(
"%s\n%s",
app.searchInput.View(),
app.resultsList.View(),
)
switch app.step {
case models.Searching:
return app.searchModel.View()

case models.Downloading:
return app.downloadModel.View()

default:
return "ERROR"
}
}

// var searchBar, content string
Expand Down Expand Up @@ -101,28 +92,10 @@ func (app app) View() string {
// return fmt.Sprintf("Something bad happened")
// }

type app struct {
state models.State
searchInput textinput.Model
resultsList list.Model
}

func main() {
searchInput := textinput.New()
searchInput.Prompt = "Search: "
searchInput.Placeholder = "Type to search..."
searchInput.Focus()

resultsList := list.New(make([]list.Item, 0), list.NewDefaultDelegate(), 0, 0)
resultsList.Title = "Results"
resultsList.SetShowPagination(false)

app := app{
state: models.State{
Step: models.Searching,
},
searchInput: searchInput,
resultsList: resultsList,
step: models.Searching,
searchModel: views.NewSearchModel(),
}

if _, err := tea.NewProgram(app, tea.WithAltScreen()).Run(); err != nil {
Expand Down
21 changes: 21 additions & 0 deletions views/download.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package views

import tea "github.com/charmbracelet/bubbletea"

var _ tea.Model = SearchModel{}

type DownloadModel struct {
}

func (m DownloadModel) Init() tea.Cmd {
return nil
}

func (m DownloadModel) Update(tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
}

// View implements tea.Model.
func (m DownloadModel) View() string {
return ""
}
106 changes: 106 additions & 0 deletions views/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package views

import (
"fmt"
"time"
"tui/test/models"

"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

var _ tea.Model = SearchModel{}

type searchResultMsg []list.Item

type apiErrorMsg error

type SearchModel struct {
apiState models.ApiState
searchInput textinput.Model
resultsList list.Model
}

var appStyle = lipgloss.NewStyle().Padding(1, 2)

func NewSearchModel() SearchModel {
searchInput := textinput.New()
searchInput.Prompt = "Search: "
searchInput.Placeholder = "Type to search..."
searchInput.Focus()

resultsList := list.New(make([]list.Item, 0), list.NewDefaultDelegate(), 0, 0)
resultsList.Title = "Results"
resultsList.SetShowPagination(false)

return SearchModel{
searchInput: searchInput,
resultsList: resultsList,
}
}

func (m SearchModel) Init() tea.Cmd {
return nil
}

func (m SearchModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
var cmd tea.Cmd

switch msg := msg.(type) {
case tea.KeyMsg:
if msg.Type == tea.KeyRunes || msg.Type == tea.KeyBackspace || msg.Type == tea.KeySpace {
m.searchInput, cmd = m.searchInput.Update(msg)
cmds = append(cmds, cmd)

cmd = m.handleSearch()
cmds = append(cmds, cmd)

return m, tea.Batch(cmds...)
}

case tea.WindowSizeMsg:
h, v := appStyle.GetFrameSize()
m.resultsList.SetSize(msg.Width-h, msg.Height-v)
return m, nil

case searchResultMsg:
cmd := m.resultsList.SetItems(msg)
return m, cmd

case apiErrorMsg:
m.apiState.Status = models.Error
m.apiState.Error = msg
return m, nil
}

// Update the components
m.resultsList, cmd = m.resultsList.Update(msg)
cmds = append(cmds, cmd)

return m, tea.Batch(cmds...)

}

func (m SearchModel) handleSearch() tea.Cmd {
m.apiState.Status = models.Loading
return tea.Tick(time.Millisecond*300, func(t time.Time) tea.Msg {
characters, err := models.FetchCharacters(m.searchInput.Value())
if err != nil {
return apiErrorMsg(err)
}

return searchResultMsg(characters)
})
}

// View implements tea.Model.
func (m SearchModel) View() string {
return fmt.Sprintf(
"%s\n%s",
m.searchInput.View(),
m.resultsList.View(),
)
}

0 comments on commit 9291a12

Please sign in to comment.