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.
- data/COPYING +504 -0
- data/README +203 -0
- data/Rantfile +104 -0
- data/TODO +19 -0
- data/bin/rant +12 -0
- data/bin/rant-import +12 -0
- data/devel-notes +50 -0
- data/doc/configure.rdoc +40 -0
- data/doc/csharp.rdoc +74 -0
- data/doc/rant-import.rdoc +32 -0
- data/doc/rant.rdoc +24 -0
- data/doc/rantfile.rdoc +227 -0
- data/doc/rubyproject.rdoc +210 -0
- data/lib/rant.rb +9 -0
- data/lib/rant/cs_compiler.rb +334 -0
- data/lib/rant/import.rb +291 -0
- data/lib/rant/import/rubydoc.rb +125 -0
- data/lib/rant/import/rubypackage.rb +417 -0
- data/lib/rant/import/rubytest.rb +97 -0
- data/lib/rant/plugin/README +50 -0
- data/lib/rant/plugin/configure.rb +345 -0
- data/lib/rant/plugin/csharp.rb +275 -0
- data/lib/rant/plugin_methods.rb +41 -0
- data/lib/rant/rantenv.rb +217 -0
- data/lib/rant/rantfile.rb +664 -0
- data/lib/rant/rantlib.rb +1118 -0
- data/lib/rant/rantsys.rb +258 -0
- data/lib/rant/rantvar.rb +82 -0
- data/rantmethods.rb +79 -0
- data/run_import +7 -0
- data/run_rant +7 -0
- data/setup.rb +1360 -0
- data/test/Rantfile +2 -0
- data/test/plugin/configure/Rantfile +47 -0
- data/test/plugin/configure/test_configure.rb +58 -0
- data/test/plugin/csharp/Hello.cs +10 -0
- data/test/plugin/csharp/Rantfile +30 -0
- data/test/plugin/csharp/src/A.cs +8 -0
- data/test/plugin/csharp/src/B.cs +8 -0
- data/test/plugin/csharp/test_csharp.rb +99 -0
- data/test/project1/Rantfile +127 -0
- data/test/project1/test_project.rb +203 -0
- data/test/project2/buildfile +14 -0
- data/test/project2/rantfile.rb +20 -0
- data/test/project2/sub1/Rantfile +12 -0
- data/test/project2/test_project.rb +87 -0
- data/test/project_rb1/README +14 -0
- data/test/project_rb1/bin/wgrep +5 -0
- data/test/project_rb1/lib/wgrep.rb +56 -0
- data/test/project_rb1/rantfile.rb +30 -0
- data/test/project_rb1/test/tc_wgrep.rb +21 -0
- data/test/project_rb1/test/text +3 -0
- data/test/project_rb1/test_project_rb1.rb +153 -0
- data/test/test_env.rb +47 -0
- data/test/test_filetask.rb +57 -0
- data/test/test_lighttask.rb +49 -0
- data/test/test_metatask.rb +29 -0
- data/test/test_rant_interface.rb +65 -0
- data/test/test_sys.rb +61 -0
- data/test/test_task.rb +115 -0
- data/test/toplevel.rf +11 -0
- data/test/ts_all.rb +4 -0
- data/test/tutil.rb +95 -0
- metadata +133 -0
data/lib/rant.rb
ADDED
@@ -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
|
data/lib/rant/import.rb
ADDED
@@ -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
|