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, [email protected] <[email protected]>
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 <[email protected]>
> 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
>>
>>
>>
>

Reply via email to