aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--environment.c4
-rw-r--r--stdlib/patterns.c16
-rw-r--r--stdlib/patterns.h2
-rw-r--r--test/paths.tm2
-rw-r--r--test/text.tm14
5 files changed, 27 insertions, 11 deletions
diff --git a/environment.c b/environment.c
index d3e27069..228c5ac4 100644
--- a/environment.c
+++ b/environment.c
@@ -294,7 +294,7 @@ env_t *new_compilation_unit(CORD *libname)
// Text methods:
{"ends_with", "Text$ends_with", "func(path:Path, suffix:Text)->Bool"},
{"has", "Text$has", "func(path:Path, pattern:Pattern)->Bool"},
- {"matches", "Text$matches", "func(path:Path, pattern:Pattern)->Bool"},
+ {"matches", "Text$matches", "func(path:Path, pattern:Pattern)->[Text]?"},
{"replace", "Text$replace", "func(path:Path, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes)->Path"},
{"replace_all", "Text$replace_all", "func(path:Path, replacements:{Pattern:Text}, backref=$/\\/, recursive=yes)->Path"},
{"starts_with", "Text$starts_with", "func(path:Path, prefix:Text)->Bool"},
@@ -320,7 +320,7 @@ env_t *new_compilation_unit(CORD *libname)
{"lines", "Text$lines", "func(text:Text)->[Text]"},
{"lower", "Text$lower", "func(text:Text)->Text"},
{"map", "Text$map", "func(text:Text, pattern:Pattern, fn:func(text:Text)->Text)->Text"},
- {"matches", "Text$matches", "func(text:Text, pattern:Pattern)->Bool"},
+ {"matches", "Text$matches", "func(text:Text, pattern:Pattern)->[Text]?"},
{"quoted", "Text$quoted", "func(text:Text, color=no)->Text"},
{"repeat", "Text$repeat", "func(text:Text, count:Int)->Text"},
{"replace", "Text$replace", "func(text:Text, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes)->Text"},
diff --git a/stdlib/patterns.c b/stdlib/patterns.c
index 0df06eba..701aff9c 100644
--- a/stdlib/patterns.c
+++ b/stdlib/patterns.c
@@ -7,6 +7,7 @@
#include "arrays.h"
#include "integers.h"
+#include "optionals.h"
#include "patterns.h"
#include "tables.h"
#include "text.h"
@@ -824,10 +825,19 @@ PUREFUNC public bool Text$has(Text_t text, Pattern_t pattern)
}
}
-PUREFUNC public bool Text$matches(Text_t text, Pattern_t pattern)
+public OptionalArray_t Text$matches(Text_t text, Pattern_t pattern)
{
- int64_t m = match(text, 0, pattern, 0, NULL, 0);
- return m == text.length;
+ capture_t captures[MAX_BACKREFS] = {};
+ int64_t match_len = match(text, 0, pattern, 0, captures, 0);
+ if (match_len != text.length)
+ return NULL_ARRAY;
+
+ Array_t capture_array = {};
+ for (int i = 0; captures[i].occupied; i++) {
+ Text_t capture = Text$slice(text, I(captures[i].index+1), I(captures[i].index+captures[i].length));
+ Array$insert(&capture_array, &capture, I(0), sizeof(Text_t));
+ }
+ return capture_array;
}
public Array_t Text$find_all(Text_t text, Pattern_t pattern)
diff --git a/stdlib/patterns.h b/stdlib/patterns.h
index 804fb286..9825cf96 100644
--- a/stdlib/patterns.h
+++ b/stdlib/patterns.h
@@ -21,7 +21,7 @@ Text_t Text$trim(Text_t text, Pattern_t pattern, bool trim_left, bool trim_right
Int_t Text$find(Text_t text, Pattern_t pattern, Int_t i, int64_t *match_length);
Array_t Text$find_all(Text_t text, Pattern_t pattern);
PUREFUNC bool Text$has(Text_t text, Pattern_t pattern);
-PUREFUNC bool Text$matches(Text_t text, Pattern_t pattern);
+Array_t Text$matches(Text_t text, Pattern_t pattern);
Text_t Text$map(Text_t text, Pattern_t pattern, Closure_t fn);
#define Pattern$hash Text$hash
diff --git a/test/paths.tm b/test/paths.tm
index 4ef0b028..92a14640 100644
--- a/test/paths.tm
+++ b/test/paths.tm
@@ -84,7 +84,7 @@ func main():
>> (./foo.txt):ends_with(".txt")
= yes
>> (./foo.txt):matches($|{..}/foo{..}|)
- = yes
+ = [".", ".txt"]?
>> (./foo.txt):replace($/.txt/, ".md")
= (./foo.md)
diff --git a/test/text.tm b/test/text.tm
index f27eaf37..f87cedfb 100644
--- a/test/text.tm
+++ b/test/text.tm
@@ -251,13 +251,19 @@ func main():
= " good(x, fn(y), BAD(z), w) "
>> "Hello":matches($/{id}/)
- = yes
+ = ["Hello"]?
>> "Hello":matches($/{lower}/)
- = no
+ = ![Text]
>> "Hello":matches($/{upper}/)
- = no
+ = ![Text]
>> "Hello...":matches($/{id}/)
- = no
+ = ![Text]
+
+ if matches := "hello world":matches($/{id} {id}/):
+ >> matches
+ = ["hello", "world"]
+ else:
+ fail("Failed to match")
>> "hello world":map($/world/, Text.upper)
= "hello WORLD"