Make replace a template

Also required me to fix a name conflict with the format template
This commit is contained in:
Flaviu Tamas 2015-01-19 15:59:45 -05:00
commit f34a7dc1f5
2 changed files with 22 additions and 14 deletions

View file

@ -423,25 +423,32 @@ proc split*(str: string, pattern: Regex, maxSplit = -1): seq[string] =
# This handles "2" # This handles "2"
result.add(str.substr(bounds.b, str.len - 1)) result.add(str.substr(bounds.b, str.len - 1))
proc replace*(str: string, pattern: Regex, template replaceImpl(str: string, pattern: Regex,
subproc: proc (match: RegexMatch): string): string = replacement: expr): stmt {.immediate, dirty.} =
# XXX seems very similar to split, maybe I can reduce code duplication # XXX seems very similar to split, maybe I can reduce code duplication
# somehow? # somehow?
result = "" result = ""
var lastIdx = 0 var lastIdx = 0
for match in str.findIter(pattern): for match {.inject.} in str.findIter(pattern):
let bounds = match.matchBounds let bounds = match.matchBounds
result.add(str.substr(lastIdx, bounds.a - 1)) result.add(str.substr(lastIdx, bounds.a - 1))
result.add(subproc(match)) let nextVal = replacement
assert(nextVal != nil)
result.add(nextVal)
lastIdx = bounds.b lastIdx = bounds.b
result.add(str.substr(lastIdx, str.len - 1)) 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 = 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
# - 1 because the string numbers are 0-indexed replaceImpl(str, pattern,
formatStr(sub, match.captures[name], match.captures[id - 1]) ) formatStr(sub, match.captures[name], match.captures[id - 1]))
# }}} # }}}

View file

@ -11,20 +11,20 @@ const StartIdent = Ident - {'0'..'9'}
template formatStr*(howExpr, namegetter, idgetter: expr): expr = template formatStr*(howExpr, namegetter, idgetter: expr): expr =
let how = howExpr let how = howExpr
result = newStringOfCap(how.len) var val = newStringOfCap(how.len)
var i = 0 var i = 0
var lastNum = 1 var lastNum = 1
while i < how.len: while i < how.len:
if how[i] != '$': if how[i] != '$':
result.add(how[i]) val.add(how[i])
i += 1 i += 1
elif how[i + 1] == '$': elif how[i + 1] == '$':
result.add('$') val.add('$')
i += 2 i += 2
elif how[i + 1] == '#': elif how[i + 1] == '#':
var id {.inject.} = lastNum var id {.inject.} = lastNum
result.add(idgetter) val.add(idgetter)
lastNum += 1 lastNum += 1
i += 2 i += 2
elif how[i + 1] in {'0'..'9'}: 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'}: while i < how.len and how[i] in {'0'..'9'}:
id += (id * 10) + (ord(how[i]) - ord('0')) id += (id * 10) + (ord(how[i]) - ord('0'))
i += 1 i += 1
result.add(idgetter) val.add(idgetter)
lastNum = id + 1 lastNum = id + 1
elif how[i + 1] in StartIdent: elif how[i + 1] in StartIdent:
i += 1 i += 1
@ -41,7 +41,7 @@ template formatStr*(howExpr, namegetter, idgetter: expr): expr =
while i < how.len and how[i] in Ident: while i < how.len and how[i] in Ident:
name.add(how[i]) name.add(how[i])
i += 1 i += 1
result.add(namegetter) val.add(namegetter)
elif how[i + 1] == '{': elif how[i + 1] == '{':
i += 2 i += 2
var name {.inject.} = "" var name {.inject.} = ""
@ -49,6 +49,7 @@ template formatStr*(howExpr, namegetter, idgetter: expr): expr =
name.add(how[i]) name.add(how[i])
i += 1 i += 1
i += 1 i += 1
result.add(namegetter) val.add(namegetter)
else: else:
raise newException(Exception, "Syntax error in format string at " & $i) raise newException(Exception, "Syntax error in format string at " & $i)
val