<commit_before>package opts

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"
)

//Opts is the main class, it contains
//all parsing state for a single set of
//arguments
type Opts struct {
	//embed item since an Opts can also be an item
	item
	parent       *Opts
	subcmds      map[string]*Opts
	opts         []*item
	args         []*item
	arglist      *argumentlist
	optnames     map[string]bool
	envnames     map[string]bool
	order        []string
	templates    map[string]string
	internalOpts struct {
		//pretend these are in the user struct :)
		Help, Version bool
	}
	cfgPath               string
	erred                 error
	cmdname               *reflect.Value
	repo, author, version string
	pkgrepo, pkgauthor    string
	//public format settings
	LineWidth int  //42
	PadAll    bool //true
	PadWidth  int  //2
}

//argumentlist represends a
//named string slice
type argumentlist struct {
	item
	min int
}

//item is the structure representing a
//an opt item
type item struct {
	val       reflect.Value
	name      string
	shortName string
	envName   string
	useEnv    bool
	typeName  string
	help      string
	defstr    string
}

//Creates a new Opts instance and Parses it
func Parse(config interface{}) *Opts {
	return New(config).Parse()
}

//New creates a new Opts instance
func New(config interface{}) *Opts {
	v := reflect.ValueOf(config)
	//nil parent -> root command
	o := fork(nil, v)
	if o.erred != nil {
		//opts has already encounted an error
		return o
	}

	//attempt to infer package name, repo, author
	pkgpath := v.Elem().Type().PkgPath()
	parts := strings.Split(pkgpath, "/")
	if len(parts) >= 3 {
		o.pkgauthor = parts[1]
		o.Name(parts[2])
		switch parts[0] {
		case "github.com", "bitbucket.org":
			o.pkgrepo = "https://" + strings.Join(parts[0:3], "/")
		}
	}

	return o
}

func fork(parent *Opts, val reflect.Value) *Opts {
	//TODO allow order and template per subcmd
	//for now, there is only the root
	var order []string = nil
	var tmpls map[string]string = nil
	if parent == nil {
		order = make([]string, len(DefaultOrder))
		copy(order, DefaultOrder)
		tmpls = map[string]string{}
	}

	//instantiate
	o := &Opts{
		item: item{
			val: val,
		},
		parent: parent,
		//each cmd/subcmd has its own set of names
		optnames: map[string]bool{},
		envnames: map[string]bool{},
		subcmds:  map[string]*Opts{},
		opts:     []*item{},
		//these are only set at the root
		order:     order,
		templates: tmpls,
		//public defaults
		LineWidth: 72,
		PadAll:    true,
		PadWidth:  2,
	}

	//all fields from val
	if val.Type().Kind() != reflect.Ptr {
		o.errorf("opts: %s should be a pointer to a struct", val.Type().Name())
		return o
	}
	o.addFields(val.Elem())

	//add help option
	g := reflect.ValueOf(&o.internalOpts).Elem()<commit_msg>subcommands use parents templates (for now)<commit_after>package opts

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"
)

//Opts is the main class, it contains
//all parsing state for a single set of
//arguments
type Opts struct {
	//embed item since an Opts can also be an item
	item
	parent       *Opts
	subcmds      map[string]*Opts
	opts         []*item
	args         []*item
	arglist      *argumentlist
	optnames     map[string]bool
	envnames     map[string]bool
	order        []string
	templates    map[string]string
	internalOpts struct {
		//pretend these are in the user struct :)
		Help, Version bool
	}
	cfgPath               string
	erred                 error
	cmdname               *reflect.Value
	repo, author, version string
	pkgrepo, pkgauthor    string
	//public format settings
	LineWidth int  //42
	PadAll    bool //true
	PadWidth  int  //2
}

//argumentlist represends a
//named string slice
type argumentlist struct {
	item
	min int
}

//item is the structure representing a
//an opt item
type item struct {
	val       reflect.Value
	name      string
	shortName string
	envName   string
	useEnv    bool
	typeName  string
	help      string
	defstr    string
}

//Creates a new Opts instance and Parses it
func Parse(config interface{}) *Opts {
	return New(config).Parse()
}

//New creates a new Opts instance
func New(config interface{}) *Opts {
	v := reflect.ValueOf(config)
	//nil parent -> root command
	o := fork(nil, v)
	if o.erred != nil {
		//opts has already encounted an error
		return o
	}

	//attempt to infer package name, repo, author
	pkgpath := v.Elem().Type().PkgPath()
	parts := strings.Split(pkgpath, "/")
	if len(parts) >= 3 {
		o.pkgauthor = parts[1]
		o.Name(parts[2])
		switch parts[0] {
		case "github.com", "bitbucket.org":
			o.pkgrepo = "https://" + strings.Join(parts[0:3], "/")
		}
	}

	return o
}

func fork(parent *Opts, val reflect.Value) *Opts {
	//TODO allow order and template per subcmd
	//for now, there is only the root
	var order []string = nil
	var tmpls map[string]string = nil
	if parent == nil {
		order = make([]string, len(DefaultOrder))
		copy(order, DefaultOrder)
		tmpls = map[string]string{}
	} else {
		order = parent.order
		tmpls = parent.templates
	}

	//instantiate
	o := &Opts{
		item: item{
			val: val,
		},
		parent: parent,
		//each cmd/subcmd has its own set of names
		optnames: map[string]bool{},
		envnames: map[string]bool{},
		subcmds:  map[string]*Opts{},
		opts:     []*item{},
		//these are only set at the root
		order:     order,
		templates: tmpls,
		//public defaults
		LineWidth: 72,
		PadAll:    true,
		PadWidth:  2,
	}

	//all fields from val
	if val.Type().Kind() != reflect.Ptr {
		o.errorf("opts: %s should be a pointer to a struct", val.Type().Name())
		return o
	}
	o.addFields(val.Elem())

	//add help option
	g := reflect.ValueOf(&o.internalOpts).Elem()
{'fraction_non_alphanumeric': 0.12108559498956159, 'fraction_numerical': 0.0041753653444676405, 'mean_word_length': 2.8480589022757696, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4237366', 'n_tokens_mistral': 2060, 'n_tokens_neox': 1980, 'n_words': 641}