| 1 |
1 |
| 2 module("path", package.seeall) |
2 --@module path |
| |
3 local path={} |
| 3 |
4 |
| 4 require("tuple") |
5 local tuple=require("tuple") |
| 5 require("lfs") |
6 local lfs=require("lfs") |
| 6 require("err") |
7 local err=require("err") |
| 7 require("config") |
8 local config=require("config") |
| 8 |
9 |
| 9 local sep=config.dirsep |
10 local sep=config.dirsep |
| 10 |
11 |
| 11 function join(p, f) |
12 function path.join(p, f) |
| 12 if p=="" then |
13 if p=="" then |
| 13 return f |
14 return f |
| 14 else |
15 else |
| 15 return p..sep..f |
16 return p..sep..f |
| 16 end |
17 end |
| 17 end |
18 end |
| 18 |
19 |
| 19 function dirbasename(p) |
20 function path.dirbasename(p) |
| 20 local d, b = string.match(p, |
21 local d, b = string.match(p, |
| 21 "^(.*)"..sep.."+([^"..sep.."]+)"..sep.."*$") |
22 "^(.*)"..sep.."+([^"..sep.."]+)"..sep.."*$") |
| 22 if not b then |
23 if not b then |
| 23 return "", p |
24 return "", p |
| 24 else |
25 else |
| 25 return d, b |
26 return d, b |
| 26 end |
27 end |
| 27 end |
28 end |
| 28 |
29 |
| 29 function dirname(p) |
30 function path.dirname(p) |
| 30 return tuple.fst(dirbasename(p)) |
31 return tuple.fst(dirbasename(p)) |
| 31 end |
32 end |
| 32 |
33 |
| 33 function dirname_slash(p) |
34 function path.dirname_slash(p) |
| 34 local dn=dirname(p) |
35 local dn=dirname(p) |
| 35 if dn=="" then |
36 if dn=="" then |
| 36 return dn |
37 return dn |
| 37 else |
38 else |
| 38 return dn..sep |
39 return dn..sep |
| 39 end |
40 end |
| 40 end |
41 end |
| 41 |
42 |
| 42 function basename(p) |
43 function path.basename(p) |
| 43 return tuple.snd(dirbasename(p)) |
44 return tuple.snd(dirbasename(p)) |
| 44 end |
45 end |
| 45 |
46 |
| 46 function rmext(p) |
47 function path.rmext(p) |
| 47 return string.gsub(p, "%.[^.]*$", "") |
48 return string.gsub(p, "%.[^.]*$", "") |
| 48 end |
49 end |
| 49 |
50 |
| 50 -- would rather do this as an iterator, but can't |
51 -- would rather do this as an iterator, but can't |
| 51 -- coroutine.yield from gsub handler |
52 -- coroutine.yield from gsub handler |
| 52 function split(p) |
53 function path.split(p) |
| 53 local t={} |
54 local t={} |
| 54 local head="" |
55 local head="" |
| 55 local s, p2 = string.match(p, "^("..sep.."+)(.*)$") |
56 local s, p2 = string.match(p, "^("..sep.."+)(.*)$") |
| 56 if s then |
57 if s then |
| 57 table.insert(t, "/.") -- root |
58 table.insert(t, "/.") -- root |
| 61 function(d) table.insert(t, d); end) |
62 function(d) table.insert(t, d); end) |
| 62 return t |
63 return t |
| 63 end |
64 end |
| 64 |
65 |
| 65 --[[ |
66 --[[ |
| 66 function parts(p) |
67 function path.parts(p) |
| 67 local s={i=1, t=split(p)} |
68 local s={i=1, t=split(p)} |
| 68 local function g(s) |
69 local function g(s) |
| 69 local v=s.t[s.i] |
70 local v=s.t[s.i] |
| 70 s.i=s.i+1 |
71 s.i=s.i+1 |
| 71 return v |
72 return v |
| 72 end |
73 end |
| 73 return g, s |
74 return g, s |
| 74 end |
75 end |
| 75 |
76 |
| 76 function makepath(p, head) |
77 function path.makepath(p, head) |
| 77 head=head or "" |
78 head=head or "" |
| 78 for d in parts(p) do |
79 for d in parts(p) do |
| 79 head=head..d |
80 head=head..d |
| 80 local a=lfs.attributes(head) |
81 local a=lfs.attributes(head) |
| 81 if not a then |
82 if not a then |