hike 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (6) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +6 -6
  3. data/lib/hike.rb +1 -1
  4. data/lib/hike/index.rb +53 -13
  5. data/lib/hike/trail.rb +69 -1
  6. metadata +18 -38
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Sam Stephenson
1
+ Copyright (c) 2011 Sam Stephenson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -9,8 +9,8 @@ implement search paths, load paths, and the like.
9
9
  Find Ruby files in this project:
10
10
 
11
11
  trail = Hike::Trail.new "/Users/sam/Projects/hike"
12
- trail.extensions.push ".rb"
13
- trail.paths.push "lib", "test"
12
+ trail.append_extension ".rb"
13
+ trail.append_paths "lib", "test"
14
14
 
15
15
  trail.find "hike/trail"
16
16
  # => "/Users/sam/Projects/hike/lib/hike/trail.rb"
@@ -21,8 +21,8 @@ Find Ruby files in this project:
21
21
  Explore your Ruby load path:
22
22
 
23
23
  trail = Hike::Trail.new "/"
24
- trail.extensions.push ".rb", ".bundle"
25
- trail.paths.replace $:
24
+ trail.append_extensions ".rb", ".bundle"
25
+ trail.append_paths *$:
26
26
 
27
27
  trail.find "net/http"
28
28
  # => "/Users/sam/.rvm/rubies/ree-1.8.7-2010.02/lib/ruby/1.8/net/http.rb"
@@ -33,7 +33,7 @@ Explore your Ruby load path:
33
33
  Explore your shell path:
34
34
 
35
35
  trail = Hike::Trail.new "/"
36
- trail.paths.replace ENV["PATH"].split(":")
36
+ trail.append_paths *ENV["PATH"].split(":")
37
37
 
38
38
  trail.find "ls"
39
39
  # => "/bin/ls"
@@ -47,6 +47,6 @@ Explore your shell path:
47
47
 
48
48
  # License
49
49
 
50
- Copyright (c) 2010 Sam Stephenson.
50
+ Copyright (c) 2011 Sam Stephenson.
51
51
 
52
52
  Released under the MIT license. See `LICENSE` for details.
@@ -1,5 +1,5 @@
1
1
  module Hike
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
 
4
4
  autoload :Extensions, "hike/extensions"
5
5
  autoload :Index, "hike/index"
@@ -11,16 +11,23 @@ module Hike
11
11
  # `Index#extensions` is an immutable `Extensions` collection.
12
12
  attr_reader :extensions
13
13
 
14
+ # `Index#aliases` is an immutable `Hash` mapping an extension to
15
+ # an `Array` of aliases.
16
+ attr_reader :aliases
17
+
14
18
  # `Index.new` is an internal method. Instead of constructing it
15
19
  # directly, create a `Trail` and call `Trail#index`.
16
- def initialize(root, paths, extensions)
20
+ def initialize(root, paths, extensions, aliases)
17
21
  @root = root
18
22
 
19
23
  # Freeze is used here so an error is throw if a mutator method
20
- # is called on the array. Mutating `@paths` or `@extensions`
21
- # would have unpredictable results.
24
+ # is called on the array. Mutating `@paths`, `@extensions`, or
25
+ # `@aliases` would have unpredictable results.
22
26
  @paths = paths.dup.freeze
23
27
  @extensions = extensions.dup.freeze
28
+ @aliases = aliases.inject({}) { |h, (k, a)|
29
+ h[k] = a.dup.freeze; h
30
+ }.freeze
24
31
  @pathnames = paths.map { |path| Pathname.new(path) }
25
32
 
26
33
  @stats = {}
@@ -65,11 +72,12 @@ module Hike
65
72
  end
66
73
  end
67
74
 
68
- # A cached version of `Dir.entries` that filters out `.` and
69
- # `..`. Returns an empty `Array` if the directory does not exist.
75
+ # A cached version of `Dir.entries` that filters out `.` files and
76
+ # `~` swap files. Returns an empty `Array` if the directory does
77
+ # not exist.
70
78
  def entries(path)
71
79
  key = path.to_s
72
- @entries[key] ||= Pathname.new(path).entries.reject { |entry| entry.to_s =~ /^\.\.?$/ }
80
+ @entries[key] ||= Pathname.new(path).entries.reject { |entry| entry.to_s =~ /^\.|~$|^\#.*\#$/ }
73
81
  rescue Errno::ENOENT
74
82
  @entries[key] = []
75
83
  end
@@ -141,23 +149,55 @@ module Hike
141
149
  paths.any? { |path| dirname.to_s[0, path.length] == path }
142
150
  end
143
151
 
152
+ # Cache results of `build_pattern_for`
153
+ def pattern_for(basename)
154
+ @patterns[basename] ||= build_pattern_for(basename)
155
+ end
156
+
144
157
  # Returns a `Regexp` that matches the allowed extensions.
145
158
  #
146
- # pattern_for("index.html") #=> /^index.html(.builder|.erb)+$/
147
- def pattern_for(basename)
148
- @patterns[basename] ||= begin
149
- extension_pattern = extensions.map { |e| Regexp.escape(e) }.join("|")
150
- /^#{Regexp.escape(basename.to_s)}(?:#{extension_pattern}|)+$/
159
+ # pattern_for("index.html") #=> /^index(.html|.htm)(.builder|.erb)*$/
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)
151
171
  end
172
+
173
+ extension_pattern = extensions.map { |e| Regexp.escape(e) }.join("|")
174
+ /^#{basename_re}(?:#{extension_pattern})*$/
152
175
  end
153
176
 
154
177
  # Sorts candidate matches by their extension
155
178
  # priority. Extensions in the front of the `extensions` carry
156
179
  # more weight.
157
180
  def sort_matches(matches, basename)
181
+ aliases = find_aliases_for(basename.extname)
182
+
158
183
  matches.sort_by do |match|
159
- extnames = match.to_s[basename.to_s.length..-1].scan(/.[^.]+/)
160
- extnames.inject(0) { |sum, ext| sum + extensions.index(ext) + 1 }
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
196
+
197
+ def find_aliases_for(extension)
198
+ @aliases.inject([]) do |aliases, (key, value)|
199
+ aliases.push(key) if value == extension
200
+ aliases
161
201
  end
162
202
  end
163
203
  end
@@ -28,6 +28,20 @@ module Hike
28
28
  # allows you to require files with specifiying `foo.rb`.
29
29
  attr_reader :extensions
30
30
 
31
+ # `Index#aliases` is a mutable `Hash` mapping an extension to
32
+ # an `Array` of aliases.
33
+ #
34
+ # trail = Hike::Trail.new
35
+ # trail.paths.push "~/Projects/hike/site"
36
+ # trail.aliases['.htm'] = 'html'
37
+ # trail.aliases['.xhtml'] = 'html'
38
+ # trail.aliases['.php'] = 'html'
39
+ #
40
+ # Aliases provide a fallback when the primary extension is not
41
+ # matched. In the example above, a lookup for "foo.html" will
42
+ # check for the existence of "foo.htm", "foo.xhtml", or "foo.php".
43
+ attr_reader :aliases
44
+
31
45
  # A Trail accepts an optional root path that defaults to your
32
46
  # current working directory. Any relative paths added to
33
47
  # `Trail#paths` will expanded relative to the root.
@@ -35,6 +49,7 @@ module Hike
35
49
  @root = Pathname.new(root).expand_path
36
50
  @paths = Paths.new(@root)
37
51
  @extensions = Extensions.new
52
+ @aliases = Hash.new { |h, k| h[k] = Extensions.new }
38
53
  end
39
54
 
40
55
  # `Trail#root` returns root path as a `String`. This attribute is immutable.
@@ -42,6 +57,50 @@ module Hike
42
57
  @root.to_s
43
58
  end
44
59
 
60
+ # Prepend `path` to `Paths` collection
61
+ def prepend_paths(*paths)
62
+ self.paths.unshift(*paths)
63
+ end
64
+ alias_method :prepend_path, :prepend_paths
65
+
66
+ # Append `path` to `Paths` collection
67
+ def append_paths(*paths)
68
+ self.paths.push(*paths)
69
+ end
70
+ alias_method :append_path, :append_paths
71
+
72
+ # Remove `path` from `Paths` collection
73
+ def remove_path(path)
74
+ self.paths.delete(path)
75
+ end
76
+
77
+ # Prepend `extension` to `Extensions` collection
78
+ def prepend_extensions(*extensions)
79
+ self.extensions.unshift(*extensions)
80
+ end
81
+ alias_method :prepend_extension, :prepend_extensions
82
+
83
+ # Append `extension` to `Extensions` collection
84
+ def append_extensions(*extensions)
85
+ self.extensions.push(*extensions)
86
+ end
87
+ alias_method :append_extension, :append_extensions
88
+
89
+ # Remove `extension` from `Extensions` collection
90
+ def remove_extension(extension)
91
+ self.extensions.delete(extension)
92
+ end
93
+
94
+ # Alias `new_extension` to `old_extension`
95
+ def alias_extension(new_extension, old_extension)
96
+ aliases[normalize_extension(new_extension)] = normalize_extension(old_extension)
97
+ end
98
+
99
+ # Remove the alias for `extension`
100
+ def unalias_extension(extension)
101
+ aliases.delete(normalize_extension(extension))
102
+ end
103
+
45
104
  # `Trail#find` returns a the expand path for a logical path in the
46
105
  # path collection.
47
106
  #
@@ -91,7 +150,7 @@ module Hike
91
150
  # index.find "test_trail"
92
151
  #
93
152
  def index
94
- Index.new(root, paths, extensions)
153
+ Index.new(root, paths, extensions, aliases)
95
154
  end
96
155
 
97
156
  # `Trail#entries` is equivalent to `Dir#entries`. It is not
@@ -107,5 +166,14 @@ module Hike
107
166
  def stat(*args)
108
167
  index.stat(*args)
109
168
  end
169
+
170
+ private
171
+ def normalize_extension(extension)
172
+ if extension[/^\./]
173
+ extension
174
+ else
175
+ ".#{extension}"
176
+ end
177
+ end
110
178
  end
111
179
  end
metadata CHANGED
@@ -1,34 +1,24 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: hike
3
- version: !ruby/object:Gem::Version
4
- hash: 19
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 1
9
- - 0
10
- version: 1.1.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Sam Stephenson
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-06-14 00:00:00 -05:00
12
+ date: 2011-07-18 00:00:00.000000000 -05:00
19
13
  default_executable:
20
14
  dependencies: []
21
-
22
15
  description: A Ruby library for finding files in a set of paths.
23
- email:
16
+ email:
24
17
  - sstephenson@gmail.com
25
18
  executables: []
26
-
27
19
  extensions: []
28
-
29
20
  extra_rdoc_files: []
30
-
31
- files:
21
+ files:
32
22
  - README.md
33
23
  - LICENSE
34
24
  - lib/hike/extensions.rb
@@ -40,36 +30,26 @@ files:
40
30
  has_rdoc: true
41
31
  homepage: http://github.com/sstephenson/hike
42
32
  licenses: []
43
-
44
33
  post_install_message:
45
34
  rdoc_options: []
46
-
47
- require_paths:
35
+ require_paths:
48
36
  - lib
49
- required_ruby_version: !ruby/object:Gem::Requirement
37
+ required_ruby_version: !ruby/object:Gem::Requirement
50
38
  none: false
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- hash: 3
55
- segments:
56
- - 0
57
- version: "0"
58
- required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
44
  none: false
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- hash: 3
64
- segments:
65
- - 0
66
- version: "0"
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
67
49
  requirements: []
68
-
69
50
  rubyforge_project:
70
51
  rubygems_version: 1.6.2
71
52
  signing_key:
72
53
  specification_version: 3
73
54
  summary: Find files in a set of paths
74
55
  test_files: []
75
-