diff --git a/spec/std/enum_spec.cr b/spec/std/enum_spec.cr index 0fd244ead5ec..fe5c36c89ddc 100644 --- a/spec/std/enum_spec.cr +++ b/spec/std/enum_spec.cr @@ -275,6 +275,32 @@ describe Enum do SpecEnum::One.clone.should eq(SpecEnum::One) end + describe ".[]" do + it "non-flags enum" do + SpecEnum[].should be_nil + SpecEnum[One].should eq SpecEnum::One + SpecEnum[1].should eq SpecEnum::Two + SpecEnum[One, Two].should eq SpecEnum::One | SpecEnum::Two + SpecEnum[One, :two].should eq SpecEnum::One | SpecEnum::Two + SpecEnum[One, 1].should eq SpecEnum::One | SpecEnum::Two + end + + it "flags enum" do + SpecEnumFlags.flags.should be_nil + SpecEnumFlags[One].should eq SpecEnumFlags::One + SpecEnumFlags[2].should eq SpecEnumFlags::Two + SpecEnumFlags[One, Two].should eq SpecEnumFlags::One | SpecEnumFlags::Two + SpecEnumFlags[One, :two].should eq SpecEnumFlags::One | SpecEnumFlags::Two + SpecEnumFlags[One, 2].should eq SpecEnumFlags::One | SpecEnumFlags::Two + end + + it "private flags enum" do + PrivateFlagsEnum.flags.should be_nil + PrivateFlagsEnum[FOO].should eq PrivateFlagsEnum::FOO + PrivateFlagsEnum[FOO, BAR].should eq PrivateFlagsEnum::FOO | PrivateFlagsEnum::BAR + end + end + describe ".flags" do it "non-flags enum" do SpecEnum.flags.should be_nil diff --git a/src/enum.cr b/src/enum.cr index 6619ad1fe9ee..db6404e0a563 100644 --- a/src/enum.cr +++ b/src/enum.cr @@ -497,12 +497,36 @@ struct Enum # ``` # IOMode.flags(Read, Write) # => IOMode::Read | IOMode::Write # ``` + # + # * `Enum.[]` is a more advanced alternative which also allows int and symbol parameters. macro flags(*values) {% for value, i in values %}\ {% if i != 0 %} | {% end %}\ {{ @type }}::{{ value }}{% end %}\ end + # Convenience macro to create a combined enum (combines given members using `|` (or) logical operator). + # + # Arguments can be the name of a member, a symbol representing a member name or a numerical value. + # + # ``` + # IOMode[Read] # => IOMode[Read] + # IOMode[1] # => IOMode[Read] + # IOMode[Read, Write] # => IOMode[Read, Write] + # IOMode[Read, 64] # => IOMode[Read, 64] + # IOMode[Read, :write, 64] # => IOMode[Read, Write, 64] + # ``` + macro [](*values) + {% for value, i in values %}\ + {% if i != 0 %} | {% end %}\ + {% if value.is_a?(Path) %} \ + {{ @type }}::{{ value }} \ + {% else %} \ + {{ @type }}.new({{value}}) \ + {% end %} \ + {% end %}\ + end + # Iterates each member of the enum. # It won't iterate the `None` and `All` members of flags enums. #