helium-console 0.1.9 → 0.1.13

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,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helium
4
+ class Console
5
+ define_formatter_for 'Date' do
6
+ def render_inline
7
+ blue object.strftime('%A, %d %b %Y')
8
+ end
9
+
10
+ def render_compact
11
+ blue object.strftime('%d/%m/%Y')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -3,7 +3,13 @@
3
3
  module Helium
4
4
  class Console
5
5
  define_formatter_for Hash do
6
- def call
6
+ def render_compact
7
+ return '{}' unless object.any?
8
+
9
+ "##{format object.class, :compact}#{light_black "[#{object.size}]"}"
10
+ end
11
+
12
+ def render_partial
7
13
  return '{}' if object.none?
8
14
  return inline_with_truncation if force_inline?
9
15
 
@@ -13,23 +19,27 @@ module Helium
13
19
  private
14
20
 
15
21
  def format_as_table
16
- table = Table.new(runner: ' ', after_key: after_key, format_keys: !all_symbol?)
17
- object.each do |key, value|
18
- key = light_blue(key.to_s) if all_symbol?
19
- table.row(key, value)
22
+ key_value = build_key_value do |kv|
23
+ object.each do |key, value|
24
+ key = light_blue(key.to_s) if all_symbol?
25
+ kv.row(key, value)
26
+ end
20
27
  end
21
28
 
22
- [
23
- '{',
24
- format(table, **options),
25
- '}'
26
- ].join("\n")
29
+ yield_lines do |y|
30
+ y << '{'
31
+ format_key_value(key_value, left: ' ', between: after_key,
32
+ format_keys: all_symbol? ? false : {}).lines.each do |line|
33
+ y << line
34
+ end
35
+ y << '}'
36
+ end
27
37
  end
28
38
 
29
39
  def inline_with_truncation
30
40
  truncated = formatted_inline_elements.with_index.inject([]) do |collected, (formatted, index)|
31
41
  new_collected = [*collected[0..-2], formatted, trunc_text(index + 1)].compact
32
- break collected if new_collected.join(', ').length > max_width - 4
42
+ break collected if length_of(new_collected.join(', ')) > max_width - 4
33
43
 
34
44
  new_collected
35
45
  end
@@ -55,15 +65,18 @@ module Helium
55
65
  end
56
66
 
57
67
  def formatted_inline_elements
68
+ max_width = 15 unless level == 1
58
69
  object.each.lazy.map do |key, value|
59
- formatted_key = format_key(key, max_lines: 1, nesting: 1, max_with: 15)
60
- formatted_value = format_nested(value, max_lines: 1, nesting: 1, max_width: 15)
70
+ formatted_key = format_key(key, max_lines: 1, nesting: 1, max_with: max_width)
71
+ formatted_value = format_nested(value, max_lines: 1, nesting: 1, max_width: max_width)
61
72
  [formatted_key, after_key, formatted_value].join
62
73
  end
63
74
  end
64
75
 
65
76
  def all_symbol?
66
- object.keys.all? { |key| key.is_a? Symbol }
77
+ return @all_symbol if defined?(@all_symbol)
78
+
79
+ @all_symbol = object.keys.all? { |key| key.is_a? Symbol }
67
80
  end
68
81
 
69
82
  def format_key(key, **options)
@@ -78,6 +91,8 @@ module Helium
78
91
 
79
92
  def trunc_text(count)
80
93
  truncated_elements = total_elements - count
94
+ return if truncated_elements.zero?
95
+
81
96
  light_black("(#{truncated_elements} #{count.zero? ? 'elements' : 'more'})")
82
97
  end
83
98
 
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helium
4
+ class Console
5
+ define_formatter_for Method do
6
+ def render_full
7
+ as_table(source: true)
8
+ end
9
+
10
+ def render_partial
11
+ as_table(source: false)
12
+ end
13
+
14
+ def render_compact
15
+ "#{yellow 'method'} #{title}"
16
+ end
17
+
18
+ private
19
+
20
+ # TODO: he method below breaks ABCSize, most likely due to an amount of colouring method calls.
21
+ # This should be simplified by altering table handling: https://github.com/helium-rb/console/issues/10
22
+ def as_table(source:) # rubocop:disable Metrics/AbcSize
23
+ key_value = build_key_value do |kv|
24
+ kv.row(magenta('receiver'), object.receiver)
25
+ kv.row(magenta('location'), object.source_location&.join(':'))
26
+ kv.row(magenta('source'), trimmed_source, format_value: false) if source && object.source_location
27
+ end
28
+
29
+ yield_lines do |y|
30
+ y << "#{light_black '#'} #{render_compact}"
31
+ format_key_value(key_value, left: light_black('| '), format_keys: false, between: light_black(': '))
32
+ .lines.each { |line| y << line }
33
+ end
34
+ end
35
+
36
+ def title
37
+ formatted_owner = format(owner, :compact)
38
+ formatted_owner = "(#{formatted_owner})" unless owner.is_a? Module
39
+
40
+ "#{formatted_owner}#{yellow(singleton_owner? ? '.' : '#')}#{yellow object.name.to_s}"
41
+ end
42
+
43
+ def owner
44
+ return @owner if defined?(@owner)
45
+
46
+ @owner = object.owner
47
+ if singleton_owner?
48
+ @owner = object.receiver
49
+ @owner = owner.ancestors.find { |ancestor| ancestor.singleton_class == object.owner } if owner.is_a? Class
50
+ end
51
+ @owner
52
+ end
53
+
54
+ def singleton_owner?
55
+ object.owner.singleton_class?
56
+ end
57
+
58
+ def trimmed_source
59
+ indent = object.source.lines.map { |line| line =~ /[^ ]/ }.min
60
+ object.source.lines.map { |line| line[indent..-1] }.join.chomp
61
+ end
62
+ end
63
+ end
64
+ end
@@ -2,22 +2,34 @@
2
2
 
3
3
  module Helium
4
4
  class Console
5
- define_formatter_for Module do
6
- def call
7
- light_yellow(object.name || anonymous_text)
5
+ define_class_formatter_for BasicObject do
6
+ def render_compact
7
+ class_name || singleton_name || anonymous_text
8
8
  end
9
9
 
10
10
  private
11
11
 
12
+ def class_name
13
+ light_yellow(object.name) if object.name
14
+ end
15
+
16
+ def singleton_name
17
+ return unless object.is_a?(Class) && object.singleton_class?
18
+
19
+ owner = ObjectSpace.each_object(object).first
20
+ "#{light_yellow 'singleton class of'} #{format owner, :compact}"
21
+ end
22
+
12
23
  def anonymous_text
13
24
  closest = (object.ancestors.grep(Class) - [Object, BasicObject]).find(&:name)&.name
14
25
 
15
26
  signature = if closest
16
- "subclass of #{closest}"
27
+ "#{light_yellow 'subclass of'} #{format closest, :compact}"
17
28
  else
18
- object.class.name.downcase
29
+ light_yellow(object.class.name.downcase)
19
30
  end
20
- "(anonymous #{signature})"
31
+
32
+ "#{light_yellow '('}#{signature})#{light_yellow ')'}"
21
33
  end
22
34
  end
23
35
  end
@@ -3,7 +3,7 @@
3
3
  module Helium
4
4
  class Console
5
5
  define_formatter_for NilClass do
6
- def call
6
+ def render_compact
7
7
  light_black('nil')
8
8
  end
9
9
  end
@@ -3,9 +3,15 @@
3
3
  module Helium
4
4
  class Console
5
5
  define_formatter_for Numeric do
6
- def call
6
+ def render_compact
7
7
  light_cyan(object.to_s)
8
8
  end
9
9
  end
10
+
11
+ define_formatter_for 'BigDecimal' do
12
+ def render_compact
13
+ light_cyan(object.to_s('F'))
14
+ end
15
+ end
10
16
  end
11
17
  end
@@ -3,28 +3,17 @@
3
3
  module Helium
4
4
  class Console
5
5
  define_formatter_for Object do
6
- def call
7
- return inline_with_truncation if force_inline?
6
+ def optimal_format
7
+ return [:compact, {}] if object.instance_variables.none?
8
8
 
9
- format_as_table
9
+ super
10
10
  end
11
11
 
12
- private
13
-
14
- def format_as_table
15
- table = Table.new(runner: light_black('| '), after_key: light_black(': '), format_keys: false)
16
-
17
- object.instance_variables.each do |inst|
18
- table.row(magenta(inst.to_s), object.instance_variable_get(inst))
19
- end
20
-
21
- [
22
- "#{light_black '#'} #{class_name}",
23
- format(table)
24
- ].reject(&:empty?).join("\n")
12
+ def render_compact
13
+ "#{format object.class, :compact}#{light_black "##{object.object_id}"}"
25
14
  end
26
15
 
27
- def inline_with_truncation
16
+ def render_inline
28
17
  class_name = class_name(short: true)
29
18
 
30
19
  vars = formatted_instance_variables(max_width: 15, max_lines: 1).inject([]) do |collected, element|
@@ -38,30 +27,22 @@ module Helium
38
27
  [class_name, formatted_vars].compact.join
39
28
  end
40
29
 
41
- # def inline_without_truncation
42
- # joined = nil
43
- #
44
- # object.each do |key, value|
45
- # return unless simple?(value)
46
- #
47
- # formatted_key = format(key, level: 3, max_with: 15)
48
- # formatted_value = format(value, level: 3, max_width: 15)
49
- # formatted = "#{formatted_key} => #{formatted_value}"
50
- #
51
- # joined = [joined, formatted].compact.join(', ')
52
- #
53
- # return if joined.length > max_width - 4
54
- # end
55
- # joined = " #{joined} " if joined
56
- # ['{', joined, '}'].compact.join
57
- # end
58
-
59
- def force_inline?
60
- level > 2
30
+ def render_partial
31
+ yield_lines do |y|
32
+ y << "#{light_black '#'} #{class_name}"
33
+ as_table.lines.each { |line| y << line }
34
+ end
61
35
  end
62
36
 
63
- def all_symbol?
64
- object.keys.all? { |key| key.is_a? Symbol }
37
+ private
38
+
39
+ def as_table
40
+ key_value = build_key_value do |kv|
41
+ object.instance_variables.each do |inst|
42
+ kv.row(magenta(inst.to_s), object.instance_variable_get(inst))
43
+ end
44
+ end
45
+ format_key_value(key_value, left: light_black('| '), between: light_black(': '), format_keys: false)
65
46
  end
66
47
 
67
48
  def formatted_instance_variables(**options)
@@ -72,7 +53,7 @@ module Helium
72
53
  end
73
54
 
74
55
  def class_name(short: false)
75
- formatted = format(object.class, short: short)
56
+ formatted = format(object.class, :compact)
76
57
  short ? "##{formatted}" : "#{formatted} instance"
77
58
  end
78
59
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helium
4
+ class Console
5
+ define_formatter_for 'Pathname' do
6
+ def render_compact
7
+ "#{format(Pathname, :compact)}: #{yellow(object.to_s)}"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helium
4
+ class Console
5
+ define_formatter_for 'Set' do
6
+ def render_compact
7
+ return render_empty if object.none?
8
+
9
+ "#{light_magenta('Set:')} #{trunc_message(object.count, all_truncated: true)}"
10
+ end
11
+
12
+ def render_partial
13
+ return render_empty if object.none?
14
+ return inline_with_truncation if options[:max_lines] == 1
15
+
16
+ inline_without_truncation || format_as_table
17
+ end
18
+
19
+ def simple?
20
+ object.none?
21
+ end
22
+
23
+ private
24
+
25
+ def render_empty
26
+ "#{light_magenta('Set:')} #{red 'empty'}"
27
+ end
28
+
29
+ def format_as_table
30
+ table = Table.new(runner: '', format_keys: false)
31
+ object.each do |element|
32
+ table.row(light_black('-'), element)
33
+ end
34
+
35
+ yield_lines do |y|
36
+ y << light_magenta('Set: {')
37
+ format(table).lines.each { |line| y << line }
38
+ y << light_magenta('}')
39
+ end
40
+ end
41
+
42
+ def inline_with_truncation
43
+ formatted = formatted_elements.with_index.inject([]) do |joined, (element, index)|
44
+ new_joined = [*joined[0..-2], element, trunc_message(object_size - index - 1, all_truncated: index.zero?)]
45
+ break joined if too_long?(new_joined, max_width: max_width - 9)
46
+
47
+ new_joined
48
+ end
49
+
50
+ "#{light_magenta('Set: {')} #{formatted.join(light_magenta(' | '))} #{light_magenta('}')}"
51
+ end
52
+
53
+ def inline_without_truncation
54
+ return unless object.all? { |element| Helium::Console.simple? element }
55
+
56
+ formatted = formatted_elements.inject([]) do |joined, element|
57
+ joined = [*joined, element]
58
+ break if too_long?(joined, max_width: max_width - 4)
59
+
60
+ joined
61
+ end
62
+
63
+ "#{light_magenta('Set: {')} #{formatted.join(light_magenta(' | '))} #{light_magenta('}')}" unless formatted.nil?
64
+ end
65
+
66
+ def too_long?(object, max_width:)
67
+ string = object.respond_to?(:join) ? object.join(' | ') : object
68
+ length_of(string) > max_width - 4
69
+ end
70
+
71
+ def formatted_elements(**options)
72
+ sorted = begin
73
+ object.sort
74
+ rescue StandardError
75
+ object
76
+ end
77
+ sorted.each.lazy.map { |element| format_nested(element, **options) }
78
+ end
79
+
80
+ def trunc_message(count, all_truncated: false)
81
+ return if count < 1
82
+
83
+ light_black "(#{count} #{all_truncated ? 'elements' : 'more'})"
84
+ end
85
+
86
+ def object_size
87
+ @object_size ||= object.size
88
+ end
89
+ end
90
+ end
91
+ end
@@ -3,26 +3,46 @@
3
3
  module Helium
4
4
  class Console
5
5
  define_formatter_for String do
6
- def call
7
- formatted = Helium::Console.format_string(
8
- object.dump.gsub('\n', "\n"),
6
+ def render_compact
7
+ render_string(object, max_width: 15, max_lines: 1)
8
+ end
9
+
10
+ def render_inline
11
+ render_string(object.gsub("\n", '\n'), max_lines: 1)
12
+ end
13
+
14
+ def render_partial
15
+ render_string(object, max_lines: max_lines || 3)
16
+ end
17
+
18
+ def render_full
19
+ render_string(object)
20
+ end
21
+
22
+ def simple?
23
+ object.lines.count == 1 && length_of(object) < 15
24
+ end
25
+
26
+ def render_string(string, max_lines: self.max_lines, max_width: self.max_width)
27
+ formatted = format_string(
28
+ "\"#{string.gsub('"', '\"')}\"",
9
29
  max_width: max_width,
10
30
  max_lines: max_lines,
11
31
  overflow: overflow,
12
- ellipses: '..."'
32
+ ellipses: '..."',
33
+ indent: indent
13
34
  )
14
35
 
15
- formatted.lines
16
- .map { |line| light_green(line) }
17
- .join
36
+ result = formatted.lines
37
+ .map { |line| light_green(line.chomp) }
38
+ .join("\n")
39
+
40
+ result = "#{result}\n" if formatted.end_with?("\n")
41
+ result
18
42
  end
19
43
 
20
44
  def max_lines
21
- case level
22
- when 1 then nil
23
- when 2 then 3
24
- else 1
25
- end
45
+ @options[:max_lines]
26
46
  end
27
47
  end
28
48
  end
@@ -3,7 +3,7 @@
3
3
  module Helium
4
4
  class Console
5
5
  define_formatter_for Symbol do
6
- def call
6
+ def render_compact
7
7
  light_blue(":#{object}")
8
8
  end
9
9
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helium
4
+ class Console
5
+ define_formatter_for Time do
6
+ def render_inline
7
+ blue object.strftime('%A, %d %b %Y, %H:%M:%S')
8
+ end
9
+
10
+ def render_compact
11
+ blue object.strftime('%d/%m/%Y, %H:%M')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,77 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'colorized_string'
3
+ require 'helium/console/colorized_string'
4
+ require 'helium/console/formatter'
4
5
 
5
6
  module Helium
6
7
  class Console
7
8
  class Registry
8
- class Element
9
- def initialize(object, **options)
10
- @object = object
11
- @options = options
12
- end
13
-
14
- def call
15
- end
16
-
17
- attr_reader :object, :options
18
-
19
- def format_nested(other_object, **options)
20
- Helium::Console.format(other_object, **nested_opts(options))
21
- end
22
-
23
- def format(other_object, **options)
24
- Helium::Console.format(other_object, **nested_opts(options, increase_level: false))
25
- end
26
-
27
- def format_string(string, **options)
28
- Helium::Console.format_string(string, **options)
29
- end
30
-
31
- def simple?
32
- false
33
- end
34
-
35
- def method_missing(name, *args)
36
- return @options[name] if @options.key?(name)
37
- return ColorizedString.new(*args).colorize(name) if ColorizedString.colors.include?(name)
38
-
39
- super
40
- end
41
-
42
- def respond_to_missing?(name, private = false)
43
- @options.key?(name) || ColorizedString.colors.include?(name) || super
44
- end
45
-
46
- def nested_opts(new_options, increase_level: true)
47
- new_options = options.merge(new_options)
48
- new_options[:level] += 1 if increase_level
49
- new_options[:ignore_objects] << object.object_id
50
- new_options
51
- end
9
+ def self.instance_formatters
10
+ @instance_formatters ||= new
11
+ end
52
12
 
53
- def length_of(string)
54
- ColorizedString.new(string).uncolorize.length
55
- end
13
+ def self.class_formatters
14
+ @class_formatters ||= new
56
15
  end
57
16
 
58
- def add(klass, &handler)
59
- define(klass) do
60
- define_method(:call, &handler)
61
- end
17
+ def add(mod, formatter)
18
+ handlers[mod] = formatter
62
19
  end
63
20
 
64
- def define(klass, &block)
65
- handlers[klass] = Class.new(Element, &block)
21
+ def define(mod, &block)
22
+ add(mod, Class.new(Formatter, &block))
66
23
  end
67
24
 
68
- def handler_for(object, **options)
69
- element_class = object.class.ancestors.find do |ancestor|
70
- break handlers[ancestor] if handlers.key?(ancestor)
25
+ def handler_for(klass)
26
+ klass.ancestors.each do |ancestor|
27
+ result = handlers[ancestor] || handlers[ancestor.name]
28
+ return result if result
71
29
  end
72
- return unless element_class
73
-
74
- element_class.new(object, **options)
30
+ handlers[BasicObject]
75
31
  end
76
32
 
77
33
  private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Helium
4
4
  class Console
5
- VERSION = '0.1.9'
5
+ VERSION = '0.1.13'
6
6
  end
7
7
  end