Parent

Class Index [+]

Quicksearch

Hike::Index

`Index` is an internal cached variant of `Trail`. It assumes the file system does not change between `find` calls. All `stat` and `entries` calls are cached for the lifetime of the `Index` object.

Attributes

paths[R]

`Index#paths` is an immutable `Paths` collection.

extensions[R]

`Index#extensions` is an immutable `Extensions` collection.

aliases[R]

`Index#aliases` is an immutable `Hash` mapping an extension to an `Array` of aliases.

Public Class Methods

new(root, paths, extensions, aliases) click to toggle source

`Index.new` is an internal method. Instead of constructing it directly, create a `Trail` and call `Trail#index`.

    # File lib/hike/index.rb, line 20
20:     def initialize(root, paths, extensions, aliases)
21:       @root = root
22: 
23:       # Freeze is used here so an error is throw if a mutator method
24:       # is called on the array. Mutating `@paths`, `@extensions`, or
25:       # `@aliases` would have unpredictable results.
26:       @paths      = paths.dup.freeze
27:       @extensions = extensions.dup.freeze
28:       @aliases    = aliases.inject({}) { |h, (k, a)|
29:                       h[k] = a.dup.freeze; h
30:                    }.freeze
31:       @pathnames  = paths.map { |path| Pathname.new(path) }
32: 
33:       @stats    = {}
34:       @entries  = {}
35:       @patterns = {}
36:     end

Public Instance Methods

entries(path) click to toggle source

A cached version of `Dir.entries` that filters out `.` files and `~` swap files. Returns an empty `Array` if the directory does not exist.

    # File lib/hike/index.rb, line 78
78:     def entries(path)
79:       key = path.to_s
80:       @entries[key] ||= Pathname.new(path).entries.reject { |entry| entry.to_s =~ /^\.|~$|^\#.*\#$/ }.sort
81:     rescue Errno::ENOENT
82:       @entries[key] = []
83:     end
find(*logical_paths, &block) click to toggle source

The real implementation of `find`. `Trail#find` generates a one time index and delegates here.

See `Trail#find` for usage.

    # File lib/hike/index.rb, line 52
52:     def find(*logical_paths, &block)
53:       if block_given?
54:         options = extract_options!(logical_paths)
55:         base_path = Pathname.new(options[:base_path] || @root)
56: 
57:         logical_paths.each do |logical_path|
58:           logical_path = Pathname.new(logical_path.sub(/^\//, ''))
59: 
60:           if relative?(logical_path)
61:             find_in_base_path(logical_path, base_path, &block)
62:           else
63:             find_in_paths(logical_path, &block)
64:           end
65:         end
66: 
67:         nil
68:       else
69:         find(*logical_paths) do |path|
70:           return path
71:         end
72:       end
73:     end
index() click to toggle source

`Index#index` returns `self` to be compatable with the `Trail` interface.

    # File lib/hike/index.rb, line 44
44:     def index
45:       self
46:     end
root() click to toggle source

`Index#root` returns root path as a `String`. This attribute is immutable.

    # File lib/hike/index.rb, line 39
39:     def root
40:       @root.to_s
41:     end
stat(path) click to toggle source

A cached version of `File.stat`. Returns nil if the file does not exist.

    # File lib/hike/index.rb, line 87
87:     def stat(path)
88:       key = path.to_s
89:       if @stats.key?(key)
90:         @stats[key]
91:       else
92:         begin
93:           @stats[key] = File.stat(path)
94:         rescue Errno::ENOENT
95:           @stats[key] = nil
96:         end
97:       end
98:     end

Protected Instance Methods

build_pattern_for(basename) click to toggle source

Returns a `Regexp` that matches the allowed extensions.

    pattern_for("index.html") #=> /^index(.html|.htm)(.builder|.erb)*$/
     # File lib/hike/index.rb, line 160
160:       def build_pattern_for(basename)
161:         extname = basename.extname
162:         aliases = find_aliases_for(extname)
163: 
164:         if aliases.any?
165:           basename = basename.basename(extname)
166:           aliases  = [extname] + aliases
167:           aliases_pattern = aliases.map { |e| Regexp.escape(e) }.join("|")
168:           basename_re = Regexp.escape(basename.to_s) + "(?:#{aliases_pattern})"
169:         else
170:           basename_re = Regexp.escape(basename.to_s)
171:         end
172: 
173:         extension_pattern = extensions.map { |e| Regexp.escape(e) }.join("|")
174:         /^#{basename_re}(?:#{extension_pattern})*$/
175:       end
extract_options!(arguments) click to toggle source
     # File lib/hike/index.rb, line 101
101:       def extract_options!(arguments)
102:         arguments.last.is_a?(Hash) ? arguments.pop.dup : {}
103:       end
find_aliases_for(extension) click to toggle source
     # File lib/hike/index.rb, line 197
197:       def find_aliases_for(extension)
198:         @aliases.inject([]) do |aliases, (key, value)|
199:           aliases.push(key) if value == extension
200:           aliases
201:         end
202:       end
find_in_base_path(logical_path, base_path, &block) click to toggle source

Finds relative logical path, `../test/test_trail`. Requires a `base_path` for reference.

     # File lib/hike/index.rb, line 119
119:       def find_in_base_path(logical_path, base_path, &block)
120:         candidate = base_path.join(logical_path)
121:         dirname, basename = candidate.split
122:         match(dirname, basename, &block) if paths_contain?(dirname)
123:       end
find_in_paths(logical_path, &block) click to toggle source

Finds logical path across all `paths`

     # File lib/hike/index.rb, line 110
110:       def find_in_paths(logical_path, &block)
111:         dirname, basename = logical_path.split
112:         @pathnames.each do |base_path|
113:           match(base_path.join(dirname), basename, &block)
114:         end
115:       end
match(dirname, basename) click to toggle source

Checks if the path is actually on the file system and performs any syscalls if necessary.

     # File lib/hike/index.rb, line 127
127:       def match(dirname, basename)
128:         # Potential `entries` syscall
129:         matches = entries(dirname)
130: 
131:         pattern = pattern_for(basename)
132:         matches = matches.select { |m| m.to_s =~ pattern }
133: 
134:         sort_matches(matches, basename).each do |path|
135:           pathname = dirname.join(path)
136: 
137:           # Potential `stat` syscall
138:           stat = stat(pathname)
139: 
140:           # Exclude directories
141:           if stat && stat.file?
142:             yield pathname.to_s
143:           end
144:         end
145:       end
paths_contain?(dirname) click to toggle source

Returns true if `dirname` is a subdirectory of any of the `paths`

     # File lib/hike/index.rb, line 148
148:       def paths_contain?(dirname)
149:         paths.any? { |path| dirname.to_s[0, path.length] == path }
150:       end
pattern_for(basename) click to toggle source

Cache results of `build_pattern_for`

     # File lib/hike/index.rb, line 153
153:       def pattern_for(basename)
154:         @patterns[basename] ||= build_pattern_for(basename)
155:       end
relative?(logical_path) click to toggle source
     # File lib/hike/index.rb, line 105
105:       def relative?(logical_path)
106:         logical_path.to_s =~ /^\.\.?\//
107:       end
sort_matches(matches, basename) click to toggle source

Sorts candidate matches by their extension priority. Extensions in the front of the `extensions` carry more weight.

     # File lib/hike/index.rb, line 180
180:       def sort_matches(matches, basename)
181:         aliases = find_aliases_for(basename.extname)
182: 
183:         matches.sort_by do |match|
184:           extnames = match.sub(basename.to_s, '').to_s.scan(/\.[^.]+/)
185:           extnames.inject(0) do |sum, ext|
186:             if i = extensions.index(ext)
187:               sum + i + 1
188:             elsif i = aliases.index(ext)
189:               sum + i + 11
190:             else
191:               sum
192:             end
193:           end
194:         end
195:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.