Pharo-dev
By thread
pharo-dev@lists.pharo.org
By month
Messages by month
- ----- 2026 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 1 participants
- 144633 messages
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 17:13, Thierry Goubier <thierry.goubier(a)gmail.com> wrote:
>
>
>
> 2017-09-28 17:08 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
>
>
> > On 28 Sep 2017, at 16:58, phil(a)highoctane.be wrote:
> >
> > I stand corrected.
> >
> > Nuclear style feature then.
> >
> > 'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM' interpolate
> >
> > Feels like
> >
> > STR='sudo reboot'; $(STR)
> >
> > in bash when one is sudoer.
>
> Yeah, but it is always the original programmer who writes the template (including the 'Smalltalk snapshot:false andQuit: true' and the 'sudo reboot' in you examples), you would not do that for any good reason.
>
> Typically, you would write something like
>
> 'My name is {firstname} {lastname}' interpolate.
>
> in a method of an object with firstname and lastname as instance variables. To access the binding, #evaluate: is used. Though a malicious person could enter 'Smalltalk snapshot:false andQuit: true' as name, it is not that expression that gets evaluated. So in that respect there is no risk.
>
> The risk would be when the template string itself would be (partially) based on used input.
>
> which is easy to overlook:
>
> aString interpolate
>
> People are on average a bit more carefull when they use #compile: or #evaluate:.
>
> Thierry
100% correct, hence my warning.
> > Phil
> >
> > On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> >
> >
> > > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> > >
> > > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
> > >
> > > Phil
> >
> > Yes, Mustache is a cool templating engine, but it is similar to #format: not to #interpolate. With true string interpolation, you do not provide a context, you just write the expressions inline. Compare the following two:
> >
> > 'Today is {1} format: { Date today }.
> >
> > 'Today is { Date today }' interpolate.
> >
> > > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> > > Hi,
> > >
> > > I got into a little office discussion about string interpolation as it is done in different programming languages.
> > >
> > > In Pharo we have String>>#format: which is pretty nice. It works as follows:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={1} and y={2}' format: { x. y }.
> > >
> > > It is also possible to use a dictionary with keys, like this:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> > >
> > > But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
> > >
> > > Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
> > >
> > > => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
> > >
> > > Here is the implementation I came up with:
> > >
> > > String>>#interpolate
> > > "Format the receiver by interpolating the evaluation of expressions
> > > in between curly brackets in the context of the sender as in the following 3 oneline examples.
> > > 'Today is {Date today}' interpolate.
> > > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > > 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
> > >
> > > | senderContext |
> > > senderContext := thisContext sender.
> > > ^ self class new: self size streamContents: [ :out | | stream |
> > > stream := self readStream.
> > > [ stream atEnd ] whileFalse: [ | currentChar |
> > > (currentChar := stream next) == ${
> > > ifTrue: [ | expression result |
> > > expression := stream upTo: $}.
> > > result := Compiler new
> > > evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> > > out nextPutAll: result asString ]
> > > ifFalse: [
> > > currentChar == $\
> > > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> > > ifFalse: [ out nextPut: currentChar ] ] ] ]
> > >
> > > It is a hack that could certainly be improved. And there is of course an obvious security problem.
> > >
> > > Thoughts ?
> > >
> > > Sven
> > >
> > >
> > >
> >
> >
> >
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Thierry Goubier
2017-09-28 17:08 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
>
>
> > On 28 Sep 2017, at 16:58, phil(a)highoctane.be wrote:
> >
> > I stand corrected.
> >
> > Nuclear style feature then.
> >
> > 'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM'
> interpolate
> >
> > Feels like
> >
> > STR='sudo reboot'; $(STR)
> >
> > in bash when one is sudoer.
>
> Yeah, but it is always the original programmer who writes the template
> (including the 'Smalltalk snapshot:false andQuit: true' and the 'sudo
> reboot' in you examples), you would not do that for any good reason.
>
> Typically, you would write something like
>
> 'My name is {firstname} {lastname}' interpolate.
>
> in a method of an object with firstname and lastname as instance
> variables. To access the binding, #evaluate: is used. Though a malicious
> person could enter 'Smalltalk snapshot:false andQuit: true' as name, it is
> not that expression that gets evaluated. So in that respect there is no
> risk.
>
> The risk would be when the template string itself would be (partially)
> based on used input.
>
which is easy to overlook:
aString interpolate
People are on average a bit more carefull when they use #compile: or
#evaluate:.
Thierry
>
> > Phil
> >
> > On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
> >
> >
> > > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> > >
> > > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-
> templates-for-smalltalk/
> > >
> > > Phil
> >
> > Yes, Mustache is a cool templating engine, but it is similar to #format:
> not to #interpolate. With true string interpolation, you do not provide a
> context, you just write the expressions inline. Compare the following two:
> >
> > 'Today is {1} format: { Date today }.
> >
> > 'Today is { Date today }' interpolate.
> >
> > > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
> > > Hi,
> > >
> > > I got into a little office discussion about string interpolation as it
> is done in different programming languages.
> > >
> > > In Pharo we have String>>#format: which is pretty nice. It works as
> follows:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={1} and y={2}' format: { x. y }.
> > >
> > > It is also possible to use a dictionary with keys, like this:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> > >
> > > But this is not true string interpolation as described in [
> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
> write the value generating expressions directly inside the strings.
> > >
> > > Since in Pharo we add features not by extending the syntax but by
> adding messages I wondered if it could be done for string interpolation.
> The goal is to make the following work:
> > >
> > > | x y |
> > > x := 123.
> > > y := #foo.
> > > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
> interpolate.
> > >
> > > => 'It seems x equals 123 and y equals foo while Pi is still
> 3.141592653589793'
> > >
> > > Here is the implementation I came up with:
> > >
> > > String>>#interpolate
> > > "Format the receiver by interpolating the evaluation of expressions
> > > in between curly brackets in the context of the sender as in the
> following 3 oneline examples.
> > > 'Today is {Date today}' interpolate.
> > > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > > 'In {#strings} you can escape \{ by prefixing it with \\'
> interpolate."
> > >
> > > | senderContext |
> > > senderContext := thisContext sender.
> > > ^ self class new: self size streamContents: [ :out | | stream |
> > > stream := self readStream.
> > > [ stream atEnd ] whileFalse: [ | currentChar |
> > > (currentChar := stream next) == ${
> > > ifTrue: [ | expression result |
> > > expression := stream upTo: $}.
> > > result := Compiler new
> > > evaluate: expression in: senderContext to: nil
> notifying: nil ifFail: [ ^ nil ] logged: false.
> > > out nextPutAll: result asString ]
> > > ifFalse: [
> > > currentChar == $\
> > > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream
> next ] ]
> > > ifFalse: [ out nextPut: currentChar ] ] ] ]
> > >
> > > It is a hack that could certainly be improved. And there is of course
> an obvious security problem.
> > >
> > > Thoughts ?
> > >
> > > Sven
> > >
> > >
> > >
> >
> >
> >
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 16:55, Ron Teitelbaum <ron(a)usmedrec.com> wrote:
>
> Hi All,
>
> To solve this problem I do this:
>
> replaceTokensIn: aString
> ^self tokens inject: aString into: [:str :assoc |
> ((str explode: assoc key) mergeDelimited: assoc value value)].
>
> tokens is a collection of key value pairs.
>
> aString := 'Dear {!user}'.
>
> self tokens: {'{!user}' -> [self user]}.
>
> self replaceTokensIn: aString.
>
> I like using the blocks because they can be almost anything and since they are defined by the developer the security issue goes away. It's not a streaming solution which would be nice for a much longer text and it does rewrite the string for every token.
I think I understand what you mean. When there is no #evaluate: involved, there is no risk.
#explode: and #mergeDelimited: are not standard messages though ...
> On Thu, Sep 28, 2017 at 10:27 AM, phil(a)highoctane.be <phil(a)highoctane.be> wrote:
> We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
>
> Phil
>
> On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> Hi,
>
> I got into a little office discussion about string interpolation as it is done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 16:58, phil(a)highoctane.be wrote:
>
> I stand corrected.
>
> Nuclear style feature then.
>
> 'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM' interpolate
>
> Feels like
>
> STR='sudo reboot'; $(STR)
>
> in bash when one is sudoer.
Yeah, but it is always the original programmer who writes the template (including the 'Smalltalk snapshot:false andQuit: true' and the 'sudo reboot' in you examples), you would not do that for any good reason.
Typically, you would write something like
'My name is {firstname} {lastname}' interpolate.
in a method of an object with firstname and lastname as instance variables. To access the binding, #evaluate: is used. Though a malicious person could enter 'Smalltalk snapshot:false andQuit: true' as name, it is not that expression that gets evaluated. So in that respect there is no risk.
The risk would be when the template string itself would be (partially) based on used input.
> Phil
>
> On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
>
> > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> >
> > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
> >
> > Phil
>
> Yes, Mustache is a cool templating engine, but it is similar to #format: not to #interpolate. With true string interpolation, you do not provide a context, you just write the expressions inline. Compare the following two:
>
> 'Today is {1} format: { Date today }.
>
> 'Today is { Date today }' interpolate.
>
> > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> > Hi,
> >
> > I got into a little office discussion about string interpolation as it is done in different programming languages.
> >
> > In Pharo we have String>>#format: which is pretty nice. It works as follows:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={1} and y={2}' format: { x. y }.
> >
> > It is also possible to use a dictionary with keys, like this:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> >
> > But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
> >
> > Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
> >
> > => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
> >
> > Here is the implementation I came up with:
> >
> > String>>#interpolate
> > "Format the receiver by interpolating the evaluation of expressions
> > in between curly brackets in the context of the sender as in the following 3 oneline examples.
> > 'Today is {Date today}' interpolate.
> > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
> >
> > | senderContext |
> > senderContext := thisContext sender.
> > ^ self class new: self size streamContents: [ :out | | stream |
> > stream := self readStream.
> > [ stream atEnd ] whileFalse: [ | currentChar |
> > (currentChar := stream next) == ${
> > ifTrue: [ | expression result |
> > expression := stream upTo: $}.
> > result := Compiler new
> > evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> > out nextPutAll: result asString ]
> > ifFalse: [
> > currentChar == $\
> > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> > ifFalse: [ out nextPut: currentChar ] ] ] ]
> >
> > It is a hack that could certainly be improved. And there is of course an obvious security problem.
> >
> > Thoughts ?
> >
> > Sven
> >
> >
> >
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by philï¼ highoctane.be
I stand corrected.
Nuclear style feature then.
'Let me get out of here {Smalltalk snapshot:false andQuit: true}. BOOM'
interpolate
Feels like
STR='sudo reboot'; $(STR)
in bash when one is sudoer.
Phil
On Thu, Sep 28, 2017 at 4:43 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
>
>
> > On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
> >
> > We also have http://norbert.hartl.name/blog/2013/10/03/mustache-
> templates-for-smalltalk/
> >
> > Phil
>
> Yes, Mustache is a cool templating engine, but it is similar to #format:
> not to #interpolate. With true string interpolation, you do not provide a
> context, you just write the expressions inline. Compare the following two:
>
> 'Today is {1} format: { Date today }.
>
> 'Today is { Date today }' interpolate.
>
> > On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
> > Hi,
> >
> > I got into a little office discussion about string interpolation as it
> is done in different programming languages.
> >
> > In Pharo we have String>>#format: which is pretty nice. It works as
> follows:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={1} and y={2}' format: { x. y }.
> >
> > It is also possible to use a dictionary with keys, like this:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
> >
> > But this is not true string interpolation as described in [
> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
> write the value generating expressions directly inside the strings.
> >
> > Since in Pharo we add features not by extending the syntax but by adding
> messages I wondered if it could be done for string interpolation. The goal
> is to make the following work:
> >
> > | x y |
> > x := 123.
> > y := #foo.
> > 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
> interpolate.
> >
> > => 'It seems x equals 123 and y equals foo while Pi is still
> 3.141592653589793'
> >
> > Here is the implementation I came up with:
> >
> > String>>#interpolate
> > "Format the receiver by interpolating the evaluation of expressions
> > in between curly brackets in the context of the sender as in the
> following 3 oneline examples.
> > 'Today is {Date today}' interpolate.
> > | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> > 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
> >
> > | senderContext |
> > senderContext := thisContext sender.
> > ^ self class new: self size streamContents: [ :out | | stream |
> > stream := self readStream.
> > [ stream atEnd ] whileFalse: [ | currentChar |
> > (currentChar := stream next) == ${
> > ifTrue: [ | expression result |
> > expression := stream upTo: $}.
> > result := Compiler new
> > evaluate: expression in: senderContext to: nil notifying:
> nil ifFail: [ ^ nil ] logged: false.
> > out nextPutAll: result asString ]
> > ifFalse: [
> > currentChar == $\
> > ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next
> ] ]
> > ifFalse: [ out nextPut: currentChar ] ] ] ]
> >
> > It is a hack that could certainly be improved. And there is of course an
> obvious security problem.
> >
> > Thoughts ?
> >
> > Sven
> >
> >
> >
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Ron Teitelbaum
Hi All,
To solve this problem I do this:
replaceTokensIn: aString
^self tokens inject: aString into: [:str :assoc |
((str explode: assoc key) mergeDelimited: assoc value value)].
tokens is a collection of key value pairs.
aString := 'Dear {!user}'.
self tokens: {'{!user}' -> [self user]}.
self replaceTokensIn: aString.
I like using the blocks because they can be almost anything and since they
are defined by the developer the security issue goes away. It's not a
streaming solution which would be nice for a much longer text and it does
rewrite the string for every token.
On Thu, Sep 28, 2017 at 10:27 AM, phil(a)highoctane.be <phil(a)highoctane.be>
wrote:
> We also have http://norbert.hartl.name/blog/2013/10/03/mustache-
> templates-for-smalltalk/
>
> Phil
>
> On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu>
> wrote:
>
>> Hi,
>>
>> I got into a little office discussion about string interpolation as it is
>> done in different programming languages.
>>
>> In Pharo we have String>>#format: which is pretty nice. It works as
>> follows:
>>
>> | x y |
>> x := 123.
>> y := #foo.
>> 'x={1} and y={2}' format: { x. y }.
>>
>> It is also possible to use a dictionary with keys, like this:
>>
>> | x y |
>> x := 123.
>> y := #foo.
>> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>>
>> But this is not true string interpolation as described in [
>> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
>> write the value generating expressions directly inside the strings.
>>
>> Since in Pharo we add features not by extending the syntax but by adding
>> messages I wondered if it could be done for string interpolation. The goal
>> is to make the following work:
>>
>> | x y |
>> x := 123.
>> y := #foo.
>> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
>> interpolate.
>>
>> => 'It seems x equals 123 and y equals foo while Pi is still
>> 3.141592653589793'
>>
>> Here is the implementation I came up with:
>>
>> String>>#interpolate
>> "Format the receiver by interpolating the evaluation of expressions
>> in between curly brackets in the context of the sender as in the
>> following 3 oneline examples.
>> 'Today is {Date today}' interpolate.
>> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
>> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>>
>> | senderContext |
>> senderContext := thisContext sender.
>> ^ self class new: self size streamContents: [ :out | | stream |
>> stream := self readStream.
>> [ stream atEnd ] whileFalse: [ | currentChar |
>> (currentChar := stream next) == ${
>> ifTrue: [ | expression result |
>> expression := stream upTo: $}.
>> result := Compiler new
>> evaluate: expression in: senderContext to: nil notifying:
>> nil ifFail: [ ^ nil ] logged: false.
>> out nextPutAll: result asString ]
>> ifFalse: [
>> currentChar == $\
>> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next
>> ] ]
>> ifFalse: [ out nextPut: currentChar ] ] ] ]
>>
>> It is a hack that could certainly be improved. And there is of course an
>> obvious security problem.
>>
>> Thoughts ?
>>
>> Sven
>>
>>
>>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
Thierry,
> On 28 Sep 2017, at 16:38, Thierry Goubier <thierry.goubier(a)gmail.com> wrote:
>
> Hi Sven,
>
> Jason and Andrew wrote a string interpolation implementation for Andrew's language, Grace, in the parser. It works rather well and isn't too difficult to implement...
Like I said, I wanted to add the feature without changing the language (syntax). Using thisContext and the compiler makes that possible.
> The equivalent would be to add it to RB Parser, and, security wise, it would be as vulnerable as calling Compiler evaluate: 'an unsafe string'.
That is what I mean: it is an implicit #evaluate: call, the risk is comparable to an SQL injection attack if the attacker could write the template (not that likely though).
> Regards,
>
> Thierry
>
> 2017-09-28 16:20 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
> Hi,
>
> I got into a little office discussion about string interpolation as it is done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Sven Van Caekenberghe
> On 28 Sep 2017, at 16:27, phil(a)highoctane.be wrote:
>
> We also have http://norbert.hartl.name/blog/2013/10/03/mustache-templates-for-smalltalk/
>
> Phil
Yes, Mustache is a cool templating engine, but it is similar to #format: not to #interpolate. With true string interpolation, you do not provide a context, you just write the expressions inline. Compare the following two:
'Today is {1} format: { Date today }.
'Today is { Date today }' interpolate.
> On Thu, Sep 28, 2017 at 4:20 PM, Sven Van Caekenberghe <sven(a)stfx.eu> wrote:
> Hi,
>
> I got into a little office discussion about string interpolation as it is done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [ https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding messages I wondered if it could be done for string interpolation. The goal is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}' interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying: nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ] ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] String Interpolation
by Thierry Goubier
Hi Sven,
Jason and Andrew wrote a string interpolation implementation for Andrew's
language, Grace, in the parser. It works rather well and isn't too
difficult to implement...
The equivalent would be to add it to RB Parser, and, security wise, it
would be as vulnerable as calling Compiler evaluate: 'an unsafe string'.
Regards,
Thierry
2017-09-28 16:20 GMT+02:00 Sven Van Caekenberghe <sven(a)stfx.eu>:
> Hi,
>
> I got into a little office discussion about string interpolation as it is
> done in different programming languages.
>
> In Pharo we have String>>#format: which is pretty nice. It works as
> follows:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={1} and y={2}' format: { x. y }.
>
> It is also possible to use a dictionary with keys, like this:
>
> | x y |
> x := 123.
> y := #foo.
> 'x={x} and y={y}' format: { #x->x. #y->y } asDictionary.
>
> But this is not true string interpolation as described in [
> https://en.wikipedia.org/wiki/String_interpolation ]. The idea is to
> write the value generating expressions directly inside the strings.
>
> Since in Pharo we add features not by extending the syntax but by adding
> messages I wondered if it could be done for string interpolation. The goal
> is to make the following work:
>
> | x y |
> x := 123.
> y := #foo.
> 'It seems x equals {x} and y equals {y} while Pi is still {Float pi}'
> interpolate.
>
> => 'It seems x equals 123 and y equals foo while Pi is still
> 3.141592653589793'
>
> Here is the implementation I came up with:
>
> String>>#interpolate
> "Format the receiver by interpolating the evaluation of expressions
> in between curly brackets in the context of the sender as in the
> following 3 oneline examples.
> 'Today is {Date today}' interpolate.
> | x | x := 123. 'x equals {x} and pi equals {Float pi}' interpolate.
> 'In {#strings} you can escape \{ by prefixing it with \\' interpolate."
>
> | senderContext |
> senderContext := thisContext sender.
> ^ self class new: self size streamContents: [ :out | | stream |
> stream := self readStream.
> [ stream atEnd ] whileFalse: [ | currentChar |
> (currentChar := stream next) == ${
> ifTrue: [ | expression result |
> expression := stream upTo: $}.
> result := Compiler new
> evaluate: expression in: senderContext to: nil notifying:
> nil ifFail: [ ^ nil ] logged: false.
> out nextPutAll: result asString ]
> ifFalse: [
> currentChar == $\
> ifTrue: [ stream atEnd ifFalse: [ out nextPut: stream next ]
> ]
> ifFalse: [ out nextPut: currentChar ] ] ] ]
>
> It is a hack that could certainly be improved. And there is of course an
> obvious security problem.
>
> Thoughts ?
>
> Sven
>
>
>
Sept. 28, 2017
Re: [Pharo-dev] Epicea wishlist
by Martin Dias
Stef, ok I add your request in the issue tracker:
https://pharo.fogbugz.com/f/cases/20474/Epicea-Keep-filter-across-session-i…
It's kind of funny because the filters were kept across seassions and I
*intentionally* added the filter cleaning when session selection changes.
IMO it was misleading to keep them as you want, but also I understand your
point... I think moving the filters widget to other place in the window can
do it.
MartÃÂn
On Thu, Sep 7, 2017 at 3:15 AM, Stephane Ducasse <stepharo.self(a)gmail.com>
wrote:
> Hi martin
>
> I'm missing two features:
>
> - keep the filter across session because this is boring to have to
> redo them all over.
> - a search for entities accross session.
> - a search inside a session
> For example I was looking for all the changes I did to the UI part of
> my application but I was doing many development
> loading different unrelated package and saving after.
>
> Right now you can restrict to view changes but only if you have a
> first entity of the package for example so you have to look first is
> there an entity of this package.
>
> Stef
>
>
Sept. 28, 2017