Created
January 4, 2013 23:00
-
-
Save StefanKarpinski/4458304 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@unix_only begin | |
const path_separator = "/" | |
const path_separator_regex = r"/+" | |
const path_absolute_regex = r"^/" | |
const path_parse_regex = r"^(.*?/|)([^/]+?)(\.[^\.]+|)$" | |
splitdrive(path::String) = ("",path) | |
end | |
@windows_only begin | |
const path_separator = "\\" | |
const path_separator_regex = r"[/\\]+" | |
const path_absolute_regex = r"^(?:\w+:)?[/\\]" | |
const path_parse_regex = r"^(.*?[/\\]|)([^/\\]+?)(\.[^\.]+|)$" | |
function splitdrive(path::String) | |
# TODO: split out network drives? | |
m = match(r"^(\w+:|)(.*)$", path) | |
m.captures[1], m.captures[2] | |
end | |
end | |
isabspath(path::String) = ismatch(path_absolute_regex, path) | |
joinpath(a::String) = a | |
joinpath(a::String, b::String, c::String...) = joinpath(joinpath(a,b), c...) | |
joinpath(a::String, b::String) = isempty(a) || isabspath(b) ? b : | |
ismatch(path_separator_regex, a[thisind(a,end):end]) ? | |
strcat(a,b) : strcat(a,path_separator,b) | |
function parsepath(path::String) | |
m = match(path_parse_regex, path) | |
m != nothing ? (m.captures[2], m.captures[3], m.captures[4]) : (path, "", "") | |
end | |
function normpath(path::String) | |
isabs = isabspath(path) | |
drive, path = splitdrive(path) | |
parts = split(path, path_separator_regex) | |
# isdir = ismatch(r"^\.{0,2}$", parts[end]) | |
parts = filter(x->!isempty(x) && x!=".", parts) | |
while true | |
clean = true | |
for j = 1:length(parts)-1 | |
if parts[j] != ".." && parts[j+1] == ".." | |
del(parts, j:j+1) | |
clean = false | |
break | |
end | |
end | |
clean && break | |
end | |
if isabs | |
while isabs && !isempty(parts) && parts[1] == ".." | |
shift(parts) | |
end | |
elseif isempty(parts) | |
push(parts, ".") | |
end | |
path = join(parts, path_separator) | |
if isabs | |
path = strcat(path_separator, path) | |
end | |
# if isdir && !isempty(parts) && !ismatch(r"^\.{0,2}$", parts[end]) | |
# path = strcat(path, path_separator) | |
# end | |
strcat(drive,path) | |
end | |
normpath(a::String, b::String...) = normpath(joinpath(a,b...)) | |
abspath(path::String) = normpath(isabspath(path) ? path : joinpath(pwd(),path)) | |
function realpath(path::String) | |
path = tilde_expand(path) | |
sp = ccall(:realpath, Ptr{Uint8}, (Ptr{Uint8}, Ptr{Uint8}), path, C_NULL) | |
system_error(:realpath, sp != C_NULL) | |
s = bytestring(sp) | |
c_free(sp) | |
return s | |
end |
(I was referring to normpath
of course.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just a small question: why the removal of the
isdir
check? Performance? Compatibility with ThatOtherOS? Originally, I introduced it so that paths like/dir1/dir2/filename/.
or/dir1/dir2/filename/anything/..
are not resolved to/dir1/dir2/filename
, i.e. they don't yield a valid file name, which seems wrong (and bug-prone) to me.