pharo-users@lists.pharo.org

Any question about pharo is welcome

View all threads

mapping CamelCase to <custom-tag-name>

SB
Siemen Baader
Sat, Oct 22, 2022 8:56 AM

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

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
KO
Kasper Osterbye
Sat, Oct 22, 2022 12:53 PM

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

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
KO
Kasper Osterbye
Sat, Oct 22, 2022 2:07 PM

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

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 >
SB
Siemen Baader
Mon, Oct 24, 2022 6:56 AM

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

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 > > >
RO
Richard O'Keefe
Wed, Oct 26, 2022 9:41 AM

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

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 >
RO
Richard O'Keefe
Wed, Oct 26, 2022 9:46 AM

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

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 >> >
KO
Kasper Osterbye
Wed, Oct 26, 2022 10:37 AM

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

> > 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
SB
Siemen Baader
Sat, Nov 5, 2022 10:13 AM

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

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 >> >
RO
Richard O'Keefe
Sun, Nov 6, 2022 10:57 PM

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

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 > > >