// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16: //go:build go1.25 package hooks import ( "bytes" "errors" "fmt" "strings" "text/template" "github.com/spf13/cobra" ) func ParseTemplate(hookTemplate string, cmd *cobra.Command) ([]string, error) { out := hookTemplate if strings.Contains(hookTemplate, "{{") { // Message may be a template. msgContext := commandInfo{cmd: cmd} tmpl, err := template.New("").Funcs(template.FuncMap{ "command": msgContext.command, "flagValue": msgContext.flagValue, "argValue": msgContext.argValue, // kept for backward-compatibility with old templates. "flag": func(_ any, flagName string) (string, error) { return msgContext.flagValue(flagName) }, "arg": func(_ any, i int) (string, error) { return msgContext.argValue(i) }, }).Parse(hookTemplate) if err != nil { return nil, err } var b bytes.Buffer err = tmpl.Execute(&b, msgContext) if err != nil { return nil, err } out = b.String() } return strings.Split(out, "\n"), nil } var ErrHookTemplateParse = errors.New("failed to parse hook template") // commandInfo provides info about the command for which the hook was invoked. // It is used for templated hook-messages. type commandInfo struct { cmd *cobra.Command } // Name returns the name of the (sub)command for which the hook was invoked. // // It's used for backward-compatibility with old templates. func (c commandInfo) Name() string { return c.command() } // command returns the name of the (sub)command for which the hook was invoked. func (c commandInfo) command() string { if c.cmd == nil { return "" } return c.cmd.Name() } // flagValue returns the value that was set for the given flag when the hook was invoked. func (c commandInfo) flagValue(flagName string) (string, error) { if c.cmd == nil { return "", fmt.Errorf("%w: flagValue: cmd is nil", ErrHookTemplateParse) } f := c.cmd.Flag(flagName) if f == nil { return "", fmt.Errorf("%w: flagValue: no flags found", ErrHookTemplateParse) } return f.Value.String(), nil } // argValue returns the value of the nth argument. func (c commandInfo) argValue(n int) (string, error) { if c.cmd == nil { return "", fmt.Errorf("%w: arg: cmd is nil", ErrHookTemplateParse) } flags := c.cmd.Flags() v := flags.Arg(n) if v == "" && n >= flags.NArg() { return "", fmt.Errorf("%w: arg: %dth argument not set", ErrHookTemplateParse, n) } return v, nil }