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 b2d0b0fa3ed0ba64481d95dbd87cb9988a641e3b
Author: [email protected] <[email protected]>
AuthorDate: Sun Mar 8 22:53:06 2026 -0600

    feat: add naming conversion functions for ego-gen code generator
    
    Introduce pure Go utilities to map Eolian naming conventions to
    idiomatic Go identifiers. These functions handle conversion of:
    - Eolian class names to Go package names and type names
    - Snake case properties to getter/setter pairs
    - Comma-separated events to "On"-prefixed callback names
    - Enum types to exported Go type names
    
    Includes comprehensive table-driven test coverage for all conversion
    functions across common naming patterns.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 cmd/ego-gen/naming.go      | 115 +++++++++++++++++++++++++++++++++++++
 cmd/ego-gen/naming_test.go | 139 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 254 insertions(+)

diff --git a/cmd/ego-gen/naming.go b/cmd/ego-gen/naming.go
new file mode 100644
index 0000000..7842303
--- /dev/null
+++ b/cmd/ego-gen/naming.go
@@ -0,0 +1,115 @@
+package main
+
+import (
+	"strings"
+	"unicode"
+)
+
+// ClassToPackage returns the Go package name derived from a fully-qualified
+// Eolian class name. For names with three or more dot-separated segments the
+// second segment (index 1) is returned lowercased. For two-segment names the
+// first segment is returned lowercased.
+//
+// Examples:
+//
+//	"Efl.Ui.Button"  → "ui"
+//	"Efl.Loop"       → "efl"
+func ClassToPackage(eolianName string) string {
+	parts := strings.Split(eolianName, ".")
+	if len(parts) >= 3 {
+		return strings.ToLower(parts[1])
+	}
+	// Two-part name such as "Efl.Loop" — use the first part.
+	return strings.ToLower(parts[0])
+}
+
+// ClassToGoName returns the exported Go type name derived from a
+// fully-qualified Eolian class name. The last dot-separated segment is taken
+// and any underscores are removed by converting the value to CamelCase via
+// SnakeToCamel.
+//
+// Examples:
+//
+//	"Efl.Ui.Button"      → "Button"
+//	"Efl.Ui.Spin_Button" → "SpinButton"
+func ClassToGoName(eolianName string) string {
+	parts := strings.Split(eolianName, ".")
+	last := parts[len(parts)-1]
+	return SnakeToCamel(last)
+}
+
+// SnakeToCamel converts a snake_case identifier to CamelCase. Each underscore-
+// separated word is title-cased and the underscores are removed. An empty
+// string is returned unchanged.
+//
+// Examples:
+//
+//	"text"               → "Text"
+//	"text_set"           → "TextSet"
+//	"autorepeat_enabled" → "AutorepeatEnabled"
+func SnakeToCamel(s string) string {
+	if s == "" {
+		return ""
+	}
+	words := strings.Split(s, "_")
+	var b strings.Builder
+	for _, w := range words {
+		if w == "" {
+			continue
+		}
+		runes := []rune(w)
+		runes[0] = unicode.ToUpper(runes[0])
+		b.WriteString(string(runes))
+	}
+	return b.String()
+}
+
+// PropertyToGetterSetter returns the idiomatic Go getter and setter method
+// names for an Eolian property name. The getter is the CamelCase form of the
+// property; the setter is "Set" prepended to the getter.
+//
+// Examples:
+//
+//	"text"               → ("Text", "SetText")
+//	"autorepeat_enabled" → ("AutorepeatEnabled", "SetAutorepeatEnabled")
+func PropertyToGetterSetter(prop string) (getter, setter string) {
+	getter = SnakeToCamel(prop)
+	setter = "Set" + getter
+	return
+}
+
+// EventToGoName converts an Eolian event name to an idiomatic Go callback
+// method name. Eolian events use comma-separated words; each word is
+// title-cased and the result is prefixed with "On".
+//
+// Examples:
+//
+//	"clicked"       → "OnClicked"
+//	"key,down"      → "OnKeyDown"
+//	"pointer,move"  → "OnPointerMove"
+func EventToGoName(event string) string {
+	words := strings.Split(event, ",")
+	var b strings.Builder
+	b.WriteString("On")
+	for _, w := range words {
+		if w == "" {
+			continue
+		}
+		runes := []rune(w)
+		runes[0] = unicode.ToUpper(runes[0])
+		b.WriteString(string(runes))
+	}
+	return b.String()
+}
+
+// EnumTypeToGoName returns the exported Go type name for a fully-qualified
+// Eolian enum type name. It behaves identically to ClassToGoName: the last
+// dot-separated segment is taken and converted to CamelCase.
+//
+// Examples:
+//
+//	"Efl.Ui.Dir"              → "Dir"
+//	"Efl.Gfx.Image_Scale_Type" → "ImageScaleType"
+func EnumTypeToGoName(eolianName string) string {
+	return ClassToGoName(eolianName)
+}
diff --git a/cmd/ego-gen/naming_test.go b/cmd/ego-gen/naming_test.go
new file mode 100644
index 0000000..ee1e2e1
--- /dev/null
+++ b/cmd/ego-gen/naming_test.go
@@ -0,0 +1,139 @@
+package main
+
+import (
+	"testing"
+)
+
+func TestClassToPackage(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+		want  string
+	}{
+		{"three parts", "Efl.Ui.Button", "ui"},
+		{"three parts canvas", "Efl.Canvas.Image", "canvas"},
+		{"three parts net", "Efl.Net.Server", "net"},
+		{"three parts io", "Efl.Io.Reader", "io"},
+		{"two parts loop", "Efl.Loop", "efl"},
+		{"two parts object", "Efl.Object", "efl"},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got := ClassToPackage(tc.input)
+			if got != tc.want {
+				t.Errorf("ClassToPackage(%q) = %q, want %q", tc.input, got, tc.want)
+			}
+		})
+	}
+}
+
+func TestClassToGoName(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+		want  string
+	}{
+		{"simple button", "Efl.Ui.Button", "Button"},
+		{"snake case last segment", "Efl.Ui.Spin_Button", "SpinButton"},
+		{"two parts loop", "Efl.Loop", "Loop"},
+		{"two parts object", "Efl.Object", "Object"},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got := ClassToGoName(tc.input)
+			if got != tc.want {
+				t.Errorf("ClassToGoName(%q) = %q, want %q", tc.input, got, tc.want)
+			}
+		})
+	}
+}
+
+func TestSnakeToCamel(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+		want  string
+	}{
+		{"single word", "text", "Text"},
+		{"two words", "text_set", "TextSet"},
+		{"three words", "autorepeat_enabled", "AutorepeatEnabled"},
+		{"empty string", "", ""},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got := SnakeToCamel(tc.input)
+			if got != tc.want {
+				t.Errorf("SnakeToCamel(%q) = %q, want %q", tc.input, got, tc.want)
+			}
+		})
+	}
+}
+
+func TestPropertyToGetterSetter(t *testing.T) {
+	tests := []struct {
+		name      string
+		input     string
+		wantGet   string
+		wantSet   string
+	}{
+		{"simple property", "text", "Text", "SetText"},
+		{"snake property", "autorepeat_enabled", "AutorepeatEnabled", "SetAutorepeatEnabled"},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			gotGet, gotSet := PropertyToGetterSetter(tc.input)
+			if gotGet != tc.wantGet {
+				t.Errorf("PropertyToGetterSetter(%q) getter = %q, want %q", tc.input, gotGet, tc.wantGet)
+			}
+			if gotSet != tc.wantSet {
+				t.Errorf("PropertyToGetterSetter(%q) setter = %q, want %q", tc.input, gotSet, tc.wantSet)
+			}
+		})
+	}
+}
+
+func TestEventToGoName(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+		want  string
+	}{
+		{"simple event", "clicked", "OnClicked"},
+		{"comma separated two words", "key,down", "OnKeyDown"},
+		{"pointer move", "pointer,move", "OnPointerMove"},
+		{"idle enter", "idle,enter", "OnIdleEnter"},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got := EventToGoName(tc.input)
+			if got != tc.want {
+				t.Errorf("EventToGoName(%q) = %q, want %q", tc.input, got, tc.want)
+			}
+		})
+	}
+}
+
+func TestEnumTypeToGoName(t *testing.T) {
+	tests := []struct {
+		name  string
+		input string
+		want  string
+	}{
+		{"simple enum", "Efl.Ui.Dir", "Dir"},
+		{"snake case last segment", "Efl.Gfx.Image_Scale_Type", "ImageScaleType"},
+	}
+
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			got := EnumTypeToGoName(tc.input)
+			if got != tc.want {
+				t.Errorf("EnumTypeToGoName(%q) = %q, want %q", tc.input, got, tc.want)
+			}
+		})
+	}
+}

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

Reply via email to