config.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package main
  2. import (
  3. "os"
  4. "path/filepath"
  5. "github.com/charmbracelet/bubbles/textinput"
  6. "github.com/pelletier/go-toml/v2"
  7. )
  8. // Constants for file permissions
  9. const (
  10. configDirPerm = 0755
  11. configFilePerm = 0600
  12. )
  13. // config holds the application configuration.
  14. type config struct {
  15. Email string `toml:"email"`
  16. }
  17. // configPath returns the path to the configuration file, following XDG config directory conventions.
  18. func configPath() (string, error) {
  19. xdgConfigHome := os.Getenv("XDG_CONFIG_HOME")
  20. var configDir string
  21. if xdgConfigHome != "" {
  22. configDir = filepath.Join(xdgConfigHome, "sdm-tui")
  23. } else {
  24. homeDir, err := os.UserHomeDir()
  25. if err != nil {
  26. return "", err
  27. }
  28. configDir = filepath.Join(homeDir, ".config", "sdm-tui")
  29. }
  30. return filepath.Join(configDir, "config.toml"), nil
  31. }
  32. // saveConfig saves the email to the configuration file.
  33. func saveConfig(email string) error {
  34. configPath, err := configPath()
  35. if err != nil {
  36. return err
  37. }
  38. if err := os.MkdirAll(filepath.Dir(configPath), configDirPerm); err != nil {
  39. return err
  40. }
  41. cfg := config{Email: email}
  42. data, err := toml.Marshal(cfg)
  43. if err != nil {
  44. return err
  45. }
  46. return os.WriteFile(configPath, data, configFilePerm)
  47. }
  48. // loadConfig loads the email from the configuration file.
  49. // It also handles migration from the old "email" file format to the new TOML format.
  50. func loadConfig() string {
  51. configPath, err := configPath()
  52. if err != nil {
  53. return ""
  54. }
  55. data, err := os.ReadFile(configPath)
  56. if err != nil {
  57. oldEmailPath := filepath.Join(filepath.Dir(configPath), "email")
  58. if oldData, err := os.ReadFile(oldEmailPath); err == nil {
  59. email := string(oldData)
  60. if email != "" {
  61. if err := saveConfig(email); err == nil {
  62. os.Remove(oldEmailPath)
  63. }
  64. }
  65. return email
  66. }
  67. return ""
  68. }
  69. var cfg config
  70. if err := toml.Unmarshal(data, &cfg); err != nil {
  71. return ""
  72. }
  73. return cfg.Email
  74. }
  75. // loadEmailIntoInput loads a saved email into the text input and returns whether an email was found.
  76. func loadEmailIntoInput(ti textinput.Model) (textinput.Model, bool) {
  77. savedEmail := loadConfig()
  78. if savedEmail != "" {
  79. ti.SetValue(savedEmail)
  80. return ti, true
  81. }
  82. return ti, false
  83. }