ronin-gen 1.0.1 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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