tagMeta struct

Fields:

  • Name (string)
  • Type (string)
  • Choices ([]string)

Binder struct

Binder manages mapping of keys to handlers, auto-discovery from struct tags,

before/after hooks, and optional JSON backup.

Fields:

  • dst (any)
  • handlers (map[string]HandlerFunc)
  • hooks (*hooks)

Methods:

AddBool

AddBool overrides the default handler for key with a custom bool→error function.


Parameters:
  • key string
  • fn func(bool) error

Show/Hide Method Body
{
	b.handlers[key] = wrapBool(fn)
}

AddInt

AddInt overrides the default handler for key with a custom int→error function.


Parameters:
  • key string
  • fn func(int64) error

Show/Hide Method Body
{
	b.handlers[key] = wrapInt(fn)
}

AddDuration

AddDuration overrides the default handler for key with a custom duration→error function.


Parameters:
  • key string
  • fn func(time.Duration) error

Show/Hide Method Body
{
	b.handlers[key] = wrapDuration(fn)
}

AddEnum

AddEnum overrides the default handler for key with a custom enum handler enforcing choices.


Parameters:
  • key string
  • choices []string
  • fn func(string) error

Show/Hide Method Body
{
	b.handlers[key] = wrapEnum(choices, fn)
}

AddStrings

AddStrings overrides the default handler for key with a custom []string→error function.


Parameters:
  • key string
  • fn func([]string) error

Show/Hide Method Body
{
	b.handlers[key] = fn
}

BeforeHook

BeforeHook registers a hook called before setting a field.


Parameters:
  • key string
  • fn HookFunc

References:


Show/Hide Method Body
{
	b.hooks.addBefore(key, fn)
}

AfterHook

AfterHook registers a hook called after setting a field.


Parameters:
  • key string
  • fn HookFunc

References:


Show/Hide Method Body
{
	b.hooks.addAfter(key, fn)
}

Run

Run applies handler for key with args, invoking before and after hooks.


Parameters:
  • key string
  • args []string

Returns:
  • error

Show/Hide Method Body
{
	b.hooks.runBefore(key, args)
	h, ok := b.handlers[key]
	if !ok {
		return fmt.Errorf("no handler for key %s", key)
	}
	err := h(args)
	b.hooks.runAfter(key, args)
	return err
}

RunAll

RunAll applies multiple key→args mappings in sequence.


Parameters:
  • batch map[string][]string

Returns:
  • error

Show/Hide Method Body
{
	for k, args := range batch {
		if err := b.Run(k, args); err != nil {
			return err
		}
	}
	return nil
}

HandlerFunc type

HandlerFunc processes raw args for a field.

Type Definition:

func(args []string) error

HookFunc type

HookFunc defines a hook signature.

Type Definition:

func(key string, args []string)

hooks struct

hooks stores before/after hook functions.

Fields:

  • before (map[string][]HookFunc)
  • after (map[string][]HookFunc)

Methods:

addBefore

addBefore registers a before-hook for a key.


Parameters:
  • key string
  • fn HookFunc

References:


Show/Hide Method Body
{
	h.before[key] = append(h.before[key], fn)
}

addAfter

addAfter registers an after-hook for a key.


Parameters:
  • key string
  • fn HookFunc

References:


Show/Hide Method Body
{
	h.after[key] = append(h.after[key], fn)
}

runBefore

runBefore executes all before-hooks for a key.


Parameters:
  • key string
  • args []string

Show/Hide Method Body
{
	for _, fn := range h.before[key] {
		fn(key, args)
	}
}

runAfter

runAfter executes all after-hooks for a key.


Parameters:
  • key string
  • args []string

Show/Hide Method Body
{
	for _, fn := range h.after[key] {
		fn(key, args)
	}
}

NewBinder function

NewBinder creates a Binder for dst and optionally writes a JSON backup to backupDir.

Parameters:

  • dst any
  • backupDir string
  • autobackup bool

Returns:

  • *Binder
  • error
Show/Hide Function Body
{
	if autobackup {
		if err := os.MkdirAll(backupDir, 0o755); err != nil {
			return nil, err
		}
		backupPath := filepath.Join(backupDir, fmt.Sprintf("backup-%d.json", time.Now().Unix()))
		f, err := os.Create(backupPath)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		if err := json.NewEncoder(f).Encode(dst); err != nil {
			return nil, err
		}
	}
	b := &Binder{
		dst:      dst,
		handlers: make(map[string]HandlerFunc),
		hooks:    newHooks(),
	}
	autoDiscover(b)
	return b, nil
}

parseTag function

parseTag splits a tag like "socketX11,bool" or "mode,enum,dev|prod" into tagMeta.

Parameters:

  • tag string

Returns:

  • tagMeta

References:

Show/Hide Function Body
{
	parts := strings.Split(tag, ",")
	meta := tagMeta{Name: parts[0], Type: parts[1]}
	if meta.Type == "enum" && len(parts) > 2 {
		meta.Choices = strings.Split(parts[2], "|")
	}
	return meta
}

autoDiscover function

autoDiscover inspects dst struct tags and registers default handlers.

Parameters:

  • b *Binder
Show/Hide Function Body
{
	v := reflect.ValueOf(b.dst).Elem()
	t := v.Type()
	for i := range t.NumField() {
		f := t.Field(i)
		tag := f.Tag.Get("flag")
		if tag == "" {
			continue
		}
		meta := parseTag(tag)
		field := v.Field(i)
		switch meta.Type {
		case "bool":
			b.handlers[meta.Name] = defaultBool(field)
		case "int":
			b.handlers[meta.Name] = defaultInt(field)
		case "duration":
			b.handlers[meta.Name] = defaultDuration(field)
		case "enum":
			b.handlers[meta.Name] = defaultEnum(field, meta.Choices)
		case "strings":
			b.handlers[meta.Name] = defaultStrings(field)
		}
	}
}

wrapBool function

wrapBool adapts fn to HandlerFunc.

Parameters:

  • fn func(bool) error

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		v, err := strconv.ParseBool(args[0])
		if err != nil {
			return err
		}
		return fn(v)
	}
}

defaultBool function

defaultBool returns a HandlerFunc that sets a reflect.Bool field.

Parameters:

  • field reflect.Value

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		v, err := strconv.ParseBool(args[0])
		if err != nil {
			return err
		}
		field.SetBool(v)
		return nil
	}
}

wrapInt function

wrapInt adapts fn to HandlerFunc.

Parameters:

  • fn func(int64) error

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		v, err := strconv.ParseInt(args[0], 10, 64)
		if err != nil {
			return err
		}
		return fn(v)
	}
}

defaultInt function

defaultInt returns a HandlerFunc that sets a reflect.Int field.

Parameters:

  • field reflect.Value

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		v, err := strconv.ParseInt(args[0], 10, 64)
		if err != nil {
			return err
		}
		field.SetInt(v)
		return nil
	}
}

wrapDuration function

wrapDuration adapts fn to HandlerFunc.

Parameters:

  • fn func(time.Duration) error

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		d, err := time.ParseDuration(args[0])
		if err != nil {
			return err
		}
		return fn(d)
	}
}

defaultDuration function

defaultDuration returns a HandlerFunc that sets a duration-stored-as-int64 field.

Parameters:

  • field reflect.Value

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		d, err := time.ParseDuration(args[0])
		if err != nil {
			return err
		}
		field.SetInt(int64(d))
		return nil
	}
}

wrapEnum function

wrapEnum enforces allowed choices then calls fn.

Parameters:

  • choices []string
  • fn func(string) error

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		v := args[0]
		for _, c := range choices {
			if v == c {
				return fn(v)
			}
		}
		return fmt.Errorf("invalid value %q, must be one of %v", v, choices)
	}
}

defaultEnum function

defaultEnum returns a HandlerFunc that sets a string field with validation.

Parameters:

  • field reflect.Value
  • choices []string

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		v := args[0]
		for _, c := range choices {
			if v == c {
				field.SetString(v)
				return nil
			}
		}
		return fmt.Errorf("invalid value %q, must be one of %v", v, choices)
	}
}

defaultStrings function

defaultStrings returns a HandlerFunc that sets a []string field.

Parameters:

  • field reflect.Value

Returns:

  • HandlerFunc

References:

Show/Hide Function Body
{
	return func(args []string) error {
		var parts []string
		if len(args) == 1 {
			parts = strings.Split(args[0], ":")
		} else {
			parts = args
		}
		slice := reflect.MakeSlice(field.Type(), len(parts), len(parts))
		for i, s := range parts {
			slice.Index(i).SetString(s)
		}
		field.Set(slice)
		return nil
	}
}

newHooks function

newHooks creates an empty hooks registry.

Returns:

  • *hooks
Show/Hide Function Body
{
	return &hooks{
		before: make(map[string][]HookFunc),
		after:  make(map[string][]HookFunc),
	}
}

encoding/json import

Import example:

import "encoding/json"

fmt import

Import example:

import "fmt"

os import

Import example:

import "os"

path/filepath import

Import example:

import "path/filepath"

time import

Import example:

import "time"

reflect import

Import example:

import "reflect"

strings import

Import example:

import "strings"

fmt import

Import example:

import "fmt"

reflect import

Import example:

import "reflect"

strconv import

Import example:

import "strconv"

strings import

Import example:

import "strings"

time import

Import example:

import "time"