Giter VIP home page Giter VIP logo

go-enum's People

Contributors

abice avatar alewkinr avatar angaz avatar bradleyjkemp avatar charlieparkes avatar conornevin avatar dependabot[bot] avatar dsonck92 avatar ghostiam avatar lastpossum avatar mmorel-35 avatar omegaatt36 avatar pswaminathan avatar superstas avatar thinkchaos avatar twelvelabs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

go-enum's Issues

Allow setting a custom string value for number based enums

I have the following code:

// ENUM(v1 = 1)
type Version int

The full name of the version is actually x/v1, which if used directly is kind of ugly, especially since the special characters cannot be part of the variable name.
While I can use string based enum to get around it:

// ENUM(v1 = x/v1)
type Version string

I'd love to be able to provide a string representation override to the int version with a flag like --stringOverride='v1:x/v1' or semantics inside the comment block itself.

Problem using closing parentheses in enum values

For an enum like the following:

// ENUM(
// Foo1 (X),
// Foo2 (Y),
// ).
type Example string

The generated code reads:

const (
	// ExampleFoo1X is a Example of type Foo1 (X.
	ExampleFoo1X Example = "Foo1 (X"
	// ExampleFoo2Y is a Example of type Foo2 (Y.
	ExampleFoo2Y Example = "Foo2 (Y"
)

Could the issue be in that trimAllTheThings removes ) and all subsequent characters?

Negative enum values not supported

While trying to transfer over some API defined ENUMs, I discovered that negative enum values are not supported:

// ENUM(Unknown = -1, Good, Bad)
type Status int
failed parsing the data part of enum value 'Unknown = -1': strconv.ParseUint: parsing "-1": invalid syntax

generate errors with generic file

this is the generic definetion in the generate file.

type client interface {
	kernel.Client | bootnode.Client | upgrade.Client | media.Client
}

when i use go-enum -f xxx.go, returns this error:
Error=generate: error parsing input file 'dbc.go': dbc.go:13:16: expected ';', found '|' (and 1 more errors)

Support custom values for integer enums

Context: a performant way to implement a set of integer enum values is to combine all the values in a single int. For example, let's say we want to implement a set of colours:

type Colour int32

const (
	ColourRed Colour = 1 << iota
	ColourGreen
	ColourBlue
)

func main() {
	colourSet := ColourRed | ColourGreen
	printColours(colourSet)
}

func printColours(colourSet Colour) {
	if colourSet&ColourRed != 0 {
		fmt.Println("Red")
	}

	if colourSet&ColourGreen != 0 {
		fmt.Println("Green")
	}

	if colourSet&ColourBlue != 0 {
		fmt.Println("Blue")
	}
}

It would be great to use this technique with enums generated by go-enum. However, by default the enum values are always strictly incrementing in value, rather than incrementing the bit position. I'm not sure if there is any way to override the default way that values are generated but still use the other features of the package?

Text after ) will be included in the last enum value

When adhering to godot linter rules, I must add a trailing . to the end of the ENUM(...). But this will result in ). to be added to the string name:

// ENUM(1).
type Test int8

generates

const (
	// Test1 is a Test of type 1)..
	Test1 Test = iota
)

const _TestName = "1)."

But even worse, on a multiline variant, it will add an empty item, colliding with the type:

// ENUM(
//   X
//   Y
//   Z
// ).
type Test int8

generates

const (
	// TestX is a Test of type X.
	TestX Test = iota
	// TestY is a Test of type Y.
	TestY
	// TestZ is a Test of type Z.
	TestZ
	// Test is a Test of type )..
	Test
)

const _TestName = "XYZ)."

I tried (to no avail) to disable godot for the ENUM line, since I find it a bit pointless. However, this does mean that it's also not possible to add some text behind the closing ) which may be useful. Especially considering ENUM(...values...) kinda implies that parsing stops at )

linter unconvert (unnecessary conversion)

*_enum.go:38:23:warning: unnecessary conversion (unconvert)

func ParseABC(name string) (ABC, error) {
	if x, ok := _ABCValue[name]; ok {
		return ABC(x), nil // <--
	}
	return ABC(0), fmt.Errorf("%s is not a valid ABC", name)
}

Generates `foo_test_enum.go` from `foo_test.go` instead of `foo_enum_test.go`

When I have a file foos_test.go with:

//go:generate go-enum --marshal
package trygoenum

// ENUM(bob, alice, john, sally)
type People int

and I run go generate ./... go-enum creates foos_test_enum.go.

This causes go build ./... to fail:

$ go build ./...
# try-go-enum.invalid
./foos_test_enum.go:16:12: undefined: People
./foos_test_enum.go:29:22: undefined: People
./foos_test_enum.go:37:9: undefined: People
./foos_test_enum.go:44:31: undefined: People
./foos_test_enum.go:52:32: undefined: People
./foos_test_enum.go:56:9: undefined: People
./foos_test_enum.go:60:9: undefined: People
./foos_test_enum.go:65:10: undefined: People

I would say ideally go-enum should put enums for _test.go files in _enum_test.go files.

Use a config file instead of code for enum definitino

Hi. I like the project. I'm wondering if you have considered or would like to have a contribution where the enum definitions are in a config file instead of in a code stub?

I think it would be quite interesting to have them defined in something similar to how go-swagger or sqlc does it.

An idea of a possible configuration file:

version: 1
enums:
  - package: animal
    target: internal/animal
    name: Animal
    type: int
    alias:
      "+": Plus
      "#": Sharp
    values:
      cat:
      dog:
      fish:
      fish++:
      fish#:
  - package: color
    target: internal/color
    name: Color
    type: int
    values:
      Black:
      White:
      Red:
      Green:
        - value: 33
          comment: Green starts with 33
      Blue:
      grey:
      yellow:
      blue-green:
      red-orange:
      yellow_green:
      red-orange-blue:
    generate:
      marshal: true
      lower: true
      pointer: true
      mustparse: true

questions about empty strings

Two questions about empty strings:

  1. Enumeration values currently do not support empty strings? (because there is a valid empty string case)
  2. The mysql type is varchar, default: "". In this case, the Scanner and Valuer interfaces can only be implemented manually?

Docker image with go-enum

Could you please provide an "official" multi-arch docker image to use this tool? It can be simply deployed to the ghcr.io, for example. Use case - a more simple installation in the docker context, like:

COPY --from=abice/go-enum:v0.5.5 /usr/local/bin/go-enum /bin/go-enum

If you need help with it, I can make a PR with the required changes.

Sanitising EnumValue.Name

I'm parsing an xml file format that has a lot of different enumerations and have been using go-enum with quite good success. I'm wondering if you would accept a pull request to tidy up EnumValue.Name even more?

Specifically I would like to strip out some common separators that are invalid in go identifiers like -

Currently EnumValue.Name is run through strings.Title, I think it would be relatively trivial to also strip out non-go-identifier characters at the same time.

Question: How to support camel case format

How do I define ENUM to achieve this?

  1. The text in name is in lower case
  2. Int values in enumeration are case sensitive
const(
xxxDataSwap = iota
xxxBootNode
)

__Name="dataswapbootnode"

Also, can I ignore Parse's error like this:

ParseXXX(name)Type{
    //return a default value
}

Would be nice to have -forceupper opt

Hello there!

Just started to use your library and I’m missing something like —forceupper option.

I believe many people prefer enums to have string values in uppercase, but if I put THING in the enum comment I receive ugly SomeTHING constant.

I see, that option forcelower works in the way I need, but in the opposite direction.

ParseFoo should return an error

ParseColor("chartreuse") returns Black.. that's not good. You could start the enum with like ColorNone, but that's ugly. Better to just have ParseColor return (Color, error).

Error if ENUM starts from value = 1

// SearchPropertyType search property type
// ENUM(
// Apartment = 1
// Room
// House
// Plot
// Commercial
// Development
// )
type SearchPropertyType int32

produces error: Error=generate: error formatting code domain:358:59: expected ';', found 'IDENT' SearchPropertyType (and 4 more errors)
generated code:

const (
	// SearchPropertyTypeApartment is a SearchPropertyType of type Apartment
    SearchPropertyTypeApartment SearchPropertyType = iota SearchPropertyType = iota + 1
	// SearchPropertyTypeRoom is a SearchPropertyType of type Room
    SearchPropertyTypeRoom  SearchPropertyType = iota + 1

problematic code is here: https://github.com/abice/go-enum/blob/master/generator/enum.tmpl#L17

workaround for that is to add underscore as first value:

// SearchPropertyType search property type
// ENUM(
// _
// Apartment = 1
// Room
// House
// Plot
// Commercial
// Development
// )
type SearchPropertyType int32

but it will be great if it works without the workaround

Recommendation: Use const instead of plain numbers in internal map

The final generated code now looks like this:

const (
    // ColorBlack is a Color of type Black.
    ColorBlack Color = iota
    // ColorWhite is a Color of type White.
    ColorWhite
    // ColorRed is a Color of type Red.
    ColorRed
    // ColorGreen is a Color of type Green.
    // Green starts with 33
    ColorGreen Color = iota + 30
    // ColorBlue is a Color of type Blue.
    ColorBlue
    // ColorGrey is a Color of type Grey.
    ColorGrey
    // ColorYellow is a Color of type Yellow.
    ColorYellow
    // ColorBlueGreen is a Color of type Blue-Green.
    ColorBlueGreen
    // ColorRedOrange is a Color of type Red-Orange.
    ColorRedOrange
    // ColorYellowGreen is a Color of type Yellow_green.
    ColorYellowGreen
    // ColorRedOrangeBlue is a Color of type Red-Orange-Blue.
    ColorRedOrangeBlue
)

const _ColorName = "BlackWhiteRedGreenBluegreyyellowblue-greenred-orangeyellow_greenred-orange-blue"

var _ColorMap = map[Color]string{
    0:  _ColorName[0:5],
    1:  _ColorName[5:10],
    2:  _ColorName[10:13],
    33: _ColorName[13:18],
    34: _ColorName[18:22],
    35: _ColorName[22:26],
    36: _ColorName[26:32],
    37: _ColorName[32:42],
    38: _ColorName[42:52],
    39: _ColorName[52:64],
    40: _ColorName[64:79],
}

var _ColorValue = map[string]Color{
    _ColorName[0:5]:                    0,
    strings.ToLower(_ColorName[0:5]):   0,
    _ColorName[5:10]:                   1,
    strings.ToLower(_ColorName[5:10]):  1,
    _ColorName[10:13]:                  2,
    strings.ToLower(_ColorName[10:13]): 2,
    _ColorName[13:18]:                  33,
    strings.ToLower(_ColorName[13:18]): 33,
    _ColorName[18:22]:                  34,
    strings.ToLower(_ColorName[18:22]): 34,
    _ColorName[22:26]:                  35,
    strings.ToLower(_ColorName[22:26]): 35,
    _ColorName[26:32]:                  36,
    strings.ToLower(_ColorName[26:32]): 36,
    _ColorName[32:42]:                  37,
    strings.ToLower(_ColorName[32:42]): 37,
    _ColorName[42:52]:                  38,
    strings.ToLower(_ColorName[42:52]): 38,
    _ColorName[52:64]:                  39,
    strings.ToLower(_ColorName[52:64]): 39,
    _ColorName[64:79]:                  40,
    strings.ToLower(_ColorName[64:79]): 40,
}

where the numbers are not very easy to read
I think it would be easier to read if it could look like the following:

var _ColorMap = map[Color]string{
    ColorBlack:  _ColorName[0:5],
    ColorWhite:  _ColorName[5:10],
    ...
}

var _ColorValue = map[string]Color{
    _ColorName[0:5]:                    ColorBlack,
    strings.ToLower(_ColorName[0:5]):   ColorBlack,
    _ColorName[5:10]:                   ColorWhite,
    strings.ToLower(_ColorName[5:10]):  ColorWhite,
    ...

Support interface for flag

Thanks for this handy tool. Do you think it is reasonable to implement the following interface so that it can be used as a Flag.

// Value is the interface to the dynamic value stored in a flag.
// (The default value is represented as a string.)
type Value interface {
	String() string
	Set(string) error
	Type() string
}

Currently I am manually implementing this.

Input files flag should support file globbing

I want to be able to slap all my enumerations into a single folder and use a file like gen.go to generate them. Perhaps there's something I'm missing regarding generation. But the best idea I had was to use file globbing to select all the files in the current folder for the tool. However, it does not appear to support it.

go-enum started. file: *.go
2021/03/09 15:16:59 failed generating enums
InputFile=C:\path\to\project\enums\*.go
Error=generate: error parsing input file 'C:\path\to\project\enums\*.go': open C:\path\to\project\enums\*.go: The filename, directory name, or volume label syntax is incorrect. 
project\enums\gen.go:1: running "go-enum": exit status 1

Rerunning removes version information

Example go generate command in the enum file: go:generate go-enum -f=$GOFILE --names --nocase --noprefix --prefix=Sample

Rerunning go generate ./... when there are no changes in that file provides a diff that wipes from of the go-enum metadata. Here is the diff:

-// Version: 0.4.0
-// Revision: 7e2e8bcd629be550028ecfcdc51cc0199ca124ad
-// Build Date: 2022-03-21T16:28:18Z
-// Built By: goreleaser
+// Version:
+// Revision:
+// Build Date:
+// Built By:

Support for generated "MustParse" which panics on unknown values

#79

The following is an example of what is currently generated:

// ParseFoo attempts to convert a string to a Foo
func ParseFoo(name string) (Foo, error) {
	if x, ok := _FooValue[name]; ok {
		return x, nil
	}
	return Foo(0), fmt.Errorf("%s is not a valid Foo", name)
}

To ease in a common use case of wanting to panic on an error, consider also generating (behind a flag -must?) the following:

// MustParseFoo attempts to convert a string to a Foo, panicking if unknown.
func MustParseFoo(name string) Foo {
    x, err := ParseFoo(name)
    if err != nil {
        panic(err)
    }
    return x
}

Function for getting a list of values

--names adds ...Names() to get a list of enum names, but I would like to just get a list of enum values instead. I can kind of achieve the same thing by using MustParse...() with values from ...Names() but I would still be more comfortable just having ...Values().

Mainly making this issue to see how you feel about the request or if there may already be a way to do it that I don't know of.

Getting stringer error

Just tonight I am getting errors similar to
Failed writing enum data for enum: "AssociationType": template: generator:306:32: executing "stringer" at : wrong number of args for stringify: want 2 got 1

go 1.15
go-enum 0.3.10

My Makefile simply states

go get -u github.com/abice/go-enum
go generate ./...

That generates the errors as it is using V0.3.10

if I do

go get -u github.com/abice/[email protected]
go generate ./...

Then it all works as expected

uint64

Hello,

it appears v0.311 silently fails and generates no output at all with

type uint64
constant values > maxint32

Support option to override generated file suffix

First of all thanks so much for creating and maintaining this great tool!

I hope I did not just overlook this in the docs but it would be nice to have the option to change the suffix of the generated files.

So instead of <filename>_enum.go being able change the pattern to <filename>_enum_gen.go

Maybe via an --output-suffix flag.

Mapping enums to aliases/symbols

I have a lot of enums which need to be mapped to arbitrary strings that don't match the enum name. Am I missing a good way to handle this in the library already?

Would you be open to a PR adding optional mapping to symbols/aliases?

var _{{.enum.Name}}Symbols = map[string]{{.enum.Name}}{
{{- $vars := dict "lastoffset" 0 -}}
{{ range $rIndex, $value := .enum.Values }}
	{{- $lastOffset := pluck "lastoffset" $vars | first }}{{ $offset := sub $value.Value $rIndex }}
	{{- if $value.Comment}}
	"{{$value.Comment}}": {{$rIndex}},
	{{- end}}
{{- end}}
}

func Parse{{.enum.Name}}Symbol(bs []byte) ({{.enum.Name}}, error) {
    s := string(bs)
	if s == " " {
		s = "SPACE"
	}
	if val, ok := _{{.enum.Name}}Symbols[s]; ok {
		return val, nil
	}
	return {{.enum.Name}}(0), fmt.Errorf("'%s' is not a valid {{.enum.Name}}", string(bs))
}
/*
ENUM(
AlphaNumeric // A/N
Numeric // N
Misc // SPACE
)
*/
type FieldType int
var _FieldTypeSymbols = map[string]FieldType{
	"A/N":   0,
	"N":     1,
        "SPACE": 2,
}

func ParseFieldTypeSymbol(bs []byte) (FieldType, error) {
	s := string(bs)
	if s == " " {
		s = "SPACE"
	}
	if val, ok := _FieldTypeSymbols[s]; ok {
		return val, nil
	}
	return FieldType(0), fmt.Errorf("'%s' is not a valid FieldType", string(bs))
}

Comments should have punctuation

Problem

When each enum value is generated, it has a comment like so:

// ColorBlack is a Color of type Black
// My personalized comment.
ColorBlack Color = iota

However, sometimes IDEs will concatenate comments together, so that when hovering over a symbol, you see the following:

ColorBlack is a Color of type Black My personalized comment.

This is not a problem with the IDE.

The blog post Godoc: documenting Go code states:

The convention is simple: to document a type, variable, constant, function, or even a package, write a regular comment directly preceding its declaration, with no intervening blank line.

// Fprint formats using the default formats for its operands and writes to w.

Notice this comment is a complete sentence that begins with the name of the element it describes. This important convention allows us to generate documentation in a variety of formats, from plain text to HTML to UNIX man pages, and makes it read better when tools truncate it for brevity, such as when they extract the first line or sentence.

And the Contribution Guide states:

Write in complete sentences with correct punctuation, just like for your comments in Go.

Solution

The first line comment generated by go-enum should include punctuation.

The first example would become:

// ColorBlack is a Color of type Black.
// My personalized comment.
ColorBlack Color = iota

And the IDE would show:

ColorBlack is a Color of type Black. My personalized comment.

Specify custom value for enum string ?

Is it possible to specify custom value for enum string ? Like this for example:

/* ENUM(
PROD = "https://prod",
DEV = "http://dev"
)
*/
type Environment string

Which could generate this

const (
	PROD Environment = "https://prod"
	DEV Environment = "http://dev"
)

add support SQL Scan/Value interface

It is necessary to use types in structures that are populated through a database

Now I'm writing this code, but it can be generated like Marshal/UnmarshalText

// ENUM(...)
type TimesheetStatus int

// Scan implements the Scanner interface.
func (x *TimesheetStatus) Scan(value interface{}) error {
	var name string

	switch v := value.(type) {
	case string:
		name = v
	case []byte:
		name = string(v)
	case nil:
		return errors.New("destination pointer is nil")
	}

	tmp, err := ParseTimesheetStatus(name)
	if err != nil {
		return err
	}

	*x = tmp
	return nil
}

// Value implements the driver Valuer interface.
func (x TimesheetStatus) Value() (driver.Value, error) {
	return x.String(), nil
}

Custom prefix with `--prefix` is appending not replacing

I'm using go-enum v0.5.0 Linux x86_64
I've created an enum as such:

//go:generate go-enum -f=$GOFILE --marshal --names --nocamel --prefix TokenTypeEnum_
package tokens
/*
ENUM(
	AD_HOC_USER = 1
	APP_USER
	OTHER
	RFID
)
*/
type TokenTypeEnum uint8

By default, the --nocamel flag gives me TokenTypeEnum<name> but I want the constants to be named TokenTypeEnum_<name> for readability but instead I'm getting TokenTypeEnum_TokenTypeEnum<name>

The README suggests the --prefix flag should be replacing the existing prefix but it's not.
--noprefix removes both prefixes

Unable to compile on Darwin

go get github.com/abice/go-enum@v0.2.3
# github.com/Bowery/prompt
../../../Go/pkg/mod/github.com/!bowery/prompt@v0.0.0-20190916142128-fa8279994f75/ioctl_unix.go:25:28: undefined: unix.SYS_IOCTL
../../../Go/pkg/mod/github.com/!bowery/prompt@v0.0.0-20190916142128-fa8279994f75/ioctl_unix.go:38:28: undefined: unix.SYS_IOCTL
../../../Go/pkg/mod/github.com/!bowery/prompt@v0.0.0-20190916142128-fa8279994f75/ioctl_unix.go:55:28: undefined: unix.SYS_IOCTL

Please check in your dependencies

Your package is not go-get-able if you don't check in your vendor directory. This is what happens right now if I try to go get your package:

go get github.com/abice/go-enum
# github.com/Masterminds/sprig
../../Masterminds/sprig/crypto.go:35:37: multiple-value uuid.NewV4() in single-value context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.