mapping CamelCase to <custom-tag-name>
Hi, I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements. MYCustomElement and CustomElement to <my-custom-element> and <custom-element> There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join. Thanks for any hints! cheers Siemen
My feeling is that it cannot be solved by regular expressions. The reason it that there is the regular expressions in smalltalk/pharo does not have look-ahead or backtracking. In your example the capital Y is part of MY, but C starts a new word. I do not know of anyway to express that in smalltalk regular expressions. So I believe this is one of the cases where you add an extension method to string which does the job using plain coding. Best, Kasper
On 22 Oct 2022, at 10.56, Siemen Baader <siemenbaader@gmail.com> wrote:
Hi,
I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements.
MYCustomElement and CustomElement
to <my-custom-element> and <custom-element>
There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join.
Thanks for any hints!
cheers Siemen
I took this a my afternoon code-quiz, so here is a solution if you want it: splitCamelCase | str split word| "Split an expanded camelcase word into constituents. Extened camel case allow some words to be fully uppercase" "'ZAPMeToo' splitCamelCase >>> #('ZAP' 'Me' 'Too')" str := ReadStream on: self. split := OrderedCollection new. word := WriteStream on: ''. [ str atEnd ] whileFalse: [ | char | char := str next. (char isUppercase and: [str atEnd or: [str peek isLowercase]]) ifTrue: [ split add: word contents. word := WriteStream on: '' ]. word nextPut: char ]. split add: word contents. ^ split asArray You should then use cute join and asLowercase to go rest of the way. Best, Kasper
On 22 Oct 2022, at 14.53, Kasper Osterbye <kasper.osterbye@gmail.com> wrote:
My feeling is that it cannot be solved by regular expressions. The reason it that there is the regular expressions in smalltalk/pharo does not have look-ahead or backtracking. In your example the capital Y is part of MY, but C starts a new word. I do not know of anyway to express that in smalltalk regular expressions.
So I believe this is one of the cases where you add an extension method to string which does the job using plain coding.
Best,
Kasper
On 22 Oct 2022, at 10.56, Siemen Baader <siemenbaader@gmail.com> wrote:
Hi,
I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements.
MYCustomElement and CustomElement
to <my-custom-element> and <custom-element>
There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join.
Thanks for any hints!
cheers Siemen
Thank you very much, Kasper! Even with an implementation, wow.. I will use your solution. cheers Siemen On Sat, Oct 22, 2022 at 4:08 PM Kasper Osterbye <kasper.osterbye@gmail.com> wrote:
I took this a my afternoon code-quiz, so here is a solution if you want it: splitCamelCase | str split word| "Split an expanded camelcase word into constituents. Extened camel case allow some words to be fully uppercase" "'ZAPMeToo' splitCamelCase >>> #('ZAP' 'Me' 'Too')" str := ReadStream on: self. split := OrderedCollection new. word := WriteStream on: ''. [ str atEnd ] whileFalse: [ | char | char := str next. (char isUppercase and: [str atEnd or: [str peek isLowercase]]) ifTrue: [ split add: word contents. word := WriteStream on: '' ]. word nextPut: char ]. split add: word contents. ^ split asArray
You should then use cute join and asLowercase to go rest of the way.
Best,
Kasper
On 22 Oct 2022, at 14.53, Kasper Osterbye <kasper.osterbye@gmail.com> wrote:
My feeling is that it cannot be solved by regular expressions. The reason it that there is the regular expressions in smalltalk/pharo does not have look-ahead or backtracking. In your example the capital Y is part of MY, but C starts a new word. I do not know of anyway to express that in smalltalk regular expressions.
So I believe this is one of the cases where you add an extension method to string which does the job using plain coding.
Best,
Kasper
On 22 Oct 2022, at 10.56, Siemen Baader <siemenbaader@gmail.com> wrote:
Hi,
I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements.
MYCustomElement and CustomElement
to <my-custom-element> and <custom-element>
There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join.
Thanks for any hints!
cheers Siemen
What's wrong with $- join: (s cutCamelCase collect: [ :each | each asLowercase]) where s is the string you want to transform? I'm sure you're aware of the proverb: You have a problem and you decide to solve it with a regular expression. Now you have TWO problems. MYWeirdName and MyWeirdName both map to my-weird-name, but perhaps you are happy with that. On Sat, 22 Oct 2022 at 21:57, Siemen Baader <siemenbaader@gmail.com> wrote:
Hi,
I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements.
MYCustomElement and CustomElement
to <my-custom-element> and <custom-element>
There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join.
Thanks for any hints!
cheers Siemen
The important thing is that there is no NEED to write a new method to split a Smalltalk identifier into pieces, because there already *IS* such a method. Only write a new method if the existing one doesn't actually work for you. For example, what do you want to be done with strings or symbols that contain non-alphanumeric characters, like #== ? What do you want done with underscores and digits in strings like 'INTL_61_123_456'? On Wed, 26 Oct 2022 at 22:41, Richard O'Keefe <raoknz@gmail.com> wrote:
What's wrong with
$- join: (s cutCamelCase collect: [ :each | each asLowercase])
where s is the string you want to transform? I'm sure you're aware of the proverb: You have a problem and you decide to solve it with a regular expression. Now you have TWO problems.
MYWeirdName and MyWeirdName both map to my-weird-name, but perhaps you are happy with that.
On Sat, 22 Oct 2022 at 21:57, Siemen Baader <siemenbaader@gmail.com> wrote:
Hi,
I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements.
MYCustomElement and CustomElement
to <my-custom-element> and <custom-element>
There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join.
Thanks for any hints!
cheers Siemen
But there IS a #cutCamelCase method in Pharo. It comes from Roassal2. Here it is, copied from Pharo 9.0.0: cutCamelCase "Breaks apart words written in camel case. It's not simply using piecesCutWhere: because we want to also deal with abbreviations and thus we need to decide based on three characters, not just on two: ('FOOBar') piecesCutWhereCamelCase asArray = #('FOO' 'Bar'). ('FOOBar12AndSomething') piecesCutWhereCamelCase asArray = #('FOO' 'Bar' '12' 'And' 'Something') " | start previous current next pieces | self isEmpty ifTrue: [^self]. start := 1. pieces := OrderedCollection new. 3 to: self size do: [ :index | previous := self at: index - 2. current := self at: index - 1. next := self at: index. ((previous isLowercase and: [current isUppercase]) or: [ (previous isUppercase and: [current isUppercase and: [next isLowercase ]]) or: [ (previous isDigit not and: [current isDigit]) or: [ previous isDigit and: [current isDigit not] ]]]) ifTrue: [ pieces add: (self copyFrom: start to: index - 2). start := index - 1]. ]. pieces addAll: ((self copyFrom: start to: self size) piecesCutWhere: [:a :b | (a isDigit and: [b isDigit not]) or: [a isDigit not and: [b isDigit ]]]). ^pieces On Wed, 26 Oct 2022 at 23:37, Kasper Osterbye <kasper.osterbye@gmail.com> wrote:
What's wrong with
$- join: (s cutCamelCase collect: [ :each | each asLowercase])
There is no method called cutCamelCase in Pharo. If there was, this was exactly the right solution to use something existing.
Best,
Kasper
Hi Richard, On Wed, Oct 26, 2022 at 11:42 AM Richard O'Keefe <raoknz@gmail.com> wrote:
What's wrong with
$- join: (s cutCamelCase collect: [ :each | each asLowercase])
where s is the string you want to transform? I'm sure you're aware of the proverb: You have a problem and you decide to solve it with a regular expression. Now you have TWO problems.
I was not, but I like it :)
MYWeirdName and MyWeirdName both map to my-weird-name, but perhaps you are happy with that.
Indeed - that is not a problem in my situation. cheers Siemen
On Sat, 22 Oct 2022 at 21:57, Siemen Baader <siemenbaader@gmail.com> wrote:
Hi,
I'm looking for an elegant way to convert class names with optional namespace prefixes to names for custom html elements.
MYCustomElement and CustomElement
to <my-custom-element> and <custom-element>
There must be an elegant way to do it with regex or inject, but I'm embarrassed to say I can't get my head around it. I can get it to match the regex '((:isUppercase:+)*)((:isUppercase::isLowercase:+)*)', (if I recall correctly) but can't get a collection of the individual elements 'MY' 'Custom" 'Element' to lowercase and join.
Thanks for any hints!
cheers Siemen
participants (3)
-
Kasper Osterbye -
Richard O'Keefe -
Siemen Baader