Refactor ZoomState

This commit is contained in:
Daisuke Maki 2026-02-17 13:25:21 +09:00
parent 24df34ddda
commit a813e7198e
5 changed files with 61 additions and 44 deletions

View file

@ -907,7 +907,7 @@ func doZoomIn(ctx context.Context, state *Peco, _ Event) {
}
// Already zoomed in?
if state.PreZoomBuffer() != nil {
if state.Zoom().Buffer() != nil {
state.Hub().SendStatusMsg(ctx, "Already zoomed in", 0)
return
}
@ -933,7 +933,7 @@ func doZoomIn(ctx context.Context, state *Peco, _ Event) {
// Save current state for ZoomOut
loc := state.Location()
curLineNo := loc.LineNumber()
state.SetPreZoomState(currentBuf, curLineNo)
state.Zoom().Set(currentBuf, curLineNo)
// Map cursor to the new context buffer position
newLineNo := 0
@ -942,9 +942,7 @@ func doZoomIn(ctx context.Context, state *Peco, _ Event) {
newLineNo = indices[curLineNo]
}
state.mutex.Lock()
state.currentLineBuffer = contextBuf
state.mutex.Unlock()
state.setCurrentLineBufferNoNotify(contextBuf)
loc.SetLineNumber(newLineNo)
state.Hub().SendDraw(ctx, &hub.DrawOptions{DisableCache: true})
@ -956,21 +954,19 @@ func doZoomOut(ctx context.Context, state *Peco, _ Event) {
defer g.End()
}
preZoom := state.PreZoomBuffer()
preZoom := state.Zoom().Buffer()
if preZoom == nil {
state.Hub().SendStatusMsg(ctx, "Not zoomed in", 0)
return
}
loc := state.Location()
savedLineNo := state.PreZoomLineNo()
savedLineNo := state.Zoom().LineNo()
state.mutex.Lock()
state.currentLineBuffer = preZoom
state.mutex.Unlock()
state.setCurrentLineBufferNoNotify(preZoom)
loc.SetLineNumber(savedLineNo)
state.ClearPreZoomState()
state.Zoom().Clear()
state.Hub().SendDraw(ctx, &hub.DrawOptions{DisableCache: true})
}

View file

@ -1019,8 +1019,8 @@ func TestDoZoomInOut(t *testing.T) {
require.True(t, isCtx, "current buffer should be ContextBuffer after ZoomIn")
// Pre-zoom state should be saved
require.Equal(t, filtered, state.PreZoomBuffer(), "preZoomBuffer should be the filtered buffer")
require.Equal(t, 0, state.PreZoomLineNo(), "preZoomLineNo should be 0")
require.Equal(t, filtered, state.Zoom().Buffer(), "preZoomBuffer should be the filtered buffer")
require.Equal(t, 0, state.Zoom().LineNo(), "preZoomLineNo should be 0")
// Should have sent a draw
drawArgs := rHub.getDrawArgs()
@ -1049,7 +1049,7 @@ func TestDoZoomInOut(t *testing.T) {
require.Equal(t, 0, state.Location().LineNumber(), "cursor should be restored")
// Pre-zoom state should be cleared
require.Nil(t, state.PreZoomBuffer(), "preZoomBuffer should be nil after ZoomOut")
require.Nil(t, state.Zoom().Buffer(), "preZoomBuffer should be nil after ZoomOut")
// Should have sent a draw
drawArgs := rHub.getDrawArgs()
@ -1069,7 +1069,7 @@ func TestDoZoomInOut(t *testing.T) {
require.Equal(t, "Nothing to zoom into", statusMsgs[0])
// PreZoom should not be set
require.Nil(t, state.PreZoomBuffer())
require.Nil(t, state.Zoom().Buffer())
})
t.Run("ZoomOut when not zoomed", func(t *testing.T) {

View file

@ -120,11 +120,7 @@ type Peco struct {
// "freezes" the current results to filter on top of them.
frozenSource *MemoryBuffer
// preZoomBuffer holds the filtered buffer before ZoomIn was applied,
// so ZoomOut can restore it. nil means not zoomed.
preZoomBuffer Buffer
// preZoomLineNo holds the cursor position before ZoomIn was applied.
preZoomLineNo int
zoom ZoomState
// cancelFunc is called for Exit()
cancelFunc func()

31
peco.go
View file

@ -225,34 +225,17 @@ func (p *Peco) ClearFrozenSource() {
p.frozenSource = nil
}
// PreZoomBuffer returns the saved buffer from before ZoomIn, or nil if not zoomed.
func (p *Peco) PreZoomBuffer() Buffer {
p.mutex.Lock()
defer p.mutex.Unlock()
return p.preZoomBuffer
func (p *Peco) Zoom() *ZoomState {
return &p.zoom
}
// SetPreZoomState saves the current buffer and cursor position before zooming in.
func (p *Peco) SetPreZoomState(buf Buffer, lineNo int) {
// setCurrentLineBufferNoNotify sets the current line buffer under p.mutex
// without sending a draw event. Used by ZoomIn/ZoomOut where the caller
// manages draw notifications.
func (p *Peco) setCurrentLineBufferNoNotify(b Buffer) {
p.mutex.Lock()
defer p.mutex.Unlock()
p.preZoomBuffer = buf
p.preZoomLineNo = lineNo
}
// ClearPreZoomState clears the saved zoom state.
func (p *Peco) ClearPreZoomState() {
p.mutex.Lock()
defer p.mutex.Unlock()
p.preZoomBuffer = nil
p.preZoomLineNo = 0
}
// PreZoomLineNo returns the saved cursor position from before ZoomIn.
func (p *Peco) PreZoomLineNo() int {
p.mutex.Lock()
defer p.mutex.Unlock()
return p.preZoomLineNo
p.currentLineBuffer = b
}
func (p *Peco) Filters() *filter.Set {

42
zoom.go Normal file
View file

@ -0,0 +1,42 @@
package peco
import "sync"
// ZoomState holds the saved buffer and cursor position from before
// a ZoomIn operation, so that ZoomOut can restore them. A nil buffer
// means not currently zoomed.
type ZoomState struct {
mutex sync.Mutex
buffer Buffer
lineNo int
}
// Buffer returns the saved buffer from before ZoomIn, or nil if not zoomed.
func (z *ZoomState) Buffer() Buffer {
z.mutex.Lock()
defer z.mutex.Unlock()
return z.buffer
}
// LineNo returns the saved cursor position from before ZoomIn.
func (z *ZoomState) LineNo() int {
z.mutex.Lock()
defer z.mutex.Unlock()
return z.lineNo
}
// Set saves the current buffer and cursor position before zooming in.
func (z *ZoomState) Set(buf Buffer, lineNo int) {
z.mutex.Lock()
defer z.mutex.Unlock()
z.buffer = buf
z.lineNo = lineNo
}
// Clear clears the saved zoom state.
func (z *ZoomState) Clear() {
z.mutex.Lock()
defer z.mutex.Unlock()
z.buffer = nil
z.lineNo = 0
}