rant 0.3.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 (64) hide show
  1. data/COPYING +504 -0
  2. data/README +203 -0
  3. data/Rantfile +104 -0
  4. data/TODO +19 -0
  5. data/bin/rant +12 -0
  6. data/bin/rant-import +12 -0
  7. data/devel-notes +50 -0
  8. data/doc/configure.rdoc +40 -0
  9. data/doc/csharp.rdoc +74 -0
  10. data/doc/rant-import.rdoc +32 -0
  11. data/doc/rant.rdoc +24 -0
  12. data/doc/rantfile.rdoc +227 -0
  13. data/doc/rubyproject.rdoc +210 -0
  14. data/lib/rant.rb +9 -0
  15. data/lib/rant/cs_compiler.rb +334 -0
  16. data/lib/rant/import.rb +291 -0
  17. data/lib/rant/import/rubydoc.rb +125 -0
  18. data/lib/rant/import/rubypackage.rb +417 -0
  19. data/lib/rant/import/rubytest.rb +97 -0
  20. data/lib/rant/plugin/README +50 -0
  21. data/lib/rant/plugin/configure.rb +345 -0
  22. data/lib/rant/plugin/csharp.rb +275 -0
  23. data/lib/rant/plugin_methods.rb +41 -0
  24. data/lib/rant/rantenv.rb +217 -0
  25. data/lib/rant/rantfile.rb +664 -0
  26. data/lib/rant/rantlib.rb +1118 -0
  27. data/lib/rant/rantsys.rb +258 -0
  28. data/lib/rant/rantvar.rb +82 -0
  29. data/rantmethods.rb +79 -0
  30. data/run_import +7 -0
  31. data/run_rant +7 -0
  32. data/setup.rb +1360 -0
  33. data/test/Rantfile +2 -0
  34. data/test/plugin/configure/Rantfile +47 -0
  35. data/test/plugin/configure/test_configure.rb +58 -0
  36. data/test/plugin/csharp/Hello.cs +10 -0
  37. data/test/plugin/csharp/Rantfile +30 -0
  38. data/test/plugin/csharp/src/A.cs +8 -0
  39. data/test/plugin/csharp/src/B.cs +8 -0
  40. data/test/plugin/csharp/test_csharp.rb +99 -0
  41. data/test/project1/Rantfile +127 -0
  42. data/test/project1/test_project.rb +203 -0
  43. data/test/project2/buildfile +14 -0
  44. data/test/project2/rantfile.rb +20 -0
  45. data/test/project2/sub1/Rantfile +12 -0
  46. data/test/project2/test_project.rb +87 -0
  47. data/test/project_rb1/README +14 -0
  48. data/test/project_rb1/bin/wgrep +5 -0
  49. data/test/project_rb1/lib/wgrep.rb +56 -0
  50. data/test/project_rb1/rantfile.rb +30 -0
  51. data/test/project_rb1/test/tc_wgrep.rb +21 -0
  52. data/test/project_rb1/test/text +3 -0
  53. data/test/project_rb1/test_project_rb1.rb +153 -0
  54. data/test/test_env.rb +47 -0
  55. data/test/test_filetask.rb +57 -0
  56. data/test/test_lighttask.rb +49 -0
  57. data/test/test_metatask.rb +29 -0
  58. data/test/test_rant_interface.rb +65 -0
  59. data/test/test_sys.rb +61 -0
  60. data/test/test_task.rb +115 -0
  61. data/test/toplevel.rf +11 -0
  62. data/test/ts_all.rb +4 -0
  63. data/test/tutil.rb +95 -0
  64. metadata +133 -0
data/lib/rant.rb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rant/rantlib'
4
+
5
+ include Rant
6
+
7
+ if $0 == __FILE__
8
+ exit Rant.run
9
+ end
@@ -0,0 +1,334 @@
1
+
2
+ require 'rant/rantenv'
3
+
4
+ module Rant
5
+ # An object extending this module acts as an
6
+ # interface to a C# Compiler.
7
+ class CsCompiler
8
+
9
+ LIB_SYSTEM_XML = "System.Xml.dll"
10
+ LIB_SYSTEM_DRAWING = "System.Drawing.dll"
11
+ LIB_SYSTEM_FORMS = "System.Windows.Forms.dll"
12
+
13
+ class << self
14
+ # Get the short name for the compiler referenced by this path.
15
+ def cs_compiler_name(path)
16
+ case path
17
+ when /csc(\.exe)?$/i
18
+ "csc"
19
+ when /cscc(\.exe)?$/i
20
+ "cscc"
21
+ when /mcs(\.exe)?$/i
22
+ "mcs"
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ # Search for a C# compiler in PATH and some
29
+ # usual locations.
30
+ def look_for_cs_compiler
31
+ csc_bin = nil
32
+ if Env.on_windows?
33
+ csc_bin = "csc" if Env.find_bin "csc"
34
+ unless csc_bin
35
+ csc_bin = look_for_csc
36
+ end
37
+ end
38
+ csc_bin = "cscc" if !csc_bin && Env.find_bin("cscc")
39
+ csc_bin = "mcs" if !csc_bin && Env.find_bin("mcs")
40
+ csc_bin
41
+ end
42
+
43
+ # Searches for csc in some usual directories.
44
+ # Ment to be used on windows only!
45
+ def look_for_csc
46
+ # Is there a way to get a list of all available
47
+ # drives?
48
+ ("C".."Z").each { |drive|
49
+ ["WINDOWS", "WINNT"].each { |win_dir|
50
+ frame_dir = drive + ':\\' + win_dir +
51
+ '\Microsoft.NET\Framework'
52
+ next unless test(?d,frame_dir)
53
+ csc_pathes = []
54
+ Dir.entries(frame_dir).each { |e|
55
+ vdir = File.join(frame_dir, e)
56
+ if test(?d, vdir)
57
+ csc_path = File.join(vdir, "csc.exe")
58
+ if test(?e,csc_path)
59
+ csc_pathes << csc_path
60
+ end
61
+ end
62
+ }
63
+ next if csc_pathes.empty?
64
+ return csc_pathes.sort.last
65
+ }
66
+ }
67
+ nil
68
+ rescue
69
+ nil
70
+ end
71
+ end
72
+
73
+ # Short name for compiler, such as "csc", "cscc" or "mcs".
74
+ attr_reader :csc_name
75
+ # Descriptive name for compiler.
76
+ attr_reader :long_name
77
+ # Compiler path, or cmd on PATH
78
+ # Look also at the #csc and #csc= methods. Most times they do
79
+ # what you need.
80
+ attr_accessor :csc_bin
81
+ # Debug flag.
82
+ attr_accessor :debug
83
+ # Target filename.
84
+ attr_accessor :out
85
+ # Libraries to link angainst (usually dlls).
86
+ attr_accessor :libs
87
+ # Preprocessor defines.
88
+ attr_reader :defines
89
+ # Other args, could be options.
90
+ # Initialized to an empty array.
91
+ attr_accessor :misc_args
92
+ # Hash with compiler specific arguments.
93
+ attr_accessor :specific_args
94
+ # Sourcefiles.
95
+ attr_accessor :sources
96
+ # Resources to embedd in assembly.
97
+ attr_accessor :resources
98
+ # Library link pathes.
99
+ attr_reader :lib_link_pathes
100
+ # Entry point for executable.
101
+ attr_accessor :entry
102
+ # Optimize, defaults to true
103
+ attr_accessor :optimize
104
+ # Enable compiler warnings, defaults to true
105
+ attr_accessor :warnings
106
+
107
+ def initialize(compiler_name=nil)
108
+ self.csc_name = (compiler_name || "cscc")
109
+ @long_name = "C# Compiler"
110
+ @defines = []
111
+ @libs = []
112
+ @sources = nil
113
+ @misc_args = []
114
+ @specific_args = {
115
+ "cscc" => [],
116
+ "csc" => [],
117
+ "mcs" => [],
118
+ }
119
+ @resources = []
120
+ @debug = false
121
+ @out = "a.out"
122
+ @lib_link_pathes = []
123
+ @entry = nil
124
+ @optimize = true
125
+ @warnings = true
126
+ @csc = nil
127
+ @csc_bin = nil
128
+ end
129
+
130
+ # Command to invoke compiler.
131
+ def csc
132
+ @csc_bin || @csc_name
133
+ end
134
+
135
+ # Set this to command to invoke your compiler. Contrary to
136
+ # +cc_bin+, this also tries to determine which interface to
137
+ # use for this compiler. Finally it sets +cc_bin+.
138
+ def csc=(cmd)
139
+ name = self.class.cs_compiler_name(cmd)
140
+ @csc_name = name if name
141
+ @csc_bin = cmd
142
+ end
143
+
144
+ def csc_name= new_name
145
+ unless ["cscc", "csc", "mcs"].include?(new_name)
146
+ raise "Unsupported C# compiler `#{new_name}'"
147
+ end
148
+ @csc_name = new_name
149
+ @long_name = case @csc_name
150
+ when "cscc": "DotGNU C# compiler"
151
+ when "csc": "MS Visual.NET C# compiler"
152
+ when "mcs": "Mono C# compiler"
153
+ end
154
+ end
155
+
156
+ # Shortcut for +specific_args+.
157
+ def sargs
158
+ @specific_args
159
+ end
160
+
161
+ # Generate compilation command for executable.
162
+ def cmd_exe
163
+ send @csc_name + "_cmd_exe"
164
+ end
165
+
166
+ def cscc_cmd_exe
167
+ # This generates the compilation command
168
+ # for cscc.
169
+ cc_cmd = csc.dup
170
+ cc_cmd << " -e#{entry}" if entry
171
+ cc_cmd << cc_cmd_args
172
+ cc_cmd
173
+ end
174
+
175
+ def csc_cmd_exe
176
+ # This generates the compilation command
177
+ # for csc.
178
+ cc_cmd = csc.dup
179
+ # Use target:winexe only if not debugging,
180
+ # because this will suppress a background console window.
181
+ cc_cmd << " /target:winexe" unless debug
182
+ cc_cmd << " /main:#{entry}" if entry
183
+ cc_cmd << cc_cmd_args
184
+ cc_cmd
185
+ end
186
+
187
+ def mcs_cmd_exe
188
+ # Generate compilation command for mcs.
189
+ cc_cmd = csc.dup
190
+ cc_cmd << " -target:exe"
191
+ cc_cmd << " -main:#{entry}" if entry
192
+ cc_cmd << cc_cmd_args
193
+ cc_cmd
194
+ end
195
+
196
+ # Generate command for DLL.
197
+ def cmd_dll
198
+ send @csc_name + "_cmd_dll"
199
+ end
200
+
201
+ def cscc_cmd_dll
202
+ cc_cmd = csc.dup
203
+ cc_cmd << " -shared"
204
+ cc_cmd << cc_cmd_args
205
+ cc_cmd
206
+ end
207
+
208
+ def csc_cmd_dll
209
+ cc_cmd = csc.dup
210
+ cc_cmd << " /target:library"
211
+ cc_cmd << cc_cmd_args
212
+ cc_cmd
213
+ end
214
+
215
+ def mcs_cmd_dll
216
+ cc_cmd = csc.dup
217
+ cc_cmd << " -target:library"
218
+ cc_cmd << cc_cmd_args
219
+ cc_cmd
220
+ end
221
+
222
+ # Generate command for object file.
223
+ def cmd_object
224
+ send @csc_name + "_cmd_object"
225
+ end
226
+
227
+ def cscc_cmd_object
228
+ cc_cmd = csc.dup
229
+ cc_cmd << " -c"
230
+ cc_cmd << cc_cmd_args
231
+ cc_cmd
232
+ end
233
+
234
+ def csc_cmd_object
235
+ cc_cmd = csc.dup
236
+ cc_cmd << " /target:module"
237
+ cc_cmd << cc_cmd_args
238
+ cc_cmd
239
+ end
240
+
241
+ def mcs_cmd_object
242
+ cc_cmd = csc.dup
243
+ cc_cmd << " -target:module"
244
+ cc_cmd << cc_cmd_args
245
+ cc_cmd
246
+ end
247
+
248
+ def to_s
249
+ csc + "\n" + "Interface: " + csc_name
250
+ end
251
+
252
+ private
253
+ def cc_cmd_args
254
+ send @csc_name + "_cmd_args"
255
+ end
256
+
257
+ def cscc_cmd_args
258
+ cc_args = ""
259
+ cc_args << " -o #{out}" if out
260
+ cc_args << " -g -DDEBUG" if debug
261
+ defines.each { |p|
262
+ cc_args << " -D#{p}"
263
+ }
264
+ cc_args << " -Wall" if warnings
265
+ cc_args << " -O2" if optimize
266
+ lib_link_pathes.each { |p|
267
+ cc_args << " -L #{Env.shell_path(p)}"
268
+ }
269
+ libs.each { |p|
270
+ cc_args << " -l #{Env.shell_path(p)}"
271
+ }
272
+ cc_args << " " << misc_args.join(' ') if misc_args
273
+ sargs = specific_args["cscc"]
274
+ cc_args << " " << sargs.join(' ') if sargs
275
+ resources.each { |p|
276
+ cc_args << " -fresources=#{Env.shell_path(p)}"
277
+ }
278
+ cc_args << " " << sources.arglist if sources
279
+ cc_args
280
+ end
281
+
282
+ def csc_cmd_args
283
+ cc_args = ""
284
+ cc_args << " /out:#{Env.shell_path(out)}" if out
285
+ cc_args << " /debug /d:DEBUG" if debug
286
+ defines.each { |p|
287
+ cc_args << " /d:#{p}"
288
+ }
289
+ cc_args << " /optimize" if optimize
290
+ # TODO: cc_args << " -Wall" if warnings
291
+ lib_link_pathes.each { |p|
292
+ #TODO: cc_args << " -L #{p}"
293
+ }
294
+ libs.each { |p|
295
+ cc_args << " /r:#{Env.shell_path(p)}"
296
+ }
297
+ cc_args << " " << misc_args.join(' ') if misc_args
298
+ sargs = specific_args["csc"]
299
+ cc_args << " " << sargs.join(' ') if sargs
300
+ resources.each { |p|
301
+ cc_args << " /res:#{Env.shell_path(p)}"
302
+ }
303
+ cc_args << " " << sources.arglist if sources
304
+ cc_args
305
+ end
306
+
307
+ def mcs_cmd_args
308
+ cc_args = ""
309
+ cc_args << " -o #{Env.shell_path(out)}" if out
310
+ cc_args << " -g -d:DEBUG" if debug
311
+ defines.each { |p|
312
+ cc_args << " -d:#{p}"
313
+ }
314
+ cc_args << " -optimize" if optimize
315
+ # Warning level for mcs: highest 4, default 2
316
+ cc_args << " -warn:4" if warnings
317
+ lib_link_pathes.each { |p|
318
+ cc_args << " -L #{Env.shell_path(p)}"
319
+ }
320
+ if libs && !libs.empty?
321
+ cc_args << " -r:" + (libs.collect { |p| Env.shell_path(p) }).join(',')
322
+ end
323
+ cc_args << " " << misc_args.join(' ') if misc_args
324
+ sargs = specific_args["mcs"]
325
+ cc_args << " " << sargs.join(' ') if sargs
326
+ resources.each { |p|
327
+ cc_args << " -resource:#{Env.shell_path(p)}"
328
+ }
329
+ cc_args << " " << sources.arglist if sources
330
+ cc_args
331
+ end
332
+
333
+ end # class CsCompiler
334
+ end # module Rant
@@ -0,0 +1,291 @@
1
+
2
+ # import.rb - Library for the rant-import command.
3
+ #
4
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
5
+
6
+ require 'getoptlong'
7
+ require 'rant/rantlib'
8
+
9
+ module Rant
10
+
11
+ class RantImportDoneException < RantDoneException
12
+ end
13
+
14
+ class RantImportAbortException < RantAbortException
15
+ end
16
+
17
+ # This class is the implementation for the rant-import command.
18
+ # Usage similar to RantApp class.
19
+ class RantImport
20
+ include Rant::Console
21
+
22
+ # TODO: We currently only look for imports and plugins
23
+ # relative to this LIB_DIR. We should also look in all pathes
24
+ # in $LOAD_PATH after looking in LIB_DIR.
25
+ LIB_DIR = File.expand_path(File.dirname(__FILE__))
26
+
27
+ OPTIONS = [
28
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT,
29
+ "Print this help and exit." ],
30
+ [ "--version", "-v", GetoptLong::NO_ARGUMENT,
31
+ "Print version of rant-import and exit." ],
32
+ [ "--plugins", "-p", GetoptLong::REQUIRED_ARGUMENT,
33
+ "Include PLUGINS (comma separated list)." ],
34
+ [ "--imports", "-i", GetoptLong::REQUIRED_ARGUMENT,
35
+ "Include IMPORTS (coma separated list)." ],
36
+ [ "--force", GetoptLong::NO_ARGUMENT,
37
+ "Force overwriting of output file." ],
38
+ [ "--with-comments", GetoptLong::NO_ARGUMENT,
39
+ "Include comments from Rant sources." ],
40
+ [ "--reduce-whitespace", "-r",GetoptLong::NO_ARGUMENT,
41
+ "Remove as much whitespace from Rant sources as possible." ],
42
+ [ "--auto", "-a", GetoptLong::NO_ARGUMENT,
43
+ "Automatically try to determine imports and plugins.\n" +
44
+ "Warning: loads Rantfile!" ],
45
+ [ "--rantfile", "-f", GetoptLong::REQUIRED_ARGUMENT,
46
+ "Load RANTFILE. This also sets --auto!\n" +
47
+ "May be given multiple times." ],
48
+ ]
49
+
50
+ class << self
51
+ def run(first_arg=nil, *other_args)
52
+ other_args = other_args.flatten
53
+ args = first_arg.nil? ? ARGV.dup : ([first_arg] + other_args)
54
+ new(args).run
55
+ end
56
+ end
57
+
58
+ # Arguments, usually those given on commandline.
59
+ attr :args
60
+ # Plugins to import.
61
+ attr :plugins
62
+ # Imports to import ;)
63
+ attr :imports
64
+ # Filename where the monolithic rant script goes to.
65
+ attr :mono_fn
66
+ # Skip comments? Defaults to true.
67
+ attr_accessor :skip_comments
68
+ # Remove whitespace from Rant sources? Defaults to false.
69
+ attr_accessor :reduce_whitespace
70
+ # Try automatic determination of imports and plugins?
71
+ # Defaults to false.
72
+ attr_accessor :auto
73
+
74
+ def initialize(*args)
75
+ @args = args.flatten
76
+ @msg_prefix = "rant-import: "
77
+ @plugins = []
78
+ @imports = []
79
+ @mono_fn = nil
80
+ @force = false
81
+ @rantapp = nil
82
+ @core_imports = []
83
+ @included_plugins = []
84
+ @included_imports = []
85
+ @skip_comments = true
86
+ @reduce_whitespace = false
87
+ @auto = false
88
+ @arg_rantfiles = []
89
+ end
90
+
91
+ def run
92
+ process_args
93
+
94
+ if @auto
95
+ @rantapp = RantApp.new(
96
+ %w(-v --stop-after-load) +
97
+ @arg_rantfiles.collect { |rf| "-f#{rf}" }
98
+ )
99
+ unless @rantapp.run == 0
100
+ abort("Auto-determination of required code failed.")
101
+ end
102
+ @imports.concat(@rantapp.imports)
103
+ @plugins.concat(@rantapp.plugins.map { |p| p.name })
104
+ end
105
+
106
+ if File.exist?(@mono_fn) && !@force
107
+ abort("#{@mono_fn} exists. Rant won't overwrite this file.",
108
+ "Add --force to override this restriction.")
109
+ end
110
+ File.open(@mono_fn, "w") { |mf|
111
+ mf << <<EOH
112
+ #!/usr/bin/env ruby
113
+
114
+ # #@mono_fn - Monolithic rant script, autogenerated by rant-import.
115
+ #
116
+ # Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
117
+ #
118
+ # This program is free software.
119
+ # You can distribute/modify this program under the terms of
120
+ # the GNU LGPL, Lesser General Public License version 2.1.
121
+ EOH
122
+ mf << mono_rant_core
123
+ mf << mono_imports
124
+ mf << mono_plugins
125
+ mf << <<EOF
126
+
127
+ Rant::CODE_IMPORTS.concat %w(#{@included_imports.join(' ')}
128
+ #{(@included_plugins.map do |i| "plugin/" + i end).join(' ')})
129
+
130
+ # Catch a `require "rant"', sad...
131
+ alias require_backup_by_rant require
132
+ def require libf
133
+ if libf == "rant"
134
+ self.class.instance_eval { include Rant }
135
+ else
136
+ begin
137
+ require_backup_by_rant libf
138
+ rescue
139
+ raise $!, caller
140
+ end
141
+ end
142
+ end
143
+
144
+ Rant.run
145
+ EOF
146
+ }
147
+ msg "Done.",
148
+ "Included imports: " + @included_imports.join(', '),
149
+ "Included plugins: " + @included_plugins.join(', '),
150
+ "Your monolithic rant was written to `#@mono_fn'!"
151
+
152
+ done
153
+ rescue RantImportDoneException
154
+ 0
155
+ rescue RantImportAbortException
156
+ $stderr.puts "rant-import aborted!"
157
+ 1
158
+ end
159
+
160
+ def process_args
161
+ # WARNING: we currently have to fool getoptlong,
162
+ # by temporory changing ARGV!
163
+ # This could cause problems.
164
+ old_argv = ARGV.dup
165
+ ARGV.replace(@args.dup)
166
+ cmd_opts = GetoptLong.new(*OPTIONS.collect { |lst| lst[0..-2] })
167
+ cmd_opts.quiet = true
168
+ cmd_opts.each { |opt, value|
169
+ case opt
170
+ when "--version"
171
+ puts "rant-import #{Rant::VERSION}"
172
+ done
173
+ when "--help": help
174
+ when "--force": @force = true
175
+ when "--with-comments": @skip_comments = false
176
+ when "--reduce-whitespace": @reduce_whitespace = true
177
+ when "--imports"
178
+ @imports.concat(value.split(/\s*,\s*/))
179
+ when "--plugins"
180
+ @plugins.concat(value.split(/\s*,\s*/))
181
+ when "--auto"
182
+ @auto = true
183
+ when "--rantfile"
184
+ @auto = true
185
+ @arg_rantfiles << value.dup
186
+ end
187
+ }
188
+ rem_args = ARGV.dup
189
+ unless rem_args.size == 1 && !@mono_fn
190
+ abort("Exactly one argument (besides options) required.",
191
+ "Type `rant-import --help' for usage.")
192
+ end
193
+ @mono_fn = rem_args.first if rem_args.first
194
+ rescue GetoptLong::Error => e
195
+ abort(e.message)
196
+ ensure
197
+ ARGV.replace(old_argv)
198
+ end
199
+
200
+ def done
201
+ raise RantImportDoneException
202
+ end
203
+
204
+ def help
205
+ puts "rant-import [OPTIONS] [-i IMPORT1,IMPORT2,...] [-p PLUGIN1,PLUGIN2...] MONO_RANT"
206
+ puts
207
+ puts " Write a monolithic rant script to MONO_RANT."
208
+ puts
209
+ puts "Options are:"
210
+ print option_listing(OPTIONS)
211
+ done
212
+ end
213
+
214
+ def abort(*text)
215
+ err_msg(*text) unless text.empty?
216
+ raise RantImportAbortException
217
+ end
218
+
219
+ # Get a monolithic rant script (as string) containing only the
220
+ # Rant core.
221
+ def mono_rant_core
222
+ # Starting point is rant/rantlib.rb.
223
+ rantlib_f = File.join(LIB_DIR, "rantlib.rb")
224
+ begin
225
+ rantlib = File.read rantlib_f
226
+ rescue
227
+ abort("When trying to read `#{rantlib_f}': #$!",
228
+ "This file should contains the core of rant, so import is impossible.",
229
+ "Please check your rant installation!")
230
+ end
231
+ @core_imports << "rantlib"
232
+ resolve_requires rantlib
233
+ end
234
+
235
+ def mono_imports
236
+ rs = ""
237
+ @imports.each { |name|
238
+ next if @included_imports.include? name
239
+ path = File.join(LIB_DIR, "import", "#{name}.rb")
240
+ unless File.exist? path
241
+ abort("No such import - #{name}")
242
+ end
243
+ msg "Including import `#{name}'", path
244
+ @included_imports << name.dup
245
+ rs << resolve_requires(File.read(path))
246
+ }
247
+ rs
248
+ end
249
+
250
+ def mono_plugins
251
+ rs = ""
252
+ @plugins.each { |name|
253
+ lc_name = name.downcase
254
+ next if @included_plugins.include? lc_name
255
+ path = File.join(LIB_DIR, "plugin", "#{lc_name}.rb")
256
+ unless File.exist? path
257
+ abort("No such plugin - #{name}")
258
+ end
259
+ msg "Including plugin `#{lc_name}'", path
260
+ @included_plugins << lc_name
261
+ rs << resolve_requires(File.read(path))
262
+ }
263
+ rs
264
+ end
265
+
266
+ # +script+ is a string. This method resolves requires of rant/
267
+ # code by directly inserting the code.
268
+ def resolve_requires script
269
+ rs = ""
270
+ script.each { |line|
271
+ # skip shebang line
272
+ next if line =~ /^#! ?(\/|\\)?\w/
273
+ # skip pure comment lines
274
+ next if line =~ /^\s*#/ if @skip_comments
275
+ if line =~ /\s*(require|load)\s+('|")rant\/(\w+)(\.rb)?('|")/
276
+ name = $3
277
+ next if @core_imports.include? name
278
+ path = File.join(LIB_DIR, "#{name}.rb")
279
+ msg "Including `#{name}'", path
280
+ @core_imports << name
281
+ rs << resolve_requires(File.read(path))
282
+ else
283
+ line.sub!(/^\s+/, '') if @reduce_whitespace
284
+ rs << line
285
+ end
286
+ }
287
+ rs
288
+ end
289
+
290
+ end # class RantImport
291
+ end # module Rant