blob: 1af227e85272d5774d20bae34685c1d073b38084 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"strings"
)
var inPlace = flag.Bool("i", false, "Formats file in place")
func usage() {
out := flag.CommandLine.Output()
fmt.Fprintf(out,
`Usage: %s [-i] [<file>...]
Format GIDL syntax in each <file>, or from standard input if no files are given.
Options:
`, os.Args[0])
flag.PrintDefaults()
}
func main() {
// Disable timestamp in logs.
log.SetFlags(0)
flag.Usage = usage
flag.Parse()
if *inPlace && flag.NArg() == 0 {
log.Fatal("-i not accepted when formatting standard input")
}
os.Exit(run())
}
// run is separate from main to avoid os.Exit skipping deferred calls.
func run() int {
var dst io.StringWriter
if !*inPlace {
stdout := bufio.NewWriter(os.Stdout)
defer stdout.Flush()
dst = stdout
}
status := 0
if flag.NArg() == 0 {
if err := format(dst, os.Stdin, "<stdin>"); err != nil {
log.Print(err)
status = 1
}
} else {
for _, filename := range flag.Args() {
if err := process(dst, filename); err != nil {
log.Print(err)
status = 1
}
}
}
return status
}
// process reads from filename and formats it to dst.
// If dst is nil, it formats the file in place instead.
func process(dst io.StringWriter, filename string) error {
flag := os.O_RDWR
if dst != nil {
flag = os.O_RDONLY
}
file, err := os.OpenFile(filename, flag, 0)
if err != nil {
return err
}
defer file.Close()
// First case: write to dst.
if dst != nil {
return format(dst, file, filename)
}
// Second case: overwrite file, if anything changed.
var b strings.Builder
if err := format(&b, file, filename); err != nil {
return err
}
stat, err := file.Stat()
if err != nil {
return err
}
if stat.Size() == int64(b.Len()) {
file.Seek(0, 0)
contents, err := io.ReadAll(file)
if err != nil {
return fmt.Errorf("%s: %w", filename, err)
}
if string(contents) == b.String() {
// Nothing changed. Skip writing.
return nil
}
}
file.Truncate(0)
file.Seek(0, 0)
if _, err := file.WriteString(b.String()); err != nil {
return fmt.Errorf("%s: %w", filename, err)
}
return nil
}