Skip to content

Commit

Permalink
refactor: simplify renderer interface
Browse files Browse the repository at this point in the history
Use Render instead of Write/WriteString
  • Loading branch information
aymanbagabas committed Aug 20, 2024
1 parent 0825f61 commit 1f88b9e
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 128 deletions.
57 changes: 41 additions & 16 deletions nil_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,44 @@ type NilRenderer struct{}

var _ Renderer = NilRenderer{}

func (NilRenderer) SetOutput(io.Writer) {}
func (NilRenderer) Flush() error { return nil }
func (NilRenderer) Close() error { return nil }
func (NilRenderer) Write([]byte) (int, error) { return 0, nil }
func (NilRenderer) WriteString(string) (int, error) { return 0, nil }
func (NilRenderer) Repaint() {}
func (NilRenderer) ClearScreen() {}
func (NilRenderer) AltScreen() bool { return false }
func (NilRenderer) EnterAltScreen() {}
func (NilRenderer) ExitAltScreen() {}
func (NilRenderer) CursorVisibility() bool { return false }
func (NilRenderer) ShowCursor() {}
func (NilRenderer) HideCursor() {}
func (NilRenderer) Execute(string) {}
func (NilRenderer) InsertAbove(string) error { return nil }
func (NilRenderer) Resize(int, int) {}
// SetOutput implements the Renderer interface.
func (NilRenderer) SetOutput(io.Writer) {}

// Flush implements the Renderer interface.
func (NilRenderer) Flush() error { return nil }

// Close implements the Renderer interface.
func (NilRenderer) Close() error { return nil }

// Render implements the Renderer interface.
func (NilRenderer) Render(string) error { return nil }

// Repaint implements the Renderer interface.
func (NilRenderer) Repaint() {}

// ClearScreen implements the Renderer interface.
func (NilRenderer) ClearScreen() {}

// AltScreen implements the Renderer interface.
func (NilRenderer) AltScreen() bool { return false }

// EnterAltScreen implements the Renderer interface.
func (NilRenderer) EnterAltScreen() {}

// ExitAltScreen implements the Renderer interface.
func (NilRenderer) ExitAltScreen() {}

// CursorVisibility implements the Renderer interface.
func (NilRenderer) CursorVisibility() bool { return false }

// ShowCursor implements the Renderer interface.
func (NilRenderer) ShowCursor() {}

// HideCursor implements the Renderer interface.
func (NilRenderer) HideCursor() {}

// InsertAbove implements the Renderer interface.
func (NilRenderer) InsertAbove(string) error { return nil }

// Resize implements the Renderer interface.
func (NilRenderer) Resize(int, int) {}
12 changes: 2 additions & 10 deletions renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@ type Renderer interface {
// Close closes the renderer and flushes any remaining data.
Close() error

// Write a frame to the renderer. The renderer can write this data to
// output at its discretion.
Write([]byte) (int, error)

// WriteString a frame to the renderer. The renderer can WriteString this
// data to output at its discretion.
WriteString(string) (int, error)
// Render renders a frame to the output.
Render(string) error

// SetOutput sets the output for the renderer.
SetOutput(io.Writer)
Expand Down Expand Up @@ -50,9 +45,6 @@ type Renderer interface {
ShowCursor()
// Hide the cursor.
HideCursor()

// Execute writes a sequence to the underlying output.
Execute(string)
}

// repaintMsg forces a full repaint.
Expand Down
30 changes: 5 additions & 25 deletions screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,23 +190,15 @@ func (p *Program) ExitAltScreen() {
//
// Deprecated: Use the WithMouseCellMotion ProgramOption instead.
func (p *Program) EnableMouseCellMotion() {
if p.renderer != nil {
p.renderer.Execute(ansi.EnableMouseCellMotion)
} else {
p.startupOptions |= withMouseCellMotion
}
p.execute(ansi.EnableMouseCellMotion)
}

// DisableMouseCellMotion disables Mouse Cell Motion tracking. This will be
// called automatically when exiting a Bubble Tea program.
//
// Deprecated: The mouse will automatically be disabled when the program exits.
func (p *Program) DisableMouseCellMotion() {
if p.renderer != nil {
p.renderer.Execute(ansi.DisableMouseCellMotion)
} else {
p.startupOptions &^= withMouseCellMotion
}
p.execute(ansi.DisableMouseCellMotion)
}

// EnableMouseAllMotion enables mouse click, release, wheel and motion events,
Expand All @@ -215,32 +207,20 @@ func (p *Program) DisableMouseCellMotion() {
//
// Deprecated: Use the WithMouseAllMotion ProgramOption instead.
func (p *Program) EnableMouseAllMotion() {
if p.renderer != nil {
p.renderer.Execute(ansi.EnableMouseAllMotion)
} else {
p.startupOptions |= withMouseAllMotion
}
p.execute(ansi.EnableMouseAllMotion)
}

// DisableMouseAllMotion disables All Motion mouse tracking. This will be
// called automatically when exiting a Bubble Tea program.
//
// Deprecated: The mouse will automatically be disabled when the program exits.
func (p *Program) DisableMouseAllMotion() {
if p.renderer != nil {
p.renderer.Execute(ansi.DisableMouseAllMotion)
} else {
p.startupOptions &^= withMouseAllMotion
}
p.execute(ansi.DisableMouseAllMotion)
}

// SetWindowTitle sets the terminal window title.
//
// Deprecated: Use the SetWindowTitle command instead.
func (p *Program) SetWindowTitle(title string) {
if p.renderer != nil {
p.renderer.Execute(ansi.SetWindowTitle(title))
} else {
p.startupTitle = title
}
p.execute(ansi.SetWindowTitle(title))
}
47 changes: 21 additions & 26 deletions standard_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ func (r *standardRenderer) Close() (err error) {
r.mtx.Lock()
defer r.mtx.Unlock()

r.Execute(ansi.EraseEntireLine)
r.execute(ansi.EraseEntireLine)
// Move the cursor back to the beginning of the line
r.Execute("\r")
r.execute("\r")

return
}

// Execute writes a sequence to the terminal.
func (r *standardRenderer) Execute(seq string) {
// execute writes the given sequence to the output.
func (r *standardRenderer) execute(seq string) {
_, _ = io.WriteString(r.out, seq)
}

Expand Down Expand Up @@ -211,9 +211,9 @@ func (r *standardRenderer) Flush() (err error) {
return
}

// WriteString writes to the internal buffer. The buffer will be outputted via the
// ticker which calls flush().
func (r *standardRenderer) WriteString(s string) (int, error) {
// Render renders the frame to the internal buffer. The buffer will be
// outputted via the ticker which calls flush().
func (r *standardRenderer) Render(s string) error {
r.mtx.Lock()
defer r.mtx.Unlock()
r.buf.Reset()
Expand All @@ -226,13 +226,8 @@ func (r *standardRenderer) WriteString(s string) (int, error) {
s = " "
}

return r.buf.WriteString(s)
}

// Write writes to the internal buffer. The buffer will be outputted via the
// ticker which calls flush().
func (r *standardRenderer) Write(p []byte) (int, error) {
return r.WriteString(string(p))
_, err := r.buf.WriteString(s)
return err
}

// Repaint forces a full repaint.
Expand All @@ -244,8 +239,8 @@ func (r *standardRenderer) ClearScreen() {
r.mtx.Lock()
defer r.mtx.Unlock()

r.Execute(ansi.EraseEntireDisplay)
r.Execute(ansi.MoveCursorOrigin)
r.execute(ansi.EraseEntireDisplay)
r.execute(ansi.MoveCursorOrigin)

r.Repaint()
}
Expand All @@ -266,24 +261,24 @@ func (r *standardRenderer) EnterAltScreen() {
}

r.altScreenActive = true
r.Execute(ansi.EnableAltScreenBuffer)
r.execute(ansi.EnableAltScreenBuffer)

// Ensure that the terminal is cleared, even when it doesn't support
// alt screen (or alt screen support is disabled, like GNU screen by
// default).
//
// Note: we can't use r.clearScreen() here because the mutex is already
// locked.
r.Execute(ansi.EraseEntireDisplay)
r.Execute(ansi.MoveCursorOrigin)
r.execute(ansi.EraseEntireDisplay)
r.execute(ansi.MoveCursorOrigin)

// cmd.exe and other terminals keep separate cursor states for the AltScreen
// and the main buffer. We have to explicitly reset the cursor visibility
// whenever we enter AltScreen.
if r.cursorHidden {
r.Execute(ansi.HideCursor)
r.execute(ansi.HideCursor)
} else {
r.Execute(ansi.ShowCursor)
r.execute(ansi.ShowCursor)
}

r.Repaint()
Expand All @@ -298,15 +293,15 @@ func (r *standardRenderer) ExitAltScreen() {
}

r.altScreenActive = false
r.Execute(ansi.DisableAltScreenBuffer)
r.execute(ansi.DisableAltScreenBuffer)

// cmd.exe and other terminals keep separate cursor states for the AltScreen
// and the main buffer. We have to explicitly reset the cursor visibility
// whenever we exit AltScreen.
if r.cursorHidden {
r.Execute(ansi.HideCursor)
r.execute(ansi.HideCursor)
} else {
r.Execute(ansi.ShowCursor)
r.execute(ansi.ShowCursor)
}

r.Repaint()
Expand All @@ -321,15 +316,15 @@ func (r *standardRenderer) ShowCursor() {
defer r.mtx.Unlock()

r.cursorHidden = false
r.Execute(ansi.ShowCursor)
r.execute(ansi.ShowCursor)
}

func (r *standardRenderer) HideCursor() {
r.mtx.Lock()
defer r.mtx.Unlock()

r.cursorHidden = true
r.Execute(ansi.HideCursor)
r.execute(ansi.HideCursor)
}

// setIgnoredLines specifies lines not to be touched by the standard Bubble Tea
Expand Down
Loading

0 comments on commit 1f88b9e

Please sign in to comment.