Files
sshm/internal/config/appconfig.go
Gu1llaum-3 f189cb37e3 feat: add --no-update-check flag and disable update check via config (issue #23)
Add support for disabling the automatic update check at startup, which could cause delays on air-gapped or offline machines due to DNS timeouts.

- Add --no-update-check CLI flag for one-time override
- Add check_for_updates field (*bool) to AppConfig with default true
- CLI flag overrides the config file setting (both feed into IsUpdateCheckEnabled)
- Move update check from --version template to TUI Init() only, respecting the new configuration
- Remove getVersionWithUpdateCheck() from cmd/root.go; --version now prints a plain version string
- Rename internal/config/keybindings.go → appconfig.go and keybindings_test.go → appconfig_test.go to reflect the broader scope of the file
- Add TestIsUpdateCheckEnabled with table-driven cases (nil config, nil field, true, false) and extend existing integration test with a CheckForUpdates round-trip
- Update README: document --no-update-check flag, config option, and rename "Custom Key Bindings" section to "Application Configuration"
2026-02-23 21:28:54 +01:00

155 lines
3.9 KiB
Go

package config
import (
"encoding/json"
"errors"
"os"
"path/filepath"
)
// KeyBindings represents configurable key bindings for the application
type KeyBindings struct {
// Quit keys - keys that will quit the application
QuitKeys []string `json:"quit_keys"`
// DisableEscQuit - if true, ESC key won't quit the application (useful for vim users)
DisableEscQuit bool `json:"disable_esc_quit"`
}
// AppConfig represents the main application configuration
type AppConfig struct {
CheckForUpdates *bool `json:"check_for_updates,omitempty"`
KeyBindings KeyBindings `json:"key_bindings"`
}
// IsUpdateCheckEnabled returns true if the update check is enabled (default: true)
func (c *AppConfig) IsUpdateCheckEnabled() bool {
if c == nil || c.CheckForUpdates == nil {
return true
}
return *c.CheckForUpdates
}
// GetDefaultKeyBindings returns the default key bindings configuration
func GetDefaultKeyBindings() KeyBindings {
return KeyBindings{
QuitKeys: []string{"q", "ctrl+c"}, // Default keeps current behavior minus ESC
DisableEscQuit: false, // Default to false for backward compatibility
}
}
// GetDefaultAppConfig returns the default application configuration
func GetDefaultAppConfig() AppConfig {
return AppConfig{
KeyBindings: GetDefaultKeyBindings(),
}
}
// GetAppConfigPath returns the path to the application config file
func GetAppConfigPath() (string, error) {
configDir, err := GetSSHMConfigDir()
if err != nil {
return "", err
}
return filepath.Join(configDir, "config.json"), nil
}
// LoadAppConfig loads the application configuration from file
// If the file doesn't exist, it returns the default configuration
func LoadAppConfig() (*AppConfig, error) {
configPath, err := GetAppConfigPath()
if err != nil {
return nil, err
}
// If config file doesn't exist, return default config and create the file
if _, err := os.Stat(configPath); os.IsNotExist(err) {
defaultConfig := GetDefaultAppConfig()
// Create config directory if it doesn't exist
configDir := filepath.Dir(configPath)
if err := os.MkdirAll(configDir, 0755); err != nil {
return nil, err
}
// Save default config to file
if err := SaveAppConfig(&defaultConfig); err != nil {
// If we can't save, just return the default config without erroring
// This allows the app to work even if config file can't be created
return &defaultConfig, nil
}
return &defaultConfig, nil
}
// Read existing config file
data, err := os.ReadFile(configPath)
if err != nil {
return nil, err
}
var config AppConfig
if err := json.Unmarshal(data, &config); err != nil {
return nil, err
}
// Validate and fill in missing fields with defaults
config = mergeWithDefaults(config)
return &config, nil
}
// SaveAppConfig saves the application configuration to file
func SaveAppConfig(config *AppConfig) error {
if config == nil {
return errors.New("config cannot be nil")
}
configPath, err := GetAppConfigPath()
if err != nil {
return err
}
// Create config directory if it doesn't exist
configDir := filepath.Dir(configPath)
if err := os.MkdirAll(configDir, 0755); err != nil {
return err
}
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
return os.WriteFile(configPath, data, 0644)
}
// mergeWithDefaults ensures all required fields are set with defaults if missing
func mergeWithDefaults(config AppConfig) AppConfig {
defaults := GetDefaultAppConfig()
// If QuitKeys is empty, use defaults
if len(config.KeyBindings.QuitKeys) == 0 {
config.KeyBindings.QuitKeys = defaults.KeyBindings.QuitKeys
}
return config
}
// ShouldQuitOnKey checks if the given key should trigger quit based on configuration
func (kb *KeyBindings) ShouldQuitOnKey(key string) bool {
// Special handling for ESC key
if key == "esc" {
return !kb.DisableEscQuit
}
// Check if key is in the quit keys list
for _, quitKey := range kb.QuitKeys {
if quitKey == key {
return true
}
}
return false
}