mirror of
https://github.com/nadoo/glider.git
synced 2025-02-24 01:45:39 +08:00
152 lines
2.6 KiB
Go
152 lines
2.6 KiB
Go
package conflag
|
|
|
|
import (
|
|
"bufio"
|
|
"flag"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// Conflag .
|
|
type Conflag struct {
|
|
*flag.FlagSet
|
|
|
|
app string
|
|
osArgs []string
|
|
cfgFile string
|
|
args []string
|
|
|
|
includes []string
|
|
|
|
// TODO: add shorthand? or just use pflag?
|
|
// shorthand map[byte]string
|
|
}
|
|
|
|
// New ...
|
|
func New(args ...string) *Conflag {
|
|
if args == nil {
|
|
args = os.Args
|
|
}
|
|
|
|
c := &Conflag{}
|
|
c.app = args[0]
|
|
c.osArgs = args[1:]
|
|
c.FlagSet = flag.NewFlagSet(c.app, flag.ExitOnError)
|
|
c.FlagSet.StringVar(&c.cfgFile, "config", "", "config file path")
|
|
|
|
return c
|
|
}
|
|
|
|
// NewFromFile ...
|
|
func NewFromFile(app, cfgFile string) *Conflag {
|
|
c := &Conflag{}
|
|
|
|
if app != "" {
|
|
c.app = app
|
|
} else {
|
|
c.app = os.Args[0]
|
|
}
|
|
|
|
c.cfgFile = cfgFile
|
|
c.FlagSet = flag.NewFlagSet(c.app, flag.ExitOnError)
|
|
|
|
c.StringSliceUniqVar(&c.includes, "include", nil, "include file")
|
|
|
|
return c
|
|
}
|
|
|
|
// Parse ...
|
|
func (c *Conflag) Parse() (err error) {
|
|
// parse 1st time and see whether there is a conf file.
|
|
err = c.FlagSet.Parse(c.osArgs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// if there is no args, just try to load the app.conf file.
|
|
if c.cfgFile == "" && len(c.osArgs) == 0 {
|
|
// trim app exetension
|
|
for i := len(c.app) - 1; i >= 0 && c.app[i] != '/' && c.app[i] != '\\'; i-- {
|
|
if c.app[i] == '.' {
|
|
c.cfgFile = c.app[:i]
|
|
break
|
|
}
|
|
}
|
|
|
|
if c.cfgFile == "" {
|
|
c.cfgFile = c.app
|
|
}
|
|
|
|
c.cfgFile += ".conf"
|
|
}
|
|
|
|
if c.cfgFile == "" {
|
|
return nil
|
|
}
|
|
|
|
fargs, err := parseFile(c.cfgFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.args = fargs
|
|
c.args = append(c.args, c.osArgs...)
|
|
|
|
// parse 2nd time to get the include file values
|
|
err = c.FlagSet.Parse(c.args)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dir := filepath.Dir(c.cfgFile)
|
|
|
|
// parse 3rd time to parse flags in include file
|
|
for _, include := range c.includes {
|
|
include = filepath.Join(dir, include)
|
|
fargs, err := parseFile(include)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.args = fargs
|
|
c.args = append(c.args, c.osArgs...)
|
|
|
|
err = c.FlagSet.Parse(c.args)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func parseFile(cfgFile string) ([]string, error) {
|
|
var s []string
|
|
|
|
fp, err := os.Open(cfgFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer fp.Close()
|
|
|
|
scanner := bufio.NewScanner(fp)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
line = strings.TrimSpace(line)
|
|
if len(line) == 0 || line[:1] == "#" {
|
|
continue
|
|
}
|
|
s = append(s, "-"+line)
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
// AppDir returns the app dir
|
|
func (c *Conflag) AppDir() string {
|
|
return filepath.Dir(os.Args[0])
|
|
}
|
|
|
|
// ConfDir returns the config file dir
|
|
func (c *Conflag) ConfDir() string {
|
|
return filepath.Dir(c.cfgFile)
|
|
}
|