coder / serpent

CLI framework for scale and configurability inspired by Cobra
Creative Commons Zero v1.0 Universal
6 stars 1 forks source link

serpent

Go Reference

serpent is a Go CLI configuration framework based on cobra and used by coder/coder. It's designed for large-scale CLIs with dozens of commands and hundreds of options. If you're building a small, self-contained tool, go with cobra.

help example

When compared to cobra, serpent strives for:

Basic Usage

See example/echo:

package main

import (
    "os"
    "strings"

    "github.com/coder/serpent"
)

func main() {
    var upper bool
    cmd := serpent.Command{
        Use:   "echo <text>",
        Short: "Prints the given text to the console.",
        Options: serpent.OptionSet{
            {
                Name:        "upper",
                Value:       serpent.BoolOf(&upper),
                Flag:        "upper",
                Description: "Prints the text in upper case.",
            },
        },
        Handler: func(inv *serpent.Invocation) error {
            if len(inv.Args) == 0 {
                inv.Stderr.Write([]byte("error: missing text\n"))
                os.Exit(1)
            }

            text := inv.Args[0]
            if upper {
                text = strings.ToUpper(text)
            }

            inv.Stdout.Write([]byte(text))
            return nil
        },
    }

    err := cmd.Invoke().WithOS().Run()
    if err != nil {
        panic(err)
    }
}

Design

This Design section assumes you have a good understanding of how cobra works.

Options

Serpent is designed for high-configurability. To us, that means providing many ways to configure the same value (env, YAML, flags, etc.) and keeping the code clean and testable as you scale the number of options.

Serpent's Option type looks like:

type Option struct {
    Name string
    Flag string
    Env string
    Default string
    Value pflag.Value
    // ...
}

And is used by each Command when passed as an array to the Options field.

More coming...

This README is a stub for now. We'll better explain the design and usage of serpent in the future.