cmd/hopp-generate: Improve command line interface
This commit is contained in:
parent
f08213cd49
commit
8f5f25780e
@ -1,48 +1,66 @@
|
||||
package main
|
||||
|
||||
import "os"
|
||||
import "fmt"
|
||||
import "strings"
|
||||
import "path/filepath"
|
||||
import "git.tebibyte.media/sashakoshka/go-cli"
|
||||
import "git.tebibyte.media/sashakoshka/goparse"
|
||||
import "git.tebibyte.media/sashakoshka/hopp/generate"
|
||||
|
||||
func main() {
|
||||
name := os.Args[0]
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s SOURCE DESTINATION\n", name)
|
||||
flagOutput := cli.NewInputFlag('o', "output", "The output file", "", cli.ValString)
|
||||
flagPackageName := cli.NewInputFlag('p', "package-name", "The package name of the file", "", cli.ValString)
|
||||
command := cli.New("Compile PDL files to program source code",
|
||||
flagOutput,
|
||||
flagPackageName)
|
||||
command.Syntax = "FILE [OPTIONS]..."
|
||||
command.ParseOrExit(os.Args)
|
||||
|
||||
if len(command.Args) != 1 {
|
||||
command.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
source := os.Args[1]
|
||||
destination := os.Args[2]
|
||||
source := command.Args[0]
|
||||
destination := flagOutput.Value
|
||||
if destination == "" {
|
||||
destination = "protocol.go"
|
||||
}
|
||||
|
||||
input, err := os.Open(source)
|
||||
handleErr(1, err)
|
||||
handleErr(command, 1, err)
|
||||
defer input.Close()
|
||||
protocol, err := generate.ParseReader(source, input)
|
||||
handleErr(1, err)
|
||||
handleErr(command, 1, err)
|
||||
|
||||
absDestination, err := filepath.Abs(destination)
|
||||
handleErr(1, err)
|
||||
packageName := cleanPackageName(strings.ReplaceAll(
|
||||
strings.ToLower(filepath.Base(absDestination)),
|
||||
" ", "_"))
|
||||
destination = filepath.Join(os.Args[2], "generated.go")
|
||||
packageName := flagPackageName.Value
|
||||
if packageName == "" {
|
||||
absDestination, err := filepath.Abs(destination)
|
||||
handleErr(command, 1, err)
|
||||
base := filepath.Base(absDestination)
|
||||
if scrounged, ok := scroungeForPackageName(base); ok {
|
||||
packageName = scrounged
|
||||
} else {
|
||||
packageName = strings.ReplaceAll(
|
||||
strings.ToLower(base),
|
||||
" ", "_")
|
||||
}
|
||||
}
|
||||
packageName = cleanPackageName(packageName)
|
||||
|
||||
output, err := os.Create(destination)
|
||||
handleErr(1, err)
|
||||
handleErr(command, 1, err)
|
||||
generator := generate.Generator {
|
||||
Output: output,
|
||||
PackageName: packageName,
|
||||
}
|
||||
_, err = generator.Generate(protocol)
|
||||
handleErr(1, err)
|
||||
fmt.Fprintf(os.Stderr, "%s: OK\n", name)
|
||||
handleErr(command, 1, err)
|
||||
command.Println(output, "OK")
|
||||
}
|
||||
|
||||
func handleErr(code int, err error) {
|
||||
func handleErr(command *cli.Cli, code int, err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", os.Args[0], parse.Format(err))
|
||||
command.Errorln(parse.Format(err))
|
||||
os.Exit(code)
|
||||
}
|
||||
}
|
||||
@ -61,3 +79,32 @@ func cleanPackageName(str string) string {
|
||||
}
|
||||
return string(buffer[:j])
|
||||
}
|
||||
|
||||
func scroungeForPackageName(dir string) (string, bool) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil { return "", false}
|
||||
for _, entry := range entries {
|
||||
if !entry.Type().IsRegular() { continue }
|
||||
file, err := os.Open(filepath.Join(dir, entry.Name()))
|
||||
if err != nil { continue }
|
||||
defer file.Close()
|
||||
// FIXME: it is entirely possible that the only file will have
|
||||
// a shitload of doc comments preceeding the package name, and
|
||||
// those comments are usually huge so this is bad
|
||||
buffer := [512]byte { }
|
||||
n, _ := file.Read(buffer[:])
|
||||
text := string(buffer[:n])
|
||||
|
||||
packageIndex := strings.Index(text, "package")
|
||||
if packageIndex < 0 { continue }
|
||||
text = text[packageIndex:]
|
||||
|
||||
newlineIndex := strings.Index(text, "\n")
|
||||
if packageIndex > 0 { text = text[:newlineIndex] }
|
||||
|
||||
fields := strings.Fields(text)
|
||||
if len(fields) < 2 { continue }
|
||||
return fields[1], true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user