func WithConfigFileParser(p ConfigFileParser) Option {
	return func(c *Context) {
		c.configFileParser = p
	}
}
WithConfigFileParser tells Parse how to interpret the config file provided
via WithConfigFile or WithConfigFileFlag.
package ff
import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"
)
func Parse(fs *flag.FlagSet, args []string, options ...Option) error {
	var c Context
	for _, option := range options {
		option(&c)
	}
	if err := fs.Parse(args); err != nil {
		return fmt.Errorf("error parsing commandline args: %w", err)
	}
	provided := map[string]bool{}
	fs.Visit(func(f *flag.Flag) {
		provided[f.Name] = true
	})
	if parseEnv := c.envVarPrefix != "" || c.envVarNoPrefix; parseEnv {
		var visitErr error
		fs.VisitAll(func(f *flag.Flag) {
			if visitErr != nil {
				return
			}
			if provided[f.Name] {
				return
			}
			var key string
			key = strings.ToUpper(f.Name)
			key = envVarReplacer.Replace(key)
			key = maybePrefix(key, c.envVarNoPrefix, c.envVarPrefix)
			value := os.Getenv(key)
			if value == "" {
				return
			}
			for _, v := range maybeSplit(value, c.envVarSplit) {
				if err := fs.Set(f.Name, v); err != nil {
					visitErr = fmt.Errorf("error setting flag %q from env var %q: %w", f.Name, key, err)
					return
				}
			}
		})
		if visitErr != nil {
			return fmt.Errorf("error parsing env vars: %w", visitErr)
		}
	}
	fs.Visit(func(f *flag.Flag) {
		provided[f.Name] = true
	})
	var configFile string
	if c.configFileVia != nil {
		configFile = *c.configFileVia
	}
	if configFile == "" && c.configFileFlagName != "" {
		if f := fs.Lookup(c.configFileFlagName); f != nil {
			configFile = f.Value.String()
		}
	}
	if parseConfig := configFile != "" && c.configFileParser != nil; parseConfig {
		f, err := os.Open(configFile)
		switch {
		case err == nil:
			defer f.Close()
			if err := c.configFileParser(f, func(name, value string) error {
				if provided[name] {
					return nil
				}
				defined := fs.Lookup(name) != nil
				switch {
				case !defined && c.ignoreUndefined:
					return nil
				case !defined && !c.ignoreUndefined:
					return fmt.Errorf("config file flag %q not defined in flag set", name)
				}
				if err := fs.Set(name, value); err != nil {
					return fmt.Errorf("error setting flag %q from config file: %w", name, err)
				}
				return nil
			}); err != nil {
				return err
			}
		case os.IsNotExist(err) && c.allowMissingConfigFile:
		default:
			return err
		}
	}
	fs.Visit(func(f *flag.Flag) {
		provided[f.Name] = true
	})
	return nil
}
type Context struct {
	configFileVia          *string
	configFileFlagName     string
	configFileParser       ConfigFileParser
	allowMissingConfigFile bool
	envVarPrefix           string
	envVarNoPrefix         bool
	envVarSplit            string
	ignoreUndefined        bool
}
type Option func(*Context)
func WithConfigFile(filename string) Option {
	return WithConfigFileVia(&filename)
}
func WithConfigFileVia(filename *string) Option {
	return func(c *Context) {
		c.configFileVia = filename
	}
}
func WithConfigFileFlag(flagname string) Option {
	return func(c *Context) {
		c.configFileFlagName = flagname
	}
}