plist4r 0.2.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.yardopts +11 -0
- data/LICENSE +3 -1
- data/README.rdoc +25 -122
- data/Rakefile +14 -0
- data/VERSION +1 -1
- data/bin/plist4r +2 -0
- data/ext/osx_plist/Makefile +157 -0
- data/ext/osx_plist/extconf.rb +9 -0
- data/ext/osx_plist/plist.c +606 -0
- data/ext/osx_plist/plist.o +0 -0
- data/lib/plist4r.rb +6 -3
- data/lib/plist4r/application.rb +1 -2
- data/lib/plist4r/backend.rb +102 -34
- data/lib/plist4r/backend/c_f_property_list.rb +65 -0
- data/lib/plist4r/backend/c_f_property_list/LICENSE +19 -0
- data/lib/plist4r/backend/c_f_property_list/README +34 -0
- data/lib/plist4r/backend/c_f_property_list/cfpropertylist.rb +6 -0
- data/lib/plist4r/backend/c_f_property_list/rbBinaryCFPropertyList.rb +663 -0
- data/lib/plist4r/backend/c_f_property_list/rbCFPlistError.rb +26 -0
- data/lib/plist4r/backend/c_f_property_list/rbCFPropertyList.rb +348 -0
- data/lib/plist4r/backend/c_f_property_list/rbCFTypes.rb +241 -0
- data/lib/plist4r/backend/c_f_property_list/rbXMLCFPropertyList.rb +116 -0
- data/lib/plist4r/backend/example.rb +37 -52
- data/lib/plist4r/backend/haml.rb +47 -36
- data/lib/plist4r/backend/libxml4r.rb +24 -20
- data/lib/plist4r/backend/osx_plist.rb +82 -0
- data/lib/plist4r/backend/ruby_cocoa.rb +172 -54
- data/lib/plist4r/backend/test/data_types.rb +163 -0
- data/lib/plist4r/backend/test/harness.rb +255 -0
- data/lib/plist4r/backend/test/output.rb +47 -0
- data/lib/plist4r/backend_base.rb +4 -2
- data/lib/plist4r/{options.rb → cli.rb} +2 -1
- data/lib/plist4r/commands.rb +13 -8
- data/lib/plist4r/config.rb +36 -9
- data/lib/plist4r/docs/Backends.html +59 -0
- data/lib/plist4r/docs/DeveloperGuide.rdoc +53 -0
- data/lib/plist4r/docs/EditingPlistFiles.rdoc +88 -0
- data/lib/plist4r/docs/InfoPlistExample.rdoc +33 -0
- data/lib/plist4r/docs/LaunchdPlistExample.rdoc +33 -0
- data/lib/plist4r/docs/PlistKeyNames.rdoc +47 -0
- data/lib/plist4r/mixin/array_dict.rb +61 -0
- data/lib/plist4r/mixin/data_methods.rb +178 -54
- data/lib/plist4r/mixin/haml4r.rb +4 -0
- data/lib/plist4r/mixin/haml4r/css_attributes.rb +19 -0
- data/lib/plist4r/mixin/haml4r/examples.rb +261 -0
- data/lib/plist4r/mixin/haml4r/haml_table_example.rb +79 -0
- data/lib/plist4r/mixin/haml4r/table.rb +157 -0
- data/lib/plist4r/mixin/haml4r/table_cell.rb +160 -0
- data/lib/plist4r/mixin/haml4r/table_cells.rb +485 -0
- data/lib/plist4r/mixin/haml4r/table_section.rb +101 -0
- data/lib/plist4r/mixin/ordered_hash.rb +9 -1
- data/lib/plist4r/mixin/popen4.rb +1 -1
- data/lib/plist4r/mixin/ruby_stdlib.rb +154 -1
- data/lib/plist4r/mixin/script.rb +133 -0
- data/lib/plist4r/mixin/table.rb +435 -0
- data/lib/plist4r/plist.rb +272 -94
- data/lib/plist4r/plist_cache.rb +42 -43
- data/lib/plist4r/plist_type.rb +31 -74
- data/lib/plist4r/plist_type/info.rb +157 -3
- data/lib/plist4r/plist_type/launchd.rb +54 -48
- data/lib/plist4r/plist_type/plist.rb +1 -3
- data/plist4r.gemspec +74 -14
- data/spec/{examples.rb → launchd_examples.rb} +131 -139
- data/spec/plist4r/application_spec.rb +37 -0
- data/spec/plist4r/backend_spec.rb +256 -0
- data/spec/plist4r/cli_spec.rb +25 -0
- data/spec/plist4r/commands_spec.rb +20 -0
- data/spec/plist4r/config_spec.rb +38 -0
- data/spec/plist4r/mixin/array_dict_spec.rb +120 -0
- data/spec/plist4r/mixin/data_methods_spec.rb +96 -0
- data/spec/plist4r/mixin/haml4r/examples.rb +261 -0
- data/spec/plist4r/mixin/ruby_stdlib_spec.rb +228 -0
- data/spec/plist4r/plist_cache_spec.rb +261 -0
- data/spec/plist4r/plist_spec.rb +841 -23
- data/spec/plist4r/plist_type_spec.rb +126 -0
- data/spec/plist4r_spec.rb +53 -27
- data/spec/scratchpad.rb +226 -0
- data/spec/spec_helper.rb +5 -1
- metadata +109 -23
- data/lib/plist4r/backend/plutil.rb +0 -25
- data/lib/plist4r/mixin.rb +0 -7
- data/plists/array_mini.xml +0 -14
- data/plists/example_big_binary.plist +0 -0
- data/plists/example_medium_binary_launchd.plist +0 -0
- data/plists/example_medium_launchd.xml +0 -53
- data/plists/mini.xml +0 -12
- data/test.rb +0 -40
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
require 'plist4r/mixin/haml4r/table_cells'
|
3
|
+
|
4
|
+
module Haml4r
|
5
|
+
|
6
|
+
# A TableSection is a container object. Its responsibility is to forward messages to
|
7
|
+
# the TableCells instance object. TableSection also holds css attributes for that
|
8
|
+
# sub-section (if applicable, these will be applied to thead, and tbody html tags).
|
9
|
+
#
|
10
|
+
# The TableSection contains other instance objects.
|
11
|
+
#
|
12
|
+
# :----------------------------------------------------:
|
13
|
+
# | |
|
14
|
+
# | :--------------------------------------------: |
|
15
|
+
# | | | |
|
16
|
+
# | | :-------------------:------------------: | |
|
17
|
+
# | | | | | | |
|
18
|
+
# | | | | | | |
|
19
|
+
# | | | TableCell | TableCell | | |
|
20
|
+
# | | | | | | |
|
21
|
+
# | | | | | | |
|
22
|
+
# | | :-------------------:------------------: | |
|
23
|
+
# | | | | | | |
|
24
|
+
# | | | | | | |
|
25
|
+
# | | | TableCell | TableCell | | |
|
26
|
+
# | | | | | | |
|
27
|
+
# | | | | | | |
|
28
|
+
# | | :- @array ----------:------------------: | |
|
29
|
+
# | | TableCells | |
|
30
|
+
# | :- @cells -----------------------------------: |
|
31
|
+
# | TableSection |
|
32
|
+
# :----------------------------------------------------:
|
33
|
+
#
|
34
|
+
class TableSection
|
35
|
+
|
36
|
+
def haml
|
37
|
+
@haml ||= <<-'EOC'
|
38
|
+
%table
|
39
|
+
%tbody{:class => self.css_class, :id => self.css_id, :style => self.css_style}
|
40
|
+
- @cells.row_range.each do |row|
|
41
|
+
%tr
|
42
|
+
- @cells.col_range.each do |col|
|
43
|
+
- c = @cells.cell col, row
|
44
|
+
- unless c.spanee
|
45
|
+
%td{:class => c.css_class, :id => c.css_id, :style => c.css_style, :colspan => @cells.colspan(col,row), :rowspan => @cells.rowspan(col,row)} #{c.content}
|
46
|
+
EOC
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
require 'haml'
|
51
|
+
engine = ::Haml::Engine.new self.haml
|
52
|
+
rendered_html_output = engine.render self
|
53
|
+
end
|
54
|
+
|
55
|
+
Attributes = Haml4r::CssAttributes
|
56
|
+
|
57
|
+
def initialize *args, &blk
|
58
|
+
@cells ||= TableCells.new *args, &blk
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing method_sym, *args, &blk
|
62
|
+
if Attributes.include? method_sym.to_s.chomp('=')
|
63
|
+
set_or_return method_sym.to_s, *args, &blk
|
64
|
+
|
65
|
+
elsif @cells.respond_to? method_sym
|
66
|
+
@cells.send method_sym, *args, &blk
|
67
|
+
|
68
|
+
else
|
69
|
+
super
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def respond_to? method_sym
|
74
|
+
return true if Attributes.include? method_sym.to_s.chomp('=')
|
75
|
+
return true if @cells.respond_to? method_sym
|
76
|
+
super
|
77
|
+
end
|
78
|
+
|
79
|
+
def set attribute, value
|
80
|
+
eval "@#{attribute} = value"
|
81
|
+
end
|
82
|
+
|
83
|
+
def value_for attribute
|
84
|
+
eval "@#{attribute}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_or_return attribute, value=nil
|
88
|
+
case attribute
|
89
|
+
when /\=$/
|
90
|
+
set attribute.to_s.chomp('='), value
|
91
|
+
else
|
92
|
+
value_for attribute.to_s
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def inspect start_col=0
|
97
|
+
@cells.inspect start_col
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -6,8 +6,11 @@ module Plist4r
|
|
6
6
|
# {ActiveSupport::OrderedHash}
|
7
7
|
#
|
8
8
|
# Copyright (c) 2005 David Hansson,
|
9
|
+
#
|
9
10
|
# Copyright (c) 2007 Mauricio Fernandez, Sam Stephenson
|
11
|
+
#
|
10
12
|
# Copyright (c) 2008 Steve Purcell, Josh Peek
|
13
|
+
#
|
11
14
|
# Copyright (c) 2009 Christoffer Sawicki
|
12
15
|
#
|
13
16
|
# Permission is hereby granted, free of charge, to any person obtaining
|
@@ -65,6 +68,11 @@ module Plist4r
|
|
65
68
|
@keys = other.keys
|
66
69
|
end
|
67
70
|
|
71
|
+
def store(key, value)
|
72
|
+
@keys << key if !has_key?(key)
|
73
|
+
super
|
74
|
+
end
|
75
|
+
|
68
76
|
def []=(key, value)
|
69
77
|
@keys << key if !has_key?(key)
|
70
78
|
super
|
@@ -77,7 +85,7 @@ module Plist4r
|
|
77
85
|
end
|
78
86
|
super
|
79
87
|
end
|
80
|
-
|
88
|
+
|
81
89
|
def delete_if
|
82
90
|
super
|
83
91
|
sync_keys!
|
data/lib/plist4r/mixin/popen4.rb
CHANGED
@@ -15,7 +15,7 @@ module Plist4r
|
|
15
15
|
#
|
16
16
|
# Don't use the "Block form" calling method. It screws up on the pipes IO.
|
17
17
|
#
|
18
|
-
# Use "Simple form", always. Simple form
|
18
|
+
# Use "Simple form", always. Simple form = more robust IO handling.
|
19
19
|
#
|
20
20
|
# @example Simple form
|
21
21
|
# def popen4_exec stdin_str, cmd, *args
|
@@ -16,14 +16,158 @@ class Object
|
|
16
16
|
end
|
17
17
|
nil
|
18
18
|
end
|
19
|
+
|
20
|
+
# Make a deep copy of an object. Including a deep copy of all the object's instance data.
|
21
|
+
# @example
|
22
|
+
# copy_of_obj = obj.deep_clone
|
23
|
+
# @return [Object] A new copy of the object
|
24
|
+
def deep_clone; Marshal::load(Marshal.dump(self)); end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Array
|
28
|
+
# And array is considered multi-dimensional if all of the first-order elements are also arrays.
|
29
|
+
# @example
|
30
|
+
# [[1],[2],[3]].multidim?
|
31
|
+
# => true
|
32
|
+
#
|
33
|
+
# [[1],2,[3]].multidim?
|
34
|
+
# => false
|
35
|
+
# @return [true,false] true for a Multi-Dimensional array, false otherwise
|
36
|
+
def multidim?
|
37
|
+
case self.size
|
38
|
+
when 0
|
39
|
+
false
|
40
|
+
else
|
41
|
+
each do |e|
|
42
|
+
return false unless e.class == Array
|
43
|
+
end
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Converts an array of values (which must respond to #succ) to an array of ranges. For example,
|
49
|
+
# @example
|
50
|
+
# [3,4,5,1,6,9,8].to_ranges => [1,3..6,8..9]
|
51
|
+
def to_ranges
|
52
|
+
array = self.compact.uniq.sort
|
53
|
+
ranges = []
|
54
|
+
if !array.empty?
|
55
|
+
# Initialize the left and right endpoints of the range
|
56
|
+
left, right = array.first, nil
|
57
|
+
array.each do |obj|
|
58
|
+
# If the right endpoint is set and obj is not equal to right's successor
|
59
|
+
# then we need to create a range.
|
60
|
+
if right && obj != right.succ
|
61
|
+
ranges << Range.new(left,right)
|
62
|
+
left = obj
|
63
|
+
end
|
64
|
+
right = obj
|
65
|
+
end
|
66
|
+
ranges << Range.new(left,right)
|
67
|
+
end
|
68
|
+
ranges
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Hash
|
73
|
+
def merge_array_of_hashes_of_arrays array_of_hashes_of_arrays
|
74
|
+
a = array_of_hashes_of_arrays
|
75
|
+
raise "not an array_of_hashes_of_arrays" unless a.is_a? Array
|
76
|
+
if a[0].is_a? Hash
|
77
|
+
h = self.deep_clone
|
78
|
+
a.each_index do |i|
|
79
|
+
raise "not an array_of_hashes_of_arrays" unless a[i].is_a? Hash
|
80
|
+
a[i].each do |k,v|
|
81
|
+
raise "not an array_of_hashes_of_arrays" unless v.is_a? Array
|
82
|
+
h[k] = [h[k]].flatten.compact + v
|
83
|
+
end
|
84
|
+
end
|
85
|
+
else
|
86
|
+
raise "not an array_of_hashes_of_arrays"
|
87
|
+
end
|
88
|
+
h
|
89
|
+
end
|
90
|
+
|
91
|
+
def merge_array_of_hashes_of_arrays! array_of_hashes_of_arrays
|
92
|
+
h = merge_array_of_hashes_of_arrays array_of_hashes_of_arrays
|
93
|
+
self.replace h
|
94
|
+
self
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Range
|
99
|
+
# The Range's computed size, ie the number of elements in range.
|
100
|
+
# @example
|
101
|
+
# (3..3).size
|
102
|
+
# => 1
|
103
|
+
#
|
104
|
+
# (0..9).size
|
105
|
+
# => 10
|
106
|
+
# @return The size of the range
|
107
|
+
def size
|
108
|
+
last - first + 1
|
109
|
+
end
|
110
|
+
|
111
|
+
# The intersection of 2 ranges. Returns nil if there are no common elements.
|
112
|
+
# @example
|
113
|
+
# 1..10 & 5..15 => 5..10
|
114
|
+
# @return [Range, nil] The intesection between 2 overlapping ranges, or zero
|
115
|
+
def & other_range
|
116
|
+
case other_range
|
117
|
+
when Range
|
118
|
+
intersection = []
|
119
|
+
each do |i|
|
120
|
+
intersection << i if other_range.include? i
|
121
|
+
end
|
122
|
+
result = intersection.to_ranges
|
123
|
+
case result[0]
|
124
|
+
when Integer
|
125
|
+
return (result[0])..(result[0])
|
126
|
+
when Range, nil
|
127
|
+
return result[0]
|
128
|
+
end
|
129
|
+
else
|
130
|
+
raise "unsupported type"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Does this range wholely include other_range? (true or false)
|
135
|
+
# @example
|
136
|
+
# (3..5).include_range? (3..3)
|
137
|
+
# => true
|
138
|
+
#
|
139
|
+
# (0..4).include_range? (6..7)
|
140
|
+
# => false
|
141
|
+
# @return [true, false]
|
142
|
+
def include_range? other_range
|
143
|
+
case other_range
|
144
|
+
when Range
|
145
|
+
if other_range.first >= self.first && other_range.last <= self.last
|
146
|
+
return true
|
147
|
+
else
|
148
|
+
return false
|
149
|
+
end
|
150
|
+
else
|
151
|
+
raise "unsupported type"
|
152
|
+
end
|
153
|
+
end
|
19
154
|
end
|
20
155
|
|
21
156
|
class String
|
157
|
+
# The blob status of this string (set this to true if a binary string)
|
158
|
+
attr_accessor :blob
|
159
|
+
|
160
|
+
# Returns whether or not +str+ is a blob.
|
161
|
+
# @return [true,false] If true, this string contains binary data. If false, its a regular string
|
162
|
+
def blob?
|
163
|
+
@blob
|
164
|
+
end
|
165
|
+
|
22
166
|
# A Camel-ized string. The reverse of {#snake_case}
|
23
167
|
# @example
|
24
168
|
# "my_plist_key".camelcase => "MyPlistKey"
|
25
169
|
def camelcase
|
26
|
-
str = self.dup.
|
170
|
+
str = self.dup.gsub(/(^|[-_.\s])([a-zA-Z0-9])/) { $2.upcase } \
|
27
171
|
.gsub('+', 'x')
|
28
172
|
end
|
29
173
|
|
@@ -36,3 +180,12 @@ class String
|
|
36
180
|
end
|
37
181
|
end
|
38
182
|
|
183
|
+
class Float
|
184
|
+
alias_method :round_orig, :round
|
185
|
+
# Round to nearest n decimal places
|
186
|
+
# @example
|
187
|
+
# 16.347.round(2) => 16.35
|
188
|
+
def round(n=0)
|
189
|
+
(self * (10.0 ** n)).round_orig * (10.0 ** (-n))
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Plist4r
|
2
|
+
# A module which is an instance of the Script class encapsulates in its scope
|
3
|
+
# the top-level methods, top-level constants, and instance variables defined in
|
4
|
+
# a ruby script file (and its subfiles) loaded by a ruby program. This allows
|
5
|
+
# use of script files to define objects that can be loaded into a program in
|
6
|
+
# much the same way that objects can be loaded from YAML or Marshal files.
|
7
|
+
#
|
8
|
+
# See intro.txt[link:files/intro_txt.html] for an overview.
|
9
|
+
#
|
10
|
+
# Usable under the Ruby license. Copyright (C)2004 Joel VanderWerf. Questions to
|
11
|
+
# mailto:vjoel@users.sourceforge.net.
|
12
|
+
class Script < Module
|
13
|
+
# The file with which the Script was instantiated.
|
14
|
+
attr_reader :__main_file
|
15
|
+
|
16
|
+
# The directory in which main_file is located, and relative to which
|
17
|
+
# #load searches for files before falling back to Kernel#load.
|
18
|
+
attr_reader :__dir
|
19
|
+
|
20
|
+
# A hash that maps <tt>filename=>true</tt> for each file that has been
|
21
|
+
# required locally by the script. This has the same semantics as <tt>$"</tt>,
|
22
|
+
# alias <tt>$LOADED_FEATURES</tt>, except that it is local to this script.
|
23
|
+
attr_reader :__loaded_features
|
24
|
+
|
25
|
+
class << self
|
26
|
+
alias load new
|
27
|
+
end
|
28
|
+
|
29
|
+
# Creates new Script, and loads _main_file_ in the scope of the Script. If a
|
30
|
+
# block is given, the script is passed to it before loading from the file, and
|
31
|
+
# constants can be defined as inputs to the script.
|
32
|
+
|
33
|
+
def initialize(main_file) # :yields: self
|
34
|
+
extend ScriptModuleMethods
|
35
|
+
@__main_file = File.expand_path(main_file)
|
36
|
+
@__dir = File.dirname(@__main_file)
|
37
|
+
@__loaded_features = {}
|
38
|
+
|
39
|
+
yield self if block_given?
|
40
|
+
load_in_module(@__main_file)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Loads _file_ into this Script. Searches relative to the local dir, that is,
|
44
|
+
# the dir of the file given in the original call to
|
45
|
+
# <tt>Script.load(file)</tt>, loads the file, if found, into this Script's
|
46
|
+
# scope, and returns true. If the file is not found, falls back to
|
47
|
+
# <tt>Kernel.load</tt>, which searches on <tt>$LOAD_PATH</tt>, loads the file,
|
48
|
+
# if found, into global scope, and returns true. Otherwise, raises
|
49
|
+
# <tt>LoadError</tt>.
|
50
|
+
#
|
51
|
+
# The _wrap_ argument is passed to <tt>Kernel.load</tt> in the fallback case,
|
52
|
+
# when the file is not found locally.
|
53
|
+
#
|
54
|
+
# Typically called from within the main file to load additional sub files, or
|
55
|
+
# from those sub files.
|
56
|
+
|
57
|
+
def load(file, wrap = false)
|
58
|
+
load_in_module(file)
|
59
|
+
true
|
60
|
+
rescue MissingFile
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
# Analogous to <tt>Kernel#require</tt>. First tries the local dir, then falls
|
65
|
+
# back to <tt>Kernel#require</tt>. Will load a given _feature_ only once.
|
66
|
+
#
|
67
|
+
# Note that extensions (*.so, *.dll) can be required in the global scope, as
|
68
|
+
# usual, but not in the local scope. (This is not much of a limitation in
|
69
|
+
# practice--you wouldn't want to load an extension more than once.) This
|
70
|
+
# implementation falls back to <tt>Kernel#require</tt> when the argument is an
|
71
|
+
# extension or is not found locally.
|
72
|
+
|
73
|
+
def require(feature)
|
74
|
+
unless @__loaded_features[feature]
|
75
|
+
@__loaded_features[feature] = true
|
76
|
+
file = feature
|
77
|
+
file += ".rb" unless /\.rb$/ =~ file
|
78
|
+
load_in_module(file)
|
79
|
+
end
|
80
|
+
rescue MissingFile
|
81
|
+
@__loaded_features[feature] = false
|
82
|
+
super
|
83
|
+
end
|
84
|
+
|
85
|
+
# Raised by #load_in_module, caught by #load and #require.
|
86
|
+
class MissingFile < LoadError; end
|
87
|
+
|
88
|
+
# Loads _file_ in this module's context. Note that <tt>\_\_FILE\_\_</tt> and
|
89
|
+
# <tt>\_\_LINE\_\_</tt> work correctly in _file_.
|
90
|
+
# Called by #load and #require; not normally called directly.
|
91
|
+
|
92
|
+
def load_in_module(__file__)
|
93
|
+
__file__ = File.expand_path(__file__, @__dir)
|
94
|
+
module_eval("@__script_scope ||= binding\n" + IO.read(__file__),
|
95
|
+
__file__, 0)
|
96
|
+
# start numbering at 0 because of the extra line.
|
97
|
+
# The extra line does nothing in sub-script files.
|
98
|
+
rescue Errno::ENOENT
|
99
|
+
if /#{__file__}$/ =~ $!.message # No extra locals in this scope.
|
100
|
+
raise MissingFile, $!.message
|
101
|
+
else
|
102
|
+
raise
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s # :nodoc:
|
107
|
+
"#<#{self.class}:#{File.join(__dir, File.basename(__main_file))}>"
|
108
|
+
end
|
109
|
+
|
110
|
+
module ScriptModuleMethods
|
111
|
+
# This is so that <tt>def meth...</tt> behaves like in Ruby's top-level
|
112
|
+
# context. The implementation simply calls
|
113
|
+
# <tt>Module#module_function(name)</tt>.
|
114
|
+
def method_added(name) # :nodoc:
|
115
|
+
module_function(name)
|
116
|
+
end
|
117
|
+
|
118
|
+
attr_reader :__script_scope
|
119
|
+
|
120
|
+
# Gets list of local vars in the script. Does not see local vars in files
|
121
|
+
# loaded or required by that script.
|
122
|
+
def __local_variables
|
123
|
+
eval("local_variables", __script_scope)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Gets value of local var in the script. Does not see local vars in files
|
127
|
+
# loaded or required by that script.
|
128
|
+
def __local_variable_get(name)
|
129
|
+
eval(name.to_s, __script_scope)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|