study 1.0.0

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.
@@ -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: []