github.com/d0sbit/gocode@v0.0.0-20211001144653-a968ce917518/config/config.go (about) 1 // Package config has gocode config file reading and writing. 2 package config 3 4 import ( 5 "bytes" 6 "errors" 7 "fmt" 8 "io" 9 "io/fs" 10 "io/ioutil" 11 "os" 12 13 "github.com/BurntSushi/toml" 14 ) 15 16 // Config houses configuration settings and corresponds to a TOML file. 17 type Config struct { 18 Settings map[string]interface{} 19 } 20 21 // GetString returns an entry as a string or def if not found. 22 func (c *Config) GetString(key string, def string) string { 23 v, ok := c.Settings[key] 24 if !ok { 25 return def 26 } 27 return fmt.Sprint(v) 28 } 29 30 // ReadFrom implements the ReaderFrom interface and reads and parses a TOML file. 31 func (c *Config) ReadFrom(r io.Reader) (n int64, err error) { 32 33 b, err := ioutil.ReadAll(r) 34 n = int64(len(b)) 35 if err != nil { 36 return n, err 37 } 38 39 if c.Settings == nil { 40 c.Settings = make(map[string]interface{}) 41 } 42 err = toml.Unmarshal(b, &c.Settings) 43 return n, err 44 45 } 46 47 // WriteTo implements the WriterTo interafce and writes out a TOML file. 48 func (c *Config) WriteTo(w io.Writer) (n int64, err error) { 49 50 var buf bytes.Buffer 51 enc := toml.NewEncoder(&buf) 52 err = enc.Encode(&c.Settings) 53 if err != nil { 54 return 0, err 55 } 56 57 wn, err := w.Write(buf.Bytes()) 58 return int64(wn), err 59 } 60 61 // LoadFS will look for the config file in .gocode/gocode.toml and load it. 62 // If emptyIfNotFound is true then the case of the file not being present 63 // returns empty config instead of an error, or if it is false then 64 // the underlying filesystem's not found error will be returned. 65 func LoadFS(moduleFS fs.FS, emptyIfNotFound bool) (*Config, error) { 66 f, err := moduleFS.Open(".gocode/gocode.toml") 67 if err != nil { 68 if errors.Is(err, os.ErrNotExist) && emptyIfNotFound { 69 return &Config{Settings: make(map[string]interface{})}, nil 70 } 71 return nil, err 72 } 73 defer f.Close() 74 var c Config 75 _, err = c.ReadFrom(f) 76 return &c, err 77 } 78 79 // StoreFS writes a Config to the .gocode/gocode.toml. 80 // The filesystem must provide an appropriate WriteFile 81 // and MkdirAll methods. 82 // (see FileWriter and MkdirAller interfaces). 83 func StoreFS(moduleFS fs.FS, c *Config) error { 84 fw, ok := moduleFS.(wfs) 85 if !ok { 86 return errors.New("moduleFS must implement FileWriter and MkdirAller") 87 } 88 89 err := fw.MkdirAll(".gocode", 0755) 90 if err != nil { 91 return err 92 } 93 94 var buf bytes.Buffer 95 _, err = c.WriteTo(&buf) 96 if err != nil { 97 return err 98 } 99 100 return fw.WriteFile(".gocode/gocode.toml", buf.Bytes(), 0644) 101 } 102 103 // FileWriter is an FS that has a WriteFile method on it. 104 type FileWriter interface { 105 // memfs and other implementations should provide such a method to support writes 106 WriteFile(name string, data []byte, perm fs.FileMode) error 107 } 108 109 // MkdirAller has a MkdirAll call matching the os.MkdirAll signature. 110 type MkdirAller interface { 111 MkdirAll(path string, perm os.FileMode) error 112 } 113 114 type wfs interface { 115 FileWriter 116 MkdirAller 117 }