This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch main
in repository ego.

View the commit online.

commit 23181f96cfbbdbdef8c38161af6fe1bac7c5c8b5
Author: [email protected] <[email protected]>
AuthorDate: Sun Mar 29 22:00:53 2026 -0600

    feat(ego-gen): add indexed property template with accessor pattern
    
    Generate unexported accessor structs for indexed properties.
    Each accessor captures the Eo object pointer and key values,
    exposing Get() and/or Set() methods.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 cmd/ego-gen/generator_test.go       |  77 ++++++++++++++++++++++++++
 cmd/ego-gen/templates/class.go.tmpl | 105 ++++++++++++++++++++++++++++++++++++
 2 files changed, 182 insertions(+)

diff --git a/cmd/ego-gen/generator_test.go b/cmd/ego-gen/generator_test.go
index 5daff44..76da170 100644
--- a/cmd/ego-gen/generator_test.go
+++ b/cmd/ego-gen/generator_test.go
@@ -456,6 +456,83 @@ func TestGenerateClass_IndexedProperty(t *testing.T) {
 	}
 }
 
+func TestGenerateClass_IndexedPropertyMultiValue(t *testing.T) {
+	g, outDir := newTestGenerator(t)
+
+	data := ClassData{
+		PackageName:   "gfx",
+		GoName:        "ColorClass",
+		EolianName:    "Efl.Gfx.Color_Class",
+		CClassName:    "EFL_GFX_COLOR_CLASS_CLASS",
+		CClassGetFunc: "efl_gfx_color_class_class_get",
+		CPrefix:       "efl_gfx_color_class",
+		EOHeaderFile:  "efl_gfx_color_class.eo.h",
+		IsAbstract:    true,
+		IndexedProperties: []IndexedPropertyData{
+			{
+				GoAccessorMethod: "ColorClass",
+				AccessorTypeName: "colorClassProperty",
+				CGetName:         "efl_gfx_color_class_get",
+				CSetName:         "efl_gfx_color_class_set",
+				HasGet:           true,
+				HasSet:           true,
+				Keys: []ParamData{
+					{GoName: "colorClass", GoType: "string", CType: "const char *"},
+					{GoName: "layer", GoType: "int", CType: "int"},
+				},
+				IsMultiValue: true,
+				MultiGetValues: []MultiValueData{
+					{GoName: "R", LowerGoName: "r", GoType: "int", CType: "int"},
+					{GoName: "G", LowerGoName: "g", GoType: "int", CType: "int"},
+					{GoName: "B", LowerGoName: "b", GoType: "int", CType: "int"},
+					{GoName: "A", LowerGoName: "a", GoType: "int", CType: "int"},
+				},
+				MultiSetValues: []MultiValueData{
+					{GoName: "R", LowerGoName: "r", GoType: "int", CType: "int"},
+					{GoName: "G", LowerGoName: "g", GoType: "int", CType: "int"},
+					{GoName: "B", LowerGoName: "b", GoType: "int", CType: "int"},
+					{GoName: "A", LowerGoName: "a", GoType: "int", CType: "int"},
+				},
+			},
+		},
+	}
+
+	if err := g.GenerateClass(data); err != nil {
+		t.Fatalf("GenerateClass: %v", err)
+	}
+
+	outFile := filepath.Join(outDir, "gfx", "color_class.go")
+	content, err := os.ReadFile(outFile)
+	if err != nil {
+		t.Fatalf("output file not found at %s: %v", outFile, err)
+	}
+
+	src := string(content)
+
+	mustContain := []string{
+		// Accessor struct with two keys.
+		"type colorClassProperty struct",
+		"colorClass string",
+		"layer int",
+		// Accessor method with two key params.
+		"func (o *ColorClass) ColorClass(colorClass string, layer int) colorClassProperty",
+		// Multi-value getter.
+		"func (p colorClassProperty) Get() (r int, g int, b int, a int)",
+		"efl_gfx_color_class_get",
+		// Multi-value setter.
+		"func (p colorClassProperty) Set(r int, g int, b int, a int)",
+		"efl_gfx_color_class_set",
+		// String key conversion in Get/Set.
+		"C.CString(p.colorClass)",
+	}
+
+	for _, want := range mustContain {
+		if !strings.Contains(src, want) {
+			t.Errorf("output missing expected pattern %q\nfile content:\n%s", want, src)
+		}
+	}
+}
+
 func TestToSnake(t *testing.T) {
 	tests := []struct {
 		input string
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index 326db32..0392bca 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -330,6 +330,103 @@ func (o *{{$.GoName}}) {{.GoName}}({{range $i, $p := .Params}}{{if $i}}, {{end}}
     C.{{.CName}}((*C.Eo)(o.Eo()){{range .Params}}, {{template "paramArg" .}}{{end}})
 {{- end}}
 }
+{{- end}}
+{{- range $ip := .IndexedProperties}}
+
+type {{$ip.AccessorTypeName}} struct {
+    obj *C.Eo
+{{- range $ip.Keys}}
+    {{.GoName}} {{if needsStringConversion .CType}}string{{else if isBoolType .CType}}bool{{else if .IsEo}}efl.Objecter{{else if isPointerType .GoType}}unsafe.Pointer{{else}}{{.GoType}}{{end}}
+{{- end}}
+}
+
+// {{$ip.GoAccessorMethod}} returns an accessor for the {{$ip.GoAccessorMethod}} indexed property.
+func (o *{{$.GoName}}) {{$ip.GoAccessorMethod}}({{range $i, $k := $ip.Keys}}{{if $i}}, {{end}}{{$k.GoName}} {{if needsStringConversion $k.CType}}string{{else if isBoolType $k.CType}}bool{{else if $k.IsEo}}efl.Objecter{{else if isPointerType $k.GoType}}unsafe.Pointer{{else}}{{$k.GoType}}{{end}}{{end}}) {{$ip.AccessorTypeName}} {
+    return {{$ip.AccessorTypeName}}{
+        obj: (*C.Eo)(o.Eo()),
+{{- range $ip.Keys}}
+        {{.GoName}}: {{.GoName}},
+{{- end}}
+    }
+}
+
+{{- if $ip.HasGet}}
+{{- if $ip.IsMultiValue}}
+// Get returns the values for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Get() ({{range $i, $v := $ip.MultiGetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{$v.GoType}}{{end}}) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString(p.{{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- range $v := $ip.MultiGetValues}}
+    var c{{$v.GoName}} C.{{cTypeToCgo $v.CType}}
+{{- end}}
+    C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}{{range $ip.MultiGetValues}}, &c{{.GoName}}{{end}})
+    return {{range $i, $v := $ip.MultiGetValues}}{{if $i}}, {{end}}{{- if isBoolType $v.CType}}c{{$v.GoName}} != 0{{else}}{{$v.GoType}}(c{{$v.GoName}}){{end}}{{end}}
+}
+{{- else}}
+// Get returns the value for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Get() {{if $ip.IsEo}}unsafe.Pointer{{else}}{{$ip.GoType}}{{end}} {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString(p.{{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- if needsStringConversion $ip.CType}}
+    cResult := C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}})
+    return C.GoString(cResult)
+{{- else if isBoolType $ip.CType}}
+    return C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}) != 0
+{{- else if isPointerType $ip.GoType}}
+    return unsafe.Pointer(C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}))
+{{- else}}
+    return {{$ip.GoType}}(C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}))
+{{- end}}
+}
+{{- end}}
+{{- end}}
+
+{{- if $ip.HasSet}}
+{{- if $ip.IsMultiValue}}
+// Set sets the values for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Set({{range $i, $v := $ip.MultiSetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{$v.GoType}}{{end}}) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString(p.{{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+    C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}{{range $ip.MultiSetValues}}{{- if isBoolType .CType}}, func() C.{{cTypeToCgo .CType}} { if {{.LowerGoName}} { return 1 }; return 0 }(){{else}}, C.{{cTypeToCgo .CType}}({{.LowerGoName}}){{end}}{{end}})
+}
+{{- else}}
+// Set sets the value for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Set(val {{if $ip.IsEo}}efl.Objecter{{else}}{{$ip.GoType}}{{end}}) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+    c{{.GoName}} := C.CString(p.{{.GoName}})
+    defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- if needsStringConversion $ip.CType}}
+    cVal := C.CString(val)
+    defer C.free(unsafe.Pointer(cVal))
+    C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, cVal)
+{{- else if isBoolType $ip.CType}}
+    var cVal C.{{cTypeToCgo $ip.CType}}
+    if val { cVal = 1 }
+    C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, cVal)
+{{- else if isPointerType $ip.GoType}}
+    C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, val)
+{{- else}}
+    C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, C.{{cTypeToCgo $ip.CType}}(val))
+{{- end}}
+}
+{{- end}}
+{{- end}}
+
 {{- end}}
 {{- range .Events}}
 
@@ -364,3 +461,11 @@ func (o *{{$.GoName}}) {{.GoName}}(fn func({{if and .PayloadGoType (not (isPoint
 {{- else}}C.{{cTypeToCgo .CType}}({{.GoName}})
 {{- end}}
 {{- end}}
+{{- define "indexedKeyArg"}}
+{{- if needsStringConversion .CType}}c{{.GoName}}
+{{- else if isBoolType .CType}}func() C.{{cTypeToCgo .CType}} { if p.{{.GoName}} { return 1 }; return 0 }()
+{{- else if .IsEo}}(*C.Eo)(p.{{.GoName}}.Eo())
+{{- else if isPointerType .GoType}}p.{{.GoName}}
+{{- else}}C.{{cTypeToCgo .CType}}(p.{{.GoName}})
+{{- end}}
+{{- end}}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to