Class: Utopia::Path

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/utopia/path.rb

Constant Summary collapse

SEPARATOR =
"/"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(components = []) ⇒ Path

Returns a new instance of Path.



73
74
75
# File 'lib/utopia/path.rb', line 73

def initialize(components = [])
	@components = components
end

Instance Attribute Details

#componentsObject (readonly)

Returns the value of attribute components.



129
130
131
# File 'lib/utopia/path.rb', line 129

def components
  @components
end

Class Method Details

.[](path) ⇒ Object



112
113
114
# File 'lib/utopia/path.rb', line 112

def self.[] path
	self.create(path)
end

.create(path) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/utopia/path.rb', line 116

def self.create(path)
	case path
	when Path
		return path
	when Array
		return self.new(path)
	when String
		return self.new(unescape(path).split(SEPARATOR, -1))
	when Symbol
		return self.new([path])
	end
end

.prefix_length(a, b) ⇒ Object

Returns the length of the prefix which is shared by two strings.



84
85
86
# File 'lib/utopia/path.rb', line 84

def self.prefix_length(a, b)
	[a.size, b.size].min.times{|i| return i if a[i] != b[i]}
end

.shortest_path(path, root) ⇒ Object

Return the shortest relative path to get to path from root:



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/utopia/path.rb', line 89

def self.shortest_path(path, root)
	path = self.create(path)
	root = self.create(root).dirname
	
	# Find the common prefix:
	i = prefix_length(path.components, root.components) || 0
	
	# The difference between the root path and the required path, taking into account the common prefix:
	up = root.components.size - i
	
	return self.create([".."] * up + path.components[i..-1])
end

.unescape(string) ⇒ Object



106
107
108
109
110
# File 'lib/utopia/path.rb', line 106

def self.unescape(string)
	string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) {
		[$1.delete('%')].pack('H*')
	}
end

Instance Method Details

#+(other) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/utopia/path.rb', line 175

def +(other)
	if other.kind_of? Array
		return join(other)
	elsif other.kind_of? Path
		if other.absolute?
			return other
		else
			return join(other.components)
		end
	else
		return join([other.to_s])
	end
end

#-(other) ⇒ Object

Computes the difference of the path. /a/b/c - /a/b -> c a/b/c - a/b -> c



192
193
194
195
196
197
198
199
200
201
202
# File 'lib/utopia/path.rb', line 192

def -(other)
	i = 0
	
	while i < other.components.size
		break if @components[i] != other.components[i]
		
		i += 1
	end
	
	return self.class.new(@components[i,@components.size])
end

#<=>(other) ⇒ Object



276
277
278
# File 'lib/utopia/path.rb', line 276

def <=> other
	@components <=> other.components
end

#[](index) ⇒ Object



300
301
302
# File 'lib/utopia/path.rb', line 300

def [] index
	return @components[component_offset(index)]
end

#[]=(index, value) ⇒ Object

Replaces a named component, indexing as per



305
306
307
# File 'lib/utopia/path.rb', line 305

def []= index, value
	return @components[component_offset(index)] = value
end

#absolute?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'lib/utopia/path.rb', line 143

def absolute?
	return @components.first == ""
end

#ascend(&block) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/utopia/path.rb', line 246

def ascend(&block)
	return to_enum(:ascend) unless block_given?
	
	next_parent = self
	
	begin
		parent = next_parent
		
		yield parent
		
		next_parent = parent.dirname
	end until next_parent.eql?(parent)
end

#basename(*args) ⇒ Object



220
221
222
# File 'lib/utopia/path.rb', line 220

def basename(*args)
	Basename.new(@components.last, *args)
end

#delete_at(index) ⇒ Object



309
310
311
# File 'lib/utopia/path.rb', line 309

def delete_at(index)
	@components.delete_at(component_offset(index))
end

#descend(&block) ⇒ Object



234
235
236
237
238
239
240
241
242
243
244
# File 'lib/utopia/path.rb', line 234

def descend(&block)
	return to_enum(:descend) unless block_given?
	
	parent_path = []
	
	@components.each do |component|
		parent_path << component
		
		yield self.class.new(parent_path.dup)
	end
end

#directory?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'lib/utopia/path.rb', line 131

def directory?
	return @components.last == ""
end

#dirname(count = 1) ⇒ Object



224
225
226
227
228
# File 'lib/utopia/path.rb', line 224

def dirname(count = 1)
	path = self.class.new(@components[0...-count])

	return absolute? ? path.to_absolute : path
end

#dupObject



272
273
274
# File 'lib/utopia/path.rb', line 272

def dup
	return Path.new(components.dup)
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


280
281
282
283
284
285
286
# File 'lib/utopia/path.rb', line 280

def eql? other
	if self.class == other.class
		return @components.eql?(other.components)
	else
		return false
	end
end

#expand(root) ⇒ Object



171
172
173
# File 'lib/utopia/path.rb', line 171

def expand(root)
	root + self
end

#extensionObject



329
330
331
# File 'lib/utopia/path.rb', line 329

def extension
	basename(true).extension
end

#firstObject



313
314
315
316
317
318
319
# File 'lib/utopia/path.rb', line 313

def first
	if absolute?
		@components[1]
	else
		@components[0]
	end
end

#freezeObject



77
78
79
80
81
# File 'lib/utopia/path.rb', line 77

def freeze
	@components.freeze
	
	super
end

#hashObject



296
297
298
# File 'lib/utopia/path.rb', line 296

def hash
	@components.hash
end

#join(other) ⇒ Object



167
168
169
# File 'lib/utopia/path.rb', line 167

def join(other)
	self.class.new(@components + other).simplify
end

#lastObject



321
322
323
324
325
326
327
# File 'lib/utopia/path.rb', line 321

def last
	if directory?
		@components[-2]
	else
		@components[-1]
	end
end

#shortest_path(root) ⇒ Object



102
103
104
# File 'lib/utopia/path.rb', line 102

def shortest_path(root)
	self.class.shortest_path(self, root)
end

#simplifyObject



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/utopia/path.rb', line 204

def simplify
	result = absolute? ? [""] : []

	@components.each do |bit|
		if bit == ".."
			result.pop
		elsif bit != "." && bit != ""
			result << bit
		end
	end

	result << "" if directory?
	
	return self.class.new(result)
end

#split(at) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
# File 'lib/utopia/path.rb', line 260

def split(at)
	if at.kind_of? String
		at = @components.index(at)
	end
	
	if at
		return [self.class.new(@components[0...at]), self.class.new(@components[at+1..-1])]
	else
		return nil
	end
end

#start_with?(other) ⇒ Boolean

Returns:

  • (Boolean)


288
289
290
291
292
293
294
# File 'lib/utopia/path.rb', line 288

def start_with? other
	other.components.each_with_index do |part, index|
		return false if @components[index] != part
	end
	
	return true
end

#to_absoluteObject



147
148
149
150
151
152
153
# File 'lib/utopia/path.rb', line 147

def to_absolute
	if absolute?
		return self
	else
		return self.class.new([""] + @components)
	end
end

#to_directoryObject



135
136
137
138
139
140
141
# File 'lib/utopia/path.rb', line 135

def to_directory
	if directory?
		return self
	else
		return join([""])
	end
end

#to_local_path(separator = File::SEPARATOR) ⇒ Object



230
231
232
# File 'lib/utopia/path.rb', line 230

def to_local_path(separator = File::SEPARATOR)
	@components.join(separator)
end

#to_sObject



163
164
165
# File 'lib/utopia/path.rb', line 163

def to_s
	to_str
end

#to_strObject



155
156
157
158
159
160
161
# File 'lib/utopia/path.rb', line 155

def to_str
	if @components == [""]
		SEPARATOR
	else
		@components.join(SEPARATOR)
	end
end