@@ -2,18 +2,22 @@ package main
22
33import (
44 "errors"
5+ "fmt"
56 "os"
7+ "path/filepath"
68 "strings"
79
810 "github.com/go-ini/ini"
911 log "github.com/sirupsen/logrus"
1012)
1113
12- var defaultConfigContent = `[settings]
13- viewer = vim
14- feed_directory = ~/rssnix
15-
16- [feeds]`
14+ const (
15+ configEnvVar = "RSSNIX_CONFIG_HOME"
16+ defaultConfigDir = ".config/rssnix"
17+ configFileName = "config.ini"
18+ defaultViewer = "vim"
19+ defaultFeedDirectory = "~/rssnix"
20+ )
1721
1822type Configuration struct {
1923 FeedDirectory string
@@ -23,43 +27,129 @@ type Configuration struct {
2327
2428var Config Configuration
2529
26- func LoadConfig () {
30+ func LoadConfig () error {
2731 homePath , err := os .UserHomeDir ()
2832 if err != nil {
29- log .Error ("Failed to get home path" )
30- os .Exit (1 )
33+ return fmt .Errorf ("resolve home directory: %w" , err )
34+ }
35+
36+ cfgDir , err := resolveConfigDir (homePath )
37+ if err != nil {
38+ return err
3139 }
3240
33- if _ , err := os .Stat (homePath + "/.config/rssnix/config.ini" ); errors .Is (err , os .ErrNotExist ) {
41+ if err := os .MkdirAll (cfgDir , 0o755 ); err != nil {
42+ return fmt .Errorf ("ensure config directory %q: %w" , cfgDir , err )
43+ }
44+
45+ cfgPath := filepath .Join (cfgDir , configFileName )
46+ if _ , err := os .Stat (cfgPath ); errors .Is (err , os .ErrNotExist ) {
3447 log .Warn ("Config file does not exist, creating..." )
48+ if err := createDefaultConfig (cfgPath ); err != nil {
49+ return fmt .Errorf ("create default config: %w" , err )
50+ }
51+ log .Infof ("Config file created at %s" , cfgPath )
52+ } else if err != nil {
53+ return fmt .Errorf ("stat config file: %w" , err )
54+ }
55+
56+ cfg , err := ini .Load (cfgPath )
57+ if err != nil {
58+ return fmt .Errorf ("load config: %w" , err )
59+ }
60+
61+ Config = Configuration {}
62+ settings := cfg .Section ("settings" )
63+
64+ feedDirValue := strings .TrimSpace (settings .Key ("feed_directory" ).String ())
65+ if feedDirValue == "" {
66+ feedDirValue = defaultFeedDirectory
67+ }
68+ Config .FeedDirectory = expandPath (feedDirValue , homePath )
69+ if err := os .MkdirAll (Config .FeedDirectory , 0o755 ); err != nil {
70+ return fmt .Errorf ("ensure feed directory %q: %w" , Config .FeedDirectory , err )
71+ }
3572
36- os .MkdirAll (homePath + "/.config/rssnix" , 0777 )
37- file , err := os .Create (homePath + "/.config/rssnix/config.ini" )
38- if err != nil {
39- log .Error ("Failed to create a config file" )
40- os .Exit (1 )
73+ viewer := strings .TrimSpace (settings .Key ("viewer" ).String ())
74+ if viewer == "" {
75+ viewer = defaultViewer
76+ }
77+ Config .Viewer = viewer
78+
79+ feedsSection := cfg .Section ("feeds" )
80+ for _ , key := range feedsSection .Keys () {
81+ name := strings .TrimSpace (key .Name ())
82+ if name == "" {
83+ continue
4184 }
42- defer file .Close ()
4385
44- _ , err = file . WriteString ( defaultConfigContent )
45- if err != nil {
46- log .Error ( "Failed to create a config file " )
47- os . Exit ( 1 )
86+ url := strings . TrimSpace ( key . String () )
87+ if url == "" {
88+ log .WithField ( "feed" , name ). Warn ( "Feed has empty URL; skipping " )
89+ continue
4890 }
4991
50- log . Info ( " Config file created at " + homePath + "/.config/rssnix/config.ini" )
92+ Config . Feeds = append ( Config . Feeds , Feed { Name : name , URL : url } )
5193 }
5294
53- cfg , err := ini .Load (homePath + "/.config/rssnix/config.ini" )
95+ if len (Config .Feeds ) == 0 {
96+ log .Warn ("No feeds configured; use `rssnix add` or `rssnix import` to add feeds" )
97+ }
5498
55- Config = Configuration {}
56- Config .FeedDirectory = cfg .Section ("settings" ).Key ("feed_directory" ).String ()
57- if strings .HasPrefix (Config .FeedDirectory , "~" ) {
58- Config .FeedDirectory = homePath + Config .FeedDirectory [1 :]
99+ return nil
100+ }
101+
102+ func resolveConfigDir (home string ) (string , error ) {
103+ override := strings .TrimSpace (os .Getenv (configEnvVar ))
104+ if override == "" {
105+ return filepath .Join (home , defaultConfigDir ), nil
106+ }
107+
108+ override = expandPath (override , home )
109+ if ! filepath .IsAbs (override ) {
110+ override = filepath .Join (home , override )
111+ }
112+ return override , nil
113+ }
114+
115+ func expandPath (path , home string ) string {
116+ if path == "~" {
117+ return home
59118 }
60- os .MkdirAll (Config .FeedDirectory , 0777 )
61- Config .Viewer = cfg .Section ("settings" ).Key ("viewer" ).String ()
62- for _ , key := range cfg .Section ("feeds" ).Keys () {
63- Config .Feeds = append (Config .Feeds , Feed {key .Name (), key .String ()})
119+ if strings .HasPrefix (path , "~/" ) {
120+ return filepath .Join (home , path [2 :])
121+ }
122+ return path
123+ }
124+
125+ func createDefaultConfig (path string ) error {
126+ cfg := ini .Empty ()
127+ settings := cfg .Section ("settings" )
128+ settings .Key ("viewer" ).SetValue (defaultViewer )
129+ settings .Key ("feed_directory" ).SetValue (defaultFeedDirectory )
130+ cfg .Section ("feeds" )
131+ return cfg .SaveTo (path )
132+ }
133+
134+ func configFilePath () (string , error ) {
135+ homePath , err := os .UserHomeDir ()
136+ if err != nil {
137+ return "" , fmt .Errorf ("resolve home directory: %w" , err )
138+ }
139+
140+ cfgDir , err := resolveConfigDir (homePath )
141+ if err != nil {
142+ return "" , err
143+ }
144+
145+ return filepath .Join (cfgDir , configFileName ), nil
146+ }
147+
148+ func (c * Configuration ) FeedByName (name string ) (Feed , bool ) {
149+ for _ , feed := range c .Feeds {
150+ if feed .Name == name {
151+ return feed , true
152+ }
64153 }
154+ return Feed {}, false
65155}
0 commit comments