Skip to content

Commit

Permalink
feat: expose the renderer interface
Browse files Browse the repository at this point in the history
This adds the ability to use a custom renderer using a modified version
of the existing `renderer` interface.
  • Loading branch information
aymanbagabas committed Aug 20, 2024
1 parent e206b36 commit 6f7f9e6
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 238 deletions.
27 changes: 15 additions & 12 deletions nil_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ package tea

type nilRenderer struct{}

func (nilRenderer) start() {}
func (nilRenderer) stop() {}
func (nilRenderer) kill() {}
func (nilRenderer) write(string) {}
func (nilRenderer) repaint() {}
func (nilRenderer) clearScreen() {}
func (nilRenderer) altScreen() bool { return false }
func (nilRenderer) enterAltScreen() {}
func (nilRenderer) exitAltScreen() {}
func (nilRenderer) showCursor() {}
func (nilRenderer) hideCursor() {}
func (nilRenderer) execute(string) {}
var _ Renderer = nilRenderer{}

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) {}
19 changes: 7 additions & 12 deletions nil_renderer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@ import "testing"

func TestNilRenderer(t *testing.T) {
r := nilRenderer{}
r.start()
r.stop()
r.kill()
r.write("a")
r.repaint()
r.enterAltScreen()
if r.altScreen() {
r.Repaint()
r.EnterAltScreen()
if r.AltScreen() {
t.Errorf("altScreen should always return false")
}
r.exitAltScreen()
r.clearScreen()
r.showCursor()
r.hideCursor()
r.execute("")
r.ExitAltScreen()
r.ClearScreen()
r.ShowCursor()
r.HideCursor()
}
47 changes: 25 additions & 22 deletions renderer.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,46 @@
package tea

// renderer is the interface for Bubble Tea renderers.
type renderer interface {
// Start the renderer.
start()

// Stop the renderer, but render the final frame in the buffer, if any.
stop()

// Stop the renderer without doing any final rendering.
kill()
// Renderer is the interface for Bubble Tea renderers.
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(string)
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)

// Flush flushes the renderer's buffer to the output.
Flush() error

// Request a full re-render. Note that this will not trigger a render
// immediately. Rather, this method causes the next render to be a full
// repaint. Because of this, it's safe to call this method multiple times
// Repaint. Because of this, it's safe to call this method multiple times
// in succession.
repaint()
Repaint()

// Clears the terminal.
clearScreen()
// ClearScreen clear the terminal screen.
ClearScreen()

// Whether or not the alternate screen buffer is enabled.
altScreen() bool
AltScreen() bool
// Enable the alternate screen buffer.
enterAltScreen()
EnterAltScreen()
// Disable the alternate screen buffer.
exitAltScreen()
ExitAltScreen()

// CursorVisibility returns whether the cursor is visible.
CursorVisibility() bool
// Show the cursor.
showCursor()
ShowCursor()
// Hide the cursor.
hideCursor()
HideCursor()

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

// repaintMsg forces a full repaint.
Expand Down
14 changes: 7 additions & 7 deletions screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func DisabledReportFocus() Msg { return disableReportFocusMsg{} }
// Deprecated: Use the WithAltScreen ProgramOption instead.
func (p *Program) EnterAltScreen() {
if p.renderer != nil {
p.renderer.enterAltScreen()
p.renderer.EnterAltScreen()
} else {
p.startupOptions |= withAltScreen
}
Expand All @@ -179,7 +179,7 @@ func (p *Program) EnterAltScreen() {
// Deprecated: The altscreen will exited automatically when the program exits.
func (p *Program) ExitAltScreen() {
if p.renderer != nil {
p.renderer.exitAltScreen()
p.renderer.ExitAltScreen()
} else {
p.startupOptions &^= withAltScreen
}
Expand All @@ -191,7 +191,7 @@ func (p *Program) ExitAltScreen() {
// Deprecated: Use the WithMouseCellMotion ProgramOption instead.
func (p *Program) EnableMouseCellMotion() {
if p.renderer != nil {
p.renderer.execute(ansi.EnableMouseCellMotion)
p.renderer.Execute(ansi.EnableMouseCellMotion)
} else {
p.startupOptions |= withMouseCellMotion
}
Expand All @@ -203,7 +203,7 @@ func (p *Program) EnableMouseCellMotion() {
// Deprecated: The mouse will automatically be disabled when the program exits.
func (p *Program) DisableMouseCellMotion() {
if p.renderer != nil {
p.renderer.execute(ansi.DisableMouseCellMotion)
p.renderer.Execute(ansi.DisableMouseCellMotion)
} else {
p.startupOptions &^= withMouseCellMotion
}
Expand All @@ -216,7 +216,7 @@ func (p *Program) DisableMouseCellMotion() {
// Deprecated: Use the WithMouseAllMotion ProgramOption instead.
func (p *Program) EnableMouseAllMotion() {
if p.renderer != nil {
p.renderer.execute(ansi.EnableMouseAllMotion)
p.renderer.Execute(ansi.EnableMouseAllMotion)
} else {
p.startupOptions |= withMouseAllMotion
}
Expand All @@ -228,7 +228,7 @@ func (p *Program) EnableMouseAllMotion() {
// Deprecated: The mouse will automatically be disabled when the program exits.
func (p *Program) DisableMouseAllMotion() {
if p.renderer != nil {
p.renderer.execute(ansi.DisableMouseAllMotion)
p.renderer.Execute(ansi.DisableMouseAllMotion)
} else {
p.startupOptions &^= withMouseAllMotion
}
Expand All @@ -239,7 +239,7 @@ func (p *Program) DisableMouseAllMotion() {
// Deprecated: Use the SetWindowTitle command instead.
func (p *Program) SetWindowTitle(title string) {
if p.renderer != nil {
p.renderer.execute(ansi.SetWindowTitle(title))
p.renderer.Execute(ansi.SetWindowTitle(title))
} else {
p.startupTitle = title
}
Expand Down
Loading

0 comments on commit 6f7f9e6

Please sign in to comment.