rVM 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,332 @@
1
+ # = PluginHost
2
+ #
3
+ # $Id: plugin.rb 69 2006-07-11 06:00:20Z murphy $
4
+ #
5
+ # A simple subclass plugin system.
6
+ #
7
+ # Example:
8
+ # class Generators < PluginHost
9
+ # plugin_path 'app/generators'
10
+ # end
11
+ #
12
+ # class Generator
13
+ # extend Plugin
14
+ # PLUGIN_HOST = Generators
15
+ # end
16
+ #
17
+ # class FancyGenerator < Generator
18
+ # register_for :fancy
19
+ # end
20
+ #
21
+ # Generators[:fancy] #-> FancyGenerator
22
+ # # or
23
+ # require_plugin 'Generators/fancy'
24
+ #
25
+ # Thanks a lot to Murphy, this code is borrowed from coderay.
26
+ #
27
+ module PluginHost
28
+
29
+ # Raised if Encoders::[] fails because:
30
+ # * a file could not be found
31
+ # * the requested Encoder is not registered
32
+ PluginNotFound = Class.new Exception
33
+ HostNotFound = Class.new Exception
34
+
35
+ PLUGIN_HOSTS = []
36
+ PLUGIN_HOSTS_BY_ID = {} # dummy hash
37
+
38
+ # Loads all plugins using all_plugin_names and load.
39
+ def load_all
40
+ for plugin in all_plugin_names
41
+ load plugin
42
+ end
43
+ end
44
+
45
+ # Returns the Plugin for +id+.
46
+ #
47
+ # Example:
48
+ # yaml_plugin = MyPluginHost[:yaml]
49
+ def [] id, *args, &blk
50
+ plugin = validate_id(id)
51
+ begin
52
+ plugin = plugin_hash.[] plugin, *args, &blk
53
+ end while plugin.is_a? Symbol
54
+ plugin
55
+ end
56
+
57
+ # Alias for +[]+.
58
+ alias load []
59
+
60
+ def require_helper plugin_id, helper_name
61
+ path = path_to File.join(plugin_id, helper_name)
62
+ require path
63
+ end
64
+
65
+ class << self
66
+
67
+ # Adds the module/class to the PLUGIN_HOSTS list.
68
+ def extended mod
69
+ PLUGIN_HOSTS << mod
70
+ end
71
+
72
+ # Warns you that you should not #include this module.
73
+ def included mod
74
+ warn "#{name} should not be included. Use extend."
75
+ end
76
+
77
+ # Find the PluginHost for host_id.
78
+ def host_by_id host_id
79
+ unless PLUGIN_HOSTS_BY_ID.default_proc
80
+ ph = Hash.new do |h, a_host_id|
81
+ for host in PLUGIN_HOSTS
82
+ h[host.host_id] = host
83
+ end
84
+ h.fetch a_host_id, nil
85
+ end
86
+ PLUGIN_HOSTS_BY_ID.replace ph
87
+ end
88
+ PLUGIN_HOSTS_BY_ID[host_id]
89
+ end
90
+
91
+ end
92
+
93
+ # The path where the plugins can be found.
94
+ def plugin_path *args
95
+ unless args.empty?
96
+ @plugin_path = File.expand_path File.join(*args)
97
+ load_map
98
+ end
99
+ @plugin_path
100
+ end
101
+
102
+ # The host's ID.
103
+ #
104
+ # If PLUGIN_HOST_ID is not set, it is simply the class name.
105
+ def host_id
106
+ if self.const_defined? :PLUGIN_HOST_ID
107
+ self::PLUGIN_HOST_ID
108
+ else
109
+ name
110
+ end
111
+ end
112
+
113
+ # Map a plugin_id to another.
114
+ #
115
+ # Usage: Put this in a file plugin_path/_map.rb.
116
+ #
117
+ # class MyColorHost < PluginHost
118
+ # map :navy => :dark_blue,
119
+ # :maroon => :brown,
120
+ # :luna => :moon
121
+ # end
122
+ def map hash
123
+ for from, to in hash
124
+ from = validate_id from
125
+ to = validate_id to
126
+ plugin_hash[from] = to unless plugin_hash.has_key? from
127
+ end
128
+ end
129
+
130
+ # Define the default plugin to use when no plugin is found
131
+ # for a given id.
132
+ #
133
+ # See also map.
134
+ #
135
+ # class MyColorHost < PluginHost
136
+ # map :navy => :dark_blue
137
+ # default :gray
138
+ # end
139
+ def default id
140
+ id = validate_id id
141
+ plugin_hash[nil] = id
142
+ end
143
+
144
+ # Every plugin must register itself for one or more
145
+ # +ids+ by calling register_for, which calls this method.
146
+ #
147
+ # See Plugin#register_for.
148
+ def register plugin, *ids
149
+ for id in ids
150
+ unless id.is_a? Symbol
151
+ raise ArgumentError,
152
+ "id must be a Symbol, but it was a #{id.class}"
153
+ end
154
+ plugin_hash[validate_id(id)] = plugin
155
+ end
156
+ end
157
+
158
+ # A Hash of plugion_id => Plugin pairs.
159
+ def plugin_hash
160
+ @plugin_hash ||= create_plugin_hash
161
+ end
162
+
163
+ def has? id
164
+ plugin_hash.include? id
165
+ end
166
+ # Returns an array of all .rb files in the plugin path.
167
+ #
168
+ # The extension .rb is not included.
169
+ def all_plugin_names
170
+ Dir[path_to('*')].select do |file|
171
+ File.basename(file)[/^(?!_)\w+\.rb$/]
172
+ end.map do |file|
173
+ File.basename file, '.rb'
174
+ end
175
+ end
176
+
177
+ # Makes a map of all loaded plugins.
178
+ def inspect
179
+ map = plugin_hash.dup
180
+ map.each do |id, plugin|
181
+ map[id] = plugin.to_s[/(?>[\w_]+)$/]
182
+ end
183
+ "#{name}[#{host_id}]#{map.inspect}"
184
+ end
185
+
186
+ protected
187
+ # Created a new plugin list and stores it to @plugin_hash.
188
+ def create_plugin_hash
189
+ @plugin_hash =
190
+ Hash.new do |h, plugin_id|
191
+ id = validate_id(plugin_id)
192
+ path = Dir[File.join(plugin_path, "#{plugin_id}.rb")].first || path_to(id)
193
+ begin
194
+ require path
195
+ rescue LoadError => boom
196
+ if h.has_key? nil # default plugin
197
+ h[id] = h[nil]
198
+ else
199
+ raise PluginNotFound, 'Could not load plugin %p: %s' % [id, boom]
200
+ end
201
+ else
202
+ # Plugin should have registered by now
203
+ unless h.has_key? id
204
+ raise PluginNotFound,
205
+ "No #{self.name} plugin for #{id.inspect} found in #{path}."
206
+ end
207
+ end
208
+ h[id]
209
+ end
210
+ end
211
+
212
+ # Loads the map file (see map).
213
+ #
214
+ # This is done automatically when plugin_path is called.
215
+ def load_map
216
+ mapfile = path_to '_map'
217
+ if File.exist? mapfile
218
+ require mapfile
219
+ elsif $DEBUG
220
+ warn 'no _map.rb found for %s' % name
221
+ end
222
+ end
223
+
224
+ # Returns the Plugin for +id+.
225
+ # Use it like Hash#fetch.
226
+ #
227
+ # Example:
228
+ # yaml_plugin = MyPluginHost[:yaml, :default]
229
+ def fetch id, *args, &blk
230
+ plugin_hash.fetch validate_id(id), *args, &blk
231
+ end
232
+
233
+ # Returns the expected path to the plugin file for the given id.
234
+ def path_to plugin_id
235
+ File.join(plugin_path, "#{plugin_id}.rb")
236
+ end
237
+
238
+ # Converts +id+ to a Symbol if it is a String,
239
+ # or returns +id+ if it already is a Symbol.
240
+ #
241
+ # Raises +ArgumentError+ for all other objects, or if the
242
+ # given String includes non-alphanumeric characters (\W).
243
+ def validate_id id
244
+ if id.is_a? Symbol or id.nil?
245
+ id
246
+ elsif id.is_a? String
247
+ if id[/\w+/] == id
248
+ id.to_sym
249
+ else
250
+ raise ArgumentError, "Invalid id: '#{id}' given."
251
+ end
252
+ else
253
+ raise ArgumentError,
254
+ "String or Symbol expected, but #{id.class} given."
255
+ end
256
+ end
257
+
258
+ end
259
+
260
+
261
+ # = Plugin
262
+ #
263
+ # Plugins have to include this module.
264
+ #
265
+ # IMPORTANT: use extend for this module.
266
+ #
267
+ # Example: see PluginHost.
268
+ module Plugin
269
+
270
+ def included mod
271
+ warn "#{name} should not be included. Use extend."
272
+ end
273
+
274
+ # Register this class for the given langs.
275
+ # Example:
276
+ # class MyPlugin < PluginHost::BaseClass
277
+ # register_for :my_id
278
+ # ...
279
+ # end
280
+ #
281
+ # See PluginHost.register.
282
+ def register_for *ids
283
+ plugin_host.register self, *ids
284
+ end
285
+
286
+ # The host for this Plugin class.
287
+ def plugin_host host = nil
288
+ if host and not host.is_a? PluginHost
289
+ raise ArgumentError,
290
+ "PluginHost expected, but #{host.class} given."
291
+ end
292
+ self.const_set :PLUGIN_HOST, host if host
293
+ self::PLUGIN_HOST
294
+ end
295
+
296
+ # Require some helper files.
297
+ #
298
+ # Example:
299
+ #
300
+ # class MyPlugin < PluginHost::BaseClass
301
+ # register_for :my_id
302
+ # helper :my_helper
303
+ #
304
+ # The above example loads the file myplugin/my_helper.rb relative to the
305
+ # file in which MyPlugin was defined.
306
+ def helper *helpers
307
+ for helper in helpers
308
+ self::PLUGIN_HOST.require_helper plugin_id, helper.to_s
309
+ end
310
+ end
311
+
312
+ # Returns the pulgin id used by the engine.
313
+ def plugin_id
314
+ name[/[\w_]+$/].downcase
315
+ end
316
+
317
+ end
318
+
319
+
320
+ # Convenience method for plugin loading.
321
+ # The syntax used is:
322
+ #
323
+ # require_plugin '<Host ID>/<Plugin ID>'
324
+ #
325
+ # Returns the loaded plugin.
326
+ def require_plugin path
327
+ host_id, plugin_id = path.split '/', 2
328
+ host = PluginHost.host_by_id(host_id)
329
+ raise PluginHost::HostNotFound,
330
+ "No host for #{host_id.inspect} found." unless host
331
+ host.load plugin_id
332
+ end
@@ -0,0 +1,26 @@
1
+ module RVM
2
+ module Classes
3
+ class Block < RVM::Classes::Class
4
+ attr_accessor :code
5
+ register_for :block
6
+ def initialize code
7
+ super()
8
+ @type = :any
9
+ @code = code
10
+ end
11
+
12
+ def execute env
13
+ end
14
+
15
+ def execargs
16
+ true
17
+ end
18
+
19
+ def call params, env
20
+ #Logger.debug "Calling Block...(#{env},#{params})" if $DEBUG
21
+ env = RVM::Interpreter::Enviroment.new({:params => params||[]}, env)
22
+ @code.execute env
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ module RVM
2
+ module Classes
3
+ class Boolean < RVM::Classes::Class
4
+ register_for :boolean
5
+ def data_type
6
+ :boolean
7
+ end
8
+
9
+ def initialize value
10
+ super()
11
+ if value
12
+ if value.respond_to? :is_true?
13
+ @value = value.is_true?
14
+ else
15
+ @value = true
16
+ end
17
+ else
18
+ @value = false
19
+ end
20
+ end
21
+
22
+ def is_true?
23
+ @value
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module RVM
2
+ module Classes
3
+ class Error < RVM::Classes::Class
4
+ register_for :error
5
+ attr_accessor :value
6
+ @@type = :error
7
+ def initialize value, text = "This is an error!"
8
+ super()
9
+ @value = value.to_i
10
+ @text = text
11
+ end
12
+
13
+ def is_true?
14
+ false
15
+ end
16
+
17
+ def to_s
18
+ "##{@value.abs * -1} #{@text}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ require 'lib/base/classes'
2
+ module RVM
3
+ module Classes
4
+ class List < Array
5
+ extend Plugin
6
+ plugin_host Classes
7
+ register_for :list
8
+ @@type = :list
9
+ attr_reader :sepperator
10
+
11
+ def data_type
12
+ :list
13
+ end
14
+
15
+ def initialize source= [], sepperator = ' '
16
+ super()
17
+ if source.is_a?(::String) # Okay we've to hack here to get sure we get the /real/ String
18
+ source = source.split sepperator
19
+ elsif !source.is_a?(Array)
20
+ source = [source]
21
+ end
22
+ self.concat source
23
+ @sepperator = sepperator.to_s
24
+ end
25
+
26
+ def resplit(sep)
27
+ sep = sep.to_s
28
+ if sep != @sepperator
29
+ t = self.join(@sepperator)
30
+ @sepperator = sep
31
+ self.clear
32
+ self.concat(t.split(sep))
33
+ end
34
+ end
35
+
36
+ def sepperator= sep
37
+ @sepperator = sep.to_s
38
+ end
39
+
40
+ def to_s
41
+ if @sepperator
42
+ map{|i| i.to_s}.join(@sepperator)
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,70 @@
1
+ module RVM
2
+ module Classes
3
+ class Number < Class
4
+ register_for :number
5
+ @@type = :number
6
+
7
+ def initialize value
8
+ super()
9
+ if value.is_a? Numeric
10
+ @value = value
11
+ elsif value.respond_to?(:to_f) and ((v = value.to_f) != value.to_i)
12
+ @value = v
13
+ elsif value.respond_to?(:to_i)
14
+ @value = value.to_i
15
+ else
16
+ @value = "#{value}".to_f
17
+ end
18
+ if @value.to_f == @value.to_i
19
+ @value = @value.to_i
20
+ end
21
+ end
22
+
23
+ def == v
24
+ @value == v
25
+ end
26
+
27
+ def to_s
28
+ @value.to_s
29
+ end
30
+
31
+ def to_i
32
+ @value.to_i
33
+ end
34
+
35
+ def to_f
36
+ @value.to_f
37
+ end
38
+
39
+ def is_true?
40
+ @value != 0
41
+ end
42
+
43
+ def value
44
+ @value
45
+ end
46
+
47
+ def respond_to?(symbol,include_private = false)
48
+ super(symbol,include_private)
49
+ end
50
+
51
+ alias method_missing_old_number method_missing
52
+ def method_missing m, *args
53
+ if @value.respond_to? m
54
+ args.map! do |a|
55
+ if a.is_a? Number
56
+ a.value
57
+ else
58
+ Number.new(a).value
59
+ end
60
+ end
61
+ r = @value.send(m,*args)
62
+ r = Number.new(r) if r.is_a? Numeric
63
+ r
64
+ else
65
+ method_missing_old_number m, *args
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,73 @@
1
+ module RVM
2
+ module Classes
3
+ class String <String
4
+ extend Plugin
5
+ plugin_host Classes
6
+ register_for :string
7
+ @@type = :string
8
+ ANSI_MAP = {
9
+ 'h' => 1, 'H' => 22,
10
+ 'u' => 4, 'U' => 24,
11
+ 'f' => 5, 'f' => 25,
12
+ 'i' => 7, 'I' => 27,
13
+ 'n' => 0,
14
+ 'x' => 30, 'X' => 40,
15
+ 'r' => 31, 'R' => 41,
16
+ 'g' => 32, 'G' => 42,
17
+ 'y' => 33, 'Y' => 42,
18
+ 'b' => 34, 'B' => 44,
19
+ 'm' => 35, 'M' => 45,
20
+ 'c' => 36, 'C' => 45,
21
+ 'w' => 37, 'W' => 47,
22
+ }
23
+ def initialize val = ""
24
+ super val.to_s
25
+ end
26
+
27
+ def is_true?
28
+ not empty?
29
+ end
30
+
31
+ def data_type
32
+ :string
33
+ end
34
+
35
+ def center width, char = " "
36
+ c = char[0..0]
37
+ c = ' ' if c.empty?
38
+ width = width.to_i - self.length
39
+ width = 0 if width < 0
40
+ l = width / 2
41
+ r = width - l
42
+ self.class.new((c*l) + self + (c*r))
43
+ end
44
+
45
+ def ljust width, char = " "
46
+ c = char[0..0]
47
+ c = ' ' if c.empty?
48
+ width = width.to_i - self.length
49
+ width = 0 if width < 0
50
+ self.class.new(self + (c*width))
51
+ end
52
+
53
+ def rjust width, char = " "
54
+ c = char[0..0]
55
+ c = ' ' if c.empty?
56
+ width = width.to_i - self.length
57
+ width = 0 if width < 0
58
+ self.class.new((c*width) + self)
59
+ end
60
+
61
+ def + v
62
+ self.class.new(super(v))
63
+ end
64
+
65
+ def ansi colorset
66
+ colorset.gsub!(/[^#{ANSI_MAP.keys.join('')}]/,'')
67
+ colorcode = colorset.split('').map { |c| ANSI_MAP[c].to_s}.join(';')
68
+ c = "\e[#{colorcode}m"
69
+ self.class.new("#{c}#{self.gsub("\e[0m",c)}\e[0m")
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,49 @@
1
+ module RVM
2
+ module Functions
3
+ class Align < Function
4
+ #TODO: Fix this
5
+ def Align.execute params, env
6
+ if params.length >=2
7
+ alignments = params.shift
8
+ alignments.map! { |i| i.to_i }
9
+ data = []
10
+ alignments.size.times do
11
+ data << params.shift || []
12
+ end
13
+
14
+ filler = params.shift || " "
15
+ filler = filler.to_s
16
+ colsep = params.shift || " "
17
+ colsep = colsep.to_s
18
+ rowsep = params.shift || "\n"
19
+ rowsep = rowsep.to_s
20
+ running = true
21
+ str = ""
22
+ while running
23
+ i = 0;
24
+ running = false
25
+ alignments.each do |arg|
26
+ running = (item = data[i].shift) || running
27
+ if arg > 0
28
+ str << ljust(item || "",arg,filler)
29
+ else
30
+ str << rjust(item || "",arg*-1,filler)
31
+ end
32
+ str << colsep
33
+ i =+ 1
34
+ end
35
+ str << rowsep
36
+ end
37
+ RVM::Classes[:string].new(str.gsub(/[\n\s]+$/,''))
38
+ else
39
+ RVM::Classes[:error].new(1,"#-1 FUNCTION (#{self.class.to_s}) EXPECTS 2 OR MORE ARGUMENTS BUT GOT #{params.length}")
40
+ end
41
+ end
42
+
43
+ def Align.signature
44
+ [:list]
45
+ end
46
+ register_for :align
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ module RVM
2
+ module Functions
3
+ class Join < Function
4
+ def Join.execute params, env
5
+ if params.length == 2
6
+ RVM::Classes[:string].new(params[0].join(params[1]))
7
+ else
8
+ RVM::Classes[:error].new(1,"#-1 FUNCTION (#{self.class.to_s}) EXPECTS 2 OR 3 ARGUMENTS BUT GOT #{params.length}")
9
+ end
10
+ end
11
+
12
+ def Join.signature
13
+ [:list, :string]
14
+ end
15
+ register_for :join
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module RVM
2
+ module Functions
3
+ class Map < Function
4
+ def Map.execute params, env
5
+ if params.length == 2
6
+ block = params[1]
7
+ i = 0
8
+ RVM::Classes[:list].new(params[0].map do |e|
9
+ e = block.call([e, RVM::Classes[:number].new(i)], env)
10
+ i += 1
11
+ e # needed to assure that the right value is returned
12
+ end,params[0].sepperator)
13
+ else
14
+ RVM::Classes[:error].new(1,"FUNCTION (#{self.class.to_s}) EXPECTS 2 ARGUMENTS BUT GOT #{params.length}")
15
+ end
16
+ end
17
+
18
+ def Map.signature
19
+ [:list, :block]
20
+ end
21
+ register_for :map
22
+ end
23
+ end
24
+ end