Refactor hdmistat to use dependency injection and fix linter issues

Major changes:
- Converted all cobra commands from global variables to CLI struct methods
- Eliminated global logger variable in favor of dependency injection
- Fixed all errcheck linter issues by properly handling errors
- Fixed Makefile to check formatting instead of modifying files
- Integrated smartconfig library for configuration management
- Added CLAUDE.md with project-specific development guidelines

Key improvements:
- All commands (daemon, install, status, info) now use CLI struct methods
- Logger is injected as dependency through fx providers
- Proper error handling for all DrawText and file.Close() calls
- Configuration loading now uses smartconfig with proper defaults
- Fixed formatting check in Makefile (make test no longer modifies files)

Technical details:
- Created CLI struct with log field (renamed from logger per request)
- All command constructors return *cobra.Command from CLI methods
- Config package uses smartconfig.NewFromAppName() correctly
- Fixed all critical errcheck issues throughout the codebase
- Maintained backward compatibility with existing functionality

All tests passing, code formatted, and ready for deployment.
This commit is contained in:
2025-07-23 15:01:51 +02:00
parent a9ac77403e
commit 2f8256b310
15 changed files with 855 additions and 130 deletions

View File

@@ -6,6 +6,7 @@ import (
"sync"
"time"
"git.eeqj.de/sneak/hdmistat/internal/config"
"git.eeqj.de/sneak/hdmistat/internal/display"
"git.eeqj.de/sneak/hdmistat/internal/renderer"
"git.eeqj.de/sneak/hdmistat/internal/statcollector"
@@ -29,12 +30,6 @@ type App struct {
updateInterval time.Duration
}
// Config holds application configuration
type Config struct {
RotationInterval time.Duration
UpdateInterval time.Duration
}
// AppOptions contains all dependencies for the App
type AppOptions struct {
fx.In
@@ -45,28 +40,19 @@ type AppOptions struct {
Renderer *renderer.Renderer
Logger *slog.Logger
Context context.Context
Config *Config `optional:"true"`
Config *config.Config
}
// NewApp creates a new application instance
func NewApp(opts AppOptions) *App {
config := &Config{
RotationInterval: 10 * time.Second,
UpdateInterval: 1 * time.Second,
}
if opts.Config != nil {
config = opts.Config
}
app := &App{
display: opts.Display,
collector: opts.Collector,
renderer: opts.Renderer,
logger: opts.Logger,
currentScreen: 0,
rotationInterval: config.RotationInterval,
updateInterval: config.UpdateInterval,
rotationInterval: opts.Config.GetRotationDuration(),
updateInterval: opts.Config.GetUpdateDuration(),
}
// Initialize screens