package config import ( "fmt" "nilfm.cc/git/nirvash/adapter" "os" "path/filepath" "runtime" "strings" ) type Config struct { Adapter adapter.Adapter // adapter for this instance Root string // root of the site data StaticRoot string // root of static files for StaticFileManager AssetRoot string // root of Nirvash dist files (CSS, images) Plugins map[string]interface{} } func GetConfigLocation() string { home := os.Getenv("HOME") appdata := os.Getenv("APPDATA") switch runtime.GOOS { case "windows": return filepath.Join(appdata, "nirvash") case "darwin": return filepath.Join(home, "Library", "Application Support", "nirvash") case "plan9": return filepath.Join(home, "lib", "nirvash") default: return filepath.Join(home, ".config", "nirvash") } } func ensureConfigLocationExists() { _, err := os.Stat(GetConfigLocation()) if os.IsNotExist(err) { os.MkdirAll(GetConfigLocation(), os.ModePerm) } } func Read() *Config { ensureConfigLocationExists() return parseConfig(filepath.Join(GetConfigLocation(), "nirvash.conf")) } func Write(cfg *Config) error { ensureConfigLocationExists() return writeConfig(cfg, filepath.Join(GetConfigLocation(), "nirvash.conf")) } func SetAdapter(cfg *Config, adptr string) { switch adptr { case "eureka": cfg.Adapter = &adapter.EurekaAdapter{} default: panic("Unsupported adapter! Try one of [ eureka ]") } } func IsNull(cfg *Config) bool { return cfg.Adapter == nil || len(cfg.Root) == 0 || len(cfg.StaticRoot) == 0 || len(cfg.AssetRoot) == 0 } func RunWizard(cfg *Config) { fmt.Printf("All options are required.\n") defer func(cfg *Config) { if r := recover(); r != nil { fmt.Printf("Invalid selection, starting over...") RunWizard(cfg) } }(cfg) inputBuf := "" fmt.Printf("adapter? (eureka) [eureka] ") fmt.Scanln(&inputBuf) if len(strings.TrimSpace(inputBuf)) == 0 { inputBuf = "eureka" } SetAdapter(cfg, inputBuf) inputBuf = "" fmt.Printf("site data root? ") ensureNonEmptyOption(&inputBuf) cfg.Root = inputBuf inputBuf = "" fmt.Printf("static file root? ") ensureNonEmptyOption(&inputBuf) cfg.StaticRoot = inputBuf inputBuf = "" fmt.Printf("nirvash asset root? ") ensureNonEmptyOption(&inputBuf) cfg.AssetRoot = inputBuf inputBuf = "" fmt.Printf("plugins? (not implemented yet) ") ensureNonEmptyOption(&inputBuf) //cfg.Plugins = processPlugins(inputBuf) fmt.Printf("Configuration complete!\n") Write(cfg) } func ensureNonEmptyOption(buffer *string) { for { fmt.Scanln(buffer) if len(strings.TrimSpace(*buffer)) != 0 { break } } } func writeConfig(cfg *Config, configFile string) error { f, err := os.Create(configFile) if err != nil { return err } defer f.Close() f.WriteString("root=" + cfg.Root + "\n") f.WriteString("staticRoot=" + cfg.StaticRoot + "\n") f.WriteString("assetRoot=" + cfg.AssetRoot + "\n") f.WriteString("adapter=" + cfg.Adapter.Name() + "\n") f.WriteString("plugins=\n") return nil } func parseConfig(configFile string) *Config { f, err := os.ReadFile(configFile) cfg := &Config{} if err != nil { return cfg } fileData := string(f[:]) lines := strings.Split(fileData, "\n") for _, l := range lines { if len(l) == 0 { continue } if !strings.Contains(l, "=") { panic("Malformed config not in INI format") } kvp := strings.Split(l, "=") k := strings.TrimSpace(kvp[0]) v := strings.TrimSpace(kvp[1]) switch k { case "root": cfg.Root = v case "staticRoot": cfg.StaticRoot = v case "assetRoot": cfg.AssetRoot = v case "plugins": // not implemented case "adapter": SetAdapter(cfg, v) default: panic("Unrecognized config option: " + k) } } return cfg }