summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-06-29 07:36:38 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-06-29 07:36:38 -0700
commitd5d2a4c79c2e6203798cf985df5f23964a04817f (patch)
treea7e7d9451eaba0e99bb8dfb7e7081170ad55db89
parent86fd2fab95618f6b097a80002da783f02a799d75 (diff)
downloadtxr-d5d2a4c79c2e6203798cf985df5f23964a04817f.tar.gz
txr-d5d2a4c79c2e6203798cf985df5f23964a04817f.tar.bz2
txr-d5d2a4c79c2e6203798cf985df5f23964a04817f.zip
path-cat: becomes variadic.
* stream.c (path_vcat): New static function. (stream_init): Register path-cat instrinsic to path_vcat rather than path_cat. * tests/018/path.tl: path-cat tests: all examples from documentation, plus others. * txr.1: Documented existing behaviors that were not clear, like when inputs are empty. Documented new variadic semantics. Examples added.
-rw-r--r--stream.c21
-rw-r--r--tests/018/path.tl32
-rw-r--r--txr.158
3 files changed, 103 insertions, 8 deletions
diff --git a/stream.c b/stream.c
index cb853d98..fe3cc0bb 100644
--- a/stream.c
+++ b/stream.c
@@ -5116,6 +5116,25 @@ val path_cat(val dir_name, val base_name)
return scat(lit("/"), dir_name, base_name, nao);
}
+static val path_vcat(struct args *args)
+{
+ cnum ix = 0;
+
+ if (!args_more(args, ix)) {
+ return lit(".");
+ } else {
+ val accum = args_get(args, &ix);
+
+ if (!stringp(accum))
+ uw_throwf(file_error_s, lit("path-cat: ~s isn't a string"), accum, nao);
+
+ while (args_more(args, ix))
+ accum = path_cat(accum, args_get(args, &ix));
+
+ return accum;
+ }
+}
+
val make_byte_input_stream(val obj)
{
val self = lit("make-byte-input-stream");
@@ -5376,7 +5395,7 @@ void stream_init(void)
reg_fun(intern(lit("dir-name"), user_package), func_n1(dir_name));
reg_fun(intern(lit("short-suffix"), user_package), func_n2o(short_suffix, 1));
reg_fun(intern(lit("long-suffix"), user_package), func_n2o(long_suffix, 1));
- reg_fun(intern(lit("path-cat"), user_package), func_n2(path_cat));
+ reg_fun(intern(lit("path-cat"), user_package), func_n0v(path_vcat));
reg_varl(intern(lit("path-sep-chars"), user_package), static_str(path_sep_chars));
reg_fun(intern(lit("get-indent-mode"), user_package), func_n1(get_indent_mode));
reg_fun(intern(lit("test-set-indent-mode"), user_package), func_n3(test_set_indent_mode));
diff --git a/tests/018/path.tl b/tests/018/path.tl
index 16c44d77..96298dfd 100644
--- a/tests/018/path.tl
+++ b/tests/018/path.tl
@@ -96,3 +96,35 @@
(base-name "a.b/" ".b") "a"
(base-name "a.b/" ".b/") "a.b"
(base-name "a.b/" "a.b") "a.b")
+
+(mtest
+ (path-cat "" "") ""
+ (path-cat "" ".") "."
+ (path-cat "." "") "."
+ (path-cat "." ".") "."
+ (path-cat "abc" ".") "abc"
+ (path-cat "." "abc") "abc"
+ (path-cat "./" ".") "./"
+ (path-cat "." "./") "./"
+ (path-cat "abc/" ".") "abc/"
+ (path-cat "./" "abc") "abc"
+ (path-cat "/" ".") "/"
+ (path-cat "/" "abc") "/abc"
+ (path-cat "ab/cd" "ef") "ab/cd/ef"
+ (path-cat "a" "b" "c") "a/b/c"
+ (path-cat "a" "b" "" "c" "/") "a/b/c/")
+
+(mtest
+ (path-cat) "."
+ (path-cat 3) :error
+ (path-cat "") ""
+ (path-cat "/") "/"
+ (path-cat ".") "."
+ (path-cat "" "" "") ""
+ (path-cat "." "" "") "."
+ (path-cat "" "." "") "."
+ (path-cat "" "" ".") "."
+ (path-cat "." "." ".") "."
+ (path-cat "abc/" "/def/" "g") "abc/def/g"
+ (path-cat "abc/" "/def/" "g/") "abc/def/g/"
+ (path-cat "" "abc/" "/def/" "g/") "abc/def/g/")
diff --git a/txr.1 b/txr.1
index 3f7a0dc5..e00bc31b 100644
--- a/txr.1
+++ b/txr.1
@@ -57365,19 +57365,25 @@ extracted from this last component.
.coNP Function @ path-cat
.synb
-.mets (path-cat < dir-path << rel-path )
+.mets (path-cat >> [ dir-path <> { rel-path }*])
.syne
.desc
The
.code path-cat
-function joins the directory pathname given by the character
-string argument
+joints together zero or more paths, returning the combined path.
+All arguments are strings.
+
+The following description defines the behavior when
+.code path-cat
+is given exactly two arguments, which are interpreted as
.meta dir-path
-with the relative pathname given by
-.metn rel-path ,
-returning the joined path.
+and
+.metn rel-path .
+A description of the variable argument semantics follows.
-The function is related to the functions
+Firstly, the two-argument
+.code path-cat
+is related to the functions
.code dir-name
and
.code base-name
@@ -57422,6 +57428,40 @@ string is
.meta dir-name
itself.
+If
+.meta dir-path
+is an empty string, then
+.code rel-path
+is returned, and
+.IR "vice versa" .
+
+The variadic semantics of
+.code path-cat
+is as follows.
+
+If
+.code path-cat
+is called with no arguments at all, it returns the path
+.str .
+(period) denoting the relative path of the current directory.
+
+If
+.code path-cat
+is called with one argument, that argument is returned.
+
+If
+.code path-cat
+is called with three or more arguments, a left-associative reduction
+takes place using the two-argument semantics. The first two arguments
+are catenated into a single path, which is then catenated
+with the third argument, and so on.
+
+The above semantics implies that the following equivalence holds:
+
+.verb
+ [reduce-left path-cat list] <--> [apply path-cat list]
+.brev
+
.TP* Examples:
.verb
@@ -57444,6 +57484,10 @@ itself.
(path-cat "/" "abc") --> "/abc"
(path-cat "ab/cd" "ef") --> "ab/cd/ef"
+
+ (path-cat "a" "b" "c") --> "a/b/c"
+
+ (path-cat "a" "b" "" "c" "/") --> "a/b/c/"
.brev
.coNP Function @ rel-path