metaruby 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/History.txt +1 -0
- data/Manifest.txt +40 -0
- data/README.md +318 -0
- data/Rakefile +39 -0
- data/lib/metaruby/class.rb +120 -0
- data/lib/metaruby/dsls/doc.rb +78 -0
- data/lib/metaruby/dsls/find_through_method_missing.rb +76 -0
- data/lib/metaruby/dsls.rb +2 -0
- data/lib/metaruby/gui/exception_view.rb +124 -0
- data/lib/metaruby/gui/html/button.rb +65 -0
- data/lib/metaruby/gui/html/collection.rb +103 -0
- data/lib/metaruby/gui/html/exception_view.css +8 -0
- data/lib/metaruby/gui/html/jquery.min.js +154 -0
- data/lib/metaruby/gui/html/jquery.selectfilter.js +65 -0
- data/lib/metaruby/gui/html/jquery.tagcloud.min.js +8 -0
- data/lib/metaruby/gui/html/jquery.tinysort.min.js +8 -0
- data/lib/metaruby/gui/html/list.rhtml +24 -0
- data/lib/metaruby/gui/html/page.css +55 -0
- data/lib/metaruby/gui/html/page.rb +283 -0
- data/lib/metaruby/gui/html/page.rhtml +13 -0
- data/lib/metaruby/gui/html/page_body.rhtml +17 -0
- data/lib/metaruby/gui/html/rock-website.css +694 -0
- data/lib/metaruby/gui/html.rb +16 -0
- data/lib/metaruby/gui/model_browser.rb +262 -0
- data/lib/metaruby/gui/model_selector.rb +266 -0
- data/lib/metaruby/gui/rendering_manager.rb +112 -0
- data/lib/metaruby/gui/ruby_constants_item_model.rb +253 -0
- data/lib/metaruby/gui.rb +9 -0
- data/lib/metaruby/inherited_attribute.rb +482 -0
- data/lib/metaruby/module.rb +158 -0
- data/lib/metaruby/registration.rb +157 -0
- data/lib/metaruby/test.rb +79 -0
- data/lib/metaruby.rb +17 -0
- data/manifest.xml +12 -0
- data/test/suite.rb +15 -0
- data/test/test_attributes.rb +323 -0
- data/test/test_class.rb +68 -0
- data/test/test_dsls.rb +49 -0
- data/test/test_module.rb +105 -0
- data/test/test_registration.rb +182 -0
- metadata +160 -0
@@ -0,0 +1,253 @@
|
|
1
|
+
module MetaRuby
|
2
|
+
module GUI
|
3
|
+
# A Qt item model that lists Ruby modules that match a given predicate
|
4
|
+
# (given at construction time)
|
5
|
+
class RubyConstantsItemModel < Qt::AbstractItemModel
|
6
|
+
ModuleInfo = Struct.new :id, :name, :this, :parent, :children, :row, :types, :full_name, :keyword_string, :path
|
7
|
+
TypeInfo = Struct.new :name, :priority, :color
|
8
|
+
|
9
|
+
attr_reader :predicate
|
10
|
+
attr_reader :id_to_module
|
11
|
+
attr_reader :filtered_out_modules
|
12
|
+
attr_reader :type_info
|
13
|
+
attr_accessor :title
|
14
|
+
attr_reader :object_paths
|
15
|
+
# @return [Set<Object>] a set of objects that should not be
|
16
|
+
# discovered
|
17
|
+
attr_reader :excludes
|
18
|
+
|
19
|
+
def initialize(type_info = Hash.new, &predicate)
|
20
|
+
super()
|
21
|
+
@predicate = predicate || proc { true }
|
22
|
+
@type_info = type_info
|
23
|
+
@title = "Model Browser"
|
24
|
+
@excludes = [Qt].to_set
|
25
|
+
|
26
|
+
@id_to_module = []
|
27
|
+
@filtered_out_modules = Set.new
|
28
|
+
@object_paths = Hash.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def reload
|
32
|
+
@id_to_module = []
|
33
|
+
@filtered_out_modules = Set.new
|
34
|
+
|
35
|
+
info = discover_module(Object)
|
36
|
+
info.id = id_to_module.size
|
37
|
+
info.name = title
|
38
|
+
update_module_type_info(info)
|
39
|
+
info.row = 0
|
40
|
+
id_to_module << info
|
41
|
+
|
42
|
+
@object_paths = Hash.new
|
43
|
+
generate_paths(object_paths, info, "")
|
44
|
+
|
45
|
+
emit dataChanged(Qt::ModelIndex.new, Qt::ModelIndex.new)
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_paths(paths, info, current)
|
49
|
+
info.children.each do |child|
|
50
|
+
child_uri = current + '/' + child.name
|
51
|
+
paths[child.this] = child_uri
|
52
|
+
generate_paths(paths, child, child_uri)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def update_module_type_info(info)
|
57
|
+
types = info.types.to_set
|
58
|
+
info.children.each do |child_info|
|
59
|
+
types |= child_info.types.to_set
|
60
|
+
end
|
61
|
+
info.types = types.to_a.sort_by do |type|
|
62
|
+
type_info[type].priority
|
63
|
+
end.reverse
|
64
|
+
end
|
65
|
+
|
66
|
+
def discover_module(mod, stack = Array.new)
|
67
|
+
return if excludes.include?(mod)
|
68
|
+
stack.push mod
|
69
|
+
|
70
|
+
children = []
|
71
|
+
mod_info = ModuleInfo.new(nil, nil, mod, nil, children, nil, Set.new)
|
72
|
+
|
73
|
+
is_needed = (mod.kind_of?(Class) && mod == Object) || predicate.call(mod)
|
74
|
+
|
75
|
+
if mod.respond_to?(:constants)
|
76
|
+
children_modules = begin mod.constants
|
77
|
+
rescue TypeError
|
78
|
+
puts "cannot discover module #{mod}"
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
|
82
|
+
children_modules = children_modules.map do |child_name|
|
83
|
+
next if !mod.const_defined_here?(child_name)
|
84
|
+
# Ruby issues a warning when one tries to access Config
|
85
|
+
# (it has been deprecated in favor of RbConfig). Ignore
|
86
|
+
# it explicitly
|
87
|
+
next if mod == Object && child_name == :Config
|
88
|
+
next if mod.autoload?(child_name)
|
89
|
+
child_mod = begin mod.const_get(child_name)
|
90
|
+
rescue LoadError
|
91
|
+
# Handle autoload errors
|
92
|
+
end
|
93
|
+
next if !child_mod
|
94
|
+
next if filtered_out_modules.include?(child_mod)
|
95
|
+
next if stack.include?(child_mod)
|
96
|
+
[child_name.to_s, child_mod]
|
97
|
+
end.compact.sort_by(&:first)
|
98
|
+
|
99
|
+
children_modules.each do |child_name, child_mod|
|
100
|
+
if info = discover_module(child_mod, stack)
|
101
|
+
info.id = id_to_module.size
|
102
|
+
info.name = child_name.to_s
|
103
|
+
info.parent = mod_info
|
104
|
+
info.row = children.size
|
105
|
+
children << info
|
106
|
+
id_to_module << info
|
107
|
+
else
|
108
|
+
filtered_out_modules << child_mod
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if is_needed
|
114
|
+
klass = if mod.respond_to?(:ancestors) then mod
|
115
|
+
else mod.class
|
116
|
+
end
|
117
|
+
|
118
|
+
current_priority = nil
|
119
|
+
klass.ancestors.each do |ancestor|
|
120
|
+
if info = type_info[ancestor]
|
121
|
+
current_priority ||= info.priority
|
122
|
+
if current_priority < info.priority
|
123
|
+
mod_info.types.clear
|
124
|
+
mod_info.types << ancestor
|
125
|
+
current_priority = info.priority
|
126
|
+
elsif current_priority == info.priority
|
127
|
+
mod_info.types << ancestor
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
update_module_type_info(mod_info)
|
134
|
+
|
135
|
+
if !children.empty? || is_needed
|
136
|
+
mod_info
|
137
|
+
end
|
138
|
+
ensure stack.pop
|
139
|
+
end
|
140
|
+
|
141
|
+
def headerData(section, orientation, role)
|
142
|
+
if role == Qt::DisplayRole && section == 0
|
143
|
+
Qt::Variant.new(title)
|
144
|
+
else Qt::Variant.new
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def compute_full_name(info)
|
149
|
+
if name = info.full_name
|
150
|
+
return name
|
151
|
+
else
|
152
|
+
full_name = []
|
153
|
+
current = info
|
154
|
+
while current.parent
|
155
|
+
full_name << current.name
|
156
|
+
current = current.parent
|
157
|
+
end
|
158
|
+
info.full_name = full_name.reverse
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def compute_path(info)
|
163
|
+
if path = info.path
|
164
|
+
return path
|
165
|
+
else
|
166
|
+
full_name = compute_full_name(info)
|
167
|
+
info.path = ("/" + full_name.map(&:downcase).join("/"))
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def compute_keyword_string(info)
|
172
|
+
if keywords = info.keyword_string
|
173
|
+
return keywords
|
174
|
+
else
|
175
|
+
types = info.types.map do |type|
|
176
|
+
type_info[type].name
|
177
|
+
end.sort.join(",")
|
178
|
+
paths = [compute_path(info)]
|
179
|
+
paths.concat info.children.map { |child| compute_path(child) }
|
180
|
+
info.keyword_string = "#{types};#{paths.join(",")}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def data(index, role)
|
185
|
+
if info = info_from_index(index)
|
186
|
+
if role == Qt::DisplayRole
|
187
|
+
return Qt::Variant.new(info.name)
|
188
|
+
elsif role == Qt::EditRole
|
189
|
+
return Qt::Variant.new(compute_full_name(info).join("/"))
|
190
|
+
elsif role == Qt::UserRole
|
191
|
+
return Qt::Variant.new(compute_keyword_string(info))
|
192
|
+
end
|
193
|
+
end
|
194
|
+
return Qt::Variant.new
|
195
|
+
end
|
196
|
+
|
197
|
+
def index(row, column, parent)
|
198
|
+
if info = info_from_index(parent)
|
199
|
+
if child_info = info.children[row]
|
200
|
+
return create_index(row, column, child_info.id)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
Qt::ModelIndex.new
|
204
|
+
end
|
205
|
+
|
206
|
+
def parent(child)
|
207
|
+
if info = info_from_index(child)
|
208
|
+
if info.parent
|
209
|
+
return create_index(info.parent.row, 0, info.parent.id)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
Qt::ModelIndex.new
|
213
|
+
end
|
214
|
+
|
215
|
+
def rowCount(parent)
|
216
|
+
if info = info_from_index(parent)
|
217
|
+
info.children.size
|
218
|
+
else 0
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def columnCount(parent)
|
223
|
+
return 1
|
224
|
+
end
|
225
|
+
|
226
|
+
def info_from_index(index)
|
227
|
+
if !index.valid?
|
228
|
+
return id_to_module.last
|
229
|
+
else
|
230
|
+
id_to_module[index.internal_id >> 1]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def find_index_by_model(model)
|
235
|
+
if info = id_to_module.find { |info| info.this == model }
|
236
|
+
return create_index(info.row, 0, info.id)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def find_index_by_path(*path)
|
241
|
+
current = id_to_module.last
|
242
|
+
path.each do |name|
|
243
|
+
current = id_to_module.find do |info|
|
244
|
+
info.name == name && info.parent == current
|
245
|
+
end
|
246
|
+
return if !current
|
247
|
+
end
|
248
|
+
create_index(current.row, 0, current.id)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
data/lib/metaruby/gui.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'Qt4'
|
2
|
+
require 'qtwebkit'
|
3
|
+
require 'kramdown'
|
4
|
+
require 'metaruby/gui/html'
|
5
|
+
require 'metaruby/gui/ruby_constants_item_model'
|
6
|
+
require 'metaruby/gui/rendering_manager'
|
7
|
+
require 'metaruby/gui/model_browser'
|
8
|
+
require 'metaruby/gui/model_selector'
|
9
|
+
require 'metaruby/gui/exception_view'
|