summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/nre.nim35
-rw-r--r--test/captures.nim19
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"])
+