> On 28 Sep 2017, at 17:13, Thierry Goubier <thierry.goubier@gmail.com> wrote:
>
>
>
> 2017-09-28 17:08 GMT+02:00 Sven Van Caekenberghe <sven@stfx.eu>:
>
>
> > On 28 Sep 2017, at 16:58, phil@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@stfx.eu> wrote:
> >
> >
> > > On 28 Sep 2017, at 16:27, phil@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@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
> > >
> > >
> > >
> >
> >
> >