diff options
author | Flaviu Tamas <tamasflaviu@gmail.com> | 2015-01-19 15:59:45 -0500 |
---|---|---|
committer | Flaviu Tamas <tamasflaviu@gmail.com> | 2015-01-19 16:04:21 -0500 |
commit | f34a7dc1f5829713b0d076f5d182df6f4beb1761 (patch) | |
tree | c306afe24263aa0ab6c6cc77a05a98207818f634 | |
parent | a5693675fb36588b12033d3768d41b4c63d31c4b (diff) | |
download | Nim-f34a7dc1f5829713b0d076f5d182df6f4beb1761.tar.gz |
Make replace a template
Also required me to fix a name conflict with the format template
-rw-r--r-- | src/nre.nim | 21 | ||||
-rw-r--r-- | src/private/util.nim | 15 |
2 files changed, 22 insertions, 14 deletions
diff --git a/src/nre.nim b/src/nre.nim index 6c5a1ab35..e56194fd6 100644 --- a/src/nre.nim +++ b/src/nre.nim @@ -423,25 +423,32 @@ proc split*(str: string, pattern: Regex, maxSplit = -1): seq[string] = # This handles "2" result.add(str.substr(bounds.b, str.len - 1)) -proc replace*(str: string, pattern: Regex, - subproc: proc (match: RegexMatch): string): string = +template replaceImpl(str: string, pattern: Regex, + replacement: expr): stmt {.immediate, dirty.} = # XXX seems very similar to split, maybe I can reduce code duplication # somehow? result = "" var lastIdx = 0 - for match in str.findIter(pattern): + for match {.inject.} in str.findIter(pattern): let bounds = match.matchBounds result.add(str.substr(lastIdx, bounds.a - 1)) - result.add(subproc(match)) + let nextVal = replacement + assert(nextVal != nil) + result.add(nextVal) lastIdx = bounds.b result.add(str.substr(lastIdx, str.len - 1)) + return result + +proc replace*(str: string, pattern: Regex, + subproc: proc (match: RegexMatch): string): string = + replaceImpl(str, pattern, subproc(match)) proc replace*(str: string, pattern: Regex, sub: string): string = - return str.replace(pattern, proc (match: RegexMatch): string = - # - 1 because the string numbers are 0-indexed - formatStr(sub, match.captures[name], match.captures[id - 1]) ) + # - 1 because the string numbers are 0-indexed + replaceImpl(str, pattern, + formatStr(sub, match.captures[name], match.captures[id - 1])) # }}} diff --git a/src/private/util.nim b/src/private/util.nim index 5629e81e6..72be023b2 100644 --- a/src/private/util.nim +++ b/src/private/util.nim @@ -11,20 +11,20 @@ const StartIdent = Ident - {'0'..'9'} template formatStr*(howExpr, namegetter, idgetter: expr): expr = let how = howExpr - result = newStringOfCap(how.len) + var val = newStringOfCap(how.len) var i = 0 var lastNum = 1 while i < how.len: if how[i] != '$': - result.add(how[i]) + val.add(how[i]) i += 1 elif how[i + 1] == '$': - result.add('$') + val.add('$') i += 2 elif how[i + 1] == '#': var id {.inject.} = lastNum - result.add(idgetter) + val.add(idgetter) lastNum += 1 i += 2 elif how[i + 1] in {'0'..'9'}: @@ -33,7 +33,7 @@ template formatStr*(howExpr, namegetter, idgetter: expr): expr = while i < how.len and how[i] in {'0'..'9'}: id += (id * 10) + (ord(how[i]) - ord('0')) i += 1 - result.add(idgetter) + val.add(idgetter) lastNum = id + 1 elif how[i + 1] in StartIdent: i += 1 @@ -41,7 +41,7 @@ template formatStr*(howExpr, namegetter, idgetter: expr): expr = while i < how.len and how[i] in Ident: name.add(how[i]) i += 1 - result.add(namegetter) + val.add(namegetter) elif how[i + 1] == '{': i += 2 var name {.inject.} = "" @@ -49,6 +49,7 @@ template formatStr*(howExpr, namegetter, idgetter: expr): expr = name.add(how[i]) i += 1 i += 1 - result.add(namegetter) + val.add(namegetter) else: raise newException(Exception, "Syntax error in format string at " & $i) + val |