diff --git a/+stdlib/expanduser.m b/+stdlib/expanduser.m index f419b39..485937e 100644 --- a/+stdlib/expanduser.m +++ b/+stdlib/expanduser.m @@ -15,14 +15,14 @@ e = p; -if ~all(startsWith(e, "~")) || (all(strlength(e) > 1) && ~all(startsWith(e, "~/"))) +if ~startsWith(e, "~") || (strlength(e) > 1 && ~startsWith(e, "~/")) return end home = stdlib.homedir(use_java); if ~isempty(home) - e = stdlib.join(home, extractAfter(e, 1)); + e = stdlib.join(home, strip(extractAfter(e, 1), "left", "/")); end end %function diff --git a/+stdlib/join.m b/+stdlib/join.m index b0e7c6b..3463e3a 100644 --- a/+stdlib/join.m +++ b/+stdlib/join.m @@ -1,10 +1,43 @@ -function p = join(a, b) +function p = join(a, b, use_java) %% JOIN: join two paths with posix file separator arguments a (1,1) string b (1,1) string + use_java (1,1) logical = false end -p = stdlib.posix(fullfile(a, b)); +if a == "" && b == "" + p = ""; + return +end + +a = stdlib.posix(a); +b = stdlib.posix(b); + +if a == "" + p = b; + return +end + +if b == "" + p = a; + return +end + + +if use_java + +p = stdlib.posix(java.io.File(stdlib.normalize(a, true)).toPath().resolve(stdlib.normalize(b, true))); + +else + +if startsWith(b, "/") || (ispc && stdlib.is_absolute(b)) + p = b; + return +end + +p = stdlib.normalize(a) + "/" + stdlib.normalize(b); + +end end diff --git a/+stdlib/parent.m b/+stdlib/parent.m index 72945ba..b664f89 100644 --- a/+stdlib/parent.m +++ b/+stdlib/parent.m @@ -10,6 +10,15 @@ % java is about 10x slower than intrinsic p = java.io.File(p).getParent(); else + p = stdlib.posix(p); + % drop duplicated slashes in the parent path + p = regexprep(p, "//+", "/"); + + if ispc && any(strlength(p) == [2,3]) && isletter(extractBetween(p, 1, 1)) && extractBetween(p, 2, 2) == ":" + % 2 or 3 char drive letter + p = stdlib.root(p); + return + end % have to drop_slash on input to get expected parent path p = strip(stdlib.posix(p), "right", "/"); j = strfind(p, "/"); diff --git a/test/TestFilePure.m b/test/TestFilePure.m index a5a90c0..8496347 100644 --- a/test/TestFilePure.m +++ b/test/TestFilePure.m @@ -17,8 +17,12 @@ sub_is_subdir ref_is_subdir -in_parent = {"", ".", "..", "../..", "a/b", "a/b/", "ab/.parent", "ab/.parent.txt", "a/b/../.parent.txt"} -ref_parent = {".", ".", ".", "..", "a", "a", "ab", "ab", "a/b/.."} +in_parent +ref_parent + +in_join = {"", "a", "", "a/b/", "/", "", "a", "a//", "a/b/../", "a/b", "ab/cd"} +other_join = {"", "", "b", "c/", "", "/", "b//", "b//", "c/d/../", "c/d", "/ef"} +ref_join = {"", "a", "b", "a/b/c", "/", "/", "a/b", "a/b", "a/c", "a/b/c/d", "/ef"} in_suffix = {"", "/foo/bar/baz", "/foo/bar/baz/", "foo/bar/baz.txt", "foo/bar/baz.txt.gz", ".stat", ".stat.txt"} ref_suffix = {"", "", "", ".txt", ".gz", ".stat", ".txt"} @@ -37,11 +41,14 @@ end methods (TestParameterDefinition, Static) -function [base_relative_to, other_relative_to, ref_relative_to, ref_proximate_to, in_root, ref_root] = init_relative_to(classToTest) %#ok +function [base_relative_to, other_relative_to, ref_relative_to, ref_proximate_to, in_root, ref_root, in_parent, ref_parent] = init_relative_to(classToTest) %#ok in_root = {"", "a/b", "./a/b", "../a/b", "/etc", "c:/etc"}; ref_root = {"", "", "", "", "/", ""}; +in_parent = {"", ".", "..", "../..", "a/", "a/b", "a/b/", "ab/.parent", "ab/.parent.txt", "a/b/../.parent.txt", "a/////b////c", "c:/", "c:\", "c:/a/b", "c:\a/b"}; +ref_parent = {".", ".", ".", "..", ".", "a", "a", "ab", "ab", "a/b/..", "a/b", ".", ".", "c:/a", "c:\a"}; + if ispc base_relative_to = {'', 'Hello', 'Hello', ... @@ -55,6 +62,11 @@ ref_proximate_to = ref_relative_to; ref_proximate_to{end} = other_relative_to{end}; +ref_parent{12} = "c:/"; +ref_parent{13} = "c:/"; +ref_parent{14} = "c:/a"; +ref_parent{15} = "c:/a"; + ref_root{5} = ""; ref_root{6} = "c:/"; @@ -158,6 +170,11 @@ function test_posix(tc) end +function test_join(tc, in_join, other_join, ref_join) +tc.verifyEqual(stdlib.join(in_join, other_join), ref_join) +end + + function test_filename(tc, in_filename, ref_filename) tc.verifyEqual(stdlib.filename(in_filename), string(ref_filename)) end