Compare commits

..

No commits in common. "master" and "v0.0.74" have entirely different histories.

11 changed files with 528 additions and 375 deletions

213
GuiGenerate Normal file
View File

@ -0,0 +1,213 @@
package zoopb
import (
"time"
"go.wit.com/gui"
"go.wit.com/lib/protobuf/guipb"
"go.wit.com/log"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
)
func (x *Machines) NewTable(title string) *MachinesTable {
t := new(MachinesTable)
t.x = x
pb := new(guipb.Table)
pb.Title = title
t.pb = pb
return t
}
func (t *MachinesTable) AddStringFunc(title string, f func(*Machine) string) {
t.pb.Order = append(t.pb.Order, title)
sf := new(MachineStringFunc)
sf.title = title
sf.f = f
t.stringFuncs = append(t.stringFuncs, sf)
}
func (t *MachinesTable) AddIntFunc(title string, f func(*Machine) int) {
t.pb.Order = append(t.pb.Order, title)
sf := new(MachineIntFunc)
sf.title = title
sf.f = f
t.intFuncs = append(t.intFuncs, sf)
}
func (t *MachinesTable) AddTimeFunc(title string, f func(*Machine) time.Time) {
t.pb.Order = append(t.pb.Order, title)
sf := new(MachineTimeFunc)
sf.title = title
sf.f = f
t.timeFuncs = append(t.timeFuncs, sf)
}
func (mt *MachinesTable) ShowTable() {
log.Info("zoopb.ShowTable() SENDING TO GUI")
mt.MakeTable()
gui.ShowTable(mt.pb)
}
type MachineStringFunc struct {
title string
f func(*Machine) string
}
type MachineIntFunc struct {
title string
f func(*Machine) int
}
type MachineTimeFunc struct {
title string
f func(*Machine) time.Time
}
type MachinesTable struct {
// gt *gui.NodeTable
pb *guipb.Table
x *Machines
hostnames []string
stringFuncs []*MachineStringFunc
intFuncs []*MachineIntFunc
timeFuncs []*MachineTimeFunc
}
func (mt *MachinesTable) doStringFunc(name string) bool {
for _, sf := range mt.stringFuncs {
if sf.title != name {
continue
}
log.Info("zoopb: found stringfunc name:", name)
r := new(guipb.StringRow)
r.Header = new(guipb.Widget)
r.Header.Name = name
all := mt.x.All()
for all.Scan() {
m := all.Next()
r.Vals = append(r.Vals, sf.f(m))
log.Info("zoopb: adding", name, r.Vals)
}
mt.pb.StringRows = append(mt.pb.StringRows, r)
return true
}
return false
}
func (mt *MachinesTable) doIntFunc(name string) bool {
for _, sf := range mt.intFuncs {
if sf.title != name {
continue
}
log.Info("zoopb: found intfunc name:", name)
r := new(guipb.IntRow)
r.Header = new(guipb.Widget)
r.Header.Name = name
all := mt.x.All()
for all.Scan() {
m := all.Next()
r.Vals = append(r.Vals, int64(sf.f(m)))
log.Info("zoopb: adding", name, r.Vals)
}
mt.pb.IntRows = append(mt.pb.IntRows, r)
return true
}
return false
}
func (mt *MachinesTable) doTimeFunc(name string) bool {
for _, sf := range mt.timeFuncs {
if sf.title != name {
continue
}
log.Info("zoopb: found timefunc name:", name)
r := new(guipb.TimeRow)
r.Header = new(guipb.Widget)
r.Header.Name = name
all := mt.x.All()
for all.Scan() {
m := all.Next()
t := sf.f(m)
r.Vals = append(r.Vals, timestamppb.New(t)) // convert to protobuf time
log.Info("zoopb: adding", name, r.Vals)
}
mt.pb.TimeRows = append(mt.pb.TimeRows, r)
return true
}
return false
}
func (t *MachinesTable) AddHostname() {
// t.pb.Order = append(t.pb.Order, "Hostname")
t.AddStringFunc("Hostname", func(m *zoopb.Machine) string {
return m.Hostname
})
}
func (t *MachinesTable) AddMemory() {
t.pb.Order = append(t.pb.Order, "Memory")
}
func (t *MachinesTable) AddCpus() {
t.pb.Order = append(t.pb.Order, "Cpus")
}
func (mt *MachinesTable) MakeTable() {
for _, name := range mt.pb.Order {
log.Info("zoopb: looking for row name()", name)
switch name {
case "Hostname":
r := new(guipb.StringRow)
r.Header = new(guipb.Widget)
r.Header.Name = name
all := mt.x.All()
for all.Scan() {
m := all.Next()
r.Vals = append(r.Vals, m.Hostname)
log.Info("zoopb: adding", name, r.Vals)
}
mt.pb.StringRows = append(mt.pb.StringRows, r)
continue
case "Cpus":
i := new(guipb.IntRow)
i.Header = new(guipb.Widget)
i.Header.Name = name
all := mt.x.All()
for all.Scan() {
m := all.Next()
i.Vals = append(i.Vals, m.Cpus)
log.Info("zoopb: adding", name, i.Vals)
}
mt.pb.IntRows = append(mt.pb.IntRows, i)
continue
case "Memory":
i := new(guipb.IntRow)
i.Header = new(guipb.Widget)
i.Header.Name = name
all := mt.x.All()
for all.Scan() {
m := all.Next()
i.Vals = append(i.Vals, m.Memory)
log.Info("zoopb: adding", name, i.Vals)
}
mt.pb.IntRows = append(mt.pb.IntRows, i)
continue
default:
// mt.addFuncRow(name)
}
log.Info("zoopb: didn't find name. trying StringFuncs", name)
if mt.doStringFunc(name) {
continue
}
if mt.doIntFunc(name) {
continue
}
if mt.doTimeFunc(name) {
continue
}
}
}

View File

@ -122,10 +122,3 @@ reformat-signal.proto-fruit: goimports vet build
reformat-signal.proto-fruit-debug: goimports vet build reformat-signal.proto-fruit-debug: goimports vet build
git checkout example/*.proto git checkout example/*.proto
make -C example proto-reformat-fruit-debug make -C example proto-reformat-fruit-debug
# eh, this is okay for docs I guess. notsure. but it makes pkg.go.dev better
gemini:
DEBUG=1 gemini --prompt "Can you add comments to the functions in the protoReformat.go file? Just add comments at the beginning of each function." --yolo --debug
gemini-try2:
DEBUG=1 gemini --prompt "First figure out what each GO function in protoReformat.go does. Second, make good comments to put on on each function for pkg.go.dev?" --yolo --debug

14
README
View File

@ -1,14 +1,4 @@
# This app auto-generates *.pb.go files # This app will autogenerate Sort() and Marshal() functions for .proto files
#
# It assumes you are doing GO development in ~/go/src
# Although it might work with go.work directory setups
# I haven't tested that much yet because I haven't had time
# This app DOES NOT LIKE THINGS WHEN THE PATHS ARE NOT ABSOLUTE GO namespace paths
# that is, if you make a go.work file and tell it gitea.mystuff.org/foo is actually in foo/
# none of the autogen things will probably work. Notsure. Anyway, it's not interesting
# to me to try that since this is hard enough already I don't have time to debug that
# but will of course accept patches
# It was designed to work on .proto files designed with a .proto standard # It was designed to work on .proto files designed with a .proto standard
@ -21,5 +11,3 @@
# See the examples/ for a sample fruit.proto file that documents what is needed # See the examples/ for a sample fruit.proto file that documents what is needed
# You will notice if you have checked out this project the *pb.go files are ignored in the .gitignore
# file. See the app 'forge' on how publishing and versioning works with this codebase.

View File

@ -55,7 +55,7 @@ message Basket { // `autogenpb:nomutex`
repeated Apple stacks = 6; repeated Apple stacks = 6;
} }
// "Fruit" must exist. you can put anything in it // "Fruit" must exist. you can put anything in it
message Fruit { // `autogenpb:http` `autogenpb:marshal` message Fruit {
string brand = 1; // `autogenpb:unique` `autogenpb:sort` string brand = 1; // `autogenpb:unique` `autogenpb:sort`
Apple apples = 2; Apple apples = 2;
repeated Pear pears = 3; repeated Pear pears = 3;
@ -68,7 +68,7 @@ message Fruit { // `autogenpb:http` `aut
} }
// "Fruits" MUST EXIST and start exactly this way // "Fruits" MUST EXIST and start exactly this way
// It must be "Fruit" + 's' and must match the name of this file: "fruit.proto" // It must be "Fruit" + 's' and must match the name of this file: "fruit.proto"
message Fruits { // `autogenpb:marshal` `autogenpb:mutex` `autogenpb:gui` `autogenpb:http` message Fruits { // `autogenpb:marshal` `autogenpb:mutex` `autogenpb:gui`
string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079` string uuid = 1; // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079`
string version = 2; // `autogenpb:version:v0.0.1` string version = 2; // `autogenpb:version:v0.0.1`
repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s" repeated Fruit Fruits = 3; // THIS MUST BE "Fruit" and then "Fruit" + "s"

View File

@ -50,7 +50,6 @@ message MsgName {
bool doGui = 13; // if a gui.pb.go file should be created bool doGui = 13; // if a gui.pb.go file should be created
string guiVarName = 14; // the name of the variable to use string guiVarName = 14; // the name of the variable to use
MsgName localMsgs = 15; // messages can define other local only messages MsgName localMsgs = 15; // messages can define other local only messages
bool doHTTP = 16; // make http.pb.go files
} }
message Sort { message Sort {
@ -68,6 +67,7 @@ message FormatMsg {
ONEOF = 2; ONEOF = 2;
VAR = 3; VAR = 3;
} }
int64 depth = 1; // used to indent output int64 depth = 1; // used to indent output
int64 maxVarname = 2; // max string length of var names int64 maxVarname = 2; // max string length of var names
int64 maxVartype = 3; // max string length of var types int64 maxVartype = 3; // max string length of var types
@ -104,7 +104,6 @@ message File { // `autogenpb:var:w io.Wri
repeated Sort toSort = 12; // variables that are repeated can have the standard functions generated (Sort(), etc) repeated Sort toSort = 12; // variables that are repeated can have the standard functions generated (Sort(), etc)
string goPath = 13; // the version to use in a func NewMsgName() string goPath = 13; // the version to use in a func NewMsgName()
bool doGui = 14; // if a gui.pb.go file should be created bool doGui = 14; // if a gui.pb.go file should be created
bool doHTTP = 15; // http.pb.go
} }
// I know, I know, the whole point of using protobuf // I know, I know, the whole point of using protobuf
// is so you don't need a uuid or versions because it's // is so you don't need a uuid or versions because it's
@ -123,3 +122,4 @@ message Identify { // `autogenpb:marshal`
string uuid = 1; // string uuid = 1; //
string version = 2; // string version = 2; //
} }
// footer was empty

View File

@ -14,19 +14,16 @@ import (
func (msg *MsgName) simpleAppend(w io.Writer, FRUIT, APPLES, APPLE string) string { func (msg *MsgName) simpleAppend(w io.Writer, FRUIT, APPLES, APPLE string) string {
LOCK := msg.getLockname("x") LOCK := msg.getLockname("x")
funcdef := "func (x *" + FRUIT + ") Append(y *" + APPLE + ") *" + APPLE funcdef := "func (x *" + FRUIT + ") Append(y *" + APPLE + ")"
// log.Printf("\t\t(x %s) APPEND(%s)\n", FRUIT, APPLE) // log.Printf("\t\t(x %s) APPEND(%s)\n", FRUIT, APPLE)
// append -- no check at all // append -- no check at all
fmt.Fprintln(w, "// a Append() shortcut (that does Clone() with a mutex) notsure if it really works") fmt.Fprintln(w, "// just a simple Append() shortcut (but still uses the mutex lock)")
fmt.Fprintln(w, funcdef, "{") fmt.Fprintln(w, funcdef, "{")
fmt.Fprintln(w, " "+LOCK+".Lock()") fmt.Fprintln(w, " "+LOCK+".Lock()")
fmt.Fprintln(w, " defer "+LOCK+".Unlock()") fmt.Fprintln(w, " defer "+LOCK+".Unlock()")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " z := proto.Clone(y).(*"+APPLE+")") fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", y)")
fmt.Fprintln(w, " x."+APPLES+" = append(x."+APPLES+", z)")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " return z")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
@ -95,7 +92,7 @@ func (msg *MsgName) addAppendBy(w io.Writer, STRUCT, FUNCNAME, STRUCTVAR, VARNAM
fmt.Fprintln(w, " }") fmt.Fprintln(w, " }")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " }")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " x."+STRUCTVAR+" = append(x."+STRUCTVAR+", proto.Clone(y).(*"+VARTYPE+"))") fmt.Fprintln(w, " x."+STRUCTVAR+" = append(x."+STRUCTVAR+", y)")
fmt.Fprintln(w, " return true") fmt.Fprintln(w, " return true")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")

View File

@ -49,9 +49,39 @@ func (pb *Files) makeGuiFile(pf *File) error {
FRUIT := msg.GuiVarName FRUIT := msg.GuiVarName
fruitVars := color.Vars fruitVars := color.Vars
pf.generateAutoTablePB(newf, FRUITS, FRUIT, fruitVars) pf.generateAutoTablePB(newf, FRUITS, FRUIT, fruitVars)
log.Printf("Added GUI functions for protobuf '%s' with record '%s' using mutex '%s'\n", msg.Name, msg.GuiVarName, color.Lockname) log.Printf("NEED TO ADD GUI FOR %s with var %s and found msg struct %s\n", msg.Name, msg.GuiVarName, color.Lockname)
} }
} }
// os.Exit(-1)
/*
guiMain(newf, pf.Bases.Name, pf.Base.Name)
guiStringFuncs(newf, pf.Package, pf.Bases.Name, pf.Base.Name)
for _, v := range pf.Base.Vars {
if v.IsRepeated {
// can't work against slices
continue
}
if v.VarType == "string" {
log.Printf("make Add function here %s %s %s\n", pf.Bases.Name, pf.Base.Name, v.VarName)
guiAddStringFunc(newf, pf.Bases.Name, pf.Base.Name, v.VarName)
continue
}
if v.VarType == "int64" {
log.Printf("make Add function here %s %s %s\n", pf.Bases.Name, pf.Base.Name, v.VarName)
guiAddIntFunc(newf, pf.Bases.Name, pf.Base.Name, v.VarName)
continue
}
}
FRUITS := pf.Bases.Name
FRUIT := pf.Base.Name
fRUITS := untitle(pf.Bases.Name)
fRUIT := untitle(pf.Base.Name)
guiUpdate(newf, FRUITS, FRUIT)
guiTableDelete(newf, FRUITS, FRUIT)
guiTableCustom(newf, FRUITS, fRUITS, FRUIT, fRUIT)
*/
fmt.Fprintf(newf, "\n") fmt.Fprintf(newf, "\n")
fmt.Fprintf(newf, "// END GUI\n") fmt.Fprintf(newf, "// END GUI\n")
@ -111,7 +141,6 @@ func headerGui(w io.Writer, pf *File) {
fmt.Fprintln(w, " \"go.wit.com/gui\"") fmt.Fprintln(w, " \"go.wit.com/gui\"")
fmt.Fprintln(w, " \"go.wit.com/lib/protobuf/guipb\"") fmt.Fprintln(w, " \"go.wit.com/lib/protobuf/guipb\"")
fmt.Fprintln(w, " \"go.wit.com/log\"") fmt.Fprintln(w, " \"go.wit.com/log\"")
fmt.Fprintln(w, " anypb \"google.golang.org/protobuf/types/known/anypb\"")
fmt.Fprintln(w, " timestamppb \"google.golang.org/protobuf/types/known/timestamppb\"") fmt.Fprintln(w, " timestamppb \"google.golang.org/protobuf/types/known/timestamppb\"")
fmt.Fprintln(w, ")") fmt.Fprintln(w, ")")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
@ -127,77 +156,61 @@ func guiMain(w io.Writer, FRUITS string, FRUIT string) {
fmt.Fprintln(w, " return t") fmt.Fprintln(w, " return t")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "// force the application to choose the type of data. this allows the GUI plugin to be smarter") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddStringFunc(title string, f func(*"+FRUIT+") string) *"+FRUIT+"StringFunc {")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddStringFunc(title string, f func(*"+FRUIT+") string) *"+FRUIT+"AnyFunc {")
fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf := new("+FRUIT+"StringFunc)")
fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " sf.f = f")
fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " sf.order = t.order")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " t.order += 1")
fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " t.stringFuncs = append(t.stringFuncs, sf)")
fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)")
fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_STRING")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)")
fmt.Fprintln(w, " return sf") fmt.Fprintln(w, " return sf")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "// force the application to choose the type of data. this allows the GUI plugin to be smarter") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddButtonFunc(title string, f func(*"+FRUIT+") string) *"+FRUIT+"ButtonFunc {")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddButtonFunc(title string, f func(*"+FRUIT+") string) *"+FRUIT+"AnyFunc {")
fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf := new("+FRUIT+"ButtonFunc)")
fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " sf.f = f")
fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " sf.order = t.order")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " t.order += 1")
fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " t.buttonFuncs = append(t.buttonFuncs, sf)")
fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)")
fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_STRING")
fmt.Fprintln(w, " sf.attr.Click = true")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)")
fmt.Fprintln(w, " return sf") fmt.Fprintln(w, " return sf")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "// force the application to choose the type of data. this allows the GUI plugin to be smarter") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddIntFunc(title string, f func(*"+FRUIT+") int) *"+FRUIT+"IntFunc {")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddIntFunc(title string, f func(*"+FRUIT+") int) *"+FRUIT+"AnyFunc {")
fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf := new("+FRUIT+"IntFunc)")
fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " sf.f = f")
fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " sf.order = t.order")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " t.order += 1")
fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " t.intFuncs = append(t.intFuncs, sf)")
fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)")
fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_INT")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)")
fmt.Fprintln(w, " return sf") fmt.Fprintln(w, " return sf")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "// force the application to choose the type of data. this allows the GUI plugin to be smarter") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddTimeFunc(title string, f func(*"+FRUIT+") time.Time) *"+FRUIT+"TimeFunc {")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddTimeFunc(title string, f func(*"+FRUIT+") time.Time) *"+FRUIT+"AnyFunc {")
fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)") fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, title)")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " sf := new("+FRUIT+"AnyFunc)") fmt.Fprintln(w, " sf := new("+FRUIT+"TimeFunc)")
fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, " sf.f = func(x *"+FRUIT+") any {") fmt.Fprintln(w, " sf.f = f")
fmt.Fprintln(w, " return f(x)") fmt.Fprintln(w, " sf.order = t.order")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " t.order += 1")
fmt.Fprintln(w, " sf.attr = new(guipb.ColAttr)") fmt.Fprintln(w, " t.timeFuncs = append(t.timeFuncs, sf)")
fmt.Fprintln(w, " sf.attr.Width = int32(sf.Width)")
fmt.Fprintln(w, " sf.attr.Type = guipb.ColAttr_TIME")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " // t.timeFuncs = append(t.timeFuncs, sf)")
fmt.Fprintln(w, " t.anyFuncs = append(t.anyFuncs, sf)")
fmt.Fprintln(w, " return sf") fmt.Fprintln(w, " return sf")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (sf *"+FRUIT+"AnyFunc) SetTitle(title string) {") fmt.Fprintln(w, "func (sf *"+FRUIT+"StringFunc) SetTitle(title string) {")
fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "func (sf *"+FRUIT+"IntFunc) SetTitle(title string) {")
fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "func (sf *"+FRUIT+"TimeFunc) SetTitle(title string) {")
fmt.Fprintln(w, " sf.title = title") fmt.Fprintln(w, " sf.title = title")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
@ -217,12 +230,32 @@ func guiMain(w io.Writer, FRUITS string, FRUIT string) {
fmt.Fprintln(w, " mt.parent.ShowTable(mt.pb)") fmt.Fprintln(w, " mt.parent.ShowTable(mt.pb)")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "type "+FRUIT+"AnyFunc struct {") fmt.Fprintln(w, "type "+FRUIT+"StringFunc struct {")
fmt.Fprintln(w, " title string") fmt.Fprintln(w, " title string")
fmt.Fprintln(w, " f func(*"+FRUIT+") any") fmt.Fprintln(w, " f func(*"+FRUIT+") string")
fmt.Fprintln(w, " Custom func(*"+FRUIT+")") fmt.Fprintln(w, " Custom func(*"+FRUIT+")")
fmt.Fprintln(w, " Width int") fmt.Fprintln(w, " order int")
fmt.Fprintln(w, " attr *guipb.ColAttr") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "type "+FRUIT+"ButtonFunc struct {")
fmt.Fprintln(w, " title string")
fmt.Fprintln(w, " f func(*"+FRUIT+") string")
fmt.Fprintln(w, " Custom func(*"+FRUIT+")")
fmt.Fprintln(w, " order int")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "type "+FRUIT+"IntFunc struct {")
fmt.Fprintln(w, " title string")
fmt.Fprintln(w, " f func(*"+FRUIT+") int")
fmt.Fprintln(w, " Custom func(*"+FRUIT+")")
fmt.Fprintln(w, " order int")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "type "+FRUIT+"TimeFunc struct {")
fmt.Fprintln(w, " title string")
fmt.Fprintln(w, " f func(*"+FRUIT+") time.Time")
fmt.Fprintln(w, " Custom func(*"+FRUIT+")")
fmt.Fprintln(w, " order int")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "type "+FRUITS+"Table struct {") fmt.Fprintln(w, "type "+FRUITS+"Table struct {")
@ -230,65 +263,122 @@ func guiMain(w io.Writer, FRUITS string, FRUIT string) {
fmt.Fprintln(w, " parent *gui.Node") fmt.Fprintln(w, " parent *gui.Node")
fmt.Fprintln(w, " x *"+FRUITS+"") fmt.Fprintln(w, " x *"+FRUITS+"")
fmt.Fprintln(w, " hostnames []string") fmt.Fprintln(w, " hostnames []string")
fmt.Fprintln(w, " anyFuncs []*"+FRUIT+"AnyFunc") fmt.Fprintln(w, " stringFuncs []*"+FRUIT+"StringFunc")
fmt.Fprintln(w, " intFuncs []*"+FRUIT+"IntFunc")
fmt.Fprintln(w, " timeFuncs []*"+FRUIT+"TimeFunc")
fmt.Fprintln(w, " buttonFuncs []*"+FRUIT+"ButtonFunc")
fmt.Fprintln(w, " CustomFunc func(*"+FRUIT+")") fmt.Fprintln(w, " CustomFunc func(*"+FRUIT+")")
fmt.Fprintln(w, " order int")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
} }
func guiStringFuncs(w io.Writer, ZOOPB string, FRUITS string, FRUIT string) { func guiStringFuncs(w io.Writer, ZOOPB string, FRUITS string, FRUIT string) {
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) doAnyFuncNew(sf *"+FRUIT+"AnyFunc) bool {") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) doStringFunc(name string) bool {")
fmt.Fprintln(w, " r := new(guipb.AnyCol)") fmt.Fprintln(w, " for _, sf := range mt.stringFuncs {")
fmt.Fprintln(w, " if sf.title != name {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": found stringfunc name:\", name)")
fmt.Fprintln(w, " r := new(guipb.StringRow)")
fmt.Fprintln(w, " r.Header = new(guipb.Widget)") fmt.Fprintln(w, " r.Header = new(guipb.Widget)")
fmt.Fprintln(w, " r.Header.Name = sf.title") fmt.Fprintln(w, " r.Header.Name = name")
fmt.Fprintln(w, " r.Attr = proto.Clone(sf.attr).(*guipb.ColAttr)")
fmt.Fprintln(w, "") /*
fmt.Fprintln(w, " all := mt.x.All()")
fmt.Fprintln(w, " for all.Scan() {")
fmt.Fprintln(w, " m := all.Next()")
*/
fmt.Fprintln(w, " for m := range mt.x.IterAll() {") fmt.Fprintln(w, " for m := range mt.x.IterAll() {")
fmt.Fprintln(w, " t := sf.f(m)") fmt.Fprintln(w, " r.Vals = append(r.Vals, sf.f(m))")
fmt.Fprintln(w, " switch r.Attr.Type {") fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": adding\", name, r.Vals)")
fmt.Fprintln(w, " case guipb.ColAttr_STRING:")
fmt.Fprintln(w, " // anyProto, err := anypb.New(tsProto)")
fmt.Fprintln(w, " stringValue := wrapperspb.String(t.(string))")
fmt.Fprintln(w, " anyProto, err := anypb.New(stringValue)")
fmt.Fprintln(w, " _ = err // do something with err someday (?)")
fmt.Fprintln(w, " r.Vals = append(r.Vals, anyProto)")
fmt.Fprintln(w, " // return col.Vals[row] true")
fmt.Fprintln(w, " case guipb.ColAttr_INT:")
fmt.Fprintln(w, " var finalInt int")
fmt.Fprintln(w, " finalInt = t.(int)")
fmt.Fprintln(w, " intVal := wrapperspb.Int32(int32(finalInt))")
fmt.Fprintln(w, " anyProto, _ := anypb.New(intVal)")
fmt.Fprintln(w, " r.Vals = append(r.Vals, anyProto)")
fmt.Fprintln(w, " case guipb.ColAttr_DURATION:")
fmt.Fprintln(w, " case guipb.ColAttr_TIME:")
fmt.Fprintln(w, " var goTime time.Time")
fmt.Fprintln(w, " goTime = t.(time.Time)")
fmt.Fprintln(w, " tsProto := timestamppb.New(goTime)")
fmt.Fprintln(w, " anyProto, err := anypb.New(tsProto)")
fmt.Fprintln(w, " _ = err // do something with err someday (?)")
fmt.Fprintln(w, " r.Vals = append(r.Vals, anyProto)")
fmt.Fprintln(w, " default:")
fmt.Fprintln(w, " log.Info(\"cell unhandled type\", r.Attr.Type)")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // cellTime := r.Vals[row]") fmt.Fprintln(w, " mt.pb.StringRows = append(mt.pb.StringRows, r)")
fmt.Fprintln(w, " // s := shell.FormatDuration(time.Since(cellTime.AsTime()))") fmt.Fprintln(w, " return true")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) doButtonFunc(name string) bool {")
fmt.Fprintln(w, " mt.pb.AnyCols = append(mt.pb.AnyCols, r)") fmt.Fprintln(w, " for _, sf := range mt.buttonFuncs {")
fmt.Fprintln(w, " if sf.title != name {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": found stringfunc name:\", name)")
fmt.Fprintln(w, " r := new(guipb.ButtonRow)")
fmt.Fprintln(w, " r.Header = new(guipb.Widget)")
fmt.Fprintln(w, " r.Header.Name = name")
fmt.Fprintln(w, " for m := range mt.x.IterAll() {")
fmt.Fprintln(w, " r.Vals = append(r.Vals, sf.f(m))")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": adding\", name, r.Vals)")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " mt.pb.ButtonRows = append(mt.pb.ButtonRows, r)")
fmt.Fprintln(w, " return true") fmt.Fprintln(w, " return true")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) doIntFunc(name string) bool {")
fmt.Fprintln(w, " for _, sf := range mt.intFuncs {")
fmt.Fprintln(w, " if sf.title != name {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": found intfunc name:\", name)")
fmt.Fprintln(w, " r := new(guipb.IntRow)")
fmt.Fprintln(w, " r.Header = new(guipb.Widget)")
fmt.Fprintln(w, " r.Header.Name = name")
fmt.Fprintln(w, " for m := range mt.x.IterAll() {")
fmt.Fprintln(w, " r.Vals = append(r.Vals, int64(sf.f(m)))")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": adding\", name, r.Vals)")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " mt.pb.IntRows = append(mt.pb.IntRows, r)")
fmt.Fprintln(w, " return true")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) doTimeFunc(name string) bool {")
fmt.Fprintln(w, " for _, sf := range mt.timeFuncs {")
fmt.Fprintln(w, " if sf.title != name {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": found timefunc name:\", name)")
fmt.Fprintln(w, " r := new(guipb.TimeRow)")
fmt.Fprintln(w, " r.Header = new(guipb.Widget)")
fmt.Fprintln(w, " r.Header.Name = name")
fmt.Fprintln(w, " for m := range mt.x.IterAll() {")
fmt.Fprintln(w, " t := sf.f(m)")
fmt.Fprintln(w, " r.Vals = append(r.Vals, timestamppb.New(t)) // convert to protobuf time")
fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": adding\", name, r.Vals)")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " mt.pb.TimeRows = append(mt.pb.TimeRows, r)")
fmt.Fprintln(w, " return true")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) MakeTable() {") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) MakeTable() {")
fmt.Fprintln(w, " for _, sf := range mt.anyFuncs {") fmt.Fprintln(w, " for _, name := range mt.pb.Order {")
fmt.Fprintln(w, " mt.doAnyFuncNew(sf)") fmt.Fprintln(w, " // log.Info(\""+ZOOPB+": looking for row name()\", name)")
fmt.Fprintln(w, " if mt.doStringFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if mt.doIntFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if mt.doTimeFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if mt.doButtonFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " }") fmt.Fprintln(w, " }")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
} }
func guiAddStringFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) { func guiAddStringFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) {
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) Add"+BRAND+"() *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) Add"+BRAND+"() *"+FRUIT+"StringFunc {")
fmt.Fprintln(w, " sf := t.AddStringFunc(\""+BRAND+"\", func(m *"+FRUIT+") string {") fmt.Fprintln(w, " sf := t.AddStringFunc(\""+BRAND+"\", func(m *"+FRUIT+") string {")
fmt.Fprintln(w, " return m."+BRAND+"") fmt.Fprintln(w, " return m."+BRAND+"")
fmt.Fprintln(w, " })") fmt.Fprintln(w, " })")
@ -298,12 +388,22 @@ func guiAddStringFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) {
func guiAddIntFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) { func guiAddIntFunc(w io.Writer, FRUITS string, FRUIT string, BRAND string) {
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) Add"+BRAND+"() *"+FRUIT+"AnyFunc {") fmt.Fprintln(w, "func (t *"+FRUITS+"Table) Add"+BRAND+"() {")
fmt.Fprintln(w, " custf := t.AddIntFunc(\""+BRAND+"\", func(m *"+FRUIT+") int {") fmt.Fprintln(w, " t.AddIntFunc(\""+BRAND+"\", func(m *"+FRUIT+") int {")
fmt.Fprintln(w, " return int(m."+BRAND+")") fmt.Fprintln(w, " return int(m."+BRAND+")")
fmt.Fprintln(w, " })") fmt.Fprintln(w, " })")
fmt.Fprintln(w, " return custf")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
/*
// examples of what these look like
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddMemory() {")
fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, \"Memory\")")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (t *"+FRUITS+"Table) AddCpus() {")
fmt.Fprintln(w, " t.pb.Order = append(t.pb.Order, \"Cpus\")")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
*/
} }
func guiUpdate(w io.Writer, FRUITS string, FRUIT string) { func guiUpdate(w io.Writer, FRUITS string, FRUIT string) {
@ -312,10 +412,28 @@ func guiUpdate(w io.Writer, FRUITS string, FRUIT string) {
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "// START TABLE UPDATE (doesn't work yet)") fmt.Fprintln(w, "// START TABLE UPDATE")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) todoUpdate() {")
fmt.Fprintln(w, " for _, name := range mt.pb.Order {")
fmt.Fprintln(w, " // log.Info(\""+FRUIT+"pb: trying to update row()\", name)")
fmt.Fprintln(w, " if mt.updateStringFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if mt.updateTimeFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " /*")
fmt.Fprintln(w, " if mt.updateIntFunc(name) {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " */")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // mt.dumpStringFunc(\"Hostname\")")
fmt.Fprintln(w, " mt.parent.UpdateTable(mt.pb)")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) dumpStringFunc(name string) {") fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) dumpStringFunc(name string) {")
fmt.Fprintln(w, " for i, r := range mt.pb.StringCols {") fmt.Fprintln(w, " for i, r := range mt.pb.StringRows {")
fmt.Fprintln(w, " // log.Info(\"could use\", i, r.Header.Name, \"for name =\", name)") fmt.Fprintln(w, " // log.Info(\"could use\", i, r.Header.Name, \"for name =\", name)")
fmt.Fprintln(w, " if r.Header.Name == name {") fmt.Fprintln(w, " if r.Header.Name == name {")
fmt.Fprintln(w, " log.Info(\"dump Strings row\", i, r.Header.Name, r.Vals)") fmt.Fprintln(w, " log.Info(\"dump Strings row\", i, r.Header.Name, r.Vals)")
@ -324,6 +442,70 @@ func guiUpdate(w io.Writer, FRUITS string, FRUIT string) {
fmt.Fprintln(w, " }") fmt.Fprintln(w, " }")
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) updateStringFunc(name string) bool {")
fmt.Fprintln(w, " // log.Info(\"LOOKING FOR STRING row\", name)")
fmt.Fprintln(w, " var found *guipb.StringRow")
fmt.Fprintln(w, " for _, r := range mt.pb.StringRows {")
fmt.Fprintln(w, " // log.Info(\"could use\", i, r.Header.Name, \"for name =\", name)")
fmt.Fprintln(w, " if r.Header.Name == name {")
fmt.Fprintln(w, " // log.Info(\"found row\", i, r.Header.Name)")
fmt.Fprintln(w, " found = r")
fmt.Fprintln(w, " break")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if found == nil {")
fmt.Fprintln(w, " log.Info(\"did not find string row\", name)")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " for _, sf := range mt.stringFuncs {")
fmt.Fprintln(w, " if sf.title != name {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\""+FRUIT+"pb: starting\", name, found.Vals)")
fmt.Fprintln(w, " for i, _ := range found.Vals {")
fmt.Fprintln(w, " tmp := sf.f(mt.x."+FRUITS+"[i])")
fmt.Fprintln(w, " if tmp == \"www.wit.com\" {")
fmt.Fprintln(w, " log.Info(\"virtpb: FOUND WWW\", i)")
fmt.Fprintln(w, " tmp = \"new.www\"")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " found.Vals[i] = tmp")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\""+FRUIT+"pb: ending\", name, found.Vals)")
fmt.Fprintln(w, " return true")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) updateTimeFunc(name string) bool {")
fmt.Fprintln(w, " log.Info(\"LOOKING FOR TIME row\", name)")
fmt.Fprintln(w, " var found *guipb.TimeRow")
fmt.Fprintln(w, " for i, r := range mt.pb.TimeRows {")
fmt.Fprintln(w, " // log.Info(\"could use\", i, r.Header.Name, \"for name =\", name)")
fmt.Fprintln(w, " if r.Header.Name == name {")
fmt.Fprintln(w, " log.Info(\"found row\", i, r.Header.Name)")
fmt.Fprintln(w, " found = r")
fmt.Fprintln(w, " break")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if found == nil {")
fmt.Fprintln(w, " log.Info(\"did not find time row\", name)")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " for _, sf := range mt.timeFuncs {")
fmt.Fprintln(w, " if sf.title != name {")
fmt.Fprintln(w, " continue")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\"updateTimeFunc() has row len =\", len(mt.x."+FRUITS+"))")
fmt.Fprintln(w, " // log.Info(\"virtpb: starting\", name, found.Vals)")
fmt.Fprintln(w, " for i, _ := range found.Vals {")
fmt.Fprintln(w, " newt := sf.f(mt.x."+FRUITS+"[i])")
fmt.Fprintln(w, " found.Vals[i] = timestamppb.New(newt) // convert to protobuf time")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " // log.Info(\"virtpb: ending\", name, found.Vals)")
fmt.Fprintln(w, " return true")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return false")
fmt.Fprintln(w, "}")
} }
func guiTableDelete(w io.Writer, FRUITS string, FRUIT string) { func guiTableDelete(w io.Writer, FRUITS string, FRUIT string) {
@ -344,8 +526,9 @@ func guiTableCustom(w io.Writer, FRUITS string, fRUITS string, FRUIT string, fRU
fmt.Fprintln(w, " row := mt.x."+FRUITS+"[w.Location.Y-1]") fmt.Fprintln(w, " row := mt.x."+FRUITS+"[w.Location.Y-1]")
fmt.Fprintln(w, " // log.Info(\"got to "+fRUITS+"Custom() with\", w.Location.X, w.Location.Y-1)") fmt.Fprintln(w, " // log.Info(\"got to "+fRUITS+"Custom() with\", w.Location.X, w.Location.Y-1)")
fmt.Fprintln(w, "") fmt.Fprintln(w, "")
fmt.Fprintln(w, " for i, sf := range mt.anyFuncs {") fmt.Fprintln(w, " for _, sf := range mt.buttonFuncs {")
fmt.Fprintln(w, " if i == int(w.Location.X) {") fmt.Fprintln(w, " if sf.order == int(w.Location.X) {")
fmt.Fprintln(w, " // log.Info(\"found order\", sf.order)")
fmt.Fprintln(w, " if sf.Custom != nil {") fmt.Fprintln(w, " if sf.Custom != nil {")
fmt.Fprintln(w, " log.Info(\"doing Custom() func for button\")") fmt.Fprintln(w, " log.Info(\"doing Custom() func for button\")")
fmt.Fprintln(w, " sf.Custom(row)") fmt.Fprintln(w, " sf.Custom(row)")

View File

@ -1,129 +0,0 @@
// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
// Use of this source code is governed by the GPL 3.0
package main
import (
"fmt"
"io"
"os"
"go.wit.com/log"
)
func (pb *Files) makeHTTPFile(pf *File) error {
newf, _ := os.OpenFile(pf.Filebase+".http.pb.go", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
defer newf.Close()
headerHTTP(newf, pf)
fmt.Fprintf(newf, "// START HTTP\n")
fmt.Fprintf(newf, "\n")
/*
FRUITS := pf.Bases.Name
FRUIT := pf.Base.Name
fruitVars := pf.Base.Vars
pf.generateAutoTablePB(newf, FRUITS, FRUIT, fruitVars)
*/
for _, msg := range pf.allMsg() {
if msg.DoHTTP {
FRUITS := msg.Name
fRUITS := untitle(FRUITS)
httpSendReply(newf, FRUITS)
httpPost(newf, FRUITS, fRUITS)
log.Printf("func (p *%s) HttpPost(baseURL string, route string) (*%s, *httppb.HttpRequest, error)\n", FRUITS, FRUITS)
}
}
fmt.Fprintf(newf, "// END HTTP\n")
return nil
}
func headerHTTP(w io.Writer, pf *File) {
// header must come first
headerComment(w)
fmt.Fprintf(w, "package %s\n", pf.Package)
fmt.Fprintln(w, "")
fmt.Fprintln(w, "import (")
fmt.Fprintln(w, " \"time\"")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " \"go.wit.com/lib/protobuf/httppb\"")
fmt.Fprintln(w, ")")
fmt.Fprintln(w, "")
}
func httpTest(w io.Writer, FRUITS string, fRUITS string, FRUIT string, fRUIT string) {
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) "+fRUITS+"Custom(w *guipb.Widget) {")
fmt.Fprintln(w, " row := mt.x."+FRUITS+"[w.Location.Y-1]")
fmt.Fprintln(w, " // log.Info(\"got to "+fRUITS+"Custom() with\", w.Location.X, w.Location.Y-1)")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " for _, sf := range mt.buttonFuncs {")
fmt.Fprintln(w, " if sf.order == int(w.Location.X) {")
fmt.Fprintln(w, " // log.Info(\"found order\", sf.order)")
fmt.Fprintln(w, " if sf.Custom != nil {")
fmt.Fprintln(w, " log.Info(\"doing Custom() func for button\")")
fmt.Fprintln(w, " sf.Custom(row)")
fmt.Fprintln(w, " return")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " mt.CustomFunc(row)")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) Custom(f func(*"+FRUIT+")) {")
fmt.Fprintln(w, " mt.pb.RegisterCustom(mt."+fRUITS+"Custom)")
fmt.Fprintln(w, " mt.CustomFunc = f")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "")
fmt.Fprintln(w, "func (mt *"+FRUITS+"Table) GetUuid() string {")
fmt.Fprintln(w, " return mt.pb.Uuid")
fmt.Fprintln(w, "}")
fmt.Fprintln(w, "// END TABLE UPDATE")
}
func httpSendReply(w io.Writer, FRUITS string) {
fmt.Fprintln(w, "func (p *"+FRUITS+") SendReply(w http.ResponseWriter, reqPB *httppb.HttpRequest) error {")
fmt.Fprintln(w, " data, err := p.Marshal()")
fmt.Fprintln(w, " if err != nil {")
fmt.Fprintln(w, " // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, err))")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " if len(data) == 0 {")
fmt.Fprintln(w, " // reqPB.Errors = append(reqPB.Errors, \"Patches PB data was nil/emtpy without Marsha() error\")")
fmt.Fprintln(w, " return nil")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " _, err = w.Write(data)")
fmt.Fprintln(w, " if err != nil {")
fmt.Fprintln(w, " // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, i, err))")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, " return err")
fmt.Fprintln(w, "}")
}
func httpPost(w io.Writer, FRUITS string, fRUITS string) {
fmt.Fprintln(w, "// Marshal protobuf, then http POST, then Unmarshal() to protobuf again")
fmt.Fprintln(w, "func (p *"+FRUITS+") HttpPost(baseURL string, route string) (*"+FRUITS+", *httppb.HttpRequest, error) {")
fmt.Fprintln(w, " data, err := p.Marshal()")
fmt.Fprintln(w, " if err != nil {")
fmt.Fprintln(w, " return nil, nil, err")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " tmp := filepath.Join(\""+fRUITS+"\",route)")
fmt.Fprintln(w, " reqPB, err := httppb.DoPost(baseURL, tmp, data)")
fmt.Fprintln(w, " if reqPB == nil {")
fmt.Fprintln(w, " return nil, nil, err")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " if len(reqPB.ServerData) == 0 {")
fmt.Fprintln(w, " return nil, reqPB, fmt.Errorf(\"server returned len(data)=0\")")
fmt.Fprintln(w, " }")
fmt.Fprintln(w, "")
fmt.Fprintln(w, " newpb := new("+FRUITS+")")
fmt.Fprintln(w, " err = newpb.Unmarshal(reqPB.ServerData)")
fmt.Fprintln(w, " return newpb, reqPB, err")
fmt.Fprintln(w, "}")
}

11
main.go
View File

@ -19,8 +19,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/alexflint/go-arg"
"github.com/go-cmd/cmd" "github.com/go-cmd/cmd"
"go.wit.com/dev/alexflint/arg"
"go.wit.com/lib/fhelp" "go.wit.com/lib/fhelp"
"go.wit.com/lib/gui/shell" "go.wit.com/lib/gui/shell"
"go.wit.com/log" "go.wit.com/log"
@ -208,15 +208,6 @@ func main() {
badExit(err) badExit(err)
} }
} }
if pf.DoHTTP {
if err := pb.makeHTTPFile(pf); err != nil {
badExit(err)
}
}
log.Info("")
log.Info("you may have to run 'goimport -w *.go' on the new *pb.go files")
log.Info("")
} }
func okExit(s string) { func okExit(s string) {

View File

@ -192,12 +192,7 @@ func (pf *File) parseForMessage(line string) *MsgName {
} }
if strings.Contains(line, "`autogenpb:marshal`") { if strings.Contains(line, "`autogenpb:marshal`") {
msg.DoMarshal = true msg.DoMarshal = true
} // log.Info("Added Marshal=true:", msg.Name)
if strings.Contains(line, "`autogenpb:http") {
log.Info("got autogenpb:http")
pf.DoHTTP = true
msg.DoHTTP = true
msg.DoMarshal = true // http requires Marshal
} }
if strings.Contains(line, "`autogenpb:gui") { if strings.Contains(line, "`autogenpb:gui") {
log.Info("got autogenpb:gui") log.Info("got autogenpb:gui")

View File

@ -37,10 +37,6 @@ type Message interface {
} }
*/ */
// protoReformatComments reads a .proto file, processes its comments using
// commentPreprocessor and commentPreprocessorFull, and writes the modified
// content back to the file. This function serves as a dedicated comment
// processing tool.
func protoReformatComments(filename string) error { func protoReformatComments(filename string) error {
// read in the .proto file // read in the .proto file
data, err := os.ReadFile(filename) data, err := os.ReadFile(filename)
@ -62,9 +58,6 @@ func protoReformatComments(filename string) error {
return nil return nil
} }
// protoReformat reads a .proto file, parses it into a structured format,
// aligns its contents for readability, and writes the formatted output back to
// the original file. It acts as the main entry point for the formatting process.
func protoReformat(filename string) error { func protoReformat(filename string) error {
// read in the .proto file // read in the .proto file
data, err := os.ReadFile(filename) data, err := os.ReadFile(filename)
@ -84,18 +77,6 @@ func protoReformat(filename string) error {
return saveFile(filename, newfile) return saveFile(filename, newfile)
} }
// doParse is the core parsing engine for the protoReformat tool. It processes
// the raw lines of a .proto file and constructs a hierarchical tree of
// FormatMsg structs.
//
// This tree mirrors the .proto file's logical structure, representing `message`,
// `enum`, and `oneof` blocks as distinct nodes. The function recursively
// handles nested definitions and carefully preserves associated comments and
// surrounding whitespace, which are essential for the final formatting.
//
// The returned *FormatMsg is the root of this tree, containing the complete,
// structured representation of the file, which is then used by the format
// functions to generate a clean, aligned output.
func doParse(lines []string) *FormatMsg { func doParse(lines []string) *FormatMsg {
var comments string var comments string
@ -175,9 +156,6 @@ func doParse(lines []string) *FormatMsg {
return basemsg return basemsg
} }
// saveFile writes the provided data to a specified file, creating it if it
// doesn't exist or truncating it if it does. It ensures the data is trimmed of
// surrounding whitespace before writing.
func saveFile(filename string, data string) error { func saveFile(filename string, data string) error {
pf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) pf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil { if err != nil {
@ -192,9 +170,6 @@ func saveFile(filename string, data string) error {
return nil return nil
} }
// newDepth creates a new FormatMsg, representing a nested message structure.
// It inherits formatting parameters from its parent and increments the nesting
// depth, which is used to calculate indentation.
func newDepth(fmtmsg *FormatMsg, header string) *FormatMsg { func newDepth(fmtmsg *FormatMsg, header string) *FormatMsg {
newmsg := new(FormatMsg) newmsg := new(FormatMsg)
lastMessage = newmsg lastMessage = newmsg
@ -206,9 +181,6 @@ func newDepth(fmtmsg *FormatMsg, header string) *FormatMsg {
return newmsg return newmsg
} }
// newMessage creates a new FormatMsg of a specified type (e.g., message, enum)
// and appends it to the parent's list of messages. It associates the new
// message with its preceding comments.
func (msgPB *FormatMsg) newMessage(header string, comments string, msgType FormatMsg_Type) *FormatMsg { func (msgPB *FormatMsg) newMessage(header string, comments string, msgType FormatMsg_Type) *FormatMsg {
newmsg := newDepth(msgPB, header) newmsg := newDepth(msgPB, header)
newmsg.Type = msgType newmsg.Type = msgType
@ -220,9 +192,6 @@ func (msgPB *FormatMsg) newMessage(header string, comments string, msgType Forma
return newmsg return newmsg
} }
// load recursively parses the content within a message, enum, or oneof block.
// It consumes lines from the global line scanner until it reaches the closing
// brace '}' of the current block, creating nested messages as needed.
func (msg *FormatMsg) load() { func (msg *FormatMsg) load() {
// fmtmsg := msg.msgPB // fmtmsg := msg.msgPB
for allTheLines.Scan() { for allTheLines.Scan() {
@ -265,10 +234,7 @@ func (msg *FormatMsg) load() {
return return
} }
// tokenMsgVar parses a line containing a field definition within a .proto message. // returns vartype, varname, id, end
// It extracts and returns the variable type, name, ID, and any trailing comments
// or options. For example, from "string name = 1; // User's name", it returns
// "string", "name", "1", and "// User's name".
func tokenMsgVar(line string) (string, string, string, string) { func tokenMsgVar(line string) (string, string, string, string) {
parts := strings.Split(line, ";") parts := strings.Split(line, ";")
front := parts[0] front := parts[0]
@ -287,8 +253,6 @@ func tokenMsgVar(line string) (string, string, string, string) {
return vartype, varname, id, end return vartype, varname, id, end
} }
// slicesPop removes and returns the last element from a slice of strings,
// along with the modified slice. It is a utility function for tokenizing lines.
func slicesPop(parts []string) ([]string, string) { func slicesPop(parts []string) ([]string, string) {
if len(parts) == 0 { if len(parts) == 0 {
return nil, "" return nil, ""
@ -301,9 +265,7 @@ func slicesPop(parts []string) ([]string, string) {
return parts[0 : x-1], end return parts[0 : x-1], end
} }
// makeLineIter creates a Go 1.24+ style iterator (iter.Seq) from a byte slice // 'for x := range' syntax using the smartly done golang 1.24 'iter'
// of file content. This allows for convenient line-by-line iteration using
// `for ... range`.
func makeLineIter(data []byte) iter.Seq[string] { func makeLineIter(data []byte) iter.Seq[string] {
items := strings.Split(string(data), "\n") items := strings.Split(string(data), "\n")
// log.Println("Made All() Iter.Seq[] with length", len(items)) // log.Println("Made All() Iter.Seq[] with length", len(items))
@ -316,9 +278,7 @@ func makeLineIter(data []byte) iter.Seq[string] {
} }
} }
// setMaxSizes calculates the maximum length of field types and names within a // find the max length of varname and vartype
// message. These values are used later to determine the padding required for
// consistent alignment of fields.
func setMaxSizes(curmsg *FormatMsg) { func setMaxSizes(curmsg *FormatMsg) {
for _, line := range curmsg.Lines { for _, line := range curmsg.Lines {
parts := strings.Split(line, ";") parts := strings.Split(line, ";")
@ -337,8 +297,7 @@ func setMaxSizes(curmsg *FormatMsg) {
} }
} }
// padBase generates the indentation string for message headers and footers // use this for header and footer lines
// based on their nesting depth.
func (msg *FormatMsg) padBase() string { func (msg *FormatMsg) padBase() string {
var pad string var pad string
for i := 1; i < int(msg.Depth); i += 1 { for i := 1; i < int(msg.Depth); i += 1 {
@ -347,8 +306,7 @@ func (msg *FormatMsg) padBase() string {
return pad return pad
} }
// pad generates the indentation string for lines inside a message block, // use this for lines inside the message
// such as field definitions, based on the message's nesting depth.
func (msg *FormatMsg) pad() string { func (msg *FormatMsg) pad() string {
var pad string var pad string
for i := 0; i < int(msg.Depth); i += 1 { for i := 0; i < int(msg.Depth); i += 1 {
@ -357,8 +315,6 @@ func (msg *FormatMsg) pad() string {
return pad return pad
} }
// padding generates an indentation string with a custom offset, allowing for
// flexible alignment calculations.
func (msg *FormatMsg) padding(offset int) string { func (msg *FormatMsg) padding(offset int) string {
var pad string var pad string
for i := offset; i < int(msg.Depth); i += 1 { for i := offset; i < int(msg.Depth); i += 1 {
@ -367,8 +323,6 @@ func (msg *FormatMsg) padding(offset int) string {
return pad return pad
} }
// formatEnum formats an enum block, including its header, values, and footer,
// ensuring proper indentation.
func formatEnum(curmsg *FormatMsg) []string { func formatEnum(curmsg *FormatMsg) []string {
var newmsg []string var newmsg []string
newmsg = append(newmsg, curmsg.formatLineBase(curmsg.Header, "enum header")) newmsg = append(newmsg, curmsg.formatLineBase(curmsg.Header, "enum header"))
@ -386,8 +340,6 @@ func formatEnum(curmsg *FormatMsg) []string {
return newmsg return newmsg
} }
// formatOneof formats a oneof block, aligning its fields and comments
// according to the calculated padding.
func formatOneof(curmsg *FormatMsg) []string { func formatOneof(curmsg *FormatMsg) []string {
// curmsg.formatStandardSizes() // curmsg.formatStandardSizes()
@ -408,9 +360,7 @@ func formatOneof(curmsg *FormatMsg) []string {
return newmsg return newmsg
} }
// formatStandardSizes traverses the message tree and standardizes the padding // set all children to have the same max sizes
// for field types and names across all sibling messages. This ensures that
// fields in adjacent messages are vertically aligned, improving readability.
func (parent *FormatMsg) formatStandardSizes() { func (parent *FormatMsg) formatStandardSizes() {
var bigType int64 var bigType int64
var bigName int64 var bigName int64
@ -456,8 +406,6 @@ func (parent *FormatMsg) formatStandardSizes() {
} }
} }
// format is the main formatting dispatcher. It calls the appropriate formatting
// function (formatEnum, formatOneof, or formatMessage) based on the message type.
func (parent *FormatMsg) format() []string { func (parent *FormatMsg) format() []string {
parent.formatStandardSizes() parent.formatStandardSizes()
@ -473,8 +421,6 @@ func (parent *FormatMsg) format() []string {
} }
} }
// formatFooter formats the closing brace '}' of a message block, applying the
// correct base indentation.
func (msg *FormatMsg) formatFooter(line string, dbg string) string { func (msg *FormatMsg) formatFooter(line string, dbg string) string {
if line == "" { if line == "" {
if argv.Debug { if argv.Debug {
@ -485,8 +431,6 @@ func (msg *FormatMsg) formatFooter(line string, dbg string) string {
return msg.formatLineBase(line, "footer") return msg.formatLineBase(line, "footer")
} }
// formatPadAfter adds a blank line after a message block if the original
// file contained one, preserving vertical spacing.
func (msg *FormatMsg) formatPadAfter() string { func (msg *FormatMsg) formatPadAfter() string {
if argv.Debug { if argv.Debug {
return msg.formatLineBase("", "pad after") return msg.formatLineBase("", "pad after")
@ -494,8 +438,6 @@ func (msg *FormatMsg) formatPadAfter() string {
return "" return ""
} }
// formatHeader formats the opening line of a message block (e.g., "message Foo {"),
// aligning any trailing comments.
func (msg *FormatMsg) formatHeader(line string, dbg string) string { func (msg *FormatMsg) formatHeader(line string, dbg string) string {
if line == "" { if line == "" {
if msg.Depth != 0 { if msg.Depth != 0 {
@ -521,8 +463,6 @@ func (msg *FormatMsg) formatHeader(line string, dbg string) string {
return fmt.Sprintf(hmm, msg.padBase(), start, " ", end) return fmt.Sprintf(hmm, msg.padBase(), start, " ", end)
} }
// formatLineBase formats a line using the base indentation level, suitable for
// headers, footers, and comments outside of message bodies.
func (msg *FormatMsg) formatLineBase(line string, dbg string) string { func (msg *FormatMsg) formatLineBase(line string, dbg string) string {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if argv.Debug { if argv.Debug {
@ -531,8 +471,6 @@ func (msg *FormatMsg) formatLineBase(line string, dbg string) string {
return fmt.Sprintf("%s%s", msg.padBase(), line) return fmt.Sprintf("%s%s", msg.padBase(), line)
} }
// formatLine formats a line using the standard block indentation, suitable for
// field definitions and other content inside a message body.
func (msg *FormatMsg) formatLine(line string, dbg string) string { func (msg *FormatMsg) formatLine(line string, dbg string) string {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if argv.Debug { if argv.Debug {
@ -541,8 +479,6 @@ func (msg *FormatMsg) formatLine(line string, dbg string) string {
return fmt.Sprintf("%s%s", msg.pad(), line) return fmt.Sprintf("%s%s", msg.pad(), line)
} }
// formatComment formats a comment line, aligning it with the surrounding code
// based on the calculated maximum field widths.
func (msg *FormatMsg) formatComment(line string, dbg string) string { func (msg *FormatMsg) formatComment(line string, dbg string) string {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
pad := fmt.Sprintf("%d", msg.MaxVartype+msg.MaxVarname+13) // 21 is correct? pad := fmt.Sprintf("%d", msg.MaxVartype+msg.MaxVarname+13) // 21 is correct?
@ -554,8 +490,6 @@ func (msg *FormatMsg) formatComment(line string, dbg string) string {
return fmt.Sprintf("%s%s", msg.pad(), comment) return fmt.Sprintf("%s%s", msg.pad(), comment)
} }
// formatVarLine formats a field definition line, padding the type and name to
// ensure vertical alignment with other fields in the same scope.
func (msg *FormatMsg) formatVarLine(line string, dbg string) string { func (msg *FormatMsg) formatVarLine(line string, dbg string) string {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
mt := fmt.Sprintf("%d", msg.MaxVartype) mt := fmt.Sprintf("%d", msg.MaxVartype)
@ -576,9 +510,6 @@ func (msg *FormatMsg) formatVarLine(line string, dbg string) string {
return fmt.Sprintf("%s%s", msg.pad(), newline) return fmt.Sprintf("%s%s", msg.pad(), newline)
} }
// formatMsgLine is a dispatcher for formatting a single line within a message.
// It determines whether the line is a comment or a field definition and calls
// the appropriate formatting function.
func (msg *FormatMsg) formatMsgLine(line string, dbg string) string { func (msg *FormatMsg) formatMsgLine(line string, dbg string) string {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if line == "" { if line == "" {
@ -594,15 +525,11 @@ func (msg *FormatMsg) formatMsgLine(line string, dbg string) string {
return msg.formatVarLine(line, "var "+dbg) return msg.formatVarLine(line, "var "+dbg)
} }
// trimLines removes leading/trailing whitespace and blank lines from a slice // chop extra spaces and blank lines
// of strings by joining and splitting them.
func trimLines(lines []string) []string { func trimLines(lines []string) []string {
return strings.Split(strings.TrimSpace(strings.Join(lines, "\n")), "\n") return strings.Split(strings.TrimSpace(strings.Join(lines, "\n")), "\n")
} }
// formatMessage is the main function for formatting a `message` block. It
// orchestrates the formatting of comments, nested messages, and field
// definitions to produce a clean, aligned output.
func formatMessage(curmsg *FormatMsg) []string { func formatMessage(curmsg *FormatMsg) []string {
var newmsg []string var newmsg []string
@ -693,14 +620,11 @@ func formatMessage(curmsg *FormatMsg) []string {
} }
// DEFINE THE Lines ITERATOR. // DEFINE THE Lines ITERATOR.
// itializes a new iterator.
// newLinesScanner initializes a new LinesScanner iterator with a slice of strings.
func newLinesScanner(things []string) *LinesScanner { func newLinesScanner(things []string) *LinesScanner {
return &LinesScanner{things: things} return &LinesScanner{things: things}
} }
// LinesScanner provides an iterator over a slice of strings, allowing for
// sequential access and the ability to un-scan (step back).
type LinesScanner struct { type LinesScanner struct {
sync.Mutex sync.Mutex
@ -708,8 +632,6 @@ type LinesScanner struct {
index int index int
} }
// Scan advances the iterator to the next line. It returns false if there are
// no more lines.
func (it *LinesScanner) Scan() bool { func (it *LinesScanner) Scan() bool {
if it.index >= len(it.things) { if it.index >= len(it.things) {
return false return false
@ -720,8 +642,6 @@ func (it *LinesScanner) Scan() bool {
return true return true
} }
// UnScan moves the iterator back one line. It returns false if the iterator
// is already at the beginning.
func (it *LinesScanner) UnScan() bool { func (it *LinesScanner) UnScan() bool {
if it.index < 1 { if it.index < 1 {
it.index = 0 it.index = 0
@ -733,7 +653,7 @@ func (it *LinesScanner) UnScan() bool {
return true return true
} }
// NextRaw returns the current line from the scanner without any modification. // does no cleaning of the data
func (it *LinesScanner) NextRaw() string { func (it *LinesScanner) NextRaw() string {
if it.index-1 == len(it.things) { if it.index-1 == len(it.things) {
fmt.Println("Next() error in LinesScanner", it.index) fmt.Println("Next() error in LinesScanner", it.index)
@ -741,8 +661,7 @@ func (it *LinesScanner) NextRaw() string {
return it.things[it.index-1] return it.things[it.index-1]
} }
// Next returns the current line from the scanner with leading and trailing // trims whitespace
// whitespace removed.
func (it *LinesScanner) Next() string { func (it *LinesScanner) Next() string {
if it.index-1 == len(it.things) { if it.index-1 == len(it.things) {
fmt.Println("Next() error in LinesScanner", it.index) fmt.Println("Next() error in LinesScanner", it.index)
@ -755,9 +674,8 @@ func (it *LinesScanner) Next() string {
// END DEFINE THE ITERATOR // END DEFINE THE ITERATOR
// commentPreprocessor converts single-line C-style block comments (/* ... */) // turns: "/* test */ reserved /* linkPreviews */ 4;"
// into Go-style line comments (// ...) appended to the end of the line. // into: reserved 1; // test // linkPreviews
// For example, "/* test */ reserved 4;" becomes "reserved 4; // test".
func commentPreprocessor(line string) string { func commentPreprocessor(line string) string {
// Match all /* comment */ blocks // Match all /* comment */ blocks
re := regexp.MustCompile(`/\*([^*]+)\*/`) re := regexp.MustCompile(`/\*([^*]+)\*/`)
@ -783,8 +701,14 @@ func commentPreprocessor(line string) string {
return line return line
} }
// commentPreprocessorFull transforms multi-line C-style block comments // /* this
// (/* ... */) into a series of single-line Go-style comments (// ...). // - thing
// */
//
// becomes
//
// this
// thing
func commentPreprocessorFull(full string) string { func commentPreprocessorFull(full string) string {
// Match all /* comment */ blocks // Match all /* comment */ blocks
// re := regexp.MustCompile(`/\*([^*]+)\*/`) // re := regexp.MustCompile(`/\*([^*]+)\*/`)
@ -817,8 +741,6 @@ func commentPreprocessorFull(full string) string {
}) })
} }
// trimCommentPrefix is a helper function for commentPreprocessorFull that
// removes leading comment markers like '/*', '*', and '*/' from a line.
func trimCommentPrefix(line string) string { func trimCommentPrefix(line string) string {
trimmed := strings.TrimSpace(line) trimmed := strings.TrimSpace(line)