Skip to content

Commit

Permalink
Manage results with stack (#192)
Browse files Browse the repository at this point in the history
* Cleaned up model.

* Manage results with a stack.

* Fixed segfault in tests.
  • Loading branch information
janderland authored Nov 25, 2023
1 parent 26a4a32 commit 21c1180
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 87 deletions.
1 change: 1 addition & 0 deletions internal/app/fullscreen/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func newHelp() results.Model {
for _, str := range strings.Split(helpMsg, "\n") {
x.Push(str)
}
x.MaxWrapWidth(65)
return x
}

Expand Down
81 changes: 42 additions & 39 deletions internal/app/fullscreen/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package fullscreen

import (
"context"
"github.com/janderland/fdbq/internal/app/fullscreen/results"
"github.com/janderland/fdbq/internal/app/fullscreen/stack"
"io"
"time"

Expand All @@ -12,37 +14,9 @@ import (

"github.com/janderland/fdbq/engine"
"github.com/janderland/fdbq/internal/app/fullscreen/manager"
"github.com/janderland/fdbq/internal/app/fullscreen/results"
"github.com/janderland/fdbq/parser/format"
)

type Mode int

const (
modeScroll Mode = iota
modeInput
modeHelp
modeQuit
)

type Style struct {
results lip.Style
input lip.Style
}

type Model struct {
qm manager.QueryManager
log zerolog.Logger
latest time.Time
mode Mode

style Style
results results.Model
help results.Model
quit results.Model
input textinput.Model
}

type App struct {
Engine engine.Engine
Format format.Format
Expand All @@ -58,16 +32,14 @@ func (x *App) Run(ctx context.Context) error {
input := textinput.New()
input.Placeholder = "Query"

model := Model{
qm: manager.New(
ctx,
x.Engine,
manager.WithSingleOpts(x.SingleOpts),
manager.WithRangeOpts(x.RangeOpts),
manager.WithWrite(x.Write)),
resultsStack := stack.ResultsStack{}
resultsStack.Push(results.New(
results.WithFormat(x.Format),
results.WithLogger(x.Log)))

log: x.Log,
model := Model{
mode: modeScroll,
log: x.Log,

style: Style{
results: lip.NewStyle().
Expand All @@ -77,10 +49,16 @@ func (x *App) Run(ctx context.Context) error {
Border(lip.RoundedBorder()).
Padding(0, 1),
},
results: results.New(results.WithFormat(x.Format), results.WithLogger(x.Log)),
help: newHelp(),
quit: newQuit(),

results: resultsStack,
input: input,

qm: manager.New(
ctx,
x.Engine,
manager.WithSingleOpts(x.SingleOpts),
manager.WithRangeOpts(x.RangeOpts),
manager.WithWrite(x.Write)),
}

_, err := tea.NewProgram(
Expand All @@ -91,3 +69,28 @@ func (x *App) Run(ctx context.Context) error {
).Run()
return err
}

type Mode int

const (
modeScroll Mode = iota
modeInput
modeHelp
modeQuit
)

type Style struct {
results lip.Style
input lip.Style
}

type Model struct {
mode Mode
latest time.Time
log zerolog.Logger

style Style
input textinput.Model
results stack.ResultsStack
qm manager.QueryManager
}
28 changes: 20 additions & 8 deletions internal/app/fullscreen/results/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/janderland/fdbq/internal/app/fullscreen/results/wrap"
"github.com/rs/zerolog"
"math"
"strings"

"github.com/janderland/fdbq/engine/stream"
Expand Down Expand Up @@ -90,6 +91,11 @@ type Model struct {
// line is wrapped. 0 disables wrapping.
wrapWidth int

// maxWrapWidth caps the wrapWidth value.
// If a higher value is set the maxWrapWidth
// is used instead.
maxWrapWidth int

// spaced determines if a blank line
// appears between each item.
spaced bool
Expand Down Expand Up @@ -126,11 +132,12 @@ type Model struct {

func New(opts ...Option) Model {
x := Model{
log: zerolog.Nop(),
keyMap: defaultKeyMap(),
format: format.New(),
builder: &strings.Builder{},
list: list.New(),
log: zerolog.Nop(),
keyMap: defaultKeyMap(),
format: format.New(),
maxWrapWidth: math.MaxInt,
builder: &strings.Builder{},
list: list.New(),
}
for _, option := range opts {
option(&x)
Expand Down Expand Up @@ -170,12 +177,19 @@ func (x *Model) Height(height int) {
}

func (x *Model) WrapWidth(width int) {
if width > x.maxWrapWidth {
width = x.maxWrapWidth
}
x.log.Log().Int("wrapWidth", width).Msg("setting")
x.wrapWidth = width
x.subCursor = 0
x.updateCursors()
}

func (x *Model) MaxWrapWidth(width int) {
x.maxWrapWidth = width
}

func (x *Model) PushMany(list *list.List) {
x.log.Log().Int("n", list.Len()).Msg("pushing many")
for cursor := list.Front(); cursor != nil; cursor = cursor.Next() {
Expand Down Expand Up @@ -327,7 +341,7 @@ func (x *Model) str(item any) string {
}
}

func (x *Model) Update(msg tea.Msg) Model {
func (x *Model) Scroll(msg tea.Msg) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch {
Expand Down Expand Up @@ -365,8 +379,6 @@ func (x *Model) Update(msg tea.Msg) Model {
x.scrollUpItems(1)
}
}

return *x
}

func (x *Model) scrollDownItems(n int) bool {
Expand Down
43 changes: 43 additions & 0 deletions internal/app/fullscreen/stack/stack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package stack

import "github.com/janderland/fdbq/internal/app/fullscreen/results"

type ResultsStack struct {
stack []results.Model

height int
wrapWidth int
}

func (x *ResultsStack) Push(model results.Model) {
model.Height(x.height)
model.WrapWidth(x.wrapWidth)
x.stack = append(x.stack, model)
}

func (x *ResultsStack) Pop() {
if len(x.stack) != 0 {
x.stack = x.stack[:len(x.stack)-1]
}
}

func (x *ResultsStack) Top() *results.Model {
if len(x.stack) == 0 {
return nil
}
return &x.stack[len(x.stack)-1]
}

func (x *ResultsStack) Height(height int) {
x.height = height
for i := range x.stack {
x.stack[i].Height(height)
}
}

func (x *ResultsStack) WrapWidth(width int) {
x.wrapWidth = width
for i := range x.stack {
x.stack[i].WrapWidth(width)
}
}
26 changes: 26 additions & 0 deletions internal/app/fullscreen/stack/stack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package stack

import (
"github.com/janderland/fdbq/internal/app/fullscreen/results"
"github.com/stretchr/testify/require"
"testing"
)

func TestResultsStack(t *testing.T) {
var (
x ResultsStack
r1 = results.New()
r2 = results.New()
)

require.Nil(t, x.Top())

x.Push(r1)
require.Equal(t, &r1, x.Top())

x.Push(r2)
require.Equal(t, &r2, x.Top())

x.Pop()
require.Equal(t, &r1, x.Top())
}
35 changes: 15 additions & 20 deletions internal/app/fullscreen/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,17 @@ func (x Model) updateKey(msg tea.KeyMsg) (Model, tea.Cmd) {

case "?":
x.mode = modeHelp
x.results.Push(newHelp())
return x, nil

case "q":
x.mode = modeQuit
x.results.Push(newQuit())
return x, nil
}
}

x.results = x.results.Update(msg)
x.results.Top().Scroll(msg)
return x, nil

case modeInput:
Expand All @@ -90,7 +92,7 @@ func (x Model) updateKey(msg tea.KeyMsg) (Model, tea.Cmd) {
return x, nil

case tea.KeyUp, tea.KeyDown, tea.KeyPgUp, tea.KeyPgDown:
x.results = x.results.Update(msg)
x.results.Top().Scroll(msg)
}

var cmd tea.Cmd
Expand All @@ -101,30 +103,33 @@ func (x Model) updateKey(msg tea.KeyMsg) (Model, tea.Cmd) {
switch msg.Type {
case tea.KeyEscape:
x.mode = modeScroll
x.results.Pop()
return x, nil
}

x.help = x.help.Update(msg)
x.results.Top().Scroll(msg)
return x, nil

case modeQuit:
switch msg.Type {
case tea.KeyEscape:
x.mode = modeScroll
x.results.Pop()
return x, nil

case tea.KeyRunes:
switch msg.String() {
case "n", "N":
x.mode = modeScroll
x.results.Pop()
return x, nil

case "y", "Y":
return x, tea.Quit
}
}

x.quit = x.quit.Update(msg)
x.results.Top().Scroll(msg)
return x, nil

default:
Expand All @@ -135,7 +140,7 @@ func (x Model) updateKey(msg tea.KeyMsg) (Model, tea.Cmd) {
func (x Model) updateMouse(msg tea.MouseMsg) (Model, tea.Cmd) {
var cmd tea.Cmd
x.input, cmd = x.input.Update(msg)
x.results = x.results.Update(msg)
x.results.Top().Scroll(msg)
return x, cmd
}

Expand All @@ -144,12 +149,12 @@ func (x Model) updateAsyncQuery(msg manager.AsyncQueryMsg) (Model, tea.Cmd) {
return x, nil
}
if x.latest.Before(msg.StartedAt) {
x.results.Reset()
x.results.Top().Reset()
x.latest = msg.StartedAt
}

buf, done := msg.Buffer.Get()
x.results.PushMany(buf)
x.results.Top().PushMany(buf)
if !done {
return x, tea.Tick(50*time.Millisecond, func(_ time.Time) tea.Msg {
return msg
Expand All @@ -159,8 +164,8 @@ func (x Model) updateAsyncQuery(msg manager.AsyncQueryMsg) (Model, tea.Cmd) {
}

func (x Model) updateSingle(msg any) (Model, tea.Cmd) {
x.results.Reset()
x.results.Push(msg)
x.results.Top().Reset()
x.results.Top().Push(msg)
return x, nil
}

Expand All @@ -169,25 +174,15 @@ func (x Model) updateSize(msg tea.WindowSizeMsg) Model {
const cursorChar = 1
inputHeight := x.style.input.GetVerticalFrameSize() + inputLine

// TODO: Clean up calls to GetXXXFrameSize().
x.style.results.Height(msg.Height - x.style.results.GetVerticalFrameSize() - inputHeight)
x.style.results.Width(msg.Width - x.style.results.GetHorizontalFrameSize())

x.results.Height(x.style.results.GetHeight() - x.style.results.GetVerticalFrameSize())
x.results.WrapWidth(x.style.results.GetWidth() - x.style.results.GetHorizontalFrameSize())

x.input.Width = msg.Width - x.style.input.GetHorizontalFrameSize() - len(x.input.Prompt) - cursorChar - 2
x.style.input.Width(msg.Width - x.style.input.GetHorizontalFrameSize())

x.help.Height(x.style.results.GetHeight() - x.style.results.GetVerticalFrameSize())
helpWidth := x.style.results.GetWidth() - x.style.results.GetHorizontalFrameSize()
if helpWidth > 80 {
helpWidth = 65
}
x.help.WrapWidth(helpWidth)

x.quit.Height(x.style.results.GetHeight() - x.style.results.GetVerticalFrameSize())
x.quit.WrapWidth(x.style.results.GetWidth() - x.style.results.GetHorizontalFrameSize())

return x
}

Expand Down
Loading

0 comments on commit 21c1180

Please sign in to comment.