command/fmt: Accept input from STDIN

So that you can do automatic formatting from an editor. You probably want to
disable the `-write` and `-list` options so that you just get the
re-formatted content, e.g.

    cat main.tf | terraform fmt -write=false -list=false -

I've added a non-exported field called `input` so that we can override this
for the tests. If not specified, like in `commands.go`, then it will default
to `os.Stdin` which works on the command line.
This commit is contained in:
Dan Carley 2016-02-02 22:10:22 +00:00
parent 1b967e612f
commit e9128769b5
3 changed files with 46 additions and 7 deletions

View File

@ -3,6 +3,8 @@ package command
import (
"flag"
"fmt"
"io"
"os"
"strings"
"github.com/hashicorp/hcl/hcl/fmtcmd"
@ -10,6 +12,7 @@ import (
)
const (
stdinArg = "-"
fileExtension = "tf"
)
@ -17,10 +20,15 @@ const (
// files to a canonical format and style.
type FmtCommand struct {
Meta
opts fmtcmd.Options
opts fmtcmd.Options
input io.Reader // STDIN if nil
}
func (c *FmtCommand) Run(args []string) int {
if c.input == nil {
c.input = os.Stdin
}
args = c.Meta.process(args, false)
cmdFlags := flag.NewFlagSet("fmt", flag.ContinueOnError)
@ -40,15 +48,15 @@ func (c *FmtCommand) Run(args []string) int {
return 1
}
var dir string
var dirs []string
if len(args) == 0 {
dir = "."
} else {
dir = args[0]
dirs = []string{"."}
} else if args[0] != stdinArg {
dirs = []string{args[0]}
}
output := &cli.UiWriter{Ui: c.Ui}
err := fmtcmd.Run([]string{dir}, []string{fileExtension}, nil, output, c.opts)
err := fmtcmd.Run(dirs, []string{fileExtension}, c.input, output, c.opts)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error running fmt: %s", err))
return 2
@ -64,6 +72,7 @@ Usage: terraform fmt [options] [DIR]
Rewrites all Terraform configuration files to a canonical format.
If DIR is not specified then the current working directory will be used.
If DIR is "-" then content will be read from STDIN.
Options:

View File

@ -1,6 +1,7 @@
package command
import (
"bytes"
"fmt"
"io/ioutil"
"os"
@ -123,6 +124,34 @@ func TestFmt_directoryArg(t *testing.T) {
}
}
func TestFmt_stdinArg(t *testing.T) {
input := new(bytes.Buffer)
input.Write(fmtFixture.input)
ui := new(cli.MockUi)
c := &FmtCommand{
Meta: Meta{
ContextOpts: testCtxConfig(testProvider()),
Ui: ui,
},
input: input,
}
args := []string{
"-write=false",
"-list=false",
"-",
}
if code := c.Run(args); code != 0 {
t.Fatalf("wrong exit code. errors: \n%s", ui.ErrorWriter.String())
}
expected := fmtFixture.golden
if actual := ui.OutputWriter.Bytes(); !bytes.Equal(actual, expected) {
t.Fatalf("got: %q\nexpected: %q", actual, expected)
}
}
var fmtFixture = struct {
filename string
input, golden []byte

View File

@ -17,7 +17,8 @@ Usage: `terraform fmt [options] [DIR]`
By default, `fmt` scans the current directory for configuration files. If
the `dir` argument is provided then it will scan that given directory
instead.
instead. If `dir` is a single dash (`-`) then `fmt` will read from standard
input (STDIN).
The command-line flags are all optional. The list of available flags are: