1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
# This is free software released into the public domain (CC0 license).
class FilepathList
include Enumerable
SEPARATOR = ':'.freeze
def initialize(raw_entries = nil)
raw_entries ||= []
@entries = raw_entries.map { |e| e.as_path }
end
def select_entries(type)
raw_entries = @entries.delete_if { |e| !e.send(type.to_s + '?') }
return FilepathList.new(raw_entries)
end
def files
return select_entries(:file)
end
def links
return select_entries(:link)
end
def directories
return select_entries(:directory)
end
def /(extra_path)
return self.map { |path| path / extra_path }
end
def +(extra_entries)
return FilepathList.new(@entries + extra_entries.to_a)
end
def -(others)
remaining_entries = @entries - others.as_path_list.to_a
return FilepathList.new(remaining_entries)
end
def <<(extra_path)
return FilepathList.new(@entries + [extra_path.as_path])
end
def *(other_list)
if !other_list.is_a? FilepathList
other_list = FilepathList.new(Array(other_list))
end
other_entries = other_list.entries
paths = @entries.product(other_entries).map { |p1, p2| p1 / p2 }
return FilepathList.new(paths)
end
def remove_common_segments
all_segs = @entries.map(&:segments)
max_length = all_segs.map(&:length).min
idx_different = nil
(0..max_length).each do |i|
segment = all_segs.first[i]
different = all_segs.any? { |segs| segs[i] != segment }
if different
idx_different = i
break
end
end
idx_different ||= max_length
remaining_segs = all_segs.map { |segs| segs[idx_different..-1] }
return FilepathList.new(remaining_segs)
end
# @return [FilepathList] the path list itself
def as_path_list
self
end
def to_a
@entries
end
def to_s
@to_s ||= @entries.map(&:to_str).join(SEPARATOR)
end
# @private
def inspect
@entries.inspect
end
def ==(other)
@entries == other.as_path_list.to_a
end
module ArrayMethods
# @private
def self.define_array_method(name)
define_method(name) do |*args, &block|
return @entries.send(name, *args, &block)
end
end
define_array_method :[]
define_array_method :empty?
define_array_method :include?
define_array_method :each
define_array_method :all?
define_array_method :any?
define_array_method :none?
define_array_method :size
end
module EntriesMethods
def map(&block)
mapped_entries = @entries.map(&block)
return FilepathList.new(mapped_entries)
end
def select(pattern = nil, &block)
if !block_given?
block = proc { |e| e =~ pattern }
end
remaining_entries = @entries.select { |e| block.call(e) }
return FilepathList.new(remaining_entries)
end
def exclude(pattern = nil, &block)
if block_given?
select { |e| !block.call(e) }
else
select { |e| !(e =~ pattern) }
end
end
end
include ArrayMethods
include EntriesMethods
end
|