diff --git a/README.md b/README.md index 8aa72a0..000bdd6 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,10 @@ func sendFoo(cn net.Conn) (success bool) { At `main/bebobc-go` there is a cli utility to take .bop files and produce .go files from them, what is effectively a little more sophisticated version of the first example in this document. +## bebopfmt + +At `main/bebopfmt` there is a cli utility to format and rewrite bop files. It takes in a `-w` argument to rewrite files in place, and accepts both direct files and filepaths. + ## Known limitations The following is a list of known issues with the current version of the project, ordered by approximate priority for addressing them. @@ -71,8 +75,7 @@ Original bebop does not support one .bop file importing type definitions from an - This is nontrivial, and requires a lot of design toward the importing / packaging ecosystem. -Original bebop requires semicolons after field definitions, and so do we. It seems practical for the language parser to -treat newlines as semicolons (as Go does). +Original bebop requires semicolons after field definitions, and so do we. It seems practical for the language parser to Inject semicolons where required in tokenization. We should be able to generate server code with handlers given all valid messages have op codes. diff --git a/main/bebopc-go/main.go b/main/bebopc-go/main.go index 3d58b1f..8838a35 100644 --- a/main/bebopc-go/main.go +++ b/main/bebopc-go/main.go @@ -10,12 +10,12 @@ import ( var inputFile = flag.String("i", "", "the name of the file to compile") var outputFile = flag.String("o", "", "the name of the output file to write") -var printVersion = flag.String("version", "", "print the version of the compiler") -var printHelp = flag.String("help", "", "print usage text") +var printVersion = flag.Bool("version", false, "print the version of the compiler") +var printHelp = flag.Bool("help", false, "print usage text") var packageName = flag.String("package", "bebopgen", "specify the name of the package to generate") var generateUnsafeMethods = flag.Bool("generate-unsafe", false, "whether unchecked additional methods should be generated") -const version = "bebopc-go v0.0.5" +const version = "bebopc-go v0.0.6" func main() { err := run() @@ -28,11 +28,11 @@ func main() { func run() error { flag.Parse() - if *printHelp != "" { + if *printHelp { flag.Usage() return nil } - if *printVersion != "" { + if *printVersion { fmt.Println(version) return nil } diff --git a/main/bebopfmt/main.go b/main/bebopfmt/main.go new file mode 100644 index 0000000..e97e519 --- /dev/null +++ b/main/bebopfmt/main.go @@ -0,0 +1,116 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "os" + "path/filepath" + + "github.com/200sc/bebop" +) + +var writeInPlace = flag.Bool("w", false, "rewrite the file in place instead of printing to stdout") +var printVersion = flag.Bool("version", false, "print the version of bebopfmt") +var printHelp = flag.Bool("help", false, "print usage text") + +const version = "bebopfmt v0.0.6" + +func main() { + err := run() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + os.Exit(0) +} + +func run() error { + flag.Parse() + if *printHelp { + flag.Usage() + return nil + } + if *printVersion { + fmt.Println(version) + return nil + } + args := os.Args[1:] + actualArgs := make([]string, 0) + for _, arg := range args { + if arg == "-w" || arg == "--w" { + continue + } + actualArgs = append(actualArgs, arg) + } + if len(actualArgs) == 0 { + flag.Usage() + return fmt.Errorf("\tbobfmt (-w) myfile.bop") + } + + for _, path := range actualArgs { + f, err := os.Open(path) + if err != nil { + return fmt.Errorf("Failed to open path: %w", err) + } + finfo, err := f.Stat() + if err != nil { + f.Close() + return fmt.Errorf("Failed to stat path: %w", err) + } + var files = []string{path} + if finfo.IsDir() { + fileInfos, err := f.Readdir(0) + if err != nil { + f.Close() + return fmt.Errorf("Failed to read directory: %w", err) + } + files = make([]string, len(fileInfos)) + for i, info := range fileInfos { + files[i] = filepath.Join(path, info.Name()) + } + } + f.Close() + for _, fpath := range files { + if err := formatFile(fpath); err != nil { + return err + } + } + } + return nil +} + +func formatFile(path string) error { + // Todo: we read the file more than once, its wasteful + f, err := os.Open(path) + if err != nil { + return fmt.Errorf("Failed to open path: %w", err) + } + _, err = bebop.ReadFile(f) + if err != nil { + f.Close() + return fmt.Errorf("Failed to read file: %w", err) + } + f.Close() + f, err = os.Open(path) + if err != nil { + return fmt.Errorf("Failed to open path: %w", err) + } + + out := bytes.NewBuffer([]byte{}) + bebop.Format(f, out) + + f.Close() + + if *writeInPlace { + f, err := os.Create(path) + if err != nil { + return fmt.Errorf("Failed to open path to rewrite: %w", err) + } + f.Write(out.Bytes()) + f.Close() + } else { + fmt.Println(string(out.Bytes())) + } + return nil +}