zarldev / goenums

Type Safe Enum generator for Go
MIT License
214 stars 10 forks source link

Strings in enum extensions / complex extensions? #23

Open gerricom opened 3 months ago

gerricom commented 3 months ago

Thanks for your hard work! I really like your approach on creating good usable enums in go!

I have a very common usecase in one of my pet-projects: It is a web application and I'm in the need to hand over the enum to my frontend so that I can choose something in a select box. There are some descriptive texts in there. With the current implementation it is not really possible to hand over strings in the enum extension, especially if those strings are longer or contain one of the splitting characters that are currently used.

To stay in the solarsystem example, this is something that won't work well:

package enums

type planet int // Satellites[string],

//go:generate goenums planets.go
const (
    unknown planet = iota // invalid
    mercury               // Mercury "None"
    venus                 // Venus "None"
    earth                 // Earth "Moon"
    mars                  // Mars "Phobos, Deimos"
    jupiter               // Jupiter "Too many to list here..."
    saturn                // Saturn "even more than Jupiter. D'oh!"
    uranus                // Uranus "some around 28"
    neptune               // Neptune "only sixteen"
)

The generated struct now looks like

var Planets = planetsContainer{
    MERCURY: Planet{ 
    planet:mercury,
Satellites: "None",
},
    VENUS: Planet{ 
    planet:venus,
Satellites: "None",
},
    EARTH: Planet{ 
    planet:earth,
Satellites: "Moon",
},
    MARS: Planet{ 
    planet:mars,
Satellites: 0,
},
    JUPITER: Planet{ 
    planet:jupiter,
Satellites: "Too,
},
    SATURN: Planet{ 
    planet:saturn,
Satellites: "even,
},
    URANUS: Planet{ 
    planet:uranus,
Satellites: "some,
},
    NEPTUNE: Planet{ 
    planet:neptune,
Satellites: "only,
},
}

My very first rough idea is that an extension as data input could just accept json (compressed to a single line of course). This is not very human editable/readble of course, but it would be very dynamic and one could hand in the struct as an extension right into the initial comment (this is already working). Handing in json could look like this...?

package enums

type planetExtension struct {
    Satellites string
}

type planet int // [planetExtension]

//go:generate goenums planets.go
const (
    unknown planet = iota // invalid
    mercury               // Mercury json:{"Satellites": "None"}
    venus                 // Venus json:{"Satellites": "None"}
    earth                 // Earth json:{"Satellites": "Moon"}
    mars                  // Mars json:{"Satellites": "Phobos, Deimos"}
    jupiter               // Jupiter json:{"Satellites": "Too many to list here..."}
    saturn                // Saturn json:{"Satellites": "even more than Jupiter. D'oh!"}
    uranus                // Uranus json:{"Satellites": "some around 28"}
    neptune               // Neptune json:{"Satellites": "only sixteen"}
)
zarldev commented 3 months ago

The solution I feel is best would be to store them in a slice of strings but that also generates errors.

package enums

type planet int // Satellites([]string)

//go:generate goenums -f planets.go
const (
    mercury planet = iota // Mercury []{"None"}
    venus                 // Venus []{"None"}
    earth                 // Earth []{"Moon"}
    mars                  // Mars []{"Phobos, Deimos"}
    jupiter               // Jupiter []{"Too many to list here..."}
    saturn                // Saturn []{"even more than Jupiter. D'oh!"}
    uranus                // Uranus []{"some around 28"}
    neptune               // Neptune []{"only sixteen"}
)

Looking into supporting this.

gerricom commented 3 months ago

The solution I feel is best would be to store them in a slice

Yes, that could be a solution, but than one would need to always select the first item of that slice...

I had another idea this night: There is already a somewhat good working text format for various data types and that is CSV. RFC4180 describes clear rules of what spaces, quotes etc. are doing. And it is quite human-readable - at least better than JSON. Though you would need something like gocsv to map a csv back to a struct.