autogenpb/protoReformat.go

180 lines
4.1 KiB
Go
Raw Normal View History

2025-02-01 06:54:55 -06:00
package main
import (
"fmt"
"os"
"strings"
"go.wit.com/log"
)
// like 'goimport' but for .proto files
var maxVarname int
var maxVartype int
func protoReformat(filename string) error {
// read in the .proto file
data, err := os.ReadFile(filename)
if err != nil {
log.Info("file read failed", filename, err)
return err
}
var inMessage bool
var curmsg []string
2025-02-01 07:32:00 -06:00
var newfile string
2025-02-01 06:54:55 -06:00
// gets the max vartype and varname
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "message ") {
inMessage = true
continue
}
// find the end of the message
if strings.HasPrefix(line, "}") {
inMessage = false
formatMessage(curmsg)
curmsg = nil
continue
}
// don't format or change anything when not in a "message {" section
if !inMessage {
continue
}
curmsg = append(curmsg, line)
}
// parse the proto file for message struct names
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "message ") {
inMessage = true
parts := strings.Fields(line)
if len(parts) > 3 {
2025-02-01 07:32:00 -06:00
// hack to actually indent comments on the message line itself. you're welcome
2025-02-01 06:54:55 -06:00
start := parts[0] + " " + parts[1] + " " + parts[2]
end := strings.Join(parts[3:], " ")
offset := maxVarname + maxVartype + 16 - len(start)
pad := fmt.Sprintf("%d", offset)
hmm := "%s %" + pad + "s %s"
line = fmt.Sprintf(hmm, start, " ", end)
}
2025-02-01 07:32:00 -06:00
newfile += fmt.Sprintln(line)
2025-02-01 06:54:55 -06:00
continue
}
// find the end of the message
if strings.HasPrefix(line, "}") {
inMessage = false
2025-02-01 07:32:00 -06:00
// format and write the last message to the file
2025-02-01 06:54:55 -06:00
for _, newline := range formatMessage(curmsg) {
2025-02-01 07:32:00 -06:00
newfile += fmt.Sprintln(newline)
2025-02-01 06:54:55 -06:00
}
2025-02-01 07:32:00 -06:00
newfile += fmt.Sprintln(line)
2025-02-01 06:54:55 -06:00
curmsg = nil
continue
}
// don't format or change anything when not in a "message {" section
if !inMessage {
2025-02-01 07:32:00 -06:00
newfile += fmt.Sprintln(line)
2025-02-01 06:54:55 -06:00
continue
}
curmsg = append(curmsg, line)
}
2025-02-01 07:32:00 -06:00
pf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Info("file open error. permissions?", filename, err)
return err
}
newfile = strings.TrimSpace(newfile)
fmt.Fprintln(pf, newfile)
pf.Close()
2025-02-01 06:54:55 -06:00
// for i, s := range slices.Backward(pf.ToSort) {
return nil
}
func formatMessage(curmsg []string) []string {
var newmsg []string
// find the max length of varname and vartype
for _, line := range curmsg {
parts := strings.Split(line, ";")
if len(parts) < 2 {
2025-02-01 07:32:00 -06:00
// line is blank or just a comment
continue
2025-02-01 06:54:55 -06:00
}
vartype, varname, _, _ := tokenMsgVar(line)
if len(vartype) > maxVartype {
maxVartype = len(vartype)
}
if len(varname) > maxVarname {
maxVarname = len(varname)
}
}
for _, line := range curmsg {
2025-02-01 07:32:00 -06:00
line = strings.TrimSpace(line)
if line == "" {
newmsg = append(newmsg, line)
continue
}
if strings.HasPrefix(line, "//") {
pad := fmt.Sprintf("%d", maxVartype+maxVarname+21)
hmm := "%" + pad + "s %s"
line = fmt.Sprintf(hmm, " ", line) // todo: compute 50
newmsg = append(newmsg, line)
continue
}
2025-02-01 06:54:55 -06:00
mt := fmt.Sprintf("%d", maxVartype)
mv := fmt.Sprintf("%d", maxVarname)
hmm := " %-" + mt + "s %-" + mv + "s = %-3s %s"
vartype, varname, id, end := tokenMsgVar(line)
end = strings.TrimSpace(end)
id = id + ";"
newline := fmt.Sprintf(hmm, vartype, varname, id, end)
2025-02-01 07:32:00 -06:00
newline = strings.TrimRight(newline, " ")
2025-02-01 06:54:55 -06:00
newmsg = append(newmsg, newline)
}
return newmsg
}
// returns vartype, varname, id, end
func tokenMsgVar(line string) (string, string, string, string) {
parts := strings.Split(line, ";")
front := parts[0]
end := strings.Join(parts[1:], ";")
var id string
var varname string
var vartype string
parts = strings.Fields(front)
parts, id = slicesPop(parts)
parts, _ = slicesPop(parts) // this is the "=" sign
parts, varname = slicesPop(parts)
vartype = strings.Join(parts, " ")
return vartype, varname, id, end
}
func slicesPop(parts []string) ([]string, string) {
if len(parts) == 0 {
return nil, ""
}
if len(parts) == 1 {
return nil, parts[0]
}
x := len(parts)
end := parts[x-1]
return parts[0 : x-1], end
}