From c2bb5bb61775e72b373b54aecbc6f5c33945f53f Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 25 Oct 2022 19:51:53 +0300 Subject: [PATCH] (feat): Add option to set max FPS Added the `WithMaxFPS` option to bubbletea program struct, if it is set with a non 0 value it will set the maximum interval at which the view is updated, if it is not set or set to 0, the interval will be the `defaultFramerate` constant. --- options.go | 12 ++++++++++++ standard_renderer.go | 9 +++++++-- tea.go | 7 ++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/options.go b/options.go index 30f7e6c..31c6612 100644 --- a/options.go +++ b/options.go @@ -3,6 +3,7 @@ package tea import ( "context" "io" + "time" "github.com/muesli/termenv" ) @@ -200,3 +201,14 @@ func WithFilter(filter func(Model, Msg) Msg) ProgramOption { p.filter = filter } } + +// WithMaxFPS sets a custom maximum FPS at which we should +// update the view. +func WithMaxFPS(fps uint) ProgramOption { + if fps > maxFPS { + fps = maxFPS + } + return func(p *Program) { + p.framerate = time.Second / time.Duration(fps) + } +} diff --git a/standard_renderer.go b/standard_renderer.go index e4fb61c..6ec6873 100644 --- a/standard_renderer.go +++ b/standard_renderer.go @@ -17,6 +17,8 @@ const ( // defaultFramerate specifies the maximum interval at which we should // update the view. defaultFramerate = time.Second / 60 + + maxFPS = 120 ) // standardRenderer is a framerate-based terminal renderer, updating the view @@ -54,12 +56,15 @@ type standardRenderer struct { // newRenderer creates a new renderer. Normally you'll want to initialize it // with os.Stdout as the first argument. -func newRenderer(out *termenv.Output, useANSICompressor bool) renderer { +func newRenderer(out *termenv.Output, useANSICompressor bool, framerate time.Duration) renderer { + if framerate == 0 { + framerate = defaultFramerate + } r := &standardRenderer{ out: out, mtx: &sync.Mutex{}, done: make(chan struct{}), - framerate: defaultFramerate, + framerate: framerate, useANSICompressor: useANSICompressor, queuedMessageLines: []string{}, } diff --git a/tea.go b/tea.go index ca24eac..13131c5 100644 --- a/tea.go +++ b/tea.go @@ -19,6 +19,7 @@ import ( "runtime/debug" "sync" "syscall" + "time" "github.com/containerd/console" isatty "github.com/mattn/go-isatty" @@ -144,6 +145,10 @@ type Program struct { windowsStdin *os.File //nolint:golint,structcheck,unused filter func(Model, Msg) Msg + + // framerate specifies a custom maximum interval at which we should + // update the view. If it is 0, the default value is used. + framerate time.Duration } // Quit is a special command that tells the Bubble Tea program to exit. @@ -441,7 +446,7 @@ func (p *Program) Run() (Model, error) { // If no renderer is set use the standard one. if p.renderer == nil { - p.renderer = newRenderer(p.output, p.startupOptions.has(withANSICompressor)) + p.renderer = newRenderer(p.output, p.startupOptions.has(withANSICompressor), p.framerate) } // Check if output is a TTY before entering raw mode, hiding the cursor and