diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-10-05 06:19:02 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-10-05 06:19:02 -0700 |
commit | 2d4d37907eb060fc23cc4a9f8ebf6b577db3a18b (patch) | |
tree | f3d7a0a522c2ccacde21ab944fb53ec0c7363c85 | |
parent | 77f92bd8b4cb96ddae97b2cdec2427fd4c16c6ee (diff) | |
download | txr-2d4d37907eb060fc23cc4a9f8ebf6b577db3a18b.tar.gz txr-2d4d37907eb060fc23cc4a9f8ebf6b577db3a18b.tar.bz2 txr-2d4d37907eb060fc23cc4a9f8ebf6b577db3a18b.zip |
New functions trim-left and trim-right.
* regex.c (trim_left, trim_right): New static functions.
(regex_init): New intrinsics registered.
* tests/015/trim.tl, tests/015/trim.expected: New files.
* txr.1: Documented.
-rw-r--r-- | regex.c | 28 | ||||
-rw-r--r-- | tests/015/trim.expected | 0 | ||||
-rw-r--r-- | tests/015/trim.tl | 41 | ||||
-rw-r--r-- | txr.1 | 71 |
4 files changed, 140 insertions, 0 deletions
@@ -3224,6 +3224,32 @@ val count_until_match(val regex, val stream_in) return scan_until_common(lit("count-until-match"), regex, stream_in, nil, nil); } +static val trim_left(val regex, val string) +{ + if (regexp(regex)) { + val pos = match_regex(string, regex, nil); + if (pos) + return sub_str(string, pos, t); + } else if (starts_with(regex, string, nil, nil)) { + return sub_str(string, length(regex), t); + } + + return string; +} + +static val trim_right(val regex, val string) +{ + if (regexp(regex)) { + val pos = match_regex_right(string, regex, nil); + if (pos) + return sub_str(string, zero, minus(length(string), pos)); + } else if (ends_with(regex, string, nil, nil)) { + return sub_str(string, zero, minus(length(string), length(regex))); + } + + return string; +} + static char_set_t *create_wide_cs(void) { #ifdef FULL_UNICODE @@ -3350,6 +3376,8 @@ void regex_init(void) reg_fun(intern(lit("fr^"), user_package), func_n2o(regex_range_left_fun, 1)); reg_fun(intern(lit("fr$"), user_package), func_n2o(regex_range_right_fun, 1)); reg_fun(intern(lit("frr"), user_package), func_n3o(regex_range_search_fun, 1)); + reg_fun(intern(lit("trim-left"), user_package), func_n2(trim_left)); + reg_fun(intern(lit("trim-right"), user_package), func_n2(trim_right)); init_special_char_sets(); } diff --git a/tests/015/trim.expected b/tests/015/trim.expected new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/015/trim.expected diff --git a/tests/015/trim.tl b/tests/015/trim.tl new file mode 100644 index 00000000..da1fc0c1 --- /dev/null +++ b/tests/015/trim.tl @@ -0,0 +1,41 @@ +(load "../common") + +(mtest + (trim-left "" "") "" + (trim-left 1 "") :error + (trim-left "" 1) :error + (trim-left 1 1) :error) + +(mtest + (trim-left "" "abc") "abc" + (trim-left "a" "abc") "bc" + (trim-left "ab" "abc") "c" + (trim-left "abc" "abc") "" + (trim-left "abcd" "abc") "abc" + (trim-left "z" "abc") "abc") + +(mtest + (trim-left #// "abc") "abc" + (trim-left #/./ "abc") "bc" + (trim-left #/../ "abc") "c" + (trim-left #/.../ "abc") "" + (trim-left #/.*/ "abc") "" + (trim-left #/..../ "abc") "abc" + (trim-left #/z/ "abc") "abc") + +(mtest + (trim-right "" "abc") "abc" + (trim-right "c" "abc") "ab" + (trim-right "bc" "abc") "a" + (trim-right "abc" "abc") "" + (trim-right "xabc" "abc") "abc" + (trim-right "z" "abc") "abc") + +(mtest + (trim-right #// "abc") "abc" + (trim-right #/./ "abc") "ab" + (trim-right #/../ "abc") "a" + (trim-right #/.../ "abc") "" + (trim-right #/.*/ "abc") "" + (trim-right #/..../ "abc") "abc" + (trim-right #/z/ "abc") "abc") @@ -45689,6 +45689,77 @@ is a compiled regular expression object. For any other object type, it returns .codn nil . +.coNP Functions @ trim-left and @ trim-right +.synb +.mets (trim-left >> { regex | << prefix } << string ) +.mets (trim-right >> { regex | << suffix } << string ) +.syne +.desc +The +.code trim-left +and +.code trim-right +functions return a new string, equivalent to +.meta string +with a leading or trailing portion removed. + +If the first argument is a regular expression +.metn regex , +then, respectively, +.code trim-left +and +.code trim-right +find a prefix or suffix of +.meta string +which matches the regular expression. +If there is no match, or if the match is empty, then +.meta string +is returned. Otherwise, a copy of +.meta string +is returned in which the matching characters are removed. +If +.meta regex +matches all of +.meta string +then the empty string is returned. + +If the first argument is a character string, then it is treated +as if it were a regular expression match for that literal +sequence of characters. Thus, +.code trim-left +interprets that string as a +.meta prefix +to be removed, and +.code trim-right +as a +.metn suffix . +If +.meta string +starts with +.metn prefix , +then +.code trim-left +returns a copy of +.meta string +with +.meta prefix +removed. Otherwise, +.meta string +is returned. +Likewise, if +.meta string +ends with +.metn suffix , +then +.code trim-right +returns a copy of +.meta string +with +.meta suffix +removed. Otherwise, +.meta string +is returned. + .coNP Function @ regex-compile .synb .mets (regex-compile < form-or-string <> [ error-stream ]) |