From 47d5b304235c5b1f409b01cab95a2191eac5a230 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Sat, 18 Jul 2020 12:34:52 +0300 Subject: Add $regex.find_match() and $regex.find_search() functions --- NEWS | 2 + libbuild2/functions-regex.cxx | 98 +++++++++++++++++++++++++++++++++++++++++ tests/function/regex/testscript | 84 +++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) diff --git a/NEWS b/NEWS index f5e2016..5999e49 100644 --- a/NEWS +++ b/NEWS @@ -187,6 +187,8 @@ Version 0.13.0 See the "Install Module" chapter in the manual for details. + * New $regex.find_{match,search}() functions that operate on lists. + * The $process.run*() functions now recognize a number of portable builtins. Refer to the Testscript manual for the list and details. diff --git a/libbuild2/functions-regex.cxx b/libbuild2/functions-regex.cxx index 10067a4..a59d808 100644 --- a/libbuild2/functions-regex.cxx +++ b/libbuild2/functions-regex.cxx @@ -397,6 +397,63 @@ namespace build2 return r; } + static regex::flag_type + parse_find_flags (optional&& flags) + { + regex::flag_type r (regex::ECMAScript); + + if (flags) + { + for (auto& f: *flags) + { + string s (convert (move (f))); + + if (s == "icase") + r |= regex::icase; + else + throw invalid_argument ("invalid flag '" + s + "'"); + } + } + + return r; + } + + // Return true if any of the list elements match the regular expression. + // See find_match() overloads (below) for details. + // + static bool + find_match (names&& s, const string& re, optional&& flags) + { + regex::flag_type fl (parse_find_flags (move (flags))); + regex rge (parse_regex (re, fl)); + + for (auto& v: s) + { + if (regex_match (convert (move (v)), rge)) + return true; + } + + return false; + } + + // Return true if a part of any of the list elements matches the regular + // expression. See find_search() overloads (below) for details. + // + static bool + find_search (names&& s, const string& re, optional&& flags) + { + regex::flag_type fl (parse_find_flags (move (flags))); + regex rge (parse_regex (re, fl)); + + for (auto& v: s) + { + if (regex_search (convert (move (v)), rge)) + return true; + } + + return false; + } + // Replace matched parts of list elements using the format string and // concatenate the transformed elements. See merge() overloads (below) for // details. @@ -474,6 +531,25 @@ namespace build2 return match (move (s), convert (move (re)), move (flags)); }; + // $regex.find_match(, [, ]) + // + // Match list elements against the regular expression and return true if + // the match is found. Convert the elements to string prior to matching. + // + // The following flags are supported: + // + // icase - match ignoring case + // + f[".find_match"] = [](names s, string re, optional flags) + { + return find_match (move (s), re, move (flags)); + }; + + f[".find_match"] = [](names s, names re, optional flags) + { + return find_match (move (s), convert (move (re)), move (flags)); + }; + // $regex.search(, [, ]) // // Determine if there is a match between the regular expression and some @@ -507,6 +583,28 @@ namespace build2 return search (move (s), convert (move (re)), move (flags)); }; + // $regex.find_search(, [, ]) + // + // Determine if there is a match between the regular expression and some + // part of any of the list elements. Convert the elements to string prior + // to matching. + // + // The following flags are supported: + // + // icase - match ignoring case + // + f[".find_search"] = [](names s, string re, optional flags) + { + return find_search (move (s), re, move (flags)); + }; + + f[".find_search"] = [](names s, names re, optional flags) + { + return find_search (move (s), + convert (move (re)), + move (flags)); + }; + // $regex.replace(, , [, ]) // // Replace matched parts in a value of an arbitrary type, using the format diff --git a/tests/function/regex/testscript b/tests/function/regex/testscript index 95dfbb8..5167390 100644 --- a/tests/function/regex/testscript +++ b/tests/function/regex/testscript @@ -436,6 +436,90 @@ EOI } +: find-match +: +{ + : match + : + { + : string + : + $* <'true' + print $regex.find_match(-g -O3, [string] '-O[23]') + EOI + + : untyped + : + $* <'true' + print $regex.find_match(-g -O3, '-O[23]') + EOI + + : strings + : + $* <'true' + print $regex.find_match([strings] -g -O3, '-O[23]') + EOI + + : nomatch + : + $* <'false' + print $regex.find_match(-g -O1, '-O[23]') + EOI + } + + : flags + : + { + : icase + : + $* <'true' + print $regex.find_match(Foo.cxx, 'f[^.]+.*', icase) + EOI + } +} + +: find-search +: +{ + : match + : + { + : string + : + $* <'true' + print $regex.find_search(-g -O3, [string] '-O') + EOI + + : untyped + : + $* <'true' + print $regex.find_search(-g -O3, '-O') + EOI + + : strings + : + $* <'true' + print $regex.find_search([strings] -g -O3, '-O') + EOI + + : nomatch + : + $* <'false' + print $regex.find_search(-g, '-O') + EOI + } + + : flags + : + { + : icase + : + $* <'true' + print $regex.find_search(Foo.cxx, 'f', icase) + EOI + } +} + : merge : { -- cgit v1.1