summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-28 22:40:59 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-28 22:40:59 -0700
commitbc591cb5ee04582dbdf17a0125987ec03e8c064f (patch)
treed105da9c40623bf044a4d03ff1c8b270a1c8a466
parent3692b3b96af9159368a7bfe63798bb67ff90367f (diff)
downloadtxr-bc591cb5ee04582dbdf17a0125987ec03e8c064f.tar.gz
txr-bc591cb5ee04582dbdf17a0125987ec03e8c064f.tar.bz2
txr-bc591cb5ee04582dbdf17a0125987ec03e8c064f.zip
tok-str: takes count argument.
* eval.c (eval_init): Update registration of tok-str. * lib.c (tok_str): New argument, count_opt. Implemented in the compat 155 case; what the heck. (tok): Pass nil to new parameter of tok_str. * lib.h (tok_str): Declaration updated. * tests/015/split.tl: New tests. * txr.1: Documented.
-rw-r--r--eval.c2
-rw-r--r--lib.c28
-rw-r--r--lib.h2
-rw-r--r--tests/015/split.tl15
-rw-r--r--txr.115
5 files changed, 52 insertions, 10 deletions
diff --git a/eval.c b/eval.c
index 2b95dae4..cbe37f55 100644
--- a/eval.c
+++ b/eval.c
@@ -7217,7 +7217,7 @@ void eval_init(void)
reg_fun(intern(lit("spl"), user_package), func_n3o(spl, 2));
reg_fun(intern(lit("split-str-set"), user_package), func_n2(split_str_set));
reg_fun(intern(lit("sspl"), user_package), func_n2(sspl));
- reg_fun(intern(lit("tok-str"), user_package), func_n3o(tok_str, 2));
+ reg_fun(intern(lit("tok-str"), user_package), func_n4o(tok_str, 2));
reg_fun(intern(lit("tok"), user_package), func_n3o(tok, 2));
reg_fun(intern(lit("tok-where"), user_package), func_n2(tok_where));
reg_fun(intern(lit("list-str"), user_package), func_n1(list_str));
diff --git a/lib.c b/lib.c
index 050e8889..c4d1bc5c 100644
--- a/lib.c
+++ b/lib.c
@@ -5895,15 +5895,23 @@ val sspl(val set, val str)
return split_str_set(str, set);
}
-val tok_str(val str, val tok_regex, val keep_sep)
+val tok_str(val str, val tok_regex, val keep_sep_opt, val count_opt)
{
+ val self = lit("tok-str");
list_collect_decl (out, iter);
val pos = zero;
val last_end = zero;
val slen = length(str);
int prev_empty = 1;
+ val keep_sep = default_null_arg(keep_sep_opt);
+ val count = default_null_arg(count_opt);
+ cnum cnt = c_num(if3(count, count, negone), self);
+
+ if (count && cnt < 0)
+ uw_throwf(error_s, lit("~a: count must be nonnegative"), self, nao);
- keep_sep = default_null_arg(keep_sep);
+ if (count == zero)
+ return if2(keep_sep || slen != zero, cons(str, nil));
if (opt_compat && opt_compat <= 155) for (;;) {
cons_bind (new_pos, len, search_regex(str, tok_regex, pos, nil));
@@ -5922,6 +5930,12 @@ val tok_str(val str, val tok_regex, val keep_sep)
pos = plus(new_pos, len);
iter = list_collect(iter, sub_str(str, new_pos, pos));
+
+ if (cnt > 0 && --cnt == 0) {
+ if (pos != slen || keep_sep)
+ iter = list_collect(iter, sub_str(str, pos, t));
+ break;
+ }
} else for (;;) {
cons_bind (new_pos, len, search_regex(str, tok_regex, pos, nil));
@@ -5945,6 +5959,12 @@ val tok_str(val str, val tok_regex, val keep_sep)
if (len == zero)
pos = succ(pos);
+
+ if (cnt > 0 && --cnt == 0) {
+ if (pos != slen || keep_sep)
+ iter = list_collect(iter, sub_str(str, pos, t));
+ break;
+ }
}
return out;
@@ -5953,8 +5973,8 @@ val tok_str(val str, val tok_regex, val keep_sep)
val tok(val tok_regex, val arg1, val arg2)
{
return if3(missingp(arg2),
- tok_str(arg1, tok_regex, arg2),
- tok_str(arg2, tok_regex, arg1));
+ tok_str(arg1, tok_regex, arg2, nil),
+ tok_str(arg2, tok_regex, arg1, nil));
}
val tok_where(val str, val tok_regex)
diff --git a/lib.h b/lib.h
index 5363f47b..585a2c05 100644
--- a/lib.h
+++ b/lib.h
@@ -929,7 +929,7 @@ val split_str_keep(val str, val sep, val keep_sep_opt, val count_opt);
val spl(val sep, val arg1, val arg2);
val split_str_set(val str, val set);
val sspl(val set, val str);
-val tok_str(val str, val tok_regex, val keep_sep);
+val tok_str(val str, val tok_regex, val keep_sep_opt, val count_opt);
val tok(val tok_regex, val arg1, val arg2);
val tok_where(val str, val tok_regex);
val list_str(val str);
diff --git a/tests/015/split.tl b/tests/015/split.tl
index 8cdf7f04..9e952342 100644
--- a/tests/015/split.tl
+++ b/tests/015/split.tl
@@ -196,6 +196,21 @@
(tok-str "abcacabcac" #/ab?/ t) ("" "ab" "c" "a" "c" "ab" "c" "a" "c"))
(mtest
+ (tok-str "" #/[^,]/ : 0) ()
+ (tok-str "a,b,c" #/[^,]/ : 0) ("a,b,c")
+ (tok-str "a,b,c" #/[^,]/ : 1) ("a" ",b,c")
+ (tok-str "a,b,c" #/[^,]/ : 2) ("a" "b" ",c")
+ (tok-str "a,b,c" #/[^,]/ : 3) #"a b c"
+ (tok-str "a,b,c" #/[^,]/ : 4) #"a b c")
+
+(mtest
+ (tok-str "a,b,c" #/[^,]/ t 0) ("a,b,c")
+ (tok-str "a,b,c" #/[^,]/ t 1) ("" "a" ",b,c")
+ (tok-str "a,b,c" #/[^,]/ t 2) ("" "a" "," "b" ",c")
+ (tok-str "a,b,c" #/[^,]/ t 3) ("" "a" "," "b" "," "c" "")
+ (tok-str "a,b,c" #/[^,]/ t 4) ("" "a" "," "b" "," "c" ""))
+
+(mtest
(join) ""
(join "") ""
(join "" "") ""
diff --git a/txr.1 b/txr.1
index 6279ece1..3c68e74d 100644
--- a/txr.1
+++ b/txr.1
@@ -25563,7 +25563,7 @@ is argument order.
.coNP Functions @ tok-str and @ tok-where
.synb
-.mets (tok-str < string < regex <> [ keep-between ])
+.mets (tok-str < string < regex >> [ keep-between <> [ count ]])
.mets (tok-where < string << regex )
.syne
.desc
@@ -25619,9 +25619,7 @@ character and is extracted.
If the
.meta keep-between
-argument is specified, and is not
-.codn nil ,
-then the behavior
+argument is true, then the behavior
of
.code tok-str
changes in the following way. The pieces of
@@ -25640,6 +25638,15 @@ substring of
.meta string
between the last token and the end.
+If
+.meta count
+is specified, it must be a nonnegative integer. The value limits the
+number of tokens which are extracted. The returned list then includes
+one more item: the remainder of the string after the last extracted token.
+This item is omitted if the rest of the string is empty, unless
+.meta keep-between
+is true.
+
The
.code tok-where
function works similarly to