helium-console 0.1.9 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -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