study 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df597f9ef5df8f0f8772deef6ba1c2cd163fa3b4
4
+ data.tar.gz: 206609780a7246e7e966c2fb6cc8923fefc6ffcb
5
+ SHA512:
6
+ metadata.gz: b26ca74f73016fda6cb5074e95c13d8d25f5a40c3c12cfb8f6685272c9487990978eef2d1f9cedba3b3b8e80b9655d0e21e15a4c102c2bcf365358f3a20c75d5
7
+ data.tar.gz: b2171cfe86784a5fcb4afe044cb8c183cf8e088dbd949e717578d0b4069503a3e16b55566f5884af4cf3bab51e5c9a552b7a08b109e6e61c680d351d7cea4161
@@ -0,0 +1,14 @@
1
+ require 'study/text_highlight'
2
+ require 'study/tree_node'
3
+ require 'study/version'
4
+
5
+ module Study
6
+ module Methods
7
+ def study(target, max_depth: 10, plain: false)
8
+ TreeNode.convert(target).draw(max_depth: max_depth, plain: plain)
9
+ end
10
+ end
11
+ end
12
+
13
+ extend Study::Methods
14
+ include Study::Methods
@@ -0,0 +1,33 @@
1
+ module Study
2
+ module TextHighlight
3
+ class << self
4
+ def red(string, plain: false)
5
+ plain ? string.to_s : "\033[1;31;40m#{ string.to_s }\033[0m"
6
+ end
7
+
8
+ def yellow(string, plain: false)
9
+ plain ? string.to_s : "\033[1;33;40m#{ string.to_s }\033[0m"
10
+ end
11
+
12
+ def blue(string, plain: false)
13
+ plain ? string.to_s : "\033[1;34;40m#{ string.to_s }\033[0m"
14
+ end
15
+
16
+ def green(string, plain: false)
17
+ plain ? string.to_s : "\033[1;32;40m#{ string.to_s }\033[0m"
18
+ end
19
+
20
+ def violet(string, plain: false)
21
+ plain ? string.to_s : "\033[1;35;40m#{ string.to_s }\033[0m"
22
+ end
23
+
24
+ def cyan(string, plain: false)
25
+ plain ? string.to_s : "\033[1;36;40m#{ string.to_s }\033[0m"
26
+ end
27
+
28
+ def white(string, plain: false)
29
+ plain ? string.to_s : "\033[1;37;40m#{ string.to_s }\033[0m"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,200 @@
1
+ module Study
2
+ class TreeNode
3
+ attr_accessor :type, :value
4
+
5
+ def initialize(type:, value:)
6
+ @type = type
7
+ @value = value
8
+ end
9
+
10
+ def ==(other)
11
+ @type == other.type && @value == other.value
12
+ end
13
+
14
+ def highlight(left: nil, right: nil, nested: false, plain: false)
15
+ colored_left = left.is_a?(Integer) ? TextHighlight.violet(left, plain: plain) : TextHighlight.cyan(left, plain: plain)
16
+
17
+ if nested
18
+ [
19
+ colored_left,
20
+ TextHighlight.green(":", plain: plain),
21
+ " ",
22
+ TextHighlight.yellow(right, plain: plain)
23
+ ].join("")
24
+ else
25
+ [
26
+ colored_left,
27
+ TextHighlight.green(":", plain: plain),
28
+ " ",
29
+ TextHighlight.white(right, plain: plain)
30
+ ].join("")
31
+ end
32
+ end
33
+
34
+ def draw(indent: 0, tree_key: nil, branch_toggle: [], max_depth: 10, plain: false)
35
+ return if indent > max_depth
36
+
37
+ if indent == 0
38
+ if has_children?
39
+ draw_line(indent: 0,
40
+ text: TextHighlight.yellow(@type, plain: plain),
41
+ branch_toggle: branch_toggle,
42
+ root: true,
43
+ max_depth: max_depth,)
44
+
45
+ else
46
+ draw_line(indent: 0,
47
+ text: [TextHighlight.yellow(@type, plain: plain), TextHighlight.white(@value, plain: plain)].join(" "),
48
+ branch_toggle: branch_toggle,
49
+ root: true,
50
+ max_depth: max_depth)
51
+
52
+ return
53
+ end
54
+ end
55
+
56
+ if has_children?
57
+ if tree_key
58
+ draw_line(indent: indent,
59
+ text: highlight(left: tree_key, right: @type, nested: true, plain: plain),
60
+ branch_toggle: branch_toggle,
61
+ no_children: false,
62
+ max_depth: max_depth,
63
+ plain: plain)
64
+ end
65
+
66
+ each_child_with_last do |key, value, last|
67
+ if value.is_a?(TreeNode)
68
+ value.draw(indent: indent + 1,
69
+ tree_key: key,
70
+ branch_toggle: branch_toggle + [last],
71
+ max_depth: max_depth,
72
+ plain: plain)
73
+ else
74
+ draw_line(indent: indent + 1,
75
+ text: highlight(left: key, right: value, plain: plain),
76
+ branch_toggle: branch_toggle + [last],
77
+ max_depth: max_depth,
78
+ plain: plain)
79
+ end
80
+ end
81
+ else
82
+ draw_line(indent: indent,
83
+ text: highlight(left: tree_key, right: @value, plain: plain),
84
+ branch_toggle: branch_toggle,
85
+ max_depth: max_depth,
86
+ plain: plain)
87
+ end
88
+
89
+ nil
90
+ end
91
+
92
+ def each_child_with_last(&block)
93
+ total_size = @value.size
94
+ sorted_keys = @value.keys.sort
95
+
96
+ sorted_keys.each_with_index do |key, index|
97
+ value = @value[key]
98
+
99
+ block.call(key, value, total_size - 1 == index)
100
+ end
101
+ end
102
+
103
+ def draw_line(indent: 0, text:, branch_toggle:, root: false, no_children: true, max_depth: 10, plain: false)
104
+ if root
105
+ puts text
106
+ else
107
+ previous, current = branch_toggle[0..-2], branch_toggle[-1]
108
+
109
+ indent_lines = previous.map { |item| item ? " " : " │" }.join("")
110
+
111
+ current_branch_line = current ? " └── " : " ├── "
112
+
113
+ branch_lines = TextHighlight.green([indent_lines, current_branch_line].join(""), plain: plain)
114
+
115
+ puts [branch_lines, text].join("")
116
+
117
+ if current && (no_children || (indent >= max_depth))
118
+ puts TextHighlight.green([indent_lines].join(""), plain: plain)
119
+ end
120
+ end
121
+ end
122
+
123
+ def has_children?
124
+ ["Hash", "Array"].include?(@value.class.name)
125
+ end
126
+
127
+ def self.convert(target, registered_objects: [])
128
+ if registered_objects.include?(target.object_id)
129
+ return TreeNode.new(type: target.class.name, value: "DUPLICATE #{ target.class.name }")
130
+ else
131
+ if target.is_a?(Array) || target.is_a?(Hash) || target.instance_variables.size > 0
132
+ registered_objects << target.object_id
133
+ end
134
+ end
135
+
136
+ output = {
137
+ type: nil,
138
+ value: nil
139
+ }
140
+
141
+ target_class_name = target.class.name
142
+
143
+ if target.is_a?(Hash)
144
+ output_container = {}
145
+
146
+ target.each do |hash_key, hash_value|
147
+ output_container[hash_key] = convert(hash_value, registered_objects: registered_objects)
148
+ end
149
+
150
+ output[:value] = output_container
151
+
152
+ elsif target.is_a?(Array)
153
+ output_container = {}
154
+
155
+ target.each_with_index do |array_value, index|
156
+ output_container[index] = convert(array_value, registered_objects: registered_objects)
157
+ end
158
+
159
+ output[:value] = output_container
160
+
161
+ elsif target.instance_variables.size > 0
162
+ output_container = {}
163
+
164
+ target.instance_variables.each do |name|
165
+ value = target.instance_variable_get(name)
166
+ key = name.to_s.gsub('@', '').to_sym
167
+
168
+ # use getter method instead
169
+ if target.public_methods(false).include?(key.to_sym)
170
+ output_container[key] = convert(target.send(key.to_sym), registered_objects: registered_objects)
171
+ else
172
+ output_container[key] = convert(value, registered_objects: registered_objects)
173
+ end
174
+ end
175
+
176
+ output[:value] = output_container
177
+
178
+ elsif target_class_name == "NilClass"
179
+ output[:value] = "nil"
180
+
181
+ elsif target_class_name == "IO"
182
+ output[:value] = "<IO>"
183
+
184
+ elsif target_class_name == "Thread::Mutex"
185
+ output[:value] = "<Thread::Mutex>"
186
+
187
+ elsif target_class_name == "Proc"
188
+ output[:value] = "<Proc>"
189
+
190
+ else
191
+ output[:value] = target
192
+
193
+ end
194
+
195
+ output[:type] = target_class_name
196
+
197
+ TreeNode.new(type: output[:type], value: output[:value])
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,3 @@
1
+ module Study
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: study
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Arvin Lat
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Study Ruby objects, hashes, and arrays by exposing their internal structure
42
+ with trees, colors, and indentation
43
+ email:
44
+ - joshua.arvin.lat@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - lib/study.rb
50
+ - lib/study/text_highlight.rb
51
+ - lib/study/tree_node.rb
52
+ - lib/study/version.rb
53
+ homepage: ''
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.6.8
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Study Ruby objects, hashes, and arrays by exposing their internal structure
77
+ with trees, colors, and indentation
78
+ test_files: []