diff --git a/app/app.go b/app/app.go index efa48ae..fb54472 100644 --- a/app/app.go +++ b/app/app.go @@ -2,13 +2,18 @@ package app import ( "os" + "strings" "git.sr.ht/~rockorager/vaxis" + "git.sr.ht/~rockorager/vaxis/widgets/textinput" "git.tilde.town/nbsp/directory/ui" ) type App struct { - users ui.List + allUsers []string + users ui.List + filter textinput.Model + searching bool } func New() *App { @@ -19,24 +24,82 @@ func New() *App { users = append(users, "~"+user.Name()) } } - return &App{ui.NewList(users, 0)} + return &App{users: ui.NewList(users, 0), allUsers: users} } func (app *App) Event(state *ui.State, event vaxis.Event) { if key, ok := event.(vaxis.Key); ok && key.EventType == vaxis.EventPress { + other := false switch key.String() { - case "Ctrl+c", "Ctrl+d", "q": + case "Ctrl+c", "Ctrl+d": close(ui.Quit) - case "Down", "j", "Ctrl+n": + case "Down", "Ctrl+n": app.users.Down() - case "Up", "k", "Ctrl+p": + case "Up", "Ctrl+p": app.users.Up() - case "End", "Shift+g": + case "End": app.users.End() - case "Home", "g": + case "Home": app.users.Home() + case "Escape": + app.searching = false + default: + other = true + } + if other { + if !app.searching { + switch key.String() { + case "q": + close(ui.Quit) + case "j": + app.users.Down() + case "k": + app.users.Up() + case "g": + app.users.Home() + case "Shift+g": + app.users.End() + case "/": + app.searching = true + app.filter.SetContent("") + } + } else { + app.filter.Update(event) + app.users.SetItems(filter(app.allUsers, app.filter.String())) + } } } - app.users.Draw(state.Window().New(0, 0, 20, state.Window().Height)) + win := state.Window() + w, h := win.Size() + if len(app.users.Items()) > 0 { + app.users.Draw(win.New(0, 0, 20, h-1)) + } + for x := 0; x < w; x++ { + setCell(win, x, h-2, '─', vaxis.Style{}) + } + if app.searching { + app.filter.Draw(win.New(0, h-1, w, 1)) + } else { + win.New(0, h-1, w, 1).Print(vaxis.Segment{Text: "press / to search users", Style: vaxis.Style{Foreground: vaxis.IndexColor(8)}}) + } +} + +func setCell(win vaxis.Window, x int, y int, r rune, st vaxis.Style) { + win.SetCell(x, y, vaxis.Cell{ + Character: vaxis.Character{ + Grapheme: string([]rune{r}), + }, + Style: st, + }) +} + +func filter(users []string, query string) []string { + var filtered []string + for _, s := range users { + if strings.Contains(s, query) { + filtered = append(filtered, s) + } + } + return filtered } diff --git a/go.mod b/go.mod index fe1bd0e..93685a2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.tilde.town/nbsp/directory -go 1.23.5 +go 1.23 require git.sr.ht/~rockorager/vaxis v0.13.0 @@ -10,6 +10,7 @@ require ( github.com/mattn/go-sixel v0.0.5 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/soniakeys/quant v1.0.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/image v0.9.0 // indirect golang.org/x/sys v0.10.0 // indirect ) diff --git a/go.sum b/go.sum index cec6c31..c75b49d 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/soniakeys/quant v1.0.0/go.mod h1:HI1k023QuVbD4H8i9YdfZP2munIHU4QpjsIm github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.9.0 h1:QrzfX26snvCM20hIhBwuHI/ThTg18b/+kcKdXHvnR+g= golang.org/x/image v0.9.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= diff --git a/ui/list.go b/ui/list.go index e5d1591..9ba8d95 100644 --- a/ui/list.go +++ b/ui/list.go @@ -32,6 +32,10 @@ func (m *List) Draw(win vaxis.Window) { m.offset = m.index } + if m.offset < 0 { + m.offset = 0 + } + defaultStyle := vaxis.Style{} selectedStyle := vaxis.Style{Attribute: vaxis.AttrReverse}