ronin-gen 1.0.1 → 1.1.0.rc1

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.
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ doc
2
+ pkg
3
+ vendor/cache
4
+ Gemfile.lock
5
+ .bundle
6
+ .DS_Store
7
+ .yardoc
8
+ *.db
9
+ *.log
10
+ *.swp
11
+ *~
data/ChangeLog.md CHANGED
@@ -1,3 +1,16 @@
1
+ ### 1.1.0 / 2012-01-01
2
+
3
+ * Require parameters ~> 0.4.
4
+ * Require ronin-support ~> 0.4.
5
+ * Require ronin ~> 1.4.
6
+ * Added {Ronin::Gen::SourceCodeGenerator.template}.
7
+ * Removed thor from the dependencies.
8
+ * Refactored {Ronin::Gen::Generator} to use
9
+ [Parameters](http://github.com/postmodern/parameters) and
10
+ [FileUtils](http://rubydoc.info/stdlib/fileutils/1.9.2/file/README.rdoc).
11
+ * Refactored the `ronin gen` command to use
12
+ [Parameters::Options](http://rubydoc.info/gems/parameters/0.4.0/Parameters/Options).
13
+
1
14
  ### 1.0.1 / 2011-07-04
2
15
 
3
16
  * Require data_paths ~> 0.3.
data/Gemfile CHANGED
@@ -7,8 +7,8 @@ RONIN_URI = 'http://github.com/ronin-ruby'
7
7
  gemspec
8
8
 
9
9
  # Ronin dependencies:
10
- # gem 'ronin-support', '~> 0.2', :git => "#{RONIN_URI}/ronin-support.git"
11
- # gem 'ronin', '~> 1.1', :git => "#{RONIN_URI}/ronin.git"
10
+ # gem 'ronin-support', '~> 0.4.0.rc1', :git => "#{RONIN_URI}/ronin-support.git"
11
+ # gem 'ronin', '~> 1.4.0.rc1', :git => "#{RONIN_URI}/ronin.git"
12
12
 
13
13
  group :development do
14
14
  gem 'rake', '~> 0.8'
data/README.md CHANGED
@@ -16,10 +16,10 @@ or payloads over many common Source-Code-Management (SCM) systems.
16
16
 
17
17
  ## Features
18
18
 
19
- * Provides {Ronin::Gen::FileGenerator}, a Thor based generator class that
20
- can be used to create new generators.
21
- * Provides {Ronin::Gen::DirGenerator}, a Thor based generator that
22
- can be used to create new directory generators.
19
+ * Provides {Ronin::Gen::FileGenerator}
20
+ * Provides {Ronin::Gen::DirGenerator}
21
+ * Provides {Ronin::Gen::SourceCodeGenerator}
22
+ * Provides {Ronin::Gen::RubyGenerator}
23
23
  * Generators for creating new Ronin Repositories and Libraries.
24
24
 
25
25
  ## Synopsis
@@ -38,16 +38,25 @@ Generate a skeleton Overlay:
38
38
  ~> 0.3
39
39
  * [data_paths](http://github.com/postmodern/data_paths#readme)
40
40
  ~> 0.3
41
- * [thor](http://github.com/wycats/thor#readme)
42
- ~> 0.14.3
41
+ * [parameters](http://github.com/postmodern/parameters#readme)
42
+ ~> 0.4
43
43
  * [ronin-support](http://github.com/ronin-ruby/ronin-support#readme)
44
- ~> 0.1
44
+ ~> 0.4
45
45
  * [ronin](http://github.com/ronin-ruby/ronin#readme)
46
- ~> 1.0
46
+ ~> 1.4
47
47
 
48
48
  ## Install
49
49
 
50
- $ sudo gem install ronin-gen
50
+ ### Stable
51
+
52
+ $ gem install ronin-gen
53
+
54
+ ### Edge
55
+
56
+ $ git clone git://github.com/ronin-ruby/ronin-gen.git
57
+ $ cd ronin-gen/
58
+ $ bundle install
59
+ $ ./bin/ronin-gen --help
51
60
 
52
61
  ## License
53
62
 
data/bin/ronin-gen CHANGED
@@ -23,16 +23,4 @@ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
23
23
  require 'ronin/gen/gen'
24
24
  require 'ronin/ui/cli/commands/gen'
25
25
 
26
- if (ARGV.length > 0 && ARGV.first[0..0] != '-')
27
- name = ARGV.shift
28
-
29
- begin
30
- Ronin::Gen.generator(name).start
31
- rescue Ronin::Gen::UnknownGenerator
32
- warn "ronin-gen: unknown generator #{name}"
33
- warn "ronin-gen: run 'ronin-gen' for a list of generators"
34
- exit -1
35
- end
36
- else
37
- Ronin::UI::CLI::Commands::Gen.start
38
- end
26
+ Ronin::UI::CLI::Commands::Gen.start
@@ -6,7 +6,7 @@ gemspec
6
6
 
7
7
  # gem 'ronin-support', '~> <%= Ronin::Support::VERSION %>', :git => "#{RONIN_URI}/ronin-support.git"
8
8
  # gem 'ronin', '~> <%= Ronin::VERSION %>', :git => "#{RONIN_URI}/ronin.git"
9
- <%- unless options[:generators].empty? -%>
9
+ <%- unless @generators.empty? -%>
10
10
  # gem 'ronin-gen', '~> <%= Ronin::Gen::VERSION %>', :git => "#{RONIN_URI}/ronin-gen.git"
11
11
  <%- end -%>
12
12
 
@@ -20,7 +20,7 @@
20
20
  ## Requirements
21
21
 
22
22
  * [ronin](http://github.com/ronin-ruby/ronin#readme) ~> 1.0
23
- <%- unless options[:generators].empty? -%>
23
+ <%- unless @generators.empty? -%>
24
24
  * [ronin-gen](http://github.com/ronin-ruby/ronin-gen#readme) ~> 1.0
25
25
  <%- end -%>
26
26
 
@@ -10,7 +10,7 @@ has_yard: true
10
10
 
11
11
  dependencies:
12
12
  ronin: ~> 1.0
13
- <%- unless options[:generators].empty? -%>
13
+ <%- unless @generators.empty? -%>
14
14
  ronin-gen: ~> 1.0
15
15
  <%- end -%>
16
16
 
@@ -3,6 +3,6 @@
3
3
  module Ronin
4
4
  module <%= @module_name %>
5
5
  # <%= @name %> version
6
- VERSION = '<%= DEFAULT_VERSION %>'
6
+ VERSION = '<%= @version %>'
7
7
  end
8
8
  end
@@ -99,7 +99,7 @@ Gem::Specification.new do |gemspec|
99
99
  end
100
100
 
101
101
  if gemspec.respond_to?(:required_rubygems_version=)
102
- gemspec.required_rubygems_version = metadata['required_ruby_version']
102
+ gemspec.required_rubygems_version = metadata['required_rubygems_version']
103
103
  end
104
104
 
105
105
  parse_versions = lambda { |versions|
@@ -11,8 +11,8 @@ website: <%= @website %>
11
11
  <%- end -%>
12
12
  authors:
13
13
  <%- @authors.each do |name| -%>
14
- - <%= name -%>
14
+ - <%= name %>
15
15
  <%- end -%>
16
16
 
17
17
  description:
18
- <%= @description -%>
18
+ <%= @description %>
data/gemspec.yml CHANGED
@@ -14,10 +14,10 @@ requirements: git >= 1.6.0.0, for the library generator
14
14
  dependencies:
15
15
  open_namespace: ~> 0.3
16
16
  data_paths: ~> 0.3
17
- thor: ~> 0.14.3
17
+ parameters: ~> 0.4
18
18
  # Ronin dependencies:
19
- ronin-support: ~> 0.1
20
- ronin: ~> 1.0
19
+ ronin-support: ~> 0.4.0.rc1
20
+ ronin: ~> 1.4.0.rc1
21
21
 
22
22
  development_dependencies:
23
23
  bundler: ~> 1.0.10
@@ -28,47 +28,37 @@ module Ronin
28
28
  #
29
29
  class DirGenerator < Generator
30
30
 
31
- argument :path, :type => :string, :require => true
31
+ # The destination path for the generator
32
+ parameter :path, :type => String,
33
+ :description => 'The destination path'
32
34
 
33
35
  #
34
- # Invokes the generator.
36
+ # Invokes the new Dir Generator.
35
37
  #
36
38
  # @param [String] path
37
- # The directory to generate within.
39
+ # The path for the generator.
38
40
  #
39
- # @param [Hash] options
40
- # Additional command-line options for the generator.
41
+ # @param [Hash{Symbol => Object}] options
42
+ # Additional options for the generator.
41
43
  #
42
- # @param [Array] arguments
43
- # Additional command-line arguments for the generator.
44
+ # @api public
44
45
  #
45
- # @example
46
- # gen.generate('path/to/dir')
47
- #
48
- def self.generate(path,options={},arguments=[])
49
- super(options,[File.expand_path(path)] + arguments)
46
+ def self.generate(path,options={})
47
+ super(options.merge(:path => path))
50
48
  end
51
49
 
52
- protected
53
-
54
- #
55
- # Initializes the generator.
56
50
  #
57
- # @param [Array] arguments
58
- # Additional arguments for the generator.
51
+ # Creates the directory and invokes the generator.
59
52
  #
60
- # @param [Hash] options
61
- # Options to pass to the generator.
53
+ # @api semipublic
62
54
  #
63
- # @param [Hash] config
64
- # Additional configuration for the generator.
55
+ # @since 1.1.0
65
56
  #
66
- # @since 1.0.0
67
- #
68
- def initialize(arguments=[],options={},config={})
69
- super(arguments,options,config) do |gen|
70
- gen.destination_root = self.path
71
- end
57
+ def generate!
58
+ require_params :path
59
+
60
+ FileUtils.mkdir_p @path
61
+ chdir(@path) { super }
72
62
  end
73
63
 
74
64
  end
@@ -26,45 +26,63 @@ module Ronin
26
26
  #
27
27
  class FileGenerator < Generator
28
28
 
29
- argument :path, :type => :string, :require => true
29
+ # The destination path for the generator
30
+ parameter :path, :type => String,
31
+ :description => 'File to generate'
30
32
 
31
33
  #
32
- # Generates the file at the given path.
34
+ # Invokes the new File Generator.
33
35
  #
34
- def self.generate(options={},arguments=[])
35
- super(options,arguments) do |gen|
36
- if (self.file_extension && File.extname(gen.path).empty?)
37
- gen.path += ".#{self.file_extension}"
38
- end
39
-
40
- yield gen if block_given?
41
- end
36
+ # @param [String] path
37
+ # The path for the generator.
38
+ #
39
+ # @param [Hash{Symbol => Object}] options
40
+ # Additional options for the generator.
41
+ #
42
+ # @api public
43
+ #
44
+ def self.generate(path,options={})
45
+ super(options.merge(:path => path))
42
46
  end
43
47
 
44
- protected
45
-
46
48
  #
47
- # The file extension to append to all paths.
49
+ # Sets up the File generator.
48
50
  #
49
- # @return [String, nil]
50
- # The file extension.
51
+ # @since 1.1.0
51
52
  #
52
- # @since 1.0.0
53
+ # @api semipublic
53
54
  #
54
- def self.file_extension
55
- @file_extension
55
+ def setup
56
+ require_params :path
57
+
58
+ if (self.class.file_extension && File.extname(@path).empty?)
59
+ @path += ".#{self.class.file_extension}"
60
+ end
56
61
  end
57
62
 
63
+ protected
64
+
58
65
  #
59
- # Sets the file extension to append to all paths.
66
+ # The file extension to append to all paths.
60
67
  #
61
68
  # @param [String] ext
69
+ # The new file extension to use.
70
+ #
71
+ # @return [String, nil]
62
72
  # The file extension.
63
73
  #
64
74
  # @since 1.0.0
65
75
  #
66
- def self.file_extension!(ext)
67
- @file_extension = ext.to_s
76
+ # @api semipublic
77
+ #
78
+ def self.file_extension(ext=nil)
79
+ if ext
80
+ @file_extension = ext.to_s
81
+ else
82
+ @file_extension ||= if superclass < FileGenerator
83
+ superclass.file_extension
84
+ end
85
+ end
68
86
  end
69
87
 
70
88
  end
data/lib/ronin/gen/gen.rb CHANGED
@@ -78,7 +78,7 @@ module Ronin
78
78
  name = path.chomp('.rb')
79
79
 
80
80
  # replace any file separators with a ':', to mimic the
81
- # naming convention of Rake/Thor.
81
+ # Rake task naming convention
82
82
  name.tr!(File::SEPARATOR,':')
83
83
 
84
84
  @generators << name
@@ -17,22 +17,20 @@
17
17
  # along with Ronin Gen. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
- require 'ronin/templates/template'
20
+ require 'ronin/gen/config'
21
21
  require 'ronin/support/inflector'
22
+ require 'ronin/templates/erb'
23
+ require 'ronin/ui/output'
22
24
 
23
- require 'thor'
24
- require 'thor/group'
25
- require 'thor/actions'
25
+ require 'parameters'
26
26
  require 'data_paths/finders'
27
- require 'erb'
27
+ require 'fileutils'
28
28
 
29
29
  module Ronin
30
30
  module Gen
31
31
  #
32
- # The {Generator} class leverages `Thor::Group` and `Thor::Actions`
33
- # to create a generic generator class. The generator class can
34
- # define `class_options` that can be used to parse command-line
35
- # arguments or set directly in Ruby.
32
+ # The {Generator} class is a generate base-class for all file,
33
+ # source-code or directory generators.
36
34
  #
37
35
  # # Extending
38
36
  #
@@ -50,18 +48,16 @@ module Ronin
50
48
  # module Generators
51
49
  # class MyGenerator < FileGenerator
52
50
  #
53
- # desc 'My generator'
54
- #
55
51
  # # generator options
56
- # class_option :stuff, :type => :boolean
57
- # class_option :syntax, :type => :string
58
- # class_option :includes, :type => :array
52
+ # parameter :stuff, :type => true
53
+ # parameter :syntax, :type => String
54
+ # parameter :includes, :type => Array
59
55
  #
60
56
  # #
61
57
  # # Performs the generation.
62
58
  # #
63
59
  # def generate
64
- # erb 'some_template.erb', self.path
60
+ # erb 'some_template.erb', path
65
61
  # end
66
62
  #
67
63
  # end
@@ -75,8 +71,10 @@ module Ronin
75
71
  # class method with the options and arguments to run the generator with:
76
72
  #
77
73
  # MyGenerator.generate(
78
- # {:stuff => true, :syntax => 'bla', :includes => ['other']}
79
- # ['path/to/file'],
74
+ # :stuff => true,
75
+ # :syntax => 'bla',
76
+ # :includes => ['other']
77
+ # :path => 'path/to/file',
80
78
  # )
81
79
  #
82
80
  # To make your generator accessible to the `ronin-gen` command, simply
@@ -87,50 +85,78 @@ module Ronin
87
85
  # To run the generator using the `ronin-gen` command, simply specify
88
86
  # it's underscored name:
89
87
  #
90
- # ronin-gen my_generator path/to/file --stuff --syntax bla --includes other
88
+ # ronin-gen my_generator path/to/file --stuff \
89
+ # --syntax bla \
90
+ # --includes other
91
91
  #
92
- class Generator < Thor::Group
92
+ class Generator
93
93
 
94
- include Thor::Actions
95
- include Templates::Template
94
+ include Parameters
96
95
  include DataPaths::Finders
96
+ include FileUtils
97
+ include Templates::Erb
97
98
 
98
99
  #
99
- # Sets the namespace of new {Generator} classes.
100
+ # Initializes the generator.
101
+ #
102
+ # @param [String] path
103
+ # The destination path for the generator.
100
104
  #
101
- # @param [Class] super_class
102
- # The new {Generator} class.
105
+ # @param [Hash{Symbol => Object}] options
106
+ # The options for the generator.
107
+ #
108
+ # @yield [generator]
109
+ # The given block will be passed the newly created generator.
103
110
  #
104
- def self.inherited(super_class)
105
- class_name = super_class.name.sub('Ronin::Gen::Generators::','')
106
- gen_name = Support::Inflector.underscore(class_name.gsub('::',':'))
111
+ # @yieldparam [Generator]
112
+ # The newly created generator.
113
+ #
114
+ # @api semipublic
115
+ #
116
+ def initialize(options={})
117
+ initialize_params(options)
107
118
 
108
- super_class.namespace(gen_name)
119
+ yield self if block_given?
109
120
  end
110
121
 
111
122
  #
112
- # Defines the default source root of the generator as the current
113
- # working directory.
123
+ # The name of the generator.
114
124
  #
115
- # @since 0.2.0
125
+ # @return [String]
126
+ # The generator name.
127
+ #
128
+ # @since 1.1.0
129
+ #
130
+ # @api semipublic
116
131
  #
117
- def self.source_root
118
- @generator_source_root ||= Dir.pwd
132
+ def self.generator_name
133
+ class_name = self.name.sub('Ronin::Gen::Generators::','')
134
+
135
+ return Support::Inflector.underscore(class_name.gsub('::',':'))
119
136
  end
120
137
 
121
138
  #
122
- # Sets the source root of the generator.
139
+ # The default data directory of the generator.
123
140
  #
124
141
  # @param [String] new_dir
125
- # The new source root directory.
142
+ # The new data directory.
126
143
  #
127
- # @return [String]
128
- # The source root directory of the generator.
144
+ # @return [String, nil]
145
+ # The data directory that the generator will search for source files
146
+ # within.
129
147
  #
130
- # @since 1.0.0
148
+ # @since 1.1.0
149
+ #
150
+ # @api semipublic
131
151
  #
132
- def self.source_root=(new_dir)
133
- @genereator_source_root = File.expand_path(new_dir)
152
+ def self.data_dir(new_dir=nil)
153
+ if new_dir
154
+ @data_dir = new_dir
155
+ else
156
+ @data_dir ||= if superclass < Generator
157
+ superclass.data_dir
158
+ end
159
+ end
134
160
  end
135
161
 
136
162
  #
@@ -156,109 +182,175 @@ module Ronin
156
182
  #
157
183
  # @since 0.2.0
158
184
  #
159
- def self.generate(options={},arguments=[],&block)
160
- generator = self.new(arguments,options,&block)
161
- generator.invoke_all()
185
+ # @api public
186
+ #
187
+ def self.generate(options={},&block)
188
+ generator = new(options,&block)
162
189
 
190
+ generator.generate!
163
191
  return generator
164
192
  end
165
193
 
166
- desc "default generator task"
194
+ #
195
+ # Sets up the generator and calls {#generate}.
196
+ #
197
+ # @see #setup
198
+ # @see #generate
199
+ #
200
+ # @since 1.1.0
201
+ #
202
+ # @api public
203
+ #
204
+ def generate!
205
+ setup
206
+ generate
207
+ end
208
+
209
+ #
210
+ # Default method to initialize any instance variables before any of
211
+ # the tasks are invoked.
212
+ #
213
+ # @since 1.0.0
214
+ #
215
+ # @api semipublic
216
+ #
217
+ def setup
218
+ end
167
219
 
168
220
  #
169
221
  # Default generator method.
170
222
  #
171
223
  # @since 0.2.0
172
224
  #
225
+ # @api semipublic
226
+ #
173
227
  def generate
174
228
  end
175
229
 
176
230
  protected
177
231
 
178
232
  #
179
- # Initializes the generator.
233
+ # Runs a command.
180
234
  #
181
- # @param [Array] arguments
182
- # Additional arguments for the generator.
235
+ # @param [String] command
236
+ # The command or program to run.
183
237
  #
184
- # @param [Hash] options
185
- # Options to pass to the generator.
238
+ # @param [Array<String>] arguments
239
+ # Additional arguments to run the program with.
186
240
  #
187
- # @param [Hash] config
188
- # Additional configuration for the generator.
241
+ # @since 1.1.0
189
242
  #
190
- # @since 1.0.0
243
+ # @api semipublic
191
244
  #
192
- def initialize(arguments=[],options={},config={})
193
- super(arguments,options,config)
245
+ def run(command,*arguments)
246
+ print_action command, *arguments
194
247
 
195
- setup()
248
+ system(command,*arguments)
249
+ end
196
250
 
197
- yield self if block_given?
251
+ #
252
+ # Changes the permissions of a files or directories.
253
+ #
254
+ # @param [String, Integer] mode
255
+ # The new permissions for the files or directories.
256
+ #
257
+ # @param [Array<String>] paths
258
+ # The path to the files or directories.
259
+ #
260
+ # @since 1.1.0
261
+ #
262
+ # @api semipublic
263
+ #
264
+ def chmod(mode,paths)
265
+ print_action 'chmod', mode.to_s(8), *paths
266
+
267
+ super(mode,paths)
198
268
  end
199
269
 
200
270
  #
201
- # Default method to initialize any instance variables before any of
202
- # the tasks are invoked.
271
+ # Changes the permissions of files/directories, recursively.
203
272
  #
204
- # @since 1.0.0
273
+ # @param [String, Integer] mode
274
+ # The new permissions for the files or directories.
205
275
  #
206
- def setup
276
+ # @param [Array<String>] paths
277
+ # The path to the files or directories.
278
+ #
279
+ # @since 1.1.0
280
+ #
281
+ # @api semipublic
282
+ #
283
+ def chmod_R(mode,paths)
284
+ print_action 'chmod -R', mode.to_s(8)
285
+
286
+ super(mode,paths)
207
287
  end
208
288
 
209
289
  #
210
- # Touches a file.
290
+ # Changes ownership of files or directories.
211
291
  #
212
- # @param [String] destination
213
- # The relative path to the file to touch.
292
+ # @param [String, nil] user
293
+ # The new owner of the files or directories.
214
294
  #
215
- # @example
216
- # touch 'TODO.txt'
295
+ # @param [String, nil] group
296
+ # The new group for the files or directories.
217
297
  #
218
- # @since 0.2.0
298
+ # @param [Array<String>] paths
299
+ # The path to the files or directories.
219
300
  #
220
- def touch(destination)
221
- create_file(destination)
301
+ # @since 1.1.0
302
+ #
303
+ # @api semipublic
304
+ #
305
+ def chown(user,group,paths)
306
+ print_action 'chown', "#{user}:#{group}", *paths
307
+
308
+ super(user,group,paths)
222
309
  end
223
310
 
224
311
  #
225
- # Creates an empty directory.
312
+ # Changes ownership of files/directories, recursively.
226
313
  #
227
- # @param [String] destination
228
- # The relative path of the directory to create.
314
+ # @param [String, nil] user
315
+ # The new owner of the files or directories.
229
316
  #
230
- # @example
231
- # directory 'sub/dir'
317
+ # @param [String, nil] group
318
+ # The new group for the files or directories.
232
319
  #
233
- # @since 0.2.0
320
+ # @param [Array<String>] paths
321
+ # The path to the files or directories.
322
+ #
323
+ # @since 1.1.0
234
324
  #
235
- def mkdir(destination)
236
- empty_directory(destination)
325
+ # @api semipublic
326
+ #
327
+ def chown_R(user,group,paths)
328
+ print_action 'chown -R', "#{user}:#{group}", *paths
329
+
330
+ super(user,group,paths)
237
331
  end
238
332
 
239
333
  #
240
334
  # Copies a data file.
241
335
  #
242
- # @param [String] data_file
336
+ # @param [String] file
243
337
  # The relative path to the data file.
244
338
  #
245
339
  # @param [String] destination
246
340
  # The destination to copy the data file to.
247
341
  #
248
- # @example
249
- # copy_file 'ronin/platform/generators/extension.rb',
250
- # 'myext/extension.rb'
251
- #
252
342
  # @since 0.2.0
253
343
  #
254
- def cp(data_file,destination)
255
- copy_file(find_data_file(data_file),destination)
344
+ def cp(file,destination=file)
345
+ print_action 'cp', destination
346
+
347
+ super(data_file(file),destination)
256
348
  end
257
349
 
258
350
  #
259
351
  # Copies the contents of all data directories.
260
352
  #
261
- # @param [String] data_dir
353
+ # @param [String] directory
262
354
  # The data directories to copy from.
263
355
  #
264
356
  # @param [String, nil] destination
@@ -272,12 +364,268 @@ module Ronin
272
364
  #
273
365
  # @since 1.0.0
274
366
  #
275
- def cp_r(data_dir,destination=nil,config={})
276
- each_data_dir(data_dir) do |dir|
277
- directory(dir,destination || data_dir,config)
367
+ def cp_r(directory,destination=directory)
368
+ print_action 'cp -r', destination
369
+
370
+ data_dirs(directory) do |dir|
371
+ cp_r(dir,destination)
278
372
  end
279
373
  end
280
374
 
375
+ #
376
+ # Installs a file.
377
+ #
378
+ # @param [String] src
379
+ # The file to install.
380
+ #
381
+ # @param [String] dest
382
+ # The destination path for the file.
383
+ #
384
+ # @param [Hash] options
385
+ # Additional options.
386
+ #
387
+ # @option options [String, Integer] :mode
388
+ # The permissions of the installed file.
389
+ #
390
+ # @since 1.1.0
391
+ #
392
+ # @api semipublic
393
+ #
394
+ def install(src,dest,options={})
395
+ options = {:mode => options[:mode]} # only pass in :mode
396
+
397
+ print_action 'install', src, dest
398
+
399
+ super(data_file(src),dest,options)
400
+ end
401
+
402
+ #
403
+ # Creates a hard link.
404
+ #
405
+ # @param [String] src
406
+ # The path file/directory for the hard link.
407
+ #
408
+ # @param [String] dest
409
+ # The destination file/directory of the hard link.
410
+ #
411
+ # @since 1.1.0
412
+ #
413
+ # @api semipublic
414
+ #
415
+ def ln(src,dest)
416
+ print_action 'ln', src, dest
417
+
418
+ super(src,dest)
419
+ end
420
+
421
+ #
422
+ # Creates a symbolic link.
423
+ #
424
+ # @param [String] src
425
+ # The path file/directory for the symbolic link.
426
+ #
427
+ # @param [String] dest
428
+ # The destination file/directory of the symbolic link.
429
+ #
430
+ # @since 1.1.0
431
+ #
432
+ # @api semipublic
433
+ #
434
+ def ln_s(src,dest)
435
+ print_action 'ln -s', src, dest
436
+
437
+ super(src,dest)
438
+ end
439
+
440
+ #
441
+ # Forcibly creates a symbolic link.
442
+ #
443
+ # @param [String] src
444
+ # The path file/directory for the symbolic link.
445
+ #
446
+ # @param [String] dest
447
+ # The destination file/directory of the symbolic link.
448
+ #
449
+ # @since 1.1.0
450
+ #
451
+ # @api semipublic
452
+ #
453
+ def ln_sf(src,dest)
454
+ print_action 'ln -sf', src, dest
455
+
456
+ super(src,dest)
457
+ end
458
+
459
+ #
460
+ # Creates an empty directory.
461
+ #
462
+ # @param [String] dir
463
+ # The relative path of the directory to create.
464
+ #
465
+ # @example
466
+ # mkdir 'sub/dir'
467
+ #
468
+ # @since 0.2.0
469
+ #
470
+ def mkdir(dir)
471
+ print_action 'mkdir', dir
472
+
473
+ super(dir)
474
+ end
475
+
476
+ #
477
+ # Creates an empty directory.
478
+ #
479
+ # @param [String] dir
480
+ # The relative path of the directory to create.
481
+ #
482
+ # @example
483
+ # mkdir 'sub/dir'
484
+ #
485
+ # @since 0.2.0
486
+ #
487
+ def mkdir_p(dir)
488
+ print_action 'mkdir -p', dir
489
+
490
+ super(dir)
491
+ end
492
+
493
+ #
494
+ # Moves a file or directory.
495
+ #
496
+ # @param [String] src
497
+ # The path to the file or directory.
498
+ #
499
+ # @param [String] dest
500
+ # The new path to move the file or directory to.
501
+ #
502
+ # @api semipublic
503
+ #
504
+ # @since 1.1.0
505
+ #
506
+ def mv(src,dest)
507
+ print_action 'mv', src, dest
508
+
509
+ super(src,dest)
510
+ end
511
+
512
+ #
513
+ # Removes one or more files.
514
+ #
515
+ # @param [Array<String>] paths
516
+ # The paths of the files and directories to remove.
517
+ #
518
+ # @param [Hash] options
519
+ # Additional options.
520
+ #
521
+ # @option options [Boolean] :force
522
+ # Specifies whether to forcible remove the files.
523
+ #
524
+ # @since 1.1.0
525
+ #
526
+ # @api semipublic
527
+ #
528
+ def rm(paths,options={})
529
+ options = {:force => options[:force]} # only pass in :force
530
+
531
+ print_action 'rm', *paths
532
+
533
+ super(paths,options)
534
+ end
535
+
536
+ #
537
+ # Recursively removes files and directories.
538
+ #
539
+ # @param [Array<String>] paths
540
+ # The paths of the files and directories to remove.
541
+ #
542
+ # @param [Hash] options
543
+ # Additional options.
544
+ #
545
+ # @option options [Boolean] :force
546
+ # Specifies whether to forcible remove the files.
547
+ #
548
+ # @since 1.1.0
549
+ #
550
+ # @api semipublic
551
+ #
552
+ def rm_r(paths,options={})
553
+ options = {:force => options[:force]} # only pass in :force
554
+
555
+ print_action 'rm -r', *paths
556
+
557
+ super(paths,options)
558
+ end
559
+
560
+ #
561
+ # Forcibly removes files and directories, recursively.
562
+ #
563
+ # @param [Array<String>] paths
564
+ # The paths of the files and directories to remove.
565
+ #
566
+ # @since 1.1.0
567
+ #
568
+ # @api semipublic
569
+ #
570
+ def rm_rf(paths)
571
+ print_action 'rm -rf', *paths
572
+
573
+ super(paths)
574
+ end
575
+
576
+ #
577
+ # Removes one or more directories.
578
+ #
579
+ # @param [Array<String>] dirs
580
+ # The paths of the directories.
581
+ #
582
+ # @since 1.1.0
583
+ #
584
+ # @api semipublic
585
+ #
586
+ def rmdir(dirs)
587
+ print_action 'rmdir', *dirs
588
+
589
+ super(dirs)
590
+ end
591
+
592
+ #
593
+ # Touches a file.
594
+ #
595
+ # @param [String] destination
596
+ # The relative path to the file to touch.
597
+ #
598
+ # @example
599
+ # touch 'TODO.txt'
600
+ #
601
+ # @since 0.2.0
602
+ #
603
+ def touch(file)
604
+ print_action 'touch', file
605
+
606
+ return super(file)
607
+ end
608
+
609
+ #
610
+ # Opens a file for writing.
611
+ #
612
+ # @param [String] path
613
+ # The path of the file to write to.
614
+ #
615
+ # @yield [file]
616
+ # The given block will be passed the newly opened file.
617
+ #
618
+ # @yieldparam [File]
619
+ # The new file file, opened for writing.
620
+ #
621
+ # @since 1.1.0
622
+ #
623
+ # @api semipublic
624
+ #
625
+ def write(path,&block)
626
+ File.open(path,'wb',&block)
627
+ end
628
+
281
629
  #
282
630
  # Renders the ERB template and saves the result.
283
631
  #
@@ -292,22 +640,149 @@ module Ronin
292
640
  # will be returned.
293
641
  #
294
642
  # @example
295
- # erb 'ronin/platform/generators/Rakefile.erb', 'Rakefile.erb'
643
+ # erb 'Rakefile.erb', 'Rakefile'
296
644
  #
297
645
  # @example
298
646
  # erb '_helpers.erb'
299
647
  #
300
648
  # @since 0.2.0
301
649
  #
302
- def erb(template_path,destination=nil)
303
- if destination
304
- enter_template(template_path) do |path|
305
- template(path,destination)
650
+ def template(template_path,dest=nil)
651
+ template_path = data_path(template_path)
652
+
653
+ if dest
654
+ print_action 'erb', dest
655
+
656
+ File.open(dest,'w') do |file|
657
+ file.write(erb_file(template_path))
306
658
  end
307
659
  else
308
- read_template(template_path) do |template|
309
- ERB.new(template).result(binding).chomp
660
+ erb_file(template_path).chomp
661
+ end
662
+ end
663
+
664
+ private
665
+
666
+ #
667
+ # Joins the path with the Generators {data_dir}.
668
+ #
669
+ # @param [String] path
670
+ # A relative path.
671
+ #
672
+ # @return [String]
673
+ # The full `data/` directory path.
674
+ #
675
+ # @since 1.1.0
676
+ #
677
+ # @api private
678
+ #
679
+ def data_path(path)
680
+ if self.class.data_dir
681
+ path = File.join(self.class.data_dir,path)
682
+ end
683
+
684
+ return path
685
+ end
686
+
687
+ #
688
+ # Searches for a file within the Generators {data_dir}.
689
+ #
690
+ # @param [String] path
691
+ # The relative path to search for.
692
+ #
693
+ # @return [String]
694
+ # The path to the file.
695
+ #
696
+ # @raise [StandardError]
697
+ # The file could not be found in the Generators {data_dir}.
698
+ #
699
+ # @since 1.1.0
700
+ #
701
+ # @api private
702
+ #
703
+ def data_file(path)
704
+ unless (full_path = find_data_file(data_path(path)))
705
+ raise(StandardError,"cannot find generator file: #{path.dump}")
706
+ end
707
+
708
+ return full_path
709
+ end
710
+
711
+ #
712
+ # Searches for a directory within the Generators {data_dir}.
713
+ #
714
+ # @param [String] path
715
+ # The relative path to search for.
716
+ #
717
+ # @return [String]
718
+ # The path to the directory.
719
+ #
720
+ # @raise [StandardError]
721
+ # The directory could not be found in the Generators {data_dir}.
722
+ #
723
+ # @since 1.1.0
724
+ #
725
+ # @api private
726
+ #
727
+ def data_dir(path)
728
+ unless (full_path = find_data_dir(data_path(path)))
729
+ raise(StandardError,"cannot find generator directory: #{path.dump}")
730
+ end
731
+
732
+ return full_path
733
+ end
734
+
735
+ #
736
+ # Searches for all matching directories within the Generators {data_dir}.
737
+ #
738
+ # @param [String] path
739
+ # The relative directory path to search for.
740
+ #
741
+ # @yield [dir]
742
+ # The given block will be passed each found directory.
743
+ #
744
+ # @yieldparam [String] dir
745
+ # A directory with the same relative path.
746
+ #
747
+ # @since 1.1.0
748
+ #
749
+ # @api private
750
+ #
751
+ def data_dirs(path,&block)
752
+ each_data_dir(data_path(directory),&block)
753
+ end
754
+
755
+ # ANSI Bold code
756
+ BOLD = "\e[1m"
757
+
758
+ # ANSI Green code
759
+ GREEN = "\e[32m"
760
+
761
+ # ANSI Clear code
762
+ CLEAR = "\e[0m"
763
+
764
+ #
765
+ # Prints a file action.
766
+ #
767
+ # @param [String] command
768
+ # The command/options that represents the file action.
769
+ #
770
+ # @param [Array<String>] arguments
771
+ # Additional arguments related to the file action.
772
+ #
773
+ # @since 1.1.0
774
+ #
775
+ # @api private
776
+ #
777
+ def print_action(command,*arguments)
778
+ unless UI::Output.silent?
779
+ arguments = arguments.join(' ')
780
+
781
+ if $stdout.tty?
782
+ command = BOLD + GREEN + command + CLEAR
310
783
  end
784
+
785
+ puts "\t#{command}\t#{arguments}"
311
786
  end
312
787
  end
313
788