mirror of
https://github.com/Gu1llaum-3/sshm.git
synced 2025-10-19 01:17:20 +02:00
- Add unified application configuration system with JSON config file - Implement configurable quit keys (default: "q", "ctrl+c") - Add disable_esc_quit option for vim users to prevent accidental exits - Auto-create default config file at ~/.config/sshm/config.json - Maintain backward compatibility (ESC quit enabled by default) - Include comprehensive tests and documentation
146 lines
3.6 KiB
Go
146 lines
3.6 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 {
|
|
KeyBindings KeyBindings `json:"key_bindings"`
|
|
}
|
|
|
|
// 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
|
|
} |