Let's use "trans" instead of a regular expression, updating my example:
sub format-string(Str:D $source, *%vars --> Str:D) { return $source.trans( [%vars.keys.map: '$(' ~ * ~ ')' ] => [%vars.values] ); } so simple! But, it does not catch missing variables... I bet we can fix that by adding a regexp at the end... and also test if multi-substitution happens. Ah it all works nicely as I would like. #!/usr/bin/env perl6 my Str $source = '$(greeting), $(name). What do you think about $(any-topic)?'; my Str $output = format-string( $source, name => 'Earthling [$(any-topic)=should say "any-topic"]', any-topic => '[$(name)=should say "name"] life on other planets', ); say $output; # I don't know your greeting, Earthling [$(any-topic)=should say "any-topic"]. What do you think about [$(name)=should say "name"] life on other planets? sub format-string(Str:D $source, *%vars --> Str:D) { return $source.trans( [%vars.keys.map( '$(' ~ * ~ ')' ), / '$(' ( <[\w -]>+ ) ')' / ] => [ %vars.values, { "I don't know your $0" } ] ); } -y On Wed, Aug 29, 2018 at 1:41 PM Patrick Spek via perl6-users < perl6-users@perl.org> wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA256 > > It's supposed to be simple, since I don't need much. The most basic of > substitution is all I care about right now. I've implemented it with a > simple regex now, and it seems to work just fine. It's available as a > module[1] now, and it's used in another module of mine[2]. If anybody > wants to improve it, feel free to submit a MR on the repository[3]. > > Thanks everyone for your help! > > [1]: https://modules.perl6.org/dist/I18n::Simple:cpan:TYIL > [2]: https://gitlab.com/tyil/perl6-app-assixt > [3]: https://gitlab.com/tyil/perl6-i18n-Simple > > On Wed, 29 Aug 2018 19:28:56 +0200 > Timo Paulssen <t...@wakelift.de> wrote: > > > I should point out that the trans method has a mode that lets you pass > > placeholders and substitutions and it will Do The Right Thing > > regarding overlaps and order and everything. > > > > > > On 29/08/18 16:21, Timo Paulssen wrote: > > > There's a problem with your code, if any of the substitutions > > > contains something that looks like the placeholder thing, and if it > > > comes later in the iteration of the hash keys (which is randomized > > > now) it will substitute again. This is very likely not what you > > > want, though. > > > > > > HTH > > > - Timo > > > > > > On 28/08/18 20:04, Laurent Rosenfeld via perl6-users wrote: > > > > Hi Patrick, > > for note that this codeline: > > my Str $input = > > > > "Here be a > > > $(placeholder), for $(purpose) purposes."; > > will not compile > > > because Perl will try to interpolate $(placeholder) and $(purpose) > > > as vairables that have not been declared. > > You need to use non > > > interpolating quotes: > > my Str $input = 'Here be a $(placeholder), > > > for $(purpose) purposes.'; > > Then, I would probably use simple > > > substitutions, as with this example: > > my Str $input = 'Here be a > > > $(placeholder), for $(purpose) purposes.'; > > sub format-string > > > ($input, %substitutions) { > my $str = $input; > for keys > > > %substitutions -> $key { > $str ~~ s/$key/%substitutions{$key}/; > > > > } > return $str; > } > my %substitutes = '$(placeholder)' => > > > "placeholder", '$(purpose)' => "testing"; > my $output = > > > format-string($input, %substitutes); > say $output; > > This is the > > > output running this under the REPL: > > > my Str $input = 'Here be a > > > $(placeholder), for $(purpose) purposes.'; > Here be a > > > $(placeholder), for $(purpose) purposes. > > > > sub format-string > > > ($input, %substitutions) { > * my $str = $input; > * for keys > > > %substitutions -> $key { > * $str ~~ s/$key/%substitutions{$key}/; > > > > * } > * return $str; > * } > sub format-string ($input, > > > > %substitutions) { > > > #`(Sub|214745424) ... } > > my %substitutes = '$(placeholder)' => > > > "placeholder", '$(purpose)' => "testing"; > {$(placeholder) => > > > placeholder, $(purpose) => testing} > > my $output = > > > format-string($input, %substitutes); > Here be a placeholder, for > > > testing purposes. > > say $output; > Here be a placeholder, for > > > testing purposes. > > I hope this helps. > > Cheers, > Laurent. > > > > > > > > > > > Le mar. 28 août 2018 à 12:25, Patrick Spek via perl6-users > > > <perl6-users@perl.org <mailto:perl6-users@perl.org>> a écrit : > > > >> Hi all, > > >> > > >> I'm trying to substitute parts of a string, and thought this might > > >> be a good use of a grammar. Sadly, grammars aren't my strong suit, > > >> so I thought I'd ask the wider community for help. Maybe you guys > > >> know an even better solution than using a grammar here. > > >> > > >> So, consider a string, "Here be a $(placeholder), for $(purpose) > > >> purposes.". I want to be able to put that into a sub, along with > > >> some Pairs, and get a string with the placeholders replaced back. > > >> > > >> my Str $input = "Here be a $(placeholder), for $(purpose) > > >> purposes."; my Str $output = format-string( > > >> $input, > > >> placeholder => "placeholder", > > >> purpose => "testing", > > >> ); > > >> > > >> dd $output; # "Here be a placeholder, for testing purposes." > > >> > > >> The `format-string` sub would call the grammar and apply the actual > > >> substitution, and that's where I need your help. I am not quite > > >> sure how I would implement the grammar (and presumably it's > > >> actions) to do what I want. > > >> > > >> Thanks in advance for your help! > > >> > > > > > > > > > > > > > - -- > With kind regards, > > Patrick Spek > > > www: https://www.tyil.work/ > mail: p.s...@tyil.nl > pgp: EB9E A484 1672 2D37 16F5 A799 9ACF E193 FFBC 1F50 > > mastodon: @tyil@mastodon.social > github: @Tyil > gitlab: @tyil > > -----BEGIN PGP SIGNATURE----- > > iQEzBAEBCAAdFiEE4eL662U9iK2ST2MqN/W6H45XOE8FAluHBKQACgkQN/W6H45X > OE8I/wf/YWLWKCxj0AUvJt9xaosRPYYw2A3z8IgejA95S6UjeIgCzswal3xp0YiU > FfkUL0eSiuXc2fw3FLFl/FK0R6KzpW8V+kBpKZaB0bcU9tErpwTYwLQFyxvdgYjQ > FUiCZ+sM6963RihCJZwVMF8pzwZDOcKMmuxg67Ufd/syOHE7yZT2MV8FxXAA0xAT > pGRA00XrlSIzJTY1VQcWY5JjrbM+aD9U/QsfWiVc8oKrbAKGExJ096UQ3bcDhFzf > EwMhdGBUrkQjfGj7TPWhC9w2fmth+DiNx2EhSYZCKs7Qn0+XmaOMsznC6/Dm23sv > ok27sdgL+jr/P0x1CjrpAlxX5jgJiA== > =fDhH > -----END PGP SIGNATURE----- >