1 |
|
2 --@module path |
|
3 local path={} |
|
4 |
|
5 local tuple=require("tuple") |
|
6 local lfs=require("lfs") |
|
7 local err=require("err") |
|
8 local config=require("config") |
|
9 |
|
10 local sep=config.dirsep |
|
11 |
|
12 function path.join(p, f) |
|
13 if p=="" then |
|
14 return f |
|
15 else |
|
16 return p..sep..f |
|
17 end |
|
18 end |
|
19 |
|
20 function path.dirbasename(p) |
|
21 local d, b = string.match(p, |
|
22 "^(.*)"..sep.."+([^"..sep.."]+)"..sep.."*$") |
|
23 if not b then |
|
24 return "", p |
|
25 else |
|
26 return d, b |
|
27 end |
|
28 end |
|
29 |
|
30 function path.dirname(p) |
|
31 return tuple.fst(dirbasename(p)) |
|
32 end |
|
33 |
|
34 function path.dirname_slash(p) |
|
35 local dn=dirname(p) |
|
36 if dn=="" then |
|
37 return dn |
|
38 else |
|
39 return dn..sep |
|
40 end |
|
41 end |
|
42 |
|
43 function path.basename(p) |
|
44 return tuple.snd(dirbasename(p)) |
|
45 end |
|
46 |
|
47 function path.rmext(p) |
|
48 return string.gsub(p, "%.[^.]*$", "") |
|
49 end |
|
50 |
|
51 -- would rather do this as an iterator, but can't |
|
52 -- coroutine.yield from gsub handler |
|
53 function path.split(p) |
|
54 local t={} |
|
55 local head="" |
|
56 local s, p2 = string.match(p, "^("..sep.."+)(.*)$") |
|
57 if s then |
|
58 table.insert(t, "/.") -- root |
|
59 p=p2 |
|
60 end |
|
61 string.gsub(p, "([^"..sep.."]+)", --..sep.."+", |
|
62 function(d) table.insert(t, d); end) |
|
63 return t |
|
64 end |
|
65 |
|
66 --[[ |
|
67 function path.parts(p) |
|
68 local s={i=1, t=split(p)} |
|
69 local function g(s) |
|
70 local v=s.t[s.i] |
|
71 s.i=s.i+1 |
|
72 return v |
|
73 end |
|
74 return g, s |
|
75 end |
|
76 |
|
77 function path.makepath(p, head) |
|
78 head=head or "" |
|
79 for d in parts(p) do |
|
80 head=head..d |
|
81 local a=lfs.attributes(head) |
|
82 if not a then |
|
83 local success, e = lfs.mkdir(head) |
|
84 if not success then |
|
85 err.file(head, e) |
|
86 end |
|
87 elseif a.mode~="directory" then |
|
88 err.file(head, "not a directory") |
|
89 end |
|
90 head=head..sep |
|
91 end |
|
92 end |
|
93 ]] |
|
94 |
|
95 function path.simplify(p) |
|
96 local capts={} |
|
97 local start=string.match(p, "^(/)") |
|
98 string.gsub(p, "([^/]+)", |
|
99 function(e) |
|
100 if e==".." and #capts > 1 then |
|
101 capts[#capts]=nil |
|
102 elseif e~="." then |
|
103 table.insert(capts, e) |
|
104 end |
|
105 end) |
|
106 return (start or "")..table.concat(capts, "/") |
|
107 end |
|
108 |
|
109 function path.to_root(p) |
|
110 return string.rep("../",#(path.split(p))-1) |
|
111 end |
|
112 |
|
113 return path |
|