diff --git a/cmd/statusbar/main.go b/cmd/statusbar/main.go new file mode 100644 index 0000000..c472d0a --- /dev/null +++ b/cmd/statusbar/main.go @@ -0,0 +1,98 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log/slog" + "os" + "os/signal" + "path/filepath" + "syscall" + "time" + + "code.chimeric.al/dwrz/statusbar/cmd/statusbar/config" + "code.chimeric.al/dwrz/statusbar/internal/statusbar" +) + +var once = flag.Bool("1", false, "print output once") + +// TODO: block labels; rendered in case of error. +func main() { + flag.Parse() + + var log = slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{ + AddSource: true, + Level: slog.LevelDebug, + })) + + // Setup the main context. + // The context cancels on SIGINT or SIGTERM. + ctx, stop := signal.NotifyContext( + context.Background(), + syscall.SIGINT, + syscall.SIGTERM, + ) + defer stop() + + if err := run(ctx, log); err != nil { + log.Error("failed", slog.Any("error", err)) + os.Exit(1) + } +} + +func run(ctx context.Context, log *slog.Logger) error { + // Setup workspace and log file. + cdir, err := os.UserCacheDir() + if err != nil { + return fmt.Errorf( + "failed to determine user cache directory: %w", err, + ) + } + wdir := filepath.Join(cdir, "statusbar") + + if err := os.MkdirAll(wdir, os.ModeDir|0700); err != nil { + return fmt.Errorf("failed to create tmp dir: %w", err) + } + + flog, err := os.Create(filepath.Join(wdir, "log")) + if err != nil { + return fmt.Errorf("failed to create log file: %w", err) + } + defer flog.Close() + + var barLog = slog.New(slog.NewTextHandler(flog, &slog.HandlerOptions{ + AddSource: true, + Level: slog.LevelDebug, + })) + + // Load the config and create the blocks. + cfg, blocks, err := config.Load() + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + var bar = statusbar.New(statusbar.Parameters{ + Blocks: blocks, + Log: barLog, + Separator: cfg.Separator, + }) + + // Initial print. + fmt.Println(bar.Render(ctx)) + if *once { + return nil + } + + // Main loop. + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return nil + case <-ticker.C: + fmt.Println(bar.Render(ctx)) + } + } +}