Skip to content

davidalpert/go-printers

Repository files navigation

License: MIT v3


go-printers

A Golang module built on top of the spf13/pflag library to assist with abstracting output formatting.
README · CHANGELOG . CONTRIBUTING
Report Bug · Request Feature

Table of contents

About the project

go-printers provides a set of helpers extending the spf13/pflag library to abstract away print formatting, making it easy to separate output formatting and support printing as text, table, json, or yaml.

Built with

  • spf13/pflag - "a drop-in replacement for Go's flag package, implementing POSIX/GNU-style --flags"

Getting started

To get a local copy up and running follow these simple steps.

Installation

go get https://github.com/davidalpert/go-printers

Usage

  1. Import the package

    import (
    	"github.com/davidalpert/go-printers/v1"
    )
    
  2. Define an Options struct and a factory function to set defaults

    type MyCmdOptions struct {
      *printers.PrinterOptions
      printers.IOStreams
    }
    
    func NewMyCmdOptions(ioStreams printers.IOStreams) *MyCmdOptions {
      return &MyCmdOptions{
        IOStreams:      ioStreams,
        PrinterOptions: printers.NewPrinterOptions(),
      }
    }
    
  3. Create an instance of streams, probably in your startup code

    ioStreams := printers.DefaultOSStreams() 
    

    In a unit test you might create test streams which exposes each stream as a *bytes.Buffer:

    testStreams, testOutBuf, testErrBuf, testInBuf := printers.NewTestIOStreams()
    

    See the #NewTestIOStreams test scenario for an example of using these buffers in unit tests.

  4. Configure flags inside a cobra.Command factory:

    func NewCmdMyCmd(ioStreams printers.IOStreams) *cobra.Command {
      o := NewMyCmdOptions(ioStreams)
      var cmd = &cobra.Command{
        Use:     "mycmd",
        Args:    cobra.NoArgs,
        RunE: func(cmd *cobra.Command, args []string) error {
         if err := o.Complete(cmd, args); err != nil {
          return err
         }
         if err := o.Validate(); err != nil {
          return err
         }
         return o.Run()
        },
       }
      
       o.PrinterOptions.AddPrinterFlags(cmd.Flags())
      
       return cmd
      }
    
  5. Works well with the Complete/Validate/Run pattern:

    // Complete the options
    func (o *MyCmdOptions) Complete(cmd *cobra.Command, args []string) error {
      return nil
    }
    
    // Validate the options
    func (o *MyCmdOptions) Validate() error {
      return o.PrinterOptions.Validate()
    }
    
  6. Send any interface{} or struct to the printer:

    type Car struct {
      Make    string `json:"make"`
      Model   string `json:"model"`
      Mileage int    `json:"mileage"`
    }
    
    // String implements Stringer
    func (c *Car) String() string {
      return fmt.Sprintf("%s %s [%d miles]", c.Make, c.Model, c.Mileage)
    }
    
    func (o *MyCmdOptions) Run() error {
      newCar := Car{
        make:    "Ford",
        model:   "Taurus",
        mileage: 200000,
      }
    
      return o.IOStreams.WriteOutput(newCar, o.PrinterOptions)
    }
    

This adds an -o/--output flag to your command:

Flags:
  -h, --help            help for mycmd
  -o, --output string   output format: one of json|text|yaml. (default "text")

which can then print the same output in different formats:

  • with -o text and a type which implements Stringer:
    Ford Taurus [200000 miles]
    
  • with -o json:
    {
      "make": "Ford",
      "model": "Taurus",
      "mileage": 200000
    }
    
  • with -o yaml:
    ---
    make: Ford
    model: Taurus
    mileage: 200000
    

Roadmap

See open issues for a list of known issues and up-for-grabs tasks.

Contributing

See the CONTRIBUTING guide for local development setup and contribution guidelines.

License

Distributed under the GPU v3 License. See LICENSE for more information.

Contact

David Alpert - @davidalpert

Project Link: https://github.com/davidalpert/go-printers