Skip to content

Commit

Permalink
Allow specifying duration for --ref-rate/-r flag
Browse files Browse the repository at this point in the history
This commit changes the --ref-rate/-r flag so that it accepts both an
integer in seconds (original behavior) and a custom duration string (new
behavior). This lets the user draw the UI at a higher refresh rate such
as 30fps.

It also makes a minor change in src/tui/proc-table.go, changing from
using `time.After` to `time.Ticker` to make the code slightly more
performant.
  • Loading branch information
diamondburned authored and F1bonacc1 committed May 8, 2024
1 parent a5d39a7 commit aa251ae
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/cmd/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var attachCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(attachCmd)
attachCmd.Flags().IntVarP(pcFlags.RefreshRate, "ref-rate", "r", *pcFlags.RefreshRate, "TUI refresh rate in seconds")
attachCmd.Flags().VarP(refreshRateFlag{pcFlags.RefreshRate}, "ref-rate", "r", "TUI refresh rate in seconds or as a Go duration string (e.g. 1s)")
attachCmd.Flags().StringVarP(pcFlags.Address, "address", "a", *pcFlags.Address, "address of the target process compose server")
attachCmd.Flags().IntVarP(pcFlags.LogLength, "log-length", "l", *pcFlags.LogLength, "log length to display in TUI")
attachCmd.Flags().AddFlag(commonFlags.Lookup(flagReverse))
Expand Down
3 changes: 1 addition & 2 deletions src/cmd/project_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"os"
"os/signal"
"syscall"
"time"
)

func getProjectRunner(process []string, noDeps bool, mainProcess string, mainProcessArgs []string) *app.ProjectRunner {
Expand Down Expand Up @@ -82,7 +81,7 @@ func runTui(project *app.ProjectRunner) int {

func startTui(runner app.IProject) {
tuiOptions := []tui.Option{
tui.WithRefreshRate(time.Duration(*pcFlags.RefreshRate) * time.Second),
tui.WithRefreshRate(*pcFlags.RefreshRate),
}
if !*pcFlags.IsReadOnlyMode {
config.CreateProcCompHome()
Expand Down
37 changes: 36 additions & 1 deletion src/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"os"
"path"
"runtime"
"strconv"
"time"
)

Expand Down Expand Up @@ -72,7 +73,7 @@ func init() {
rootCmd.PersistentFlags().BoolVar(pcFlags.NoServer, "no-server", *pcFlags.NoServer, "disable HTTP server (env: "+config.EnvVarNameNoServer+")")
rootCmd.PersistentFlags().BoolVar(pcFlags.IsOrderedShutDown, "ordered-shutdown", *pcFlags.IsOrderedShutDown, "shut down processes in reverse dependency order")
rootCmd.Flags().BoolVarP(pcFlags.HideDisabled, "hide-disabled", "d", *pcFlags.HideDisabled, "hide disabled processes")
rootCmd.Flags().IntVarP(pcFlags.RefreshRate, "ref-rate", "r", *pcFlags.RefreshRate, "TUI refresh rate in seconds")
rootCmd.Flags().VarP(refreshRateFlag{pcFlags.RefreshRate}, "ref-rate", "r", "TUI refresh rate in seconds or as a Go duration string (e.g. 1s)")
rootCmd.PersistentFlags().IntVarP(pcFlags.PortNum, "port", "p", *pcFlags.PortNum, "port number (env: "+config.EnvVarNamePort+")")
rootCmd.Flags().StringArrayVarP(&opts.FileNames, "config", "f", config.GetConfigDefault(), "path to config files to load (env: "+config.EnvVarNameConfig+")")
rootCmd.Flags().StringArrayVarP(&nsAdmitter.EnabledNamespaces, "namespace", "n", nil, "run only specified namespaces (default all)")
Expand Down Expand Up @@ -159,3 +160,37 @@ func isUnixSocketMode(cmd *cobra.Command) bool {
os.Getenv(config.EnvVarUnixSocketPath) != "" ||
cmd.Flags().Changed("unix-socket")
}

// refreshRateFlag is a custom flag type for the TUI's refresh rate.
// It accepts both an integer in seconds and a duration string.
type refreshRateFlag struct {
dst *time.Duration
}

func (f refreshRateFlag) String() string {
d := *f.dst
if d%time.Second == 0 {
return strconv.Itoa(int(d / time.Second))
}
return d.String()
}

func (f refreshRateFlag) Set(str string) error {
i, err := strconv.Atoi(str)
if err == nil {
*f.dst = time.Duration(i) * time.Second
return nil
}
d, err := time.ParseDuration(str)
if err == nil {
*f.dst = d
return nil
}
return fmt.Errorf(
"invalid refresh rate %q, must be a duration or an integer in seconds",
str)
}

func (f refreshRateFlag) Type() string {
return "duration"
}
5 changes: 3 additions & 2 deletions src/config/Flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package config

import (
"math"
"time"
)

const (
// DefaultRefreshRate represents the refresh interval.
DefaultRefreshRate = 1 // secs
DefaultRefreshRate = 1 * time.Second

// DefaultLogLevel represents the default log level.
DefaultLogLevel = "info"
Expand Down Expand Up @@ -38,7 +39,7 @@ const (

// Flags represents PC configuration flags.
type Flags struct {
RefreshRate *int
RefreshRate *time.Duration
PortNum *int
Address *string
LogLevel *string
Expand Down
4 changes: 3 additions & 1 deletion src/tui/proc-table.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,14 @@ func (pv *pcView) updateTable(ctx context.Context) {
pv.appView.QueueUpdateDraw(func() {
pv.fillTableData()
})
ticker := time.NewTicker(pv.refreshRate)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
log.Debug().Msg("Table monitoring canceled")
return
case <-time.After(pv.refreshRate):
case <-ticker.C:
pv.appView.QueueUpdateDraw(func() {
pv.fillTableData()
})
Expand Down

0 comments on commit aa251ae

Please sign in to comment.