I'm trying to get Nim to replace part of a string with the result of a function.
The idea is to have blocks which will be processed, in this case I'm wrapping it in {{ }}, but I'm having trouble getting Nim to replace text within the brackets.
I've tried various variations of this: replace(f, "{{.*}}", mdReplaceNew(f))
So you can see, I'm trying to make it grab all the text within the brackets, to be replaced by the same text but processed through the mdReplaceNew proc.
Yes, I'm using the re module.
Though, is there a way to specify which replace should be used? (strutils vs re)
So with regex replace, I need to replace text within brackets with the same text run through a proc, I just can't make it do it.
@Daimon If you look at http://nim-lang.org/theindex.html#eplac you can see that re.replace takes a Regex object, while strutils.replace takes a character or string.
To specify which procedure to use, you can either take advantage of Nim's overloading mechanism (which selects the right procedure based on argument type and number), or specify the procedure to use via module prefix:
strutils.replace("Hello World", "World", "Universe")
re.replace(...)
I just can't get it to replace with the result of the proc mdReplaceNew.
I can replace with a hardcoded value no problem, but when I try to use a procs return, it just doesn't work.
re.replacef(f, re("{{(.*)}}", {reDotAll}), mdReplaceNew("$1"))
$1 should be the capture group, which is passed to mdReplaceNew, which does a bunch of changes and returns a string (This works perfectly when not using regex, so I know the proc works), but when placed in a replace like this, does not work.
The regex works and matches what it should, the mdReplaceNew proc works, just not when I put the two together. lol
I don't know if this is a bug, or just me not getting how to use it properly.
I looked at moustache, that coder uses a different tactic, matching and saving bounds, which is what I'll end up doing if I can't ge this to work.
For me that works:
import re
let orig ="Hello {{Test}}!"
proc mdReplaceNew(s: string): string =
result = s & "-World"
let res = re.replacef(orig, re("{{(.*)}}", {reDotAll}), mdReplaceNew("$1"))
echo res
Output:
Hello Test-World!
BTW: I would just parse the "{{" and "}}" with a stack for nesting and not use regex at all. Normaly templates should be fast and I think that would be faster (would compare that probably).
I'm not at that box at the moment, but I was using return instead of result, and var instead of let, I'll test and see if I can make it work.
I'm new to templates, I'm planning to take a stab at that anyway for another project, but might as well start now.
There are multiple lines between {{ and }} but I'm guessing that's not a problem for templates.
At a glance, templates and macros do not seem to be what I need.
If I understand it right, those would be useful if I'm processing files at compile time, however, I'm processing files at runtime (Like an interpreter) for a DSL.
When I get back to the box, I think I'm going to just loop each line and set a flag if the loop is inside a {{}} block, and if it is to process that block.
That should be way faster than regex anyway.
Yeah I noticed another problem.
I can get it to pass in the text, but it loses newlines and other info.
If I pass in the original as is, I can split by newlines, if I pass it in through the replace, I somehow lose the newlines and the whole thing is treated as a single block.
I'll try updating Nim and if it persists I'll try to dig around to find out what's going on.
I grabbed the binary download for Windows from the download page, which apparently is 0.10.2
After playing with this some more, I'm narrowing down the problem.
The string isn't being pass into the function, just the token symbols, so it returns the token symbol, and essentially replaces the block with the block.
This problem should be fixed already in 0.10.3 according to doms example, but I've no idea how to build that version, so at the moment I'm stuck waiting for the binary release of it.
In the mean time I do have other things to work with, such as security, simple code injection/replacement, logging, error handling, etc.
Before tokenizing like this, consider if your regexes are at the right level. What about {{ }} }}? The regex would tokenize that as {{ }} }}, not as {{ }} as expected.
{{.*?}} would tokenize {{ "}}" }} as {{ "}}
The match(es) will be available using $1,$2, etc.
However, as I pass it into the function, $1 isn't replaced by the string value, it passes the $1 as the value.
dom96 says that it works when he does it, but he uses 0.10.3, I'm using 0.10.2, assuming that's the only differences, it should work fine once the updated binary is available.
The regex works, and even if it gets the match wrong, it's still passing $1 instead of the value.