peco.peco/view.go
2026-02-20 10:55:49 +09:00

94 lines
2.2 KiB
Go

package peco
import (
"context"
"fmt"
"github.com/peco/peco/hub"
)
// View handles the drawing/updating the screen
type View struct {
layout Layout
state *Peco
}
// NewView creates a new View with the given state and its configured layout.
func NewView(state *Peco) (*View, error) {
layout, err := NewLayout(LayoutType(state.LayoutType()), state)
if err != nil {
return nil, fmt.Errorf("failed to create layout: %w", err)
}
return &View{
state: state,
layout: layout,
}, nil
}
// Loop runs the main view loop, listening for draw, paging, and status message
// events from the hub and dispatching them to the appropriate handlers.
func (v *View) Loop(ctx context.Context, cancel func()) error {
defer cancel()
h := v.state.Hub()
for {
select {
case <-ctx.Done():
return nil
case r := <-h.StatusMsgCh():
v.printStatus(r)
case r := <-h.PagingCh():
v.movePage(r)
case r := <-h.DrawCh():
opts := r.Data()
switch {
case opts != nil && opts.Prompt:
v.drawPrompt(r)
case opts != nil && opts.PurgeCache:
v.purgeDisplayCache(r)
default:
v.drawScreen(r, opts)
}
}
}
}
// printStatus renders a status message on the screen's status bar.
func (v *View) printStatus(p *hub.Payload[hub.StatusMsg]) {
defer p.Done()
r := p.Data()
v.layout.PrintStatus(r.Message(), r.Delay())
}
// purgeDisplayCache clears the cached display state, forcing a full redraw on
// the next draw cycle.
func (v *View) purgeDisplayCache(p *hub.Payload[*hub.DrawOptions]) {
defer p.Done()
v.layout.PurgeDisplayCache()
}
// drawScreen renders the current state (prompt, list, status) to the terminal screen.
func (v *View) drawScreen(p *hub.Payload[*hub.DrawOptions], options *hub.DrawOptions) {
defer p.Done()
v.layout.DrawScreen(v.state, options)
}
// drawPrompt renders the query prompt line with cursor position.
func (v *View) drawPrompt(p *hub.Payload[*hub.DrawOptions]) {
defer p.Done()
v.layout.DrawPrompt(v.state)
}
// movePage handles paging events such as scroll up/down and jump to top/bottom.
func (v *View) movePage(p *hub.Payload[hub.PagingRequest]) {
defer p.Done()
r := p.Data()
if v.layout.MovePage(v.state, r) {
v.layout.DrawScreen(v.state, nil)
}
}