From ddd65f18b4e6b6e07d97659ed9342b7785aa37c0 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sun, 20 Jul 2025 22:21:00 +0200 Subject: [PATCH] Hallucinate enum support --- class.go | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- enum.tmpl | 9 ++++ main.go | 82 ++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 enum.tmpl diff --git a/class.go b/class.go index a8b4d6f..435ab17 100644 --- a/class.go +++ b/class.go @@ -16,6 +16,10 @@ import ( var templatestr string var classTemplate *template.Template +//go:embed enum.tmpl +var enumTemplateStr string +var enumTemplate *template.Template + var fns = template.FuncMap{ "plus1": func(x int) int { return x + 1 @@ -39,14 +43,19 @@ var fns = template.FuncMap{ func init() { log := logger.Default.WithPrefix("init") - log.Info("Initializing template") + log.Info("Initializing templates") var err error classTemplate, err = template.New("class").Funcs(fns).Parse(templatestr) if err != nil { - logger.Error("Error parsing template: %v", err) + logger.Error("Error parsing class template: %v", err) return } - log.Info("Template initialized successfully") + enumTemplate, err = template.New("enum").Funcs(fns).Parse(enumTemplateStr) + if err != nil { + logger.Error("Error parsing enum template: %v", err) + return + } + log.Info("Templates initialized successfully") } type ( @@ -81,6 +90,11 @@ type ( Params []Param Comment string } + Enum struct { + Name string + Values []string + Comment string + } ) func (c *Class) GetOutFile(root string) (*os.File, error) { @@ -115,6 +129,38 @@ func (c *Class) GetOutFile(root string) (*os.File, error) { return f, nil } +func (e *Enum) GetOutFile(root string) (*os.File, error) { + log := logger.Default.WithPrefix("GetOutFile") + log.Debug("Getting output file for enum: %s", e.Name) + + if e.Name == "" { + log.Error("Name is empty") + return nil, fmt.Errorf("Name is empty") + } + + filename := fmt.Sprintf("%s.lua", e.Name) + log.Trace("Original filename: %s", filename) + + filename = strings.ReplaceAll(filename, " ", "") + filename = strings.ReplaceAll(filename, "-", "") + filename = strings.ReplaceAll(filename, ",", "") + filename = strings.ReplaceAll(filename, ":", "") + log.Trace("Cleaned filename: %s", filename) + + filePath := filepath.Join(root, filename) + filePath = filepath.Clean(filePath) + log.Debug("Full file path: %s", filePath) + + f, err := os.Create(filePath) + if err != nil { + log.Error("Error creating file: %v", err) + return nil, err + } + + log.Info("Successfully created output file: %s", filePath) + return f, nil +} + func (c *Class) Write(root string, tmpl *template.Template) error { log := logger.Default.WithPrefix("Write") log.Info("Writing class %s to output", c.ClassName) @@ -136,6 +182,91 @@ func (c *Class) Write(root string, tmpl *template.Template) error { return nil } +func (e *Enum) Write(root string, tmpl *template.Template) error { + log := logger.Default.WithPrefix("Write") + log.Info("Writing enum %s to output", e.Name) + + outfile, err := e.GetOutFile(root) + if err != nil { + log.Error("Error creating output file %v: %v", e.Name, err) + return fmt.Errorf("error creating output file %v: %v", e.Name, err) + } + + log.Debug("Executing template for enum: %s", e.Name) + err = tmpl.Execute(outfile, e) + if err != nil { + log.Error("Error writing output file %v: %v", e.Name, err) + return fmt.Errorf("error writing output file %v: %v", e.Name, err) + } + + log.Info("Successfully wrote enum %s to output", e.Name) + return nil +} + +func ParseEnum(file string) (*Enum, error) { + log := logger.Default.WithPrefix(file) + log.Info("Starting to parse enum file") + + res := Enum{ + Values: []string{}, + } + + log.Debug("Opening file: %s", file) + filehandle, err := os.Open(file) + if err != nil { + log.Error("Error opening file: %v", err) + return nil, fmt.Errorf("error opening file: %w", err) + } + + log.Debug("Creating goquery document from file") + doc, err := goquery.NewDocumentFromReader(filehandle) + if err != nil { + log.Error("Error parsing file: %v", err) + return nil, fmt.Errorf("error parsing file: %w", err) + } + + // Find all enum containers + codeblocks := doc.Find("div.floatright > div.codecontainer") + log.Trace("Found %d code blocks", codeblocks.Length()) + + codeblocks.Each(func(i int, s *goquery.Selection) { + // Check if this is an enum block + enumType := s.Find("span.type").First() + if !strings.HasPrefix(strings.TrimSpace(enumType.Text()), "enum") { + return + } + + // Get enum name from the ID attribute + enumName := s.AttrOr("id", "") + if enumName == "" { + return + } + + res.Name = enumName + + // Get enum comment if any + comment := s.Find("p").Text() + if comment != "" { + res.Comment = strings.TrimSpace(comment) + } + + // Get enum values + s.Contents().Each(func(i int, s *goquery.Selection) { + if s.Is("br") { + return + } + text := strings.TrimSpace(s.Text()) + if text == "" || strings.HasPrefix(text, "enum") { + return + } + res.Values = append(res.Values, text) + }) + }) + + log.Info("Successfully parsed enum %s with %d values", res.Name, len(res.Values)) + return &res, nil +} + func ParseClass(file string) (*Class, error) { log := logger.Default.WithPrefix(file) log.Info("Starting to parse file") diff --git a/enum.tmpl b/enum.tmpl new file mode 100644 index 0000000..db66a77 --- /dev/null +++ b/enum.tmpl @@ -0,0 +1,9 @@ +--luacheck: ignore 212 111 +---@diagnostic disable: missing-return, lowercase-global +{{if ne .Comment ""}}-- {{.Comment}}{{end}} +---@enum {{.Name}} +{{.Name}} = { +{{- range $index, $value := .Values}} + {{$value}} = "{{$value}}", +{{- end}} +} \ No newline at end of file diff --git a/main.go b/main.go index a6de22b..5b6d4a7 100644 --- a/main.go +++ b/main.go @@ -46,6 +46,19 @@ func main() { // Process each group in parallel utils.WithWorkers(100, workItems, func(worker int, item WorkItem) { + // First check for enums in each file + for _, file := range item.GroupFiles { + hasEnums, err := processEnums(file, *outdir) + if err != nil { + logger.Error("Error processing enums in file %s: %v", file, err) + } + // If the file only contained enums, skip class parsing + if hasEnums && !strings.Contains(file, "[Client]") && !strings.Contains(file, "[Server]") { + return + } + } + + // Then process classes if len(item.GroupFiles) == 1 { // Single file, process normally class, err := ParseClass(item.GroupFiles[0]) @@ -66,6 +79,75 @@ func main() { }) } +func processEnums(file string, outdir string) (bool, error) { + log := logger.Default.WithPrefix("processEnums") + log.Info("Processing enums from file: %s", file) + + filehandle, err := os.Open(file) + if err != nil { + return false, fmt.Errorf("error opening file: %w", err) + } + defer filehandle.Close() + + doc, err := goquery.NewDocumentFromReader(filehandle) + if err != nil { + return false, fmt.Errorf("error parsing file: %w", err) + } + + // Find all code containers + codeblocks := doc.Find("div.codecontainer") + log.Trace("Found %d code blocks", codeblocks.Length()) + + foundEnums := false + codeblocks.Each(func(i int, s *goquery.Selection) { + // Check if this is an enum block + enumType := s.Find("span.type").First() + if !strings.HasPrefix(strings.TrimSpace(enumType.Text()), "enum") { + return + } + + foundEnums = true + + // Get enum name from the ID attribute + enumName := s.AttrOr("id", "") + if enumName == "" { + return + } + + enum := &Enum{ + Name: enumName, + Values: []string{}, + } + + // Get enum comment if any + comment := s.Find("p").Text() + if comment != "" { + enum.Comment = strings.TrimSpace(comment) + } + + // Get enum values + s.Contents().Each(func(i int, s *goquery.Selection) { + if s.Is("br") { + return + } + text := strings.TrimSpace(s.Text()) + if text == "" || strings.HasPrefix(text, "enum") { + return + } + enum.Values = append(enum.Values, text) + }) + + if len(enum.Values) > 0 { + log.Info("Writing enum %s with %d values", enum.Name, len(enum.Values)) + if err := enum.Write(outdir, enumTemplate); err != nil { + log.Error("Error writing enum %s: %v", enum.Name, err) + } + } + }) + + return foundEnums, nil +} + func MapType(t string) string { // Handle complex types like table if strings.Contains(t, "<") && strings.Contains(t, ">") {