sirens 0.0.1

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/lib/components/component.rb +46 -0
  3. data/lib/components/component_behaviour.rb +160 -0
  4. data/lib/components/containers/splitter.rb +98 -0
  5. data/lib/components/containers/stack.rb +42 -0
  6. data/lib/components/containers/tabs.rb +24 -0
  7. data/lib/components/containers/window.rb +20 -0
  8. data/lib/components/primitive_component.rb +155 -0
  9. data/lib/components/widgets/button.rb +16 -0
  10. data/lib/components/widgets/checkbox.rb +39 -0
  11. data/lib/components/widgets/column_props.rb +23 -0
  12. data/lib/components/widgets/input_text.rb +27 -0
  13. data/lib/components/widgets/list.rb +68 -0
  14. data/lib/components/widgets/list_choice.rb +89 -0
  15. data/lib/components/widgets/radio_button.rb +33 -0
  16. data/lib/components/widgets/text.rb +31 -0
  17. data/lib/components/widgets/tree_choice.rb +82 -0
  18. data/lib/layouts/columns_builder.rb +63 -0
  19. data/lib/layouts/layout_builder.rb +203 -0
  20. data/lib/layouts/radio_button_group_builder.rb +28 -0
  21. data/lib/models/choice_model.rb +41 -0
  22. data/lib/models/list_model.rb +173 -0
  23. data/lib/models/tree_choice_model.rb +102 -0
  24. data/lib/models/value_model.rb +56 -0
  25. data/lib/models/virtual_tree_model.rb +150 -0
  26. data/lib/sirens/browsers/module_browser.rb +67 -0
  27. data/lib/sirens/browsers/object_browser.rb +103 -0
  28. data/lib/sirens/components/ancestors_list.rb +22 -0
  29. data/lib/sirens/components/class_browser.rb +38 -0
  30. data/lib/sirens/components/constants_list.rb +22 -0
  31. data/lib/sirens/components/method_source_code.rb +22 -0
  32. data/lib/sirens/components/methods_list.rb +63 -0
  33. data/lib/sirens/components/modules_list.rb +23 -0
  34. data/lib/sirens/components/namespaces_list.rb +21 -0
  35. data/lib/sirens/models/constant_model.rb +21 -0
  36. data/lib/sirens/models/method_model.rb +111 -0
  37. data/lib/sirens/models/module_browser_model.rb +225 -0
  38. data/lib/sirens/models/object_browser_model.rb +125 -0
  39. data/lib/sirens.rb +90 -0
  40. data/lib/views/button_view.rb +56 -0
  41. data/lib/views/check_button_view.rb +65 -0
  42. data/lib/views/entry_view.rb +25 -0
  43. data/lib/views/list_view.rb +230 -0
  44. data/lib/views/menu_view.rb +46 -0
  45. data/lib/views/notebook_view.rb +27 -0
  46. data/lib/views/paned_view.rb +26 -0
  47. data/lib/views/radio_button_view.rb +67 -0
  48. data/lib/views/stack_view.rb +26 -0
  49. data/lib/views/text_view.rb +112 -0
  50. data/lib/views/tree_view.rb +314 -0
  51. data/lib/views/view.rb +206 -0
  52. data/lib/views/window_view.rb +51 -0
  53. metadata +110 -0
@@ -0,0 +1,22 @@
1
+ module Sirens
2
+
3
+ class ConstantsList < Sirens::Component
4
+
5
+ # Building
6
+
7
+ def renderWith(layout)
8
+ layout.render do |component|
9
+ choices_list do
10
+ model component.model
11
+
12
+ styles(
13
+ show_headers: false
14
+ )
15
+
16
+ column label: 'Constants',
17
+ get_text_block: proc{ |constant| constant.display_string }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module Sirens
2
+ class MethodSourceCode < Sirens::Component
3
+
4
+ # Building
5
+
6
+ def renderWith(layout)
7
+ layout.render do |component|
8
+ vertical_stack do
9
+ text do
10
+ model component.model.source_code
11
+ end
12
+
13
+ input_text do
14
+ model component.model.location
15
+
16
+ styles stack_expand: false
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,63 @@
1
+ module Sirens
2
+
3
+ class MethodsList < Sirens::Component
4
+
5
+ # Building
6
+
7
+ def renderWith(layout)
8
+ layout.render do |component|
9
+ vertical_stack do
10
+
11
+ horizontal_stack do
12
+ styles(
13
+ height: 30,
14
+ stack_expand: false
15
+ )
16
+
17
+ radio_buttons_group do
18
+ radio_button label: 'instance',
19
+ id: :instance,
20
+ model: component.props[:instance_or_class_methods_chooser],
21
+ stack_expand: false
22
+
23
+ radio_button label: 'class',
24
+ id: :class,
25
+ model: component.props[:instance_or_class_methods_chooser],
26
+ stack_expand: false
27
+ end
28
+
29
+ checkbox label: 'include inherit',
30
+ model: component.props[:show_inherit_methods]
31
+ end
32
+
33
+ choices_list do
34
+ model component.model
35
+
36
+ styles id: :methods_list,
37
+ show_headers: false
38
+
39
+ column label: 'Methods',
40
+ get_text_block: proc{ |method| method }
41
+ end
42
+
43
+ horizontal_stack do
44
+ styles(
45
+ height: 30,
46
+ stack_expand: false
47
+ )
48
+
49
+ checkbox label: 'public',
50
+ model: component.props[:show_public_methods]
51
+
52
+ checkbox label: 'protected',
53
+ model: component.props[:show_protected_methods]
54
+
55
+ checkbox label: 'private',
56
+ model: component.props[:show_private_methods]
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ module Sirens
2
+ class ModulesList < Sirens::Component
3
+
4
+ # Building
5
+
6
+ def renderWith(layout)
7
+ layout.render do |component|
8
+
9
+ choices_list do
10
+ model component.model
11
+
12
+ styles(
13
+ show_headers: true
14
+ )
15
+
16
+ column label: 'Namespace modules',
17
+ get_text_block: proc{ |a_module| a_module.name }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module Sirens
2
+ class NamespacesList < Sirens::Component
3
+
4
+ # Building
5
+
6
+ def renderWith(layout)
7
+ layout.render do |component|
8
+
9
+ choices_tree do
10
+ model component.model
11
+
12
+ styles show_headers: true
13
+
14
+ column label: 'Namespaces',
15
+ get_text_block: proc{ |a_module| a_module.name }
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Sirens
2
+ class ConstantModel
3
+
4
+ # Initializing
5
+
6
+ def initialize(name:, value:)
7
+ super()
8
+
9
+ @name = name
10
+ @value = value
11
+ end
12
+
13
+ attr_reader :name, :value
14
+
15
+ def display_string()
16
+ value_print_string = value.inspect
17
+
18
+ "#{name} = #{value_print_string}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,111 @@
1
+ require 'stringio'
2
+
3
+ module Sirens
4
+ class MethodModel
5
+
6
+ # Initializing
7
+
8
+ def initialize()
9
+ super()
10
+
11
+ @method_name = ValueModel.new
12
+ @location = ValueModel.new
13
+ @source_code = ValueModel.new
14
+ end
15
+
16
+ attr_reader :method_name,
17
+ :location,
18
+ :source_code
19
+
20
+ def set_method(method)
21
+ if method.nil?
22
+ method_name.set_value(nil)
23
+ location.set_value(nil)
24
+ source_code.set_value(nil)
25
+
26
+ return
27
+ end
28
+
29
+ method_name.set_value(method.name)
30
+
31
+ method_filename, method_line_number = method.source_location
32
+
33
+ location.set_value("#{method_filename}:#{method_line_number}")
34
+
35
+ source_code.set_value(
36
+ get_source_code_of(method: method, filename: method_filename, line_number: method_line_number)
37
+ )
38
+ end
39
+
40
+ def get_source_code_of(method:, filename:, line_number:)
41
+ return 'Native method' if filename.nil? || ! File.exists?(filename)
42
+
43
+ source_code = StringIO.new
44
+
45
+ lines = File.read(filename).lines
46
+
47
+ method_comment = ''
48
+ comment_line = line_number - 1
49
+ while line_number >= 0
50
+ line = lines[comment_line - 1]
51
+
52
+ break if ! /^\s*#/.match(line)
53
+
54
+ method_comment = line + method_comment
55
+
56
+ comment_line -= 1
57
+ end
58
+
59
+ source_code.write(method_comment)
60
+
61
+ tail = lines[line_number -1 .. -1].join
62
+
63
+ stream = StringIO.new(tail)
64
+
65
+ counter = 0
66
+
67
+ keywords = ['module', 'class', 'def', 'if', 'while', 'do', 'begin']
68
+
69
+ while !stream.eof?
70
+
71
+ while !stream.eof? && (c = stream.getc) == ' '
72
+ source_code.write(' ')
73
+ end
74
+
75
+ stream.ungetc(c)
76
+
77
+ token = stream.gets(' ')
78
+
79
+ source_code.write(token)
80
+
81
+ token = token.strip
82
+
83
+ if token == 'end'
84
+ counter -= 1
85
+ elsif keywords.include?(token)
86
+ counter += 1
87
+ end
88
+
89
+ break if counter == 0
90
+ end
91
+
92
+ fix_indentation(source_code.string)
93
+ end
94
+
95
+ def fix_indentation(source_code)
96
+ lines = source_code.lines
97
+
98
+ indentation = 0
99
+
100
+ /^(\s*).*$/.match(lines.first) do |matches|
101
+ indentation = matches[1].size
102
+ end
103
+
104
+ lines = lines.collect { |line|
105
+ line.gsub!(/^\s{#{indentation}}/, '')
106
+ }
107
+
108
+ lines.join
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,225 @@
1
+ module Sirens
2
+ class ModuleBrowserModel
3
+
4
+ # Initializing
5
+
6
+ def initialize()
7
+ super()
8
+
9
+ @namespaces = TreeChoiceModel.new(
10
+ selection: nil,
11
+ roots: get_root_namespaces,
12
+ get_children_block: proc { |namespace| get_modules_in(namespace) }
13
+ )
14
+
15
+ @modules = ChoiceModel.new(selection: nil, choices: [])
16
+ @module_ancestors = ChoiceModel.new(selection: nil, choices: [])
17
+ @methods = ChoiceModel.new(selection: nil, choices: [])
18
+ @constants = ChoiceModel.new(selection: nil, choices: [])
19
+
20
+ @instance_or_class_methods_chooser = ChoiceModel.new(selection: :instance, choices: [:instance, :class])
21
+ @show_inherit_methods = ValueModel.on(false)
22
+
23
+ @show_public_methods = ValueModel.on(true)
24
+ @show_protected_methods = ValueModel.on(false)
25
+ @show_private_methods = ValueModel.on(false)
26
+
27
+ @method_source_code = MethodModel.new
28
+
29
+ connect_models
30
+ end
31
+
32
+ attr_reader :namespaces,
33
+ :modules,
34
+ :module_ancestors,
35
+ :methods,
36
+ :constants,
37
+ :instance_or_class_methods_chooser,
38
+ :show_public_methods,
39
+ :show_protected_methods,
40
+ :show_private_methods,
41
+ :show_inherit_methods,
42
+ :method_source_code
43
+
44
+ def connect_models()
45
+ @namespaces.selection.add_observer(self, :on_namespace_changed)
46
+ @modules.selection.add_observer(self, :on_class_changed)
47
+ @module_ancestors.selection.add_observer(self, :on_module_changed)
48
+ @methods.selection.add_observer(self, :on_method_changed)
49
+
50
+ @instance_or_class_methods_chooser.selection.add_observer(self, :on_methods_filter_changed)
51
+ @show_inherit_methods.add_observer(self, :on_methods_filter_changed)
52
+
53
+ @show_public_methods.add_observer(self, :on_methods_filter_changed)
54
+ @show_protected_methods.add_observer(self, :on_methods_filter_changed)
55
+ @show_private_methods.add_observer(self, :on_methods_filter_changed)
56
+ end
57
+
58
+ # Actions
59
+
60
+ def actual_namespace_hierarchy(a_module)
61
+ namespaces = a_module.name.split('::')
62
+
63
+ namespaces.pop if a_module.kind_of?(Class)
64
+
65
+ hierarchy = [Object]
66
+
67
+ namespaces.each { |module_name|
68
+ hierarchy << hierarchy.last.const_get(module_name)
69
+ }
70
+
71
+ hierarchy
72
+ end
73
+
74
+ def select_namespace(namespace)
75
+ hierarchy = actual_namespace_hierarchy(namespace)
76
+
77
+ @namespaces.set_selection(hierarchy)
78
+ end
79
+
80
+ def select_class(a_class)
81
+ hierarchy = actual_namespace_hierarchy(a_class)
82
+
83
+ @namespaces.set_selection(hierarchy)
84
+ @modules.set_selection(a_class)
85
+ @module_ancestors.set_selection(a_class)
86
+ end
87
+
88
+ # Events
89
+
90
+ def on_namespace_changed(announcement)
91
+ namespace_hierarchy = announcement.new_value
92
+
93
+ modules.set_choices(get_modules_in(namespace_hierarchy.last))
94
+ end
95
+
96
+ def on_class_changed(announcement)
97
+ a_class = announcement.new_value
98
+
99
+ ancestors = get_all_ancestors_of(a_class)
100
+
101
+ module_ancestors.set_choices(ancestors)
102
+
103
+ module_ancestors.set_selection(ancestors.last) unless ancestors.empty?
104
+ end
105
+
106
+ def on_module_changed(announcement)
107
+ on_methods_filter_changed()
108
+ end
109
+
110
+ def on_methods_filter_changed(announcement = nil)
111
+ a_module = module_ancestors.selection.value
112
+
113
+ methods.set_choices(get_all_methods_in(a_module))
114
+ constants.set_choices(get_all_constants_in(a_module))
115
+ end
116
+
117
+ def on_method_changed(announcement)
118
+ method_name = announcement.new_value
119
+
120
+ if method_name.nil?
121
+ method_source_code.set_method(nil)
122
+ return
123
+ end
124
+
125
+ a_module = module_ancestors.selection.value
126
+
127
+ if showing_instance_methods?
128
+ method = a_module.instance_method(method_name)
129
+ else
130
+ method = a_module.method(method_name)
131
+ end
132
+
133
+ method_source_code.set_method(method)
134
+ end
135
+
136
+ # Calculated
137
+
138
+ ##
139
+ # Answers all the namespaces in the running environment
140
+ #
141
+ def get_root_namespaces()
142
+ return [Object]
143
+ end
144
+
145
+ ##
146
+ # Answers child modules of a namespace
147
+ #
148
+ def get_modules_in(a_module)
149
+ return [] if a_module.nil?
150
+
151
+ modules = a_module.constants(false)
152
+ .collect { |constant| a_module.const_get(constant) }
153
+ .select { |constant| constant.kind_of?(Module) }
154
+ .sort_by { |a_module| a_module.name }
155
+
156
+ modules.prepend(a_module)
157
+ end
158
+
159
+ ##
160
+ # Answers all the modules in the given class
161
+ #
162
+ def get_all_ancestors_of(a_class)
163
+ return [] if a_class.nil?
164
+
165
+ a_class.ancestors.reverse
166
+ end
167
+
168
+ ##
169
+ # Answers all the methods in the given class
170
+ #
171
+ def get_all_methods_in(a_module)
172
+ return [] if a_module.nil?
173
+
174
+ methods = []
175
+
176
+ inherit = show_inherit_methods.value
177
+
178
+ if showing_instance_methods?
179
+ methods.concat(a_module.private_instance_methods(inherit)) if showing_private_methods?
180
+ methods.concat(a_module.protected_instance_methods(inherit)) if showing_protected_methods?
181
+ methods.concat(a_module.public_instance_methods(inherit)) if showing_public_methods?
182
+ else
183
+ methods.concat(a_module.private_methods(inherit)) if showing_private_methods?
184
+ methods.concat(a_module.protected_methods(inherit)) if showing_protected_methods?
185
+ methods.concat(a_module.public_methods(inherit)) if showing_public_methods?
186
+ end
187
+
188
+ methods.sort
189
+ end
190
+
191
+ ##
192
+ # Answers all the constants in the given class
193
+ #
194
+ def get_all_constants_in(a_module)
195
+ return [] if a_module.nil?
196
+
197
+ inherit = show_inherit_methods.value
198
+
199
+ a_module.constants(inherit)
200
+ .collect { |constant_name|
201
+ ConstantModel.new(name: constant_name, value: a_module.const_get(constant_name))
202
+ }
203
+ .select { |constant_model| ! constant_model.value.kind_of?(Module) }
204
+ .sort_by { |constant_model| constant_model.name }
205
+ end
206
+
207
+ # Asking
208
+
209
+ def showing_instance_methods?()
210
+ instance_or_class_methods_chooser.selection.value == :instance
211
+ end
212
+
213
+ def showing_private_methods?()
214
+ show_private_methods.value
215
+ end
216
+
217
+ def showing_protected_methods?()
218
+ show_protected_methods.value
219
+ end
220
+
221
+ def showing_public_methods?()
222
+ show_public_methods.value
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,125 @@
1
+ module Sirens
2
+ class ObjectBrowserModel
3
+
4
+ # Initializing
5
+
6
+ def initialize()
7
+ super()
8
+
9
+ @object = ValueModel.on(nil)
10
+
11
+ @object_instance_variables = TreeChoiceModel.new(
12
+ selection: object,
13
+ roots: [InstanceVariable.new(key: nil, value: object)],
14
+ get_children_block: proc { |instance_variable|
15
+ get_child_instance_variables_of(instance_variable.value)
16
+ }
17
+ )
18
+
19
+ @text = ValueModel.on('')
20
+
21
+ connect_models
22
+ end
23
+
24
+ def connect_models()
25
+ @object.add_observer(self, :on_object_changed)
26
+ @object_instance_variables.selection.add_observer(self, :on_instance_variable_changed)
27
+ end
28
+
29
+ # Accessors
30
+
31
+ attr_reader :object,
32
+ :object_instance_variables,
33
+ :text
34
+
35
+ def selected_inst_var_value()
36
+ tree_selection = object_instance_variables.selection.value.last
37
+
38
+ tree_selection.nil? ? nil : tree_selection.value
39
+ end
40
+
41
+ # Events
42
+
43
+ def on_object_changed(announcement)
44
+ new_object = announcement.new_value
45
+
46
+ @object_instance_variables.set_tree_roots(
47
+ [InstanceVariable.new(key: nil, value: new_object)]
48
+ )
49
+ end
50
+
51
+ def on_instance_variable_changed(announcement)
52
+ instance_variable = announcement.new_value.last
53
+
54
+ value = instance_variable.nil? ? '' : instance_variable.value.inspect
55
+
56
+ @text.set_value(value)
57
+ end
58
+
59
+ ##
60
+ # Get the child instance variables of an object.
61
+ #
62
+ def get_child_instance_variables_of(object)
63
+ if object.kind_of?(Array)
64
+ i = -1
65
+ object.collect{ |value|
66
+ i += 1
67
+ InstanceVariable.new(
68
+ key: i,
69
+ value: value
70
+ )
71
+ }
72
+ elsif object.kind_of?(Hash)
73
+ object.collect{ |key, value|
74
+ InstanceVariable.new(
75
+ key: "[#{key.inspect}]",
76
+ value: value
77
+ )
78
+ }
79
+ else
80
+ object.instance_variables.collect{ |inst_var_name|
81
+ InstanceVariable.new(
82
+ key: inst_var_name,
83
+ value: object.instance_variable_get(inst_var_name)
84
+ )
85
+ }
86
+ end
87
+ end
88
+
89
+ class InstanceVariable
90
+ def initialize(key:, value:)
91
+ @key = key
92
+ @value = value
93
+ end
94
+
95
+ attr_reader :key, :value
96
+
97
+ def display_string()
98
+ return value_display_string if key.nil?
99
+
100
+ "#{key_display_string} = #{value_display_string}"
101
+ end
102
+
103
+ def key_display_string()
104
+ if key.kind_of?(Numeric)
105
+ "[#{key}]"
106
+ else
107
+ key.to_s
108
+ end
109
+ end
110
+
111
+ def value_display_string()
112
+ return "an Array(#{value.size})" if value.kind_of?(Array)
113
+ return 'a Hash' if value.kind_of?(Hash)
114
+
115
+ string = value.to_s
116
+
117
+ if string.start_with?('#<')
118
+ "a " + value.class.name
119
+ else
120
+ value.inspect
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end