Is there a way to add entries without the "EDeviceActivityLevel_k' after this definition?
our enum EDeviceActivityLevelEnum is export (
EDeviceActivityLevel_k_EDeviceActivityLevel_Unknown => -1,
EDeviceActivityLevel_k_EDeviceActivityLevel_Idle => 0,
EDeviceActivityLevel_k_EDeviceActivityLevel_UserInteraction => 1,
EDeviceActivityLevel_k_EDeviceActivityLevel_UserInteraction_Timeout => 2,
EDeviceActivityLevel_k_EDeviceActivityLevel_Standby => 3,
EDeviceActivityLevel_k_EDeviceActivityLevel_Idle_Timeout => 4,
)
ANSWER -- Why yes, there is! See solution in the comments.
Well, it wasn't easy, and it took ages to get right, but here's a way to do it. It's not actually adding to the enum. It is more like defining constant aliases that can be exported that will return the proper value.
So, say you have a compunit with just enums. You first need to have a place to hold your new exports. You need to define it at the top, our scoped and exported, otherwise it will not work:
Your sub EXPORT, which must be defined outside of your package definition, will just re-export what was already exported, in addition to your new definitions, and will look like this:
Now comes the tricky part. For performance reasons, we want all of the hard work to be done as late into compile-time as possible, hence a BEGIN block. This block performs the real work:
So lets break this down. We want to walk the symbol table. For my purposes, all of my enum definitions end with Enum, so getting those out is easy:
We need the loop to be as deterministic as possible, so the output is sorted by key. This insures that order the enums are processed in will be the same for a given set of enums. If we just went with .pair().grep(), this would not be the case.
Now the trick is to figure out what parts to trim from the front. That work is performed by the innocuous getLongestSubstr function(). Let's take a closer look at that, since it's definition wasn't given. First we need to define another multi for the max() function:
Then, the longest substring shared between a list of strings can be found via this definition:
(For a better idea of how that all works, note that I cribbed that algorithm from somewhere else. Conway's wrtte-up explains it all in detail.)
Now that we have the longest substring, we need to count how far down we can cut things. To prevent collisions, it's probablky wise to establish a maximum number of tokens we can cut from the enum name. I selected 3 as an arbitrary limit:
From there, we piece together the portion of the prefix we are going to remove:
Please note, that the above adds collision detection. The basic rule here is that if we've encountered a collision at a specific token level, we are likely have more. Rather than add partial aliases we skip the whole set.
The idea is that we precompile our aliases in %OPENVR-RAW-ENUMS-NEW-EXPORTS. Then use that precompiled list at runtime when sub EXPORT() is executed.
Turns out to work fairly well.
Hope you find this gist useful!