ore 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.gitignore +10 -0
  2. data/ChangeLog.md +70 -7
  3. data/LICENSE.txt +1 -1
  4. data/README.md +93 -88
  5. data/Rakefile +5 -5
  6. data/data/ore/templates/base/README.md.erb +3 -0
  7. data/data/ore/templates/base/README.rdoc.erb +3 -0
  8. data/data/ore/templates/base/README.tt.erb +3 -0
  9. data/data/ore/templates/base/template.yml +2 -2
  10. data/data/ore/templates/bin/bin/[name].erb +1 -1
  11. data/data/ore/templates/bundler/Gemfile.erb +14 -3
  12. data/data/ore/templates/bundler/template.yml +7 -2
  13. data/data/ore/templates/bundler_tasks/_tasks.erb +1 -0
  14. data/data/ore/templates/bundler_tasks/template.yml +6 -0
  15. data/data/ore/templates/gem_package_task/_tasks.erb +5 -0
  16. data/data/ore/templates/gem_package_task/template.yml +4 -0
  17. data/data/ore/templates/gemspec/[name].gemspec.erb +45 -0
  18. data/data/ore/templates/gemspec/template.yml +2 -0
  19. data/data/ore/templates/{base → gemspec_yml}/[name].gemspec.erb +36 -55
  20. data/data/ore/templates/gemspec_yml/gemspec.yml.erb +41 -0
  21. data/data/ore/templates/gemspec_yml/template.yml +2 -0
  22. data/data/ore/templates/git/.gitignore.erb +3 -0
  23. data/data/ore/templates/git/template.yml +2 -0
  24. data/data/ore/templates/hg/.hgignore.erb +3 -0
  25. data/data/ore/templates/hg/template.yml +2 -0
  26. data/data/ore/templates/jeweler_tasks/_tasks.erb +3 -12
  27. data/data/ore/templates/jeweler_tasks/template.yml +4 -3
  28. data/data/ore/templates/rdoc/_tasks.erb +1 -1
  29. data/data/ore/templates/rdoc/template.yml +3 -0
  30. data/data/ore/templates/rspec/_tasks.erb +1 -1
  31. data/data/ore/templates/rspec/spec/spec_helper.rb.erb +1 -1
  32. data/data/ore/templates/rspec/template.yml +2 -2
  33. data/data/ore/templates/rubygems_tasks/_tasks.erb +14 -0
  34. data/data/ore/templates/rubygems_tasks/template.yml +7 -0
  35. data/data/ore/templates/rvmrc/.rvmrc.erb +9 -15
  36. data/data/ore/templates/yard/_gemfile_development.erb +0 -1
  37. data/data/ore/templates/yard/_tasks.erb +1 -1
  38. data/data/ore/templates/yard/template.yml +5 -2
  39. data/gemspec.yml +5 -7
  40. data/lib/ore.rb +0 -2
  41. data/lib/ore/actions.rb +85 -0
  42. data/lib/ore/cli.rb +2 -32
  43. data/lib/ore/config.rb +20 -20
  44. data/lib/ore/generator.rb +101 -203
  45. data/lib/ore/naming.rb +160 -0
  46. data/lib/ore/options.rb +67 -0
  47. data/lib/ore/template.rb +8 -0
  48. data/lib/ore/template/directory.rb +60 -41
  49. data/lib/ore/template/helpers.rb +55 -7
  50. data/lib/ore/template/template.rb +61 -0
  51. data/ore.gemspec +35 -55
  52. data/spec/gemspec_examples.rb +33 -0
  53. data/spec/generator_spec.rb +188 -70
  54. data/spec/helpers/generator.rb +4 -2
  55. data/spec/helpers/matchers.rb +33 -0
  56. data/spec/naming_spec.rb +56 -0
  57. data/spec/spec_helper.rb +1 -1
  58. metadata +104 -117
  59. data/data/ore/templates/base/.gitignore.erb +0 -3
  60. data/data/ore/templates/base/_gemfile_development.erb +0 -3
  61. data/data/ore/templates/base/gemspec.yml.erb +0 -30
  62. data/data/ore/templates/bundler/_development_dependencies.erb +0 -1
  63. data/data/ore/templates/bundler/_gitignore.erb +0 -2
  64. data/data/ore/templates/bundler/_tasks.erb +0 -3
  65. data/data/ore/templates/jeweler_tasks/_development_dependencies.erb +0 -3
  66. data/data/ore/templates/jeweler_tasks/_gemfile_development.erb +0 -1
  67. data/data/ore/templates/ore_tasks/_development_dependencies.erb +0 -3
  68. data/data/ore/templates/ore_tasks/_gemfile_development.erb +0 -1
  69. data/data/ore/templates/ore_tasks/_tasks.erb +0 -14
  70. data/data/ore/templates/ore_tasks/template.yml +0 -5
  71. data/data/ore/templates/rdoc/_gitignore.erb +0 -1
  72. data/data/ore/templates/rspec/_development_dependencies.erb +0 -3
  73. data/data/ore/templates/rspec/_gemfile_development.erb +0 -1
  74. data/data/ore/templates/yard/_development_dependencies.erb +0 -1
data/lib/ore/naming.rb ADDED
@@ -0,0 +1,160 @@
1
+ module Ore
2
+ #
3
+ # Provides methods for guessing the namespaces and directories
4
+ # of projects. {Naming} uses the naming conventions of project names
5
+ # defined by the
6
+ # [Ruby Packaging Standard (RPS)](http://chneukirchen.github.com/rps/).
7
+ #
8
+ # @since 0.9.0
9
+ #
10
+ module Naming
11
+ # The directory which contains executables for a project
12
+ BIN_DIR = 'bin'
13
+
14
+ # The directory which contains the code for a project
15
+ LIB_DIR = 'lib'
16
+
17
+ # The directory which contains C extension code for a project
18
+ EXT_DIR = 'ext'
19
+
20
+ # The directory which contains data files for a project
21
+ DATA_DIR = 'data'
22
+
23
+ # The directory which contains unit-tests for a project
24
+ TEST_DIR = 'test'
25
+
26
+ # The directory which contains spec-tests for a project
27
+ SPEC_DIR = 'spec'
28
+
29
+ # The directory which contains built packages
30
+ PKG_DIR = 'pkg'
31
+
32
+ # Words used in project names, but never in directory names
33
+ IGNORE_NAMESPACES = %w[core ruby rb java]
34
+
35
+ # Common acronyms used in namespaces
36
+ NAMESPACE_ACRONYMS = %w[
37
+ ffi yard i18n
38
+ http https ftp smtp imap pop3 ssh ssl tcp udp dns rpc
39
+ url uri www css html xhtml xml xsl json yaml csv
40
+ posix unix bsd
41
+ cpp asm
42
+ ]
43
+
44
+ # Common project prefixes and namespaces
45
+ COMMON_NAMESPACES = {
46
+ 'rubygems' => 'Gem',
47
+ 'ar' => 'ActiveRecord',
48
+ 'dm' => 'DataMapper',
49
+ 'js' => 'JavaScript',
50
+ 'msgpack' => 'MsgPack',
51
+ 'github' => 'GitHub',
52
+ 'rdoc' => 'RDoc'
53
+ }
54
+
55
+ #
56
+ # Splits the project name into individual names.
57
+ #
58
+ # @param [String] name
59
+ # The name to split.
60
+ #
61
+ # @return [Array<String>]
62
+ # The individual names of the project name.
63
+ #
64
+ def names_in(name)
65
+ name.split('-').reject do |word|
66
+ IGNORE_NAMESPACES.include?(word)
67
+ end
68
+ end
69
+
70
+ #
71
+ # Guesses the module name for a word within a project name.
72
+ #
73
+ # @param [String] word
74
+ # The word within a project name.
75
+ #
76
+ # @return [String]
77
+ # The module name.
78
+ #
79
+ # @since 0.1.1
80
+ #
81
+ def module_of(word)
82
+ if COMMON_NAMESPACES.has_key?(word)
83
+ COMMON_NAMESPACES[word]
84
+ elsif NAMESPACE_ACRONYMS.include?(word)
85
+ word.upcase
86
+ else
87
+ word.capitalize
88
+ end
89
+ end
90
+
91
+ #
92
+ # Guesses the module names from a project name.
93
+ #
94
+ # @param [String] name
95
+ # The name of the project.
96
+ #
97
+ # @return [Array<String>]
98
+ # The module names for a project.
99
+ #
100
+ def modules_of(name)
101
+ names_in(name).map do |words|
102
+ words.split('_').map { |word| module_of(word) }.join
103
+ end
104
+ end
105
+
106
+ #
107
+ # Guesses the full namespace for a project.
108
+ #
109
+ # @param [String] name
110
+ # The name of the project.
111
+ #
112
+ # @return [String]
113
+ # The full module namespace for a project.
114
+ #
115
+ def namespace_of(name)
116
+ modules_of(name).join('::')
117
+ end
118
+
119
+ #
120
+ # Converts a camel-case name to an underscored file name.
121
+ #
122
+ # @param [String] name
123
+ # The name to underscore.
124
+ #
125
+ # @return [String]
126
+ # The underscored version of the name.
127
+ #
128
+ def underscore(name)
129
+ name.gsub(/[^A-Z_][A-Z][^A-Z_]/) { |cap|
130
+ cap[0,1] + '_' + cap[1..-1]
131
+ }.downcase
132
+ end
133
+
134
+ #
135
+ # Guesses the namespace directories within `lib/` for a project.
136
+ #
137
+ # @param [String] name
138
+ # The name of the project.
139
+ #
140
+ # @return [Array<String>]
141
+ # The namespace directories for the project.
142
+ #
143
+ def namespace_dirs_of(name)
144
+ names_in(name).map { |word| underscore(word) }
145
+ end
146
+
147
+ #
148
+ # Guesses the namespace directory within `lib/` for a project.
149
+ #
150
+ # @param [String] name
151
+ # The name of the project.
152
+ #
153
+ # @return [String]
154
+ # The namespace directory for the project.
155
+ #
156
+ def namespace_path_of(name)
157
+ File.join(namespace_dirs_of(name))
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,67 @@
1
+ require 'ore/config'
2
+ require 'ore/template'
3
+
4
+ module Ore
5
+ #
6
+ # @api semipublic
7
+ #
8
+ # @since 0.9.0
9
+ #
10
+ module Options
11
+ # Default version
12
+ DEFAULT_VERSION = '0.1.0'
13
+
14
+ # Default summary
15
+ DEFAULT_SUMMARY = %q{TODO: Summary}
16
+
17
+ # Default description
18
+ DEFAULT_DESCRIPTION = %q{TODO: Description}
19
+
20
+ # Default License
21
+ DEFAULT_LICENSE = 'MIT'
22
+
23
+ # Default authors
24
+ DEFAULT_AUTHORS = [ENV['USER']]
25
+
26
+ def self.included(base)
27
+ base.extend ClassMethods
28
+ end
29
+
30
+ #
31
+ # Default options for the generator.
32
+ #
33
+ # @return [Hash{Symbol => Object}]
34
+ # The option names and default values.
35
+ #
36
+ def self.defaults
37
+ @@defaults ||= {
38
+ :templates => [],
39
+ :version => DEFAULT_VERSION,
40
+ :summary => DEFAULT_SUMMARY,
41
+ :description => DEFAULT_DESCRIPTION,
42
+ :license => DEFAULT_LICENSE,
43
+ :authors => DEFAULT_AUTHORS,
44
+ :gemspec => true,
45
+ :rubygems_tasks => true,
46
+ :rdoc => true,
47
+ :rspec => true,
48
+ :git => true
49
+ }.merge(Config.options)
50
+ end
51
+
52
+ module ClassMethods
53
+ #
54
+ # Defines a generator option.
55
+ #
56
+ # @param [Symbol] name
57
+ # The name of the option.
58
+ #
59
+ # @param [Hash{Symbol => Object}] options
60
+ # The Thor options of the option.
61
+ #
62
+ def generator_option(name,options={})
63
+ class_option(name,options.merge(:default => Options.defaults[name]))
64
+ end
65
+ end
66
+ end
67
+ end
data/lib/ore/template.rb CHANGED
@@ -1,3 +1,11 @@
1
1
  require 'ore/template/directory'
2
2
  require 'ore/template/interpolations'
3
3
  require 'ore/template/helpers'
4
+ require 'ore/template/template'
5
+ require 'ore/config'
6
+
7
+ # register builtin templates
8
+ Ore::Config.builtin_templates { |path| Ore::Template.register(path) }
9
+
10
+ # register installed templates
11
+ Ore::Config.installed_templates { |path| Ore::Template.register(path) }
@@ -6,22 +6,22 @@ require 'find'
6
6
  module Ore
7
7
  module Template
8
8
  #
9
- # Represents a template directory and the static files, ERb files
9
+ # Represents a template directory and the static files, `.erb` files
10
10
  # and sub-directories within it.
11
11
  #
12
12
  class Directory
13
13
 
14
14
  # The template configuration file
15
- @@config_file = 'template.yml'
15
+ CONFIG_FILE = 'template.yml'
16
16
 
17
17
  # Files or directory names to ignore
18
- @@ignore = ['.git', @@config_file]
18
+ IGNORE = ['.git', CONFIG_FILE]
19
19
 
20
20
  # The known markup languages and file extensions
21
- @@markups = {
21
+ MARKUPS = {
22
22
  :markdown => %w[.md .markdown],
23
- :textile => %w[.tt .textile],
24
- :rdoc => %w[.rdoc]
23
+ :textile => %w[.tt .textile],
24
+ :rdoc => %w[.rdoc]
25
25
  }
26
26
 
27
27
  # The path of the template directory
@@ -48,6 +48,21 @@ module Ore
48
48
  # The variables to use when rendering the template files
49
49
  attr_reader :variables
50
50
 
51
+ # Files to ignore
52
+ #
53
+ # @since 0.9.0
54
+ attr_reader :ignore
55
+
56
+ # Runtime dependencies defined by the template
57
+ #
58
+ # @since 0.9.0
59
+ attr_reader :dependencies
60
+
61
+ # Development dependencies defined by the template
62
+ #
63
+ # @since 0.9.0
64
+ attr_reader :development_dependencies
65
+
51
66
  #
52
67
  # Initializes a new template directory.
53
68
  #
@@ -58,13 +73,17 @@ module Ore
58
73
  @path = File.expand_path(path)
59
74
 
60
75
  @directories = []
61
- @files = {}
62
- @templates = {}
63
- @includes = Hash.new { |hash,key| hash[key] = {} }
76
+ @files = {}
77
+ @templates = {}
78
+ @includes = Hash.new { |hash,key| hash[key] = {} }
64
79
 
65
80
  @disable = []
66
- @enable = []
67
- @variables = {}
81
+ @enable = []
82
+
83
+ @ignore = []
84
+ @dependencies = {}
85
+ @development_dependencies = {}
86
+ @variables = {}
68
87
 
69
88
  load!
70
89
  scan!
@@ -134,41 +153,41 @@ module Ore
134
153
  # @since 0.2.0
135
154
  #
136
155
  def load!
137
- config_path = File.join(@path,@@config_file)
156
+ config_path = File.join(@path,CONFIG_FILE)
138
157
  return false unless File.file?(config_path)
139
158
 
140
159
  config = YAML.load_file(config_path)
160
+ return false unless config.kind_of?(Hash)
141
161
 
142
- unless config.kind_of?(Hash)
143
- raise(InvalidTemplate,"invalid configuration in #{config_path.dump}")
144
- end
162
+ @disable = Array(config['disable']).map(&:to_sym)
163
+ @enable = Array(config['enable']).map(&:to_sym)
145
164
 
146
- if (templates = config['disable'])
147
- if templates.kind_of?(Array)
148
- templates.each { |name| @disable << name.to_sym }
149
- else
150
- @disable << templates.to_sym
151
- end
152
- end
165
+ @ignore = Array(config['ignore'])
153
166
 
154
- if (templates = config['enable'])
155
- if templates.kind_of?(Array)
156
- templates.each { |name| @enable << name.to_sym }
157
- else
158
- @enable << templates.to_sym
159
- end
167
+ case (dependencies = config['dependencies'])
168
+ when Hash
169
+ @dependencies.merge!(dependencies)
170
+ when nil
171
+ else
172
+ raise(InvalidTemplate,"template dependencies must be a Hash: #{config_path.dump}")
160
173
  end
161
174
 
162
- if (variables = config['variables'])
163
- # variables must be a Hash
164
- unless variables.kind_of?(Hash)
165
- raise(InvalidTemplate,"template variables must be a Hash: #{config_path.dump}")
166
- end
175
+ case (dependencies = config['development_dependencies'])
176
+ when Hash
177
+ @development_dependencies.merge!(dependencies)
178
+ when nil
179
+ else
180
+ raise(InvalidTemplate,"template dependencies must be a Hash: #{config_path.dump}")
181
+ end
167
182
 
168
- # load the template variables
183
+ case (variables = config['variables'])
184
+ when Hash
169
185
  variables.each do |name,value|
170
186
  @variables[name.to_sym] = value
171
187
  end
188
+ when nil
189
+ else
190
+ raise(InvalidTemplate,"template variables must be a Hash: #{config_path.dump}")
172
191
  end
173
192
 
174
193
  return true
@@ -188,7 +207,7 @@ module Ore
188
207
  name = File.basename(file)
189
208
 
190
209
  # ignore certain files/directories
191
- Find.prune if @@ignore.include?(name)
210
+ Find.prune if IGNORE.include?(name)
192
211
 
193
212
  if File.directory?(file)
194
213
  @directories << file
@@ -198,14 +217,14 @@ module Ore
198
217
  case File.extname(name)
199
218
  when '.erb'
200
219
  # erb template
201
- if name[0,1] == '_'
220
+ if name.start_with?('_')
202
221
  # partial template
203
- template_dir = File.dirname(file)
204
- template_name = name[1...-4].to_sym
222
+ template_dir = File.dirname(file)
223
+ template_name = name[1..-1].chomp('.erb').to_sym
205
224
 
206
225
  @includes[template_dir][template_name] = src
207
226
  else
208
- dest = file[0...-4]
227
+ dest = file.chomp('.erb')
209
228
 
210
229
  @templates[dest] = src
211
230
  end
@@ -228,7 +247,7 @@ module Ore
228
247
  # Specifies whether the file is formatting.
229
248
  #
230
249
  def formatted?(path)
231
- @@markups.values.any? { |exts| exts.include?(File.extname(path)) }
250
+ MARKUPS.values.any? { |exts| exts.include?(File.extname(path)) }
232
251
  end
233
252
 
234
253
  #
@@ -244,7 +263,7 @@ module Ore
244
263
  # Specifies whether the file contains the given formatting.
245
264
  #
246
265
  def formatted_like?(path,markup)
247
- @@markups[markup].include?(File.extname(path))
266
+ MARKUPS[markup].include?(File.extname(path))
248
267
  end
249
268
 
250
269
  end
@@ -63,7 +63,31 @@ module Ore
63
63
  # @since 0.7.0
64
64
  #
65
65
  def git?
66
- options.git?
66
+ @scm == :git
67
+ end
68
+
69
+ #
70
+ # Determines if Hg is enabled.
71
+ #
72
+ # @return [Boolean]
73
+ # Specifies whether Hg was enabled.
74
+ #
75
+ # @since 0.9.0
76
+ #
77
+ def hg?
78
+ @scm == :hg
79
+ end
80
+
81
+ #
82
+ # Determines if SVN is enabled.
83
+ #
84
+ # @return [Boolean]
85
+ # Specifies whether SVN was enabled.
86
+ #
87
+ # @since 0.9.0
88
+ #
89
+ def svn?
90
+ @scm == :svn
67
91
  end
68
92
 
69
93
  #
@@ -95,7 +119,7 @@ module Ore
95
119
  # Specifies whether the project will contain RDoc documented.
96
120
  #
97
121
  def rdoc?
98
- options.rdoc?
122
+ enabled?(:rdoc)
99
123
  end
100
124
 
101
125
  #
@@ -138,6 +162,30 @@ module Ore
138
162
  enabled?(:bundler)
139
163
  end
140
164
 
165
+ #
166
+ # Determines if the project is using `Bundler::GemHelper`.
167
+ #
168
+ # @return [Boolean]
169
+ # Specifies whether the project is using `Bundler::GemHelper`.
170
+ #
171
+ # @since 0.9.0
172
+ #
173
+ def bundler_tasks?
174
+ enabled?(:bundler_tasks)
175
+ end
176
+
177
+ #
178
+ # Determines if the project is using `Gem::Tasks`.
179
+ #
180
+ # @return [Boolean]
181
+ # Specifies whether the project is using `Gem::Tasks`.
182
+ #
183
+ # @since 0.9.0
184
+ #
185
+ def rubygems_tasks?
186
+ enabled?(:rubygems_tasks)
187
+ end
188
+
141
189
  #
142
190
  # Determines if the project is using `Jeweler::Tasks`.
143
191
  #
@@ -151,15 +199,15 @@ module Ore
151
199
  end
152
200
 
153
201
  #
154
- # Determines if the project is using `Ore::Tasks`.
202
+ # Determines if the project is using `Gem::PackageTask`.
155
203
  #
156
204
  # @return [Boolean]
157
- # Specifies whether the project is using `Ore::Tasks`.
205
+ # Specifies whether the project is using `Gem::PackageTask`.
158
206
  #
159
- # @since 0.3.0
207
+ # @since 0.9.0
160
208
  #
161
- def ore_tasks?
162
- enabled?(:ore_tasks)
209
+ def gem_package_task?
210
+ enabled?(:gem_package_task)
163
211
  end
164
212
 
165
213
  #