xprint 0.8.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 (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/version.rb +3 -0
  3. data/lib/xprint.rb +313 -0
  4. metadata +46 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d8e6e0778467e8ed1efb112fc5a6fb7ee2e5463e1338dbffaf73aeeb61a75d0f
4
+ data.tar.gz: 43fef229c2551c8791d0b009cac768524fdb929a014701f16ed360981a014a7d
5
+ SHA512:
6
+ metadata.gz: 301cc656d0b4d0e62c6cf0c13486866b4249e7668700f11bcd9e58d2c4a28cac9a033b9ed3de430f64afde2ccb46f008a46e232f4ef5ca943e5371d9b17ecde9
7
+ data.tar.gz: 3ef89b719424f34e220ffc9aa77d4591dddb19fc695a64c257144fe3d1bf068b3569c8896b70ff85048a6fad0a4e4bcb6f722cd0af4c541259091228ff229c19
@@ -0,0 +1,3 @@
1
+ module XPrint
2
+ VERSION = '0.8.1'
3
+ end
@@ -0,0 +1,313 @@
1
+ require 'bigdecimal'
2
+ require 'date'
3
+
4
+ module XPrint
5
+ @data_classes = [
6
+ String, Integer, Float, TrueClass, FalseClass, NilClass,
7
+ Symbol, Date, Time, DateTime, BigDecimal, Rational
8
+ ]
9
+ @hash_name_classes = @data_classes + [Proc]
10
+ @tab = "\t"
11
+ @indexes = true
12
+ @full_proc_path = false
13
+ @braces = true
14
+ @date_format = '%F'
15
+ @time_format = '%c'
16
+ @datetime_format = '%FT%T%:z'
17
+ @color = false
18
+ @colors = {
19
+ attribute: :blue,
20
+ bigdecimal: :darkcyan,
21
+ classname: :darkgreen,
22
+ classobject: :green,
23
+ date: :red,
24
+ datetime: :purple,
25
+ false: :darkred,
26
+ float: :cyan,
27
+ index: :darkgrey,
28
+ integer: :cyan,
29
+ module: :green,
30
+ nil: :darkpurple,
31
+ proc: :darkyellow,
32
+ rational: :darkcyan,
33
+ string: :yellow,
34
+ struct: :green,
35
+ symbol: :darkblue,
36
+ time: :darkblue,
37
+ true: :darkgreen
38
+ }
39
+ @color_codes = {
40
+ black: "\e[30m",
41
+ blue: "\e[94m",
42
+ darkblue: "\e[34m",
43
+ cyan: "\e[96m",
44
+ darkcyan: "\e[36m",
45
+ green: "\e[92m",
46
+ darkgreen: "\e[32m",
47
+ grey: "\e[37m",
48
+ darkgrey: "\e[90m",
49
+ red: "\e[91m",
50
+ darkred: "\e[31m",
51
+ purple: "\e[95m",
52
+ darkpurple: "\e[35m",
53
+ yellow: "\e[93m",
54
+ darkyellow: "\e[33m",
55
+ reset: "\e[0m"
56
+ }
57
+
58
+ def self.set(**kwargs)
59
+ set_vars = {
60
+ tab: ->(data) { @tab = data },
61
+ indexes: ->(data) { @indexes = data },
62
+ full_proc_path: ->(data) { @full_proc_path = data },
63
+ braces: ->(data) { @braces = data },
64
+ date_format: ->(data) { @date_format = data },
65
+ time_format: ->(data) { @time_format = data },
66
+ datetime_format: ->(data) { @datetime_format = data },
67
+ color: ->(data) { @color = data }
68
+ }
69
+
70
+ kwargs.each do |keyword, arg|
71
+ if set_vars.key? keyword
72
+ set_vars[keyword].(arg)
73
+ end
74
+ end
75
+
76
+ return
77
+ end
78
+
79
+ def self.set_color_for(**kwargs)
80
+ kwargs.each do |keyword, arg|
81
+ @colors[keyword] = arg
82
+ end
83
+ end
84
+
85
+ def self.set_color_code_for(**kwargs)
86
+ kwargs.each do |keyword, arg|
87
+ @color_codes[keyword] = arg
88
+ end
89
+ end
90
+
91
+ def self.xp(*args)
92
+ args.each do |arg|
93
+ xpanded_text = self.xpand(arg, tab: @tab)
94
+
95
+ unless @braces
96
+ xpanded_text = self.shift_indentation_down(xpanded_text).lstrip()
97
+ end
98
+
99
+ puts xpanded_text
100
+ end
101
+ end
102
+
103
+ private_class_method def self.color_for(colorname)
104
+ @color_codes[colorname]
105
+ end
106
+
107
+ private_class_method def self.reset_color()
108
+ @color_codes[:reset]
109
+ end
110
+
111
+ private_class_method def self.colorize(text, type)
112
+ if @color
113
+ item_color = color_for @colors[type]
114
+ "#{item_color}#{text}#{reset_color}"
115
+ else
116
+ text
117
+ end
118
+ end
119
+
120
+ private_class_method def self.shift_indentation_down(text)
121
+ # Only shift if no
122
+ return text if text.match?(/^\S/)
123
+ result = ''
124
+
125
+ text.each_line do |line|
126
+ result += (
127
+ if line.start_with? @tab
128
+ line[@tab.length..-1]
129
+ else
130
+ line
131
+ end
132
+ )
133
+ end
134
+
135
+ return result
136
+ end
137
+
138
+ def self.xpand(x, indent: '', tab: "\t")
139
+
140
+ _indent = "#{tab}#{indent}"
141
+
142
+ # X is a "primitive" kind of data that has no subitems, so
143
+ # we can just print it.
144
+ if x.class == String
145
+ return colorize(x.inspect, :string)
146
+ elsif x.class == Integer
147
+ return colorize(x.inspect, :integer)
148
+ elsif x.class == Float
149
+ return colorize(x.inspect, :float)
150
+ elsif x.class == TrueClass
151
+ return colorize(x.inspect, :true)
152
+ elsif x.class == FalseClass
153
+ return colorize(x.inspect, :false)
154
+ elsif x.class == NilClass
155
+ return colorize(x.inspect, :nil)
156
+ elsif x.class == Symbol
157
+ return colorize(x.inspect, :symbol)
158
+
159
+ # X is a Proc, print more compact version of standard Proc.inspect
160
+ # text.
161
+ elsif x.class == Proc
162
+ type = x.lambda? ? 'Lambda' : 'Proc'
163
+ source, line = x.source_location
164
+ source = source.gsub('\\', '/')
165
+
166
+ unless @full_proc_path
167
+ source = source.split('/')[-2..-1].join('/')
168
+ end
169
+
170
+ return colorize("<#{type} @ #{source} [Line #{line}]>", :proc)
171
+
172
+ elsif x.class == Class
173
+ return colorize("<Class #{x}>", :classobject)
174
+
175
+ # X is an Array, print list of all items.
176
+ elsif x.class == Array
177
+ result = "#{@braces ? '[' : ''}\n"
178
+
179
+ x.each_with_index do |item, index|
180
+ data = xpand(item, indent: _indent, tab: tab)
181
+
182
+ result += "#{_indent}"
183
+ result += "#{colorize("[#{index}]", :index)} " if @indexes
184
+ result += "#{data}"
185
+
186
+ unless index + 1 == x.length
187
+ result += "#{@braces ? ', ' : ''} \n"
188
+ end
189
+ end
190
+
191
+ result += "\n#{indent}]" if @braces
192
+ return result
193
+
194
+ # X is a Hash, print all keys and values.
195
+ elsif x.class == Hash
196
+ result = "#{@braces ? '{' : ''}\n"
197
+
198
+ longest_key = (
199
+ x.keys.filter do |k, v|
200
+ @hash_name_classes.include? k.class
201
+ end.
202
+ map do |k, v|
203
+ k.to_s.length
204
+ end.
205
+ max()
206
+ )
207
+
208
+ longest_key = 0 if longest_key.nil?
209
+
210
+ # Color codes throw the text length, so we need to add the
211
+ # length of the color code and the code to reset the color
212
+ # that wrap around the colored word.
213
+ # The color code is like "\e[99m" and the reset "\e[0m",
214
+ # so the total length to add when using color is 9.
215
+ longest_key += 9 if @color
216
+
217
+ x.each_with_index do |(key, value), index|
218
+ data_key = "#{xpand(key, indent: _indent, tab: tab)}"
219
+
220
+ data_key = (
221
+ if @hash_name_classes.include? key.class
222
+ data_key.ljust(longest_key + 1)
223
+ else
224
+ data_key.ljust(data_key.length + longest_key)
225
+ end
226
+ )
227
+
228
+ data_value = xpand(value, indent: _indent, tab: tab)
229
+
230
+ result += "#{_indent}#{data_key} => #{data_value}"
231
+
232
+ unless index + 1 == x.length
233
+ result += "#{@braces ? ', ' : ''} \n"
234
+ end
235
+ end
236
+
237
+ result += "\n#{indent}}" if @braces
238
+
239
+ return result
240
+
241
+ # X is a commonly used special kind of object.
242
+ elsif x.class == DateTime
243
+ datetime = x.strftime @datetime_format
244
+ return colorize("DateTime(#{datetime})", :datetime)
245
+
246
+ elsif x.class == Date
247
+ date = x.strftime @date_format
248
+ return colorize("Date(#{date})", :date)
249
+
250
+ elsif x.class == Time
251
+ time = x.strftime @time_format
252
+ return colorize("Time(#{time})", :time)
253
+
254
+ elsif x.class == BigDecimal
255
+ return colorize("BigDecimal(#{x.to_s('f')})", :bigdecimal)
256
+
257
+ elsif x.class == Rational
258
+ return colorize("Rational(#{x})", :rational)
259
+
260
+ # X is a Structure; essentially a special case of X being an object.
261
+ elsif x.is_a? Struct
262
+ struct_word = colorize('Struct', :struct)
263
+ classname = colorize(x.class, :struct)
264
+ result = "#{struct_word} #{classname}#{@braces ? '(' : ''}\n"
265
+ longest_item = x.members.map { |m| m.to_s.length }.max()
266
+
267
+ x.each_pair do |name, value|
268
+ attr_name = colorize(name.to_s.ljust(longest_item), :attribute)
269
+ attr_data = xpand(value, indent: _indent, tab: tab)
270
+
271
+ result += "#{_indent}#{attr_name} = #{attr_data}\n"
272
+ end
273
+
274
+ result += "#{indent})" if @braces
275
+
276
+ return result
277
+
278
+ # X is any arbitrary object; print all instance variables.
279
+ else
280
+ is_module = x.class == Module
281
+ classname = is_module ? "Module #{x}" : x.class
282
+ classname = colorize(classname, is_module ? :module : :classname)
283
+ result = "#{classname}#{@braces ? '(' : ''}"
284
+ ivars = x.instance_variables
285
+ result += "\n" if ivars.length > 0
286
+ longest_var = ivars.map { |v| v.to_s.length }.max()
287
+
288
+ ivars.each_with_index do |var, index|
289
+ attr_name = var.to_s.ljust(longest_var)
290
+ attr_name = colorize(attr_name, :attribute)
291
+ attr_data = xpand(
292
+ x.instance_variable_get(var),
293
+ indent: _indent,
294
+ tab: tab
295
+ )
296
+
297
+ result += "#{_indent}#{attr_name} = #{attr_data}\n"
298
+ end
299
+
300
+ result += "#{ivars.length > 0 ? indent: ''})" if @braces
301
+
302
+ return result
303
+ end
304
+ end
305
+ end
306
+
307
+ def xp(*args)
308
+ XPrint::xp(*args)
309
+ end
310
+
311
+ def xpand(item, tab: "\t")
312
+ XPrint::xpand(item, tab: tab)
313
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xprint
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.1
5
+ platform: ruby
6
+ authors:
7
+ - JCabr
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Gem that allows for pretty printing data over multiple lines and with
14
+ indentation, and works with objects as well as basic data types.
15
+ email:
16
+ - jcabr.dev@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/version.rb
22
+ - lib/xprint.rb
23
+ homepage: https://github.com/JCabr/xprint.rb
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubygems_version: 3.1.2
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Gem for pretty printing any kind of object.
46
+ test_files: []