Kevin Burke
Kevin Burke

Reputation: 65024

Only implement some verbs of a fmt.Formatter (and fall back to Go defaults for others)

I want to implement some custom behavior for a printed struct. However, Go defines several different format verbs for structs, and I don't want to override all of them, just some of them.

I'm not sure how to do this in Go and it's more difficult because as far as I can tell you can't easily recover the original format string if all you have is a fmt.State - you have to enumerate the flags and then call state.Flag(flag) to see if each one is set.

Here's what I have so far - for unimplemented verbs, just create a second struct without a Format() argument and call fmt.Print on it. Is there a better way than this?

// Help values are returned by commands to indicate to the caller that it was
// called with a configuration that requested a help message rather than
// executing the command.
type Help struct {
    Cmd string
}

// Fallback for unimplemented fmt verbs
type fmtHelp struct{ cmd string }

// Format satisfies the fmt.Formatter interface, print the help message for the
// command carried by h.
func (h *Help) Format(w fmt.State, v rune) {
    switch v {
    case 's':
        printUsage(w, h.Cmd)
        printHelp(w, h.Cmd)
    case 'v':
        if w.Flag('#') {
            io.WriteString(w, "cli.Help{")
            fmt.Fprintf(w, "%#v", h.Cmd)
            io.WriteString(w, "}")
            return
        }
        printUsage(w, h.Cmd)
        printHelp(w, h.Cmd)
    default:
        // fall back to default struct formatter. TODO this does not handle
        // flags
        fmt.Fprintf(w, "%"+string(v), fmtHelp{h.Cmd})
    }
}

Upvotes: 3

Views: 679

Answers (1)

evandertino
evandertino

Reputation: 358

For fallback you would want this in your default case

    default:
        // Get the bypassed format directive
        fmtDirective := fmt.FormatString(w, v)
        fmt.Fprintf(f, fmtDirective, h.Cmd)

Check https://pkg.go.dev/fmt#FormatString

Upvotes: 0

Related Questions