diff options
-rw-r--r-- | src/nre.nim | 35 | ||||
-rw-r--r-- | test/captures.nim | 19 |
2 files changed, 54 insertions, 0 deletions
diff --git a/src/nre.nim b/src/nre.nim index 5a5cbaa45..64ed8c75d 100644 --- a/src/nre.nim +++ b/src/nre.nim @@ -2,6 +2,7 @@ import private.pcre as pcre import private.util import tables import unsigned +from future import lc, `[]` from strutils import toLower, `%` from math import ceil import optional_t @@ -102,6 +103,40 @@ proc `[]`*(self: Captures, name: string): string = ## Will fail with KeyError if `name` is not a real named capture let self = RegexMatch(self) return self.captures[self.pattern.captureNameToId.fget(name)] + +template asTableImpl(cond: bool): stmt {.immediate, dirty.} = + for key in RegexMatch(self).pattern.captureNames: + let nextVal = self[key] + if cond: + result[key] = default + else: + result[key] = nextVal + +proc asTable*(self: Captures, default: string = nil): Table[string, string] = + ## Gets all the named captures and returns them + result = initTable[string, string]() + asTableImpl(nextVal == nil) + +proc asTable*(self: CaptureBounds, default = None[Slice[int]]()): + Table[string, Option[Slice[int]]] = + ## Gets all the named captures and returns them + result = initTable[string, Option[Slice[int]]]() + asTableImpl(nextVal.isNone) + +template asSeqImpl(cond: bool): stmt {.immediate, dirty.} = + result = @[] + for i in 0 .. <RegexMatch(self).pattern.captureCount: + let nextVal = self[i] + if cond: + result.add(default) + else: + result.add(nextVal) + +proc asSeq*(self: CaptureBounds, default = None[Slice[int]]()): seq[Option[Slice[int]]] = + asSeqImpl(nextVal.isNone) + +proc asSeq*(self: Captures, default: string = nil): seq[string] = + asSeqImpl(nextVal == nil) # }}} # Creation & Destruction {{{ diff --git a/test/captures.nim b/test/captures.nim index f2699c935..b52c283b6 100644 --- a/test/captures.nim +++ b/test/captures.nim @@ -39,3 +39,22 @@ suite "captures": check(ex1.captureCount == 2) # Don't have sets, do this :< check(ex1.captureNames == @["foo", "bar"] or ex1.captureNames == @["bar", "foo"]) + + test "named capture table": + let ex1 = initRegex("(?<foo>foo)(?<bar>bar)?").exec("foo").get + check(ex1.captures.asTable == {"foo" : "foo", "bar" : nil}.toTable()) + check(ex1.captureBounds.asTable == {"foo" : Some(0..3), "bar" : None[Slice[int]]()}.toTable()) + check(ex1.captures.asTable("") == {"foo" : "foo", "bar" : ""}.toTable()) + + let ex2 = initRegex("(?<foo>foo)(?<bar>bar)?").exec("foobar").get + check(ex2.captures.asTable == {"foo" : "foo", "bar" : "bar"}.toTable()) + + test "capture sequence": + let ex1 = initRegex("(?<foo>foo)(?<bar>bar)?").exec("foo").get + check(ex1.captures.asSeq == @["foo", nil]) + check(ex1.captureBounds.asSeq == @[Some(0..3), None[Slice[int]]()]) + check(ex1.captures.asSeq("") == @["foo", ""]) + + let ex2 = initRegex("(?<foo>foo)(?<bar>bar)?").exec("foobar").get + check(ex2.captures.asSeq == @["foo", "bar"]) + |