├── .travis.yml ├── LICENSE ├── README.md └── main.go /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 1.5 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Fatih Arslan 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of hclfmt nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Archived project. No maintenance. 2 | 3 | This project is not maintained anymore and is archived. Feel free to fork and 4 | make your own changes if needed. For more detail read my blog post: [Taking an indefinite sabbatical from my projects](https://arslan.io/2018/10/09/taking-an-indefinite-sabbatical-from-my-projects/) 5 | 6 | Thanks to everyone for their valuable feedback and contributions. 7 | 8 | 9 | # hclfmt [![Build Status](http://img.shields.io/travis/fatih/hclfmt.svg?style=flat-square)](https://travis-ci.org/fatih/hclfmt) 10 | 11 | hclfmt is a command to format and prettify HCL files. It's similar to the 12 | popular `gofmt` command. Hook it with your favourite editor or use it from the 13 | command line. 14 | 15 | ## Install 16 | 17 | If you have Go installed just do: 18 | 19 | ```bash 20 | go get github.com/fatih/hclfmt 21 | ``` 22 | 23 | ## Editor integration 24 | 25 | * [vim-hclfmt plugin](https://github.com/fatih/vim-hclfmt) 26 | * [atom-hclfmt](https://atom.io/packages/hclfmt) 27 | 28 | ## Usage 29 | 30 | The usage is similar to `gofmt`. If you pass a file it prints the formatted 31 | output to std output: 32 | 33 | ```bash 34 | $ hclfmt config.hcl 35 | ``` 36 | 37 | You can pass the `-w` flag to directly overwrite your file: 38 | 39 | ```bash 40 | $ hclfmt -w config.hcl 41 | ``` 42 | 43 | If no arguments are passed, it excepts the input from standard input. 44 | 45 | 46 | ## License 47 | 48 | The BSD 3-Clause License - see 49 | [`LICENSE`](https://github.com/fatih/hclfmt/blob/master/LICENSE) for more 50 | details 51 | 52 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "os" 10 | "path/filepath" 11 | "runtime/pprof" 12 | "strings" 13 | 14 | "github.com/hashicorp/hcl/hcl/printer" 15 | ) 16 | 17 | const Version = "0.1.0" 18 | 19 | var ( 20 | write = flag.Bool("w", false, "write result to (source) file instead of stdout") 21 | cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file") 22 | version = flag.Bool("version", false, "version information") 23 | ) 24 | 25 | func main() { 26 | if err := realMain(); err != nil { 27 | fmt.Fprintln(os.Stderr, err.Error()) 28 | os.Exit(1) 29 | } 30 | } 31 | 32 | func realMain() error { 33 | flag.Usage = usage 34 | flag.Parse() 35 | 36 | if *version { 37 | fmt.Println(Version) 38 | return nil 39 | } 40 | 41 | if *cpuprofile != "" { 42 | f, err := os.Create(*cpuprofile) 43 | if err != nil { 44 | return fmt.Errorf("creating cpu profile: %s\n", err) 45 | } 46 | defer f.Close() 47 | pprof.StartCPUProfile(f) 48 | defer pprof.StopCPUProfile() 49 | } 50 | 51 | if flag.NArg() == 0 { 52 | if *write { 53 | return errors.New("error: cannot use -w with standard input") 54 | } 55 | 56 | return processFile("", os.Stdin, os.Stdout, true) 57 | } 58 | 59 | for i := 0; i < flag.NArg(); i++ { 60 | path := flag.Arg(i) 61 | switch dir, err := os.Stat(path); { 62 | case err != nil: 63 | return err 64 | case dir.IsDir(): 65 | walkDir(path) 66 | default: 67 | if err := processFile(path, nil, os.Stdout, false); err != nil { 68 | return err 69 | } 70 | } 71 | } 72 | 73 | return nil 74 | } 75 | 76 | func usage() { 77 | fmt.Fprintf(os.Stderr, "usage: hclfmt [flags] [path ...]\n") 78 | flag.PrintDefaults() 79 | os.Exit(2) 80 | } 81 | 82 | func isHclFile(f os.FileInfo) bool { 83 | // ignore non-hcl files 84 | name := f.Name() 85 | return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".hcl") 86 | } 87 | 88 | func walkDir(path string) { 89 | filepath.Walk(path, visitFile) 90 | } 91 | 92 | func visitFile(path string, f os.FileInfo, err error) error { 93 | if err == nil && isHclFile(f) { 94 | err = processFile(path, nil, os.Stdout, false) 95 | } 96 | 97 | return err 98 | } 99 | 100 | // If in == nil, the source is the contents of the file with the given filename. 101 | func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { 102 | if in == nil { 103 | f, err := os.Open(filename) 104 | if err != nil { 105 | return err 106 | } 107 | defer f.Close() 108 | in = f 109 | } 110 | 111 | src, err := ioutil.ReadAll(in) 112 | if err != nil { 113 | return err 114 | } 115 | 116 | res, err := printer.Format(src) 117 | if err != nil { 118 | return err 119 | } 120 | 121 | if *write { 122 | err = ioutil.WriteFile(filename, res, 0644) 123 | } else { 124 | _, err = out.Write(res) 125 | } 126 | 127 | return err 128 | } 129 | --------------------------------------------------------------------------------