OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// A comprehensive, cross-platform path manipulation library. | 5 /// A comprehensive, cross-platform path manipulation library. |
6 library path; | 6 library path; |
7 | 7 |
8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
9 | 9 |
10 /// An internal builder for the current OS so we can provide a straight | 10 /// An internal builder for the current OS so we can provide a straight |
11 /// functional interface and not require users to create one. | 11 /// functional interface and not require users to create one. |
12 final _builder = new Builder(); | 12 final _builder = new Builder(); |
13 | 13 |
14 /// Gets the path to the current working directory. | 14 /// Gets the path to the current working directory. |
15 String get current => new io.Directory.current().path; | 15 String get current => new io.Directory.current().path; |
16 | 16 |
17 /// Gets the path separator for the current platform. On Mac and Linux, this | 17 /// Gets the path separator for the current platform. On Mac and Linux, this |
18 /// is `/`. On Windows, it's `\`. | 18 /// is `/`. On Windows, it's `\`. |
19 String get separator => _builder.separator; | 19 String get separator => _builder.separator; |
20 | 20 |
21 /// Converts [path] to an absolute path by resolving it relative to the current | 21 /// Converts [path] to an absolute path by resolving it relative to the current |
22 /// working directory. If [path] is already an absolute path, just returns it. | 22 /// working directory. If [path] is already an absolute path, just returns it. |
23 /// | 23 /// |
24 /// path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt | 24 /// path.absolute('foo/bar.txt'); // -> /your/current/dir/foo/bar.txt |
25 String absolute(String path) => join(current, path); | 25 String absolute(String path) => join(current, path); |
26 | 26 |
27 /// Gets the part of [path] before the last separator. | |
28 /// | |
29 /// path.dirname('path/to/foo.dart'); // -> 'path/to' | |
30 /// path.dirname('path/to'); // -> 'to' | |
31 String dirname(String path) => _builder.dirname(path); | |
32 | |
27 /// Gets the part of [path] after the last separator. | 33 /// Gets the part of [path] after the last separator. |
28 /// | 34 /// |
29 /// path.basename('path/to/foo.dart'); // -> 'foo.dart' | 35 /// path.basename('path/to/foo.dart'); // -> 'foo.dart' |
30 /// path.basename('path/to'); // -> 'to' | 36 /// path.basename('path/to'); // -> 'to' |
31 String basename(String path) => _builder.basename(path); | 37 String basename(String path) => _builder.basename(path); |
32 | 38 |
33 /// Gets the part of [path] after the last separator, and without any trailing | 39 /// Gets the part of [path] after the last separator, and without any trailing |
34 /// file extension. | 40 /// file extension. |
35 /// | 41 /// |
36 /// path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' | 42 /// path.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' |
37 String basenameWithoutExtension(String path) => | 43 String basenameWithoutExtension(String path) => |
38 _builder.basenameWithoutExtension(path); | 44 _builder.basenameWithoutExtension(path); |
39 | 45 |
40 /// Gets the file extension of [path]: the portion of [basename] from the last | 46 /// Gets the file extension of [path]: the portion of [basename] from the last |
41 /// `.` to the end (including the `.` itself). | 47 /// `.` to the end (including the `.` itself). |
42 /// | 48 /// |
43 /// path.extension('path/to/foo.dart'); // -> '.dart' | 49 /// path.extension('path/to/foo.dart'); // -> '.dart' |
44 /// path.extension('path/to/foo'); // -> '' | 50 /// path.extension('path/to/foo'); // -> '' |
45 /// path.extension('path.to/foo'); // -> '' | 51 /// path.extension('path.to/foo'); // -> '' |
46 /// path.extension('path/to/foo.dart.js'); // -> '.js' | 52 /// path.extension('path/to/foo.dart.js'); // -> '.js' |
47 /// | 53 /// |
48 /// If the file name starts with a `.`, then that is not considered the | 54 /// If the file name starts with a `.`, then that is not considered the |
49 /// extension: | 55 /// extension: |
50 /// | 56 /// |
51 /// path.extension('~/.bashrc'); // -> '' | 57 /// path.extension('~/.bashrc'); // -> '' |
52 /// path.extension('~/.notes.txt'); // -> '.txt' | 58 /// path.extension('~/.notes.txt'); // -> '.txt' |
53 String extension(String path) => _builder.extension(path); | 59 String extension(String path) => _builder.extension(path); |
54 | 60 |
61 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. | |
62 /// Returns the root of [path], if it's absolute, or `null` if it's relative. | |
Bob Nystrom
2012/12/12 00:01:20
Generally, this library returns empty strings inst
nweiz
2012/12/12 00:50:37
I based it on the ParsedPath API, which also retur
Bob Nystrom
2012/12/12 01:02:13
That's part of the reason ParsedPath is still priv
nweiz
2012/12/12 02:45:57
Done.
| |
63 /// | |
64 /// // Unix | |
65 /// path.rootOf('path/to/foo'); // -> null | |
66 /// path.rootOf('/path/to/foo'); // -> '/' | |
67 /// | |
68 /// // Windows | |
69 /// path.rootOf(r'path\to\foo'); // -> null | |
70 /// path.rootOf(r'C:\path\to\foo'); // -> r'C:\' | |
71 String rootOf(String path) => _builder.rootOf(path); | |
Bob Nystrom
2012/12/12 00:01:20
"rootOf" -> "root", I think. I like English-like A
nweiz
2012/12/12 00:50:37
I had it as "root" originally, but that causes a n
Bob Nystrom
2012/12/12 01:02:13
maybe rootPrefix?
nweiz
2012/12/12 02:45:57
Done.
| |
72 | |
55 /// Returns `true` if [path] is an absolute path and `false` if it is a | 73 /// Returns `true` if [path] is an absolute path and `false` if it is a |
56 /// relative path. On POSIX systems, absolute paths start with a `/` (forward | 74 /// relative path. On POSIX systems, absolute paths start with a `/` (forward |
57 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter | 75 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter |
58 /// followed by `:/` or `:\`. | 76 /// followed by `:/` or `:\`. |
59 bool isAbsolute(String path) => _builder.isAbsolute(path); | 77 bool isAbsolute(String path) => _builder.isAbsolute(path); |
60 | 78 |
61 /// Returns `true` if [path] is a relative path and `false` if it is absolute. | 79 /// Returns `true` if [path] is a relative path and `false` if it is absolute. |
62 /// On POSIX systems, absolute paths start with a `/` (forward slash). On | 80 /// On POSIX systems, absolute paths start with a `/` (forward slash). On |
63 /// Windows, an absolute path starts with `\\`, or a drive letter followed by | 81 /// Windows, an absolute path starts with `\\`, or a drive letter followed by |
64 /// `:/` or `:\`. | 82 /// `:/` or `:\`. |
65 bool isRelative(String path) => _builder.isRelative(path); | 83 bool isRelative(String path) => _builder.isRelative(path); |
66 | 84 |
67 /// Joins the given path parts into a single path using the current platform's | 85 /// Joins the given path parts into a single path using the current platform's |
68 /// [separator]. Example: | 86 /// [separator]. Example: |
69 /// | 87 /// |
70 /// path.join('path', 'to', 'foo'); // -> 'path/to/foo' | 88 /// path.join('path', 'to', 'foo'); // -> 'path/to/foo' |
71 /// | 89 /// |
72 /// If any part ends in a path separator, then a redundant separator will not | 90 /// If any part ends in a path separator, then a redundant separator will not |
73 /// be added: | 91 /// be added: |
74 /// | 92 /// |
75 /// path.join('path/', 'to', 'foo'); // -> 'path/to/foo | 93 /// path.join('path/', 'to', 'foo'); // -> 'path/to/foo |
76 /// | 94 /// |
77 /// If a part is an absolute path, then anything before that will be ignored: | 95 /// If a part is an absolute path, then anything before that will be ignored: |
78 /// | 96 /// |
79 /// path.join('path', '/to', 'foo'); // -> '/to/foo' | 97 /// path.join('path', '/to', 'foo'); // -> '/to/foo' |
80 String join(String part1, [String part2, String part3, String part4, | 98 String join(String part1, [String part2, String part3, String part4, |
81 String part5, String part6, String part7, String part8]) { | 99 String part5, String part6, String part7, String part8]) => |
82 if (!?part2) return _builder.join(part1); | 100 _builder.join(part1, part2, part3, part4, part5, part6, part7, part8); |
83 if (!?part3) return _builder.join(part1, part2); | 101 |
84 if (!?part4) return _builder.join(part1, part2, part3); | 102 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. |
85 if (!?part5) return _builder.join(part1, part2, part3, part4); | 103 /// Splits [path] into its components using the current platform's [separator]. |
86 if (!?part6) return _builder.join(part1, part2, part3, part4, part5); | 104 /// Example: |
87 if (!?part7) return _builder.join(part1, part2, part3, part4, part5, part6); | 105 /// |
88 if (!?part8) return _builder.join(part1, part2, part3, part4, part5, part6, | 106 /// path.split('path/to/foo'); // -> ['path', 'to', 'foo'] |
89 part7); | 107 /// |
90 return _builder.join(part1, part2, part3, part4, part5, part6, part7, part8); | 108 /// If [path] is absolute, the root directory will be the first element in the |
91 } | 109 /// array. Example: |
110 /// | |
111 /// // Unix | |
112 /// path.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo'] | |
113 /// | |
114 /// // Windows | |
115 /// path.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo'] | |
116 List<String> split(String path) => _builder.split(path); | |
Bob Nystrom
2012/12/12 00:01:20
Heh, my preflight patch has an implementation of t
nweiz
2012/12/12 00:50:37
I like this version better, since it lists all dir
Bob Nystrom
2012/12/12 01:02:13
Ah, good call. Works for me.
| |
92 | 117 |
93 /// Normalizes [path], simplifying it by handling `..`, and `.`, and | 118 /// Normalizes [path], simplifying it by handling `..`, and `.`, and |
94 /// removing redundant path separators whenever possible. | 119 /// removing redundant path separators whenever possible. |
95 /// | 120 /// |
96 /// path.normalize('path/./to/..//file.text'); // -> 'path/file.txt' | 121 /// path.normalize('path/./to/..//file.text'); // -> 'path/file.txt' |
97 String normalize(String path) => _builder.normalize(path); | 122 String normalize(String path) => _builder.normalize(path); |
98 | 123 |
99 /// Attempts to convert [path] to an equivalent relative path from the current | 124 /// Attempts to convert [path] to an equivalent relative path from the current |
100 /// directory. | 125 /// directory. |
101 /// | 126 /// |
102 /// // Given current directory is /root/path: | 127 /// // Given current directory is /root/path: |
103 /// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart' | 128 /// path.relative('/root/path/a/b.dart'); // -> 'a/b.dart' |
104 /// path.relative('/root/other.dart'); // -> '../other.dart' | 129 /// path.relative('/root/other.dart'); // -> '../other.dart' |
105 /// | 130 /// |
131 /// If the [to] argument is passed, [path] is made relative to that instead. | |
Bob Nystrom
2012/12/12 00:01:20
I don't like reinterpreting one argument based on
nweiz
2012/12/12 00:50:37
The idea is that it returns "path" relative to "to
Bob Nystrom
2012/12/12 01:02:13
Before I accidentally lost the implementation, I w
nweiz
2012/12/12 02:45:57
That reads as "'foo/bar' relative from 'foo'" to m
Bob Nystrom
2012/12/12 04:52:33
Yeah, I like it a bit more. I read it as "get a pa
| |
132 /// | |
133 /// path.relative('/root/path/a/b.dart', to: '/root/path'); // -> 'a/b.dart' | |
134 /// path.relative('/root/other.dart', | |
135 /// to: '/root/path'); // -> '../other.dart' | |
136 /// | |
106 /// Since there is no relative path from one drive letter to another on Windows, | 137 /// Since there is no relative path from one drive letter to another on Windows, |
107 /// this will return an absolute path in that case. | 138 /// this will return an absolute path in that case. |
108 /// | 139 /// |
109 /// // Given current directory is C:\home: | 140 /// path.relative(r'D:\other', to: r'C:\home'); // -> 'D:\other' |
110 /// path.relative(r'D:\other'); // -> 'D:\other' | 141 String relative(String path, {String to}) => _builder.relative(path, to: to); |
111 String relative(String path) => _builder.relative(path); | |
112 | 142 |
113 /// Removes a trailing extension from the last part of [path]. | 143 /// Removes a trailing extension from the last part of [path]. |
114 /// | 144 /// |
115 /// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' | 145 /// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo' |
116 String withoutExtension(String path) => _builder.withoutExtension(path); | 146 String withoutExtension(String path) => _builder.withoutExtension(path); |
117 | 147 |
118 /// An instantiable class for manipulating paths. Unlike the top-level | 148 /// An instantiable class for manipulating paths. Unlike the top-level |
119 /// functions, this lets you explicitly select what platform the paths will use. | 149 /// functions, this lets you explicitly select what platform the paths will use. |
120 class Builder { | 150 class Builder { |
121 /// Creates a new path builder for the given style and root directory. | 151 /// Creates a new path builder for the given style and root directory. |
(...skipping 20 matching lines...) Expand all Loading... | |
142 /// The style of path that this builder works with. | 172 /// The style of path that this builder works with. |
143 final Style style; | 173 final Style style; |
144 | 174 |
145 /// The root directory that relative paths will be relative to. | 175 /// The root directory that relative paths will be relative to. |
146 final String root; | 176 final String root; |
147 | 177 |
148 /// Gets the path separator for the builder's [style]. On Mac and Linux, | 178 /// Gets the path separator for the builder's [style]. On Mac and Linux, |
149 /// this is `/`. On Windows, it's `\`. | 179 /// this is `/`. On Windows, it's `\`. |
150 String get separator => style.separator; | 180 String get separator => style.separator; |
151 | 181 |
182 /// Gets the part of [path] before the last separator. | |
183 /// | |
184 /// builder.dirname('path/to/foo.dart'); // -> 'path/to' | |
185 /// builder.dirname('path/to'); // -> 'to' | |
Bob Nystrom
2012/12/12 00:01:20
Show an example of what happens if there's a trail
nweiz
2012/12/12 00:50:37
I left that out intentionally because I want to ch
| |
186 String dirname(String path) { | |
Bob Nystrom
2012/12/12 00:01:20
Nit, but can you move this after basenameWithoutEx
nweiz
2012/12/12 00:50:37
Done.
| |
187 var parsed = _parse(path); | |
188 if (parsed.parts.isEmpty) return '.'; | |
Bob Nystrom
2012/12/12 00:01:20
You'll need to handle absolute paths here. If ther
nweiz
2012/12/12 00:50:37
Done.
| |
189 if (parsed.separators.last == '') { | |
Bob Nystrom
2012/12/12 00:01:20
!parsed.hasTrailingSeparator
nweiz
2012/12/12 00:50:37
Done.
| |
190 if (parsed.parts.length == 1) return '.'; | |
Bob Nystrom
2012/12/12 00:01:20
I think you should be able to skip this check.
nweiz
2012/12/12 00:50:37
It dirname("a") should return ".", not "".
Bob Nystrom
2012/12/12 01:02:13
Right, but I believe toString() handles that, does
nweiz
2012/12/12 02:45:57
No, it would just return ''.
| |
191 parsed.parts.removeLast(); | |
192 parsed.separators.removeLast(); | |
193 } | |
194 parsed.separators[parsed.separators.length - 1] = ''; | |
Bob Nystrom
2012/12/12 00:01:20
What's this for?
nweiz
2012/12/12 00:50:37
For paths with trailing separators, this makes dir
Bob Nystrom
2012/12/12 01:02:13
Yeah, consistency is what matters most to me here.
| |
195 return parsed.toString(); | |
196 } | |
197 | |
152 /// Gets the part of [path] after the last separator on the builder's | 198 /// Gets the part of [path] after the last separator on the builder's |
153 /// platform. | 199 /// platform. |
154 /// | 200 /// |
155 /// builder.basename('path/to/foo.dart'); // -> 'foo.dart' | 201 /// builder.basename('path/to/foo.dart'); // -> 'foo.dart' |
156 /// builder.basename('path/to'); // -> 'to' | 202 /// builder.basename('path/to'); // -> 'to' |
157 String basename(String path) => _parse(path).basename; | 203 String basename(String path) => _parse(path).basename; |
158 | 204 |
159 /// Gets the part of [path] after the last separator on the builder's | 205 /// Gets the part of [path] after the last separator on the builder's |
160 /// platform, and without any trailing file extension. | 206 /// platform, and without any trailing file extension. |
161 /// | 207 /// |
162 /// builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' | 208 /// builder.basenameWithoutExtension('path/to/foo.dart'); // -> 'foo' |
163 String basenameWithoutExtension(String path) => | 209 String basenameWithoutExtension(String path) => |
164 _parse(path).basenameWithoutExtension; | 210 _parse(path).basenameWithoutExtension; |
165 | 211 |
166 /// Gets the file extension of [path]: the portion of [basename] from the last | 212 /// Gets the file extension of [path]: the portion of [basename] from the last |
167 /// `.` to the end (including the `.` itself). | 213 /// `.` to the end (including the `.` itself). |
168 /// | 214 /// |
169 /// builder.extension('path/to/foo.dart'); // -> '.dart' | 215 /// builder.extension('path/to/foo.dart'); // -> '.dart' |
170 /// builder.extension('path/to/foo'); // -> '' | 216 /// builder.extension('path/to/foo'); // -> '' |
171 /// builder.extension('path.to/foo'); // -> '' | 217 /// builder.extension('path.to/foo'); // -> '' |
172 /// builder.extension('path/to/foo.dart.js'); // -> '.js' | 218 /// builder.extension('path/to/foo.dart.js'); // -> '.js' |
173 /// | 219 /// |
174 /// If the file name starts with a `.`, then it is not considered an | 220 /// If the file name starts with a `.`, then it is not considered an |
175 /// extension: | 221 /// extension: |
176 /// | 222 /// |
177 /// builder.extension('~/.bashrc'); // -> '' | 223 /// builder.extension('~/.bashrc'); // -> '' |
178 /// builder.extension('~/.notes.txt'); // -> '.txt' | 224 /// builder.extension('~/.notes.txt'); // -> '.txt' |
179 String extension(String path) => _parse(path).extension; | 225 String extension(String path) => _parse(path).extension; |
180 | 226 |
227 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. | |
228 /// Returns the root of [path], if it's absolute, or `null` if it's relative. | |
229 /// | |
230 /// // Unix | |
231 /// builder.rootOf('path/to/foo'); // -> null | |
232 /// builder.rootOf('/path/to/foo'); // -> '/' | |
233 /// | |
234 /// // Windows | |
235 /// builder.rootOf(r'path\to\foo'); // -> null | |
236 /// builder.rootOf(r'C:\path\to\foo'); // -> r'C:\' | |
237 String rootOf(String path) => _parse(path).root; | |
238 | |
181 /// Returns `true` if [path] is an absolute path and `false` if it is a | 239 /// Returns `true` if [path] is an absolute path and `false` if it is a |
182 /// relative path. On POSIX systems, absolute paths start with a `/` (forward | 240 /// relative path. On POSIX systems, absolute paths start with a `/` (forward |
183 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter | 241 /// slash). On Windows, an absolute path starts with `\\`, or a drive letter |
184 /// followed by `:/` or `:\`. | 242 /// followed by `:/` or `:\`. |
185 bool isAbsolute(String path) => _parse(path).isAbsolute; | 243 bool isAbsolute(String path) => _parse(path).isAbsolute; |
186 | 244 |
187 /// Returns `true` if [path] is a relative path and `false` if it is absolute. | 245 /// Returns `true` if [path] is a relative path and `false` if it is absolute. |
188 /// On POSIX systems, absolute paths start with a `/` (forward slash). On | 246 /// On POSIX systems, absolute paths start with a `/` (forward slash). On |
189 /// Windows, an absolute path starts with `\\`, or a drive letter followed by | 247 /// Windows, an absolute path starts with `\\`, or a drive letter followed by |
190 /// `:/` or `:\`. | 248 /// `:/` or `:\`. |
(...skipping 10 matching lines...) Expand all Loading... | |
201 /// | 259 /// |
202 /// If a part is an absolute path, then anything before that will be ignored: | 260 /// If a part is an absolute path, then anything before that will be ignored: |
203 /// | 261 /// |
204 /// builder.join('path', '/to', 'foo'); // -> '/to/foo' | 262 /// builder.join('path', '/to', 'foo'); // -> '/to/foo' |
205 /// | 263 /// |
206 String join(String part1, [String part2, String part3, String part4, | 264 String join(String part1, [String part2, String part3, String part4, |
207 String part5, String part6, String part7, String part8]) { | 265 String part5, String part6, String part7, String part8]) { |
208 var buffer = new StringBuffer(); | 266 var buffer = new StringBuffer(); |
209 var needsSeparator = false; | 267 var needsSeparator = false; |
210 | 268 |
211 addPart(condition, part) { | 269 var parts = [part1, part2, part3, part4, part5, part6, part7, part8]; |
212 if (!condition) return; | 270 for (var i = 1; i < parts.length; i++) { |
271 if (parts[i] == null || parts[i - 1] != null) continue; | |
Bob Nystrom
2012/12/12 00:01:20
I'd find this more intuitive if you flipped the lo
nweiz
2012/12/12 00:50:37
Done.
| |
272 throw new ArgumentError("join(): part ${i - 1} was null, but part $i was " | |
273 "not."); | |
274 } | |
275 | |
276 for (var part in parts) { | |
277 if (part == null) continue; | |
213 | 278 |
214 if (this.isAbsolute(part)) { | 279 if (this.isAbsolute(part)) { |
215 // An absolute path discards everything before it. | 280 // An absolute path discards everything before it. |
216 buffer.clear(); | 281 buffer.clear(); |
217 buffer.add(part); | 282 buffer.add(part); |
218 } else { | 283 } else { |
219 if (part.length > 0 && style.separatorPattern.hasMatch(part[0])) { | 284 if (part.length > 0 && style.separatorPattern.hasMatch(part[0])) { |
220 // The part starts with a separator, so we don't need to add one. | 285 // The part starts with a separator, so we don't need to add one. |
221 } else if (needsSeparator) { | 286 } else if (needsSeparator) { |
222 buffer.add(separator); | 287 buffer.add(separator); |
223 } | 288 } |
224 | 289 |
225 buffer.add(part); | 290 buffer.add(part); |
226 } | 291 } |
227 | 292 |
228 // Unless this part ends with a separator, we'll need to add one before | 293 // Unless this part ends with a separator, we'll need to add one before |
229 // the next part. | 294 // the next part. |
230 needsSeparator = part.length > 0 && | 295 needsSeparator = part.length > 0 && |
231 !style.separatorPattern.hasMatch(part[part.length - 1]); | 296 !style.separatorPattern.hasMatch(part[part.length - 1]); |
232 } | 297 } |
233 | 298 |
234 addPart(true, part1); | 299 return buffer.toString(); |
235 addPart(?part2, part2); | 300 } |
236 addPart(?part3, part3); | |
237 addPart(?part4, part4); | |
238 addPart(?part5, part5); | |
239 addPart(?part6, part6); | |
240 addPart(?part7, part7); | |
241 addPart(?part8, part8); | |
242 | 301 |
243 return buffer.toString(); | 302 // TODO(nweiz): add a UNC example for Windows once issue 7323 is fixed. |
303 /// Splits [path] into its components using the current platform's [separator] . | |
Bob Nystrom
2012/12/12 00:01:20
Long line.
nweiz
2012/12/12 00:50:37
Done.
| |
304 /// Example: | |
305 /// | |
306 /// builder.split('path/to/foo'); // -> ['path', 'to', 'foo'] | |
307 /// | |
308 /// If [path] is absolute, the root directory will be the first element in the | |
309 /// array. Example: | |
310 /// | |
311 /// // Unix | |
312 /// builder.split('/path/to/foo'); // -> ['/', 'path', 'to', 'foo'] | |
313 /// | |
314 /// // Windows | |
315 /// builder.split(r'C:\path\to\foo'); // -> [r'C:\', 'path', 'to', 'foo'] | |
316 List<String> split(String path) { | |
317 var parsed = _parse(path); | |
318 // Filter out empty parts that exist due to multiple separators in a row. | |
319 parsed.parts = parsed.parts.filter((part) => part != ''); | |
320 if (parsed.root != null) parsed.parts.insertRange(0, 1, parsed.root); | |
321 return parsed.parts; | |
244 } | 322 } |
245 | 323 |
246 /// Normalizes [path], simplifying it by handling `..`, and `.`, and | 324 /// Normalizes [path], simplifying it by handling `..`, and `.`, and |
247 /// removing redundant path separators whenever possible. | 325 /// removing redundant path separators whenever possible. |
248 /// | 326 /// |
249 /// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt' | 327 /// builder.normalize('path/./to/..//file.text'); // -> 'path/file.txt' |
250 String normalize(String path) { | 328 String normalize(String path) { |
251 if (path == '') return path; | 329 if (path == '') return path; |
252 | 330 |
253 var parsed = _parse(path); | 331 var parsed = _parse(path); |
(...skipping 17 matching lines...) Expand all Loading... | |
271 return join(root, part1, part2, part3, part4, part5, part6, part7); | 349 return join(root, part1, part2, part3, part4, part5, part6, part7); |
272 } | 350 } |
273 | 351 |
274 /// Attempts to convert [path] to an equivalent relative path relative to | 352 /// Attempts to convert [path] to an equivalent relative path relative to |
275 /// [root]. | 353 /// [root]. |
276 /// | 354 /// |
277 /// var builder = new Builder(root: '/root/path'); | 355 /// var builder = new Builder(root: '/root/path'); |
278 /// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart' | 356 /// builder.relative('/root/path/a/b.dart'); // -> 'a/b.dart' |
279 /// builder.relative('/root/other.dart'); // -> '../other.dart' | 357 /// builder.relative('/root/other.dart'); // -> '../other.dart' |
280 /// | 358 /// |
359 /// If the [to] argument is passed, [path] is made relative to that instead. | |
360 /// | |
361 /// builder.relative('/root/path/a/b.dart', | |
362 /// to: '/root/path'); // -> 'a/b.dart' | |
363 /// builder.relative('/root/other.dart', | |
364 /// to: '/root/path'); // -> '../other.dart' | |
365 /// | |
281 /// Since there is no relative path from one drive letter to another on | 366 /// Since there is no relative path from one drive letter to another on |
282 /// Windows, this will return an absolute path in that case. | 367 /// Windows, this will return an absolute path in that case. |
283 /// | 368 /// |
284 /// var builder = new Builder(root: r'C:\home'); | 369 /// builder.relative(r'D:\other', to: r'C:\other'); // -> 'D:\other' |
285 /// builder.relative(r'D:\other'); // -> 'D:\other' | 370 String relative(String path, {String to}) { |
286 String relative(String path) { | |
287 if (path == '') return '.'; | 371 if (path == '') return '.'; |
288 | 372 |
289 // If the base path is relative, resolve it relative to the current | 373 // If the base path is relative, resolve it relative to the current |
290 // directory. | 374 // directory. |
291 var base = root; | 375 var base = to == null ? root : to; |
292 if (this.isRelative(base)) base = absolute(base); | 376 if (this.isRelative(base)) base = absolute(base); |
293 | 377 |
294 // If the given path is relative, resolve it relative to the base. | 378 // If the given path is relative, resolve it relative to the base. |
295 if (this.isRelative(path)) return this.normalize(path); | 379 if (this.isRelative(path)) return this.normalize(path); |
296 | 380 |
297 var baseParsed = _parse(base)..normalize(); | 381 var baseParsed = _parse(base)..normalize(); |
298 var pathParsed = _parse(path)..normalize(); | 382 var pathParsed = _parse(path)..normalize(); |
299 | 383 |
300 // If the root prefixes don't match (for example, different drive letters | 384 // If the root prefixes don't match (for example, different drive letters |
301 // on Windows), then there is no relative path, so just return the absolute | 385 // on Windows), then there is no relative path, so just return the absolute |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
526 | 610 |
527 var lastDot = file.lastIndexOf('.'); | 611 var lastDot = file.lastIndexOf('.'); |
528 | 612 |
529 // If there is no dot, or it's the first character, like '.bashrc', it | 613 // If there is no dot, or it's the first character, like '.bashrc', it |
530 // doesn't count. | 614 // doesn't count. |
531 if (lastDot <= 0) return [file, '']; | 615 if (lastDot <= 0) return [file, '']; |
532 | 616 |
533 return [file.substring(0, lastDot), file.substring(lastDot)]; | 617 return [file.substring(0, lastDot), file.substring(lastDot)]; |
534 } | 618 } |
535 } | 619 } |
OLD | NEW |