3 ms·
> common case-conventions Unfortunately, we must not forget forget ABOMINATIONCase and NAMESPACED_PascalCase (we could also generalize this to any switch from
by o11c 2y ago
> common case-conventions
Unfortunately, we must not forget forget ABOMINATIONCase and NAMESPACED_PascalCase (we could also generalize this to any switch from one convention to another after the first word). I've found they usually are, in fact, identifiable and roundtrippable. I've found the following usually works (it fails for multi-word prefixes or non-leading exceptions, and of course single-word identifiers are ambiguous):
count and strip all leading, then trailing, symbols (in some languages this is not limited to underscore but said languages usually need special handling anyway)
for every chunk separated by underscore, space, or hyphen (this may be nothing):
if the chunk either has no uppercase or has no lowercase, simply use it as a word. Otherwise:
for every sliding-window pair of letters (c, d) in the chunk:
if c is uppercase:
if d is lowercase, or d is a digit and there is lowercase elsewhere:
start a new word before c
Then for the words-to-convention direction:
space and kebab case don't have any good answer for affixes AFAIK. Otherwise, restore at least the leading underscores (trailing underscores are usually keyword-avoiding)
for snake and screaming case, be sure to prepend an underscore if the *result* would start with a digit
for camel variants, prepend an underscore to each *word* that starts with a digit. But if there were originally more than 1 leading underscores, use those instead for the first word.
- flohofwoe 2y agoI mean, there can always be a function on the TranslateC step which maps 'special case' names (or even translate them to an entirely different name, for instance when there's collisions with Zig reserved keywords): translateSpecialCaseNames(.{ .{ .src = "ABOMINATIONCase", .dst = "case" }, .{ .src = "NAMESPACED_PascalCase", .dst = "pascalCase" }, }); ...in my own language bindings generator, being able to define such special case mappings is actually quite important, mainly for handling that situation where an automatic mapping would result in a reserved keyword.
- o11c 2y agoReserved words really shouldn't require manual care; "list of keywords in X language" is really easy to handle so you can just append an underscore. I do think that namespaces need to be semi-manually managed though (likely only at the project level), since often there are things that look like a namespace but shouldn't be treated like one, and it's not always obvious from a single identifier how many words should be treated as the namespace in some styles. One special case is that sometimes C-ish libraries have class-likes like {Foo, FooBar, FooBaz} where the desired mapping is {foo.Foo, foo.Bar, foo.Baz}.