Пример #1
0
// FilterArgs filters the given arguments and returns a filtered argument list.
// It only contains the arguments which are declared in the given configuration
// struct.
func FilterArgs(conf interface{}, args []string) []string {
	configArgs := []string{}

	// need to be declared so we can call it recursively
	var addFields func(fields []*structs.Field)

	addFields = func(fields []*structs.Field) {
		for _, field := range fields {
			// don't forget nested structs
			if field.Kind() == reflect.Struct {
				addFields(field.Fields())
				continue
			}

			fName := strings.ToLower(strings.Join(camelcase.Split(field.Name()), "-"))
			val, err := flags.Value(fName, args)
			if err != nil {
				continue
			}

			configArgs = append(configArgs, "--"+fName, val)
		}
	}
	addFields(structs.Fields(conf))

	return configArgs
}
Пример #2
0
func applyConfigFile(options *Options, filePath string) error {
	filePath = expandHomeDir(filePath)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return err
	}

	fileString := []byte{}
	log.Printf("Loading config file at: %s", filePath)
	fileString, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	config := make(map[string]interface{})
	hcl.Decode(&config, string(fileString))
	o := structs.New(options)
	for _, name := range o.Names() {
		configName := strings.ToLower(strings.Join(camelcase.Split(name), "_"))
		if val, ok := config[configName]; ok {
			field, ok := o.FieldOk(name)
			if !ok {
				return errors.New("No such field: " + name)
			}
			err := field.Set(val)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
Пример #3
0
// generateFieldName generates the fiels name combined with the prefix and the
// struct's field name
func (e *EnvironmentLoader) generateFieldName(prefix string, field *structs.Field) string {
	fieldName := strings.ToUpper(field.Name())
	if e.CamelCase {
		fieldName = strings.ToUpper(strings.Join(camelcase.Split(field.Name()), "_"))
	}

	return strings.ToUpper(prefix) + "_" + fieldName
}
Пример #4
0
// convert keys of a map to underscore
func ConvertKeysToUnderscore(m map[string]interface{}) map[string]interface{} {
	newMap := make(map[string]interface{})
	for k, v := range m {
		splitted := camelcase.Split(k)
		newMap[strings.ToLower(strings.Join(splitted, "_"))] = v
	}
	return newMap
}
Пример #5
0
// generateFieldName generates the field name combined with the prefix and the
// struct's field name
func (e *EnvironmentLoader) generateFieldName(prefix string, name string) string {
	fieldName := strings.ToUpper(name)
	if e.CamelCase {
		fieldName = strings.ToUpper(strings.Join(camelcase.Split(name), "_"))
	}

	return strings.ToUpper(prefix) + "_" + fieldName
}
Пример #6
0
// init initializes the selector code before the start of the animators.
func init() {
	Init(web.Loop)

	// Register all our easing providers.
	for name, vals := range EasingValues {
		cased := strings.ToLower(strings.Join(camelcase.Split(name), "-"))
		RegisterEasing(cased, NewSpline(vals[0], vals[1], vals[2], vals[3]))
	}
}
Пример #7
0
// getEnvName returns all upper case and underscore separated string, from field.
// field is a camel case string.
//
// example
//	AppName will change to APP_NAME
func getEnvName(field string) string {
	camSplit := camelcase.Split(field)
	var rst string
	for k, v := range camSplit {
		if k == 0 {
			rst = strings.ToUpper(v)
			continue
		}
		rst = rst + "_" + strings.ToUpper(v)
	}
	return rst
}
Пример #8
0
// processField generates a flag based on the given field and fieldName. If a
// nested struct is detected, a flag for each field of that nested struct is
// generated too.
func (f *FlagLoader) processField(fieldName string, field *structs.Field) error {
	if f.CamelCase {
		fieldName = strings.Join(camelcase.Split(fieldName), "-")
	}

	switch field.Kind() {
	case reflect.Struct:
		for _, ff := range field.Fields() {
			flagName := field.Name() + "-" + ff.Name()

			if f.Flatten {
				// first check if it's set or not, because if we have duplicate
				// we don't want to break the flag. Panic by giving a readable
				// output
				f.flagSet.VisitAll(func(fl *flag.Flag) {
					if strings.ToLower(ff.Name()) == fl.Name {
						// already defined
						panic(fmt.Sprintf("flag '%s' is already defined in outer struct", fl.Name))
					}
				})

				flagName = ff.Name()
			}

			if err := f.processField(flagName, ff); err != nil {
				return err
			}
		}
	default:
		// Add custom prefix to the flag if it's set
		if f.Prefix != "" {
			fieldName = f.Prefix + "-" + fieldName
		}

		// we only can get the value from expored fields, unexported fields panics
		if field.IsExported() {
			// use built-in or custom flag usage message
			flagUsageFunc := flagUsageDefault
			if f.FlagUsageFunc != nil {
				flagUsageFunc = f.FlagUsageFunc
			}
			f.flagSet.Var(newFieldValue(field), flagName(fieldName), flagUsageFunc(fieldName))
		}
	}

	return nil
}
Пример #9
0
// processField generates a flag based on the given field and fieldName. If a
// nested struct is detected, a flag for each field of that nested struct is
// generated too.
func (f *FlagLoader) processField(flagSet *flag.FlagSet, fieldName string, field *structs.Field) error {
	if !field.IsExported() {
		return nil
	}

	if f.CamelCase {
		fieldName = strings.Join(camelcase.Split(fieldName), "-")
	}

	switch {
	case field.Kind() == reflect.Struct && !implementsTextUnmarshaler(field):
		for _, ff := range field.Fields() {
			flagName := fieldName + "-" + ff.Name()

			if f.Flatten {
				// first check if it's set or not, because if we have duplicate
				// we don't want to break the flag. Panic by giving a readable
				// output
				flagSet.VisitAll(func(fl *flag.Flag) {
					if strings.ToLower(ff.Name()) == fl.Name {
						// already defined
						panic(fmt.Sprintf("flag '%s' is already defined in outer struct", fl.Name))
					}
				})

				flagName = ff.Name()
			}

			if err := f.processField(flagSet, flagName, ff); err != nil {
				return err
			}
		}
	case field.Kind() == reflect.Ptr:
		field.InitElem()
		return f.processField(flagSet, fieldName, field)
	default:
		// Add custom prefix to the flag if it's set
		if f.Prefix != "" {
			fieldName = f.Prefix + "-" + fieldName
		}

		flagSet.Var(newFieldValue(field), flagName(fieldName), flagUsage(fieldName))
	}

	return nil
}
Пример #10
0
func applyConfigFile(options *Options, filePath string) error {
	filePath = ExpandHomeDir(filePath)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return err
	}

	fileString := []byte{}
	log.Printf("Loading config file at: %s", filePath)
	fileString, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	config := make(map[string]interface{})
	hcl.Decode(&config, string(fileString))
	o := structs.New(options)
	for _, name := range o.Names() {
		configName := strings.ToLower(strings.Join(camelcase.Split(name), "_"))
		if val, ok := config[configName]; ok {
			field, ok := o.FieldOk(name)
			if !ok {
				return errors.New("No such option: " + name)
			}

			var err error
			if name == "Preferences" {
				prefs := val.([]map[string]interface{})[0]
				htermPrefs := make(map[string]interface{})
				for key, value := range prefs {
					htermPrefs[strings.Replace(key, "_", "-", -1)] = value
				}
				err = field.Set(htermPrefs)
			} else {
				err = field.Set(val)
			}

			if err != nil {
				return err
			}

		}
	}

	return nil
}
Пример #11
0
// GoIdentifierFrom provides a mechanism to mutate an arbitrary descriptive
// string (name) into a Go identifier (variable name, function name, etc) that
// e.g. can be used in generated code, taking into account a blacklist of names
// that should not be used, plus the blacklist of the go language reserved key
// words (https://golang.org/ref/spec#Keywords), in order to guarantee that a
// new name is created which will not conflict with an existing type.
//
// Identifier syntax: https://golang.org/ref/spec#Identifiers
//
// Strategy to convert arbitrary unicode string to a valid identifier:
//
// 1) Ensure name is valid UTF-8; if not, replace it with empty string
//
// 2) Split name into arrays of allowed runes (words), by considering a run of
// disallowed unicode characters to act as a separator, where allowed runes
// include unicode letters, unicode numbers, and '_' character (disallowed
// runes are discarded)
//
// 3) Split words further into sub words, by decomposing camel case words as
// per https://github.com/fatih/camelcase#usage-and-examples
//
// 4) Designate the case of all subwords of all words to be uppercase, with the
// exception of the first subword of the first word, which should be lowercase
// if exported is false, otherwise uppercase
//
// 5) For each subword of each word, adjust as follows: if designated as
// lowercase, lowercase all characters of the subword; if designated as
// uppercase, then if recognised as a common "initialism", then uppercase all
// the characters of the subword, otherwise uppercase only the first character
// of the subword. Common "Initialisms" are defined as per:
// https://github.com/golang/lint/blob/32a87160691b3c96046c0c678fe57c5bef761456/lint.go#L702
//
// 6) Rejoin subwords to form a single word
//
// 7) Rejoin words into a single string
//
// 8) If the string starts with a number, add a leading `_`
//
// 9) If the string is the empty string or "_", set as "Identifier"
//
// 10) If the resulting identifier is in the given blacklist, or the list of
// reserved key words (https://golang.org/ref/spec#Keywords), append the lowest
// integer possible, >= 1, that results in no blacklist conflict
//
// 11) Add the new name to the given blacklist
//
// Note, the `map[string]bool` construction is simply a mechanism to implement
// set semantics; a value of `true` signifies inclusion in the set.
// Non-existence is equivalent to existence with a value of `false`; therefore
// it is recommended to only store `true` values.
func GoIdentifierFrom(name string, exported bool, blacklist map[string]bool) (identifier string) {
	if !utf8.ValidString(name) {
		name = ""
	}
	for i, word := range strings.FieldsFunc(
		name,
		func(c rune) bool {
			return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '_'
		},
	) {
		caseAdaptedWord := ""
		for j, subWord := range camelcase.Split(word) {
			caseAdaptedWord += fixCase(subWord, i == 0 && j == 0 && !exported)
		}
		identifier += caseAdaptedWord
	}

	if strings.IndexFunc(
		identifier,
		func(c rune) bool {
			return unicode.IsNumber(c)
		},
	) == 0 {
		identifier = "_" + identifier
	}

	if identifier == "" || identifier == "_" {
		identifier = "Identifier"
	}

	// If name already exists, add an integer suffix to name. Start with "1" and increment
	// by 1 until an unused name is found. Example: if name FooBar was generated four times
	// , the first instance would be called FooBar, then the next would be FooBar1, the next
	// FooBar2 and the last would be assigned a name of FooBar3. We do this to guarantee we
	// don't use duplicate names for different logical entities.
	for k, baseName := 1, identifier; blacklist[identifier] || reservedKeyWords[identifier]; {
		identifier = fmt.Sprintf("%v%v", baseName, k)
		k++
	}
	blacklist[identifier] = true
	return
}
Пример #12
0
func makeTagName(s string) string {
	a := []rune(s)

	if len(a) <= 3 {
		return strings.ToLower(string(a))
	}

	spl := camelcase.Split(string(a))

	if len(spl) > 1 {
		fixed := []string{}
		for _, v := range spl {
			fixed = append(fixed, makeFirstUpperCase(strings.ToLower(v)))
		}
		x := makeFirstLowerCase(strings.Join(fixed, ""))
		return x
	}

	return makeFirstLowerCase(strings.Title(string(a)))
}
Пример #13
0
// ExcludeArgs exludes the given arguments declared in the configuration and
// returns the remaining arguments. It's the opposite of FilterArgs
func ExcludeArgs(conf interface{}, args []string) []string {
	// need to be declared so we can call it recursively
	var addFields func(fields []*structs.Field)

	addFields = func(fields []*structs.Field) {
		for _, field := range fields {
			// don't forget nested structs
			if field.Kind() == reflect.Struct {
				addFields(field.Fields())
				continue
			}

			fName := strings.ToLower(strings.Join(camelcase.Split(field.Name()), "-"))
			args = flags.Exclude(fName, args)
		}
	}
	addFields(structs.Fields(conf))

	return args
}
Пример #14
0
func convertInterfaceMap(p interface{}, except []string) map[string]string {
	nint := map[string]string{}
	var structItems map[string]interface{}

	structItems, _ = reflections.Items(p)
	for v, v2 := range structItems {
		if isZeroOfUnderlyingType(v2) || isInList(v, except) {
			continue
		}
		v = strings.ToLower(strings.Join(camelcase.Split(v), "_"))
		switch val := v2.(type) {
		case interface{}:
			sv, _ := json.Marshal(val)
			nint[v] = string(sv)
		default:
			nint[v] = fmt.Sprintf("%+v", v2)
		}
	}
	return nint
}
Пример #15
0
Файл: cli.go Проект: coryb/cliby
func populateEnv(iface Interface) {
	options := reflect.ValueOf(iface.GetOptions())
	if options.Kind() == reflect.Ptr {
		options = reflect.ValueOf(options.Elem().Interface())
	}
	if options.Kind() == reflect.Struct {
		for i := 0; i < options.NumField(); i++ {
			name := strings.Join(camelcase.Split(options.Type().Field(i).Name), "_")
			envName := fmt.Sprintf("%s_%s", strings.ToUpper(iface.Name()), strings.ToUpper(name))

			envName = strings.Map(func(r rune) rune {
				if unicode.IsDigit(r) || unicode.IsLetter(r) {
					return r
				}
				return '_'
			}, envName)
			var val string
			switch t := options.Field(i).Interface().(type) {
			case string:
				val = t
			case int, int8, int16, int32, int64:
				val = fmt.Sprintf("%d", t)
			case float32, float64:
				val = fmt.Sprintf("%f", t)
			case bool:
				val = fmt.Sprintf("%t", t)
			default:
				val, _ = util.JsonEncode(t)
				val = strings.TrimSpace(val)
				if val == "null" {
					val = ""
				}
			}
			os.Setenv(envName, val)
		}
	}
}
Пример #16
0
func makeDashedFromCamelCase(in string) string {
	splitted := camelcase.Split(in)
	return strings.ToLower(strings.Join(splitted, "-"))
}