helium-console 0.1.11 → 0.1.12
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +69 -13
- data/bin/console +1 -1
- data/lib/helium/console/colorized_string.rb +19 -0
- data/lib/helium/console/formatter.rb +116 -0
- data/lib/helium/console/printer.rb +14 -7
- data/lib/helium/console/prompt.rb +42 -0
- data/lib/helium/console/registry/array.rb +13 -3
- data/lib/helium/console/registry/booleans.rb +2 -2
- data/lib/helium/console/registry/date.rb +5 -1
- data/lib/helium/console/registry/hash.rb +13 -4
- data/lib/helium/console/registry/method.rb +53 -0
- data/lib/helium/console/registry/module.rb +18 -6
- data/lib/helium/console/registry/nil.rb +1 -1
- data/lib/helium/console/registry/numeric.rb +1 -1
- data/lib/helium/console/registry/object.rb +20 -23
- data/lib/helium/console/registry/pathname.rb +2 -2
- data/lib/helium/console/registry/set.rb +20 -13
- data/lib/helium/console/registry/string.rb +32 -12
- data/lib/helium/console/registry/symbol.rb +1 -1
- data/lib/helium/console/registry/table.rb +4 -4
- data/lib/helium/console/registry/time.rb +5 -1
- data/lib/helium/console/registry.rb +16 -83
- data/lib/helium/console/table.rb +2 -2
- data/lib/helium/console/version.rb +1 -1
- data/lib/helium/console.rb +43 -28
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eaa7f60f45f5dfc8e2debd5115c10760755ea71ae485328300af7d4a36cff972
|
4
|
+
data.tar.gz: ce41d603bfcee8df481f4132cf2b82a03842de53452474d4b71fd65d6a676d5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbd742302810644a5c0e18d9ea1bb2bb1fef2d1995a2670dea2996478cc8eaf3232b07ba42785a84e9f9bb8fbc1d57a462cf3583747d0b3366f3a8072aab1fc2
|
7
|
+
data.tar.gz: 52cfe0ed72fddd80f8c61f4063d01ff8305a0a00ca88944fc73a0d3e1e466abdc262ab55b0fd050b27891af35dad0e349fd7e5d4b08904b0da30bec90d2e43e7
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# Helium::Console
|
2
2
|
|
3
|
+
Readable console output for your ruby project!
|
4
|
+
|
3
5
|
It is really tricky to display data in the console in the readable and consistent way. Many objects needs to display other objects, which might break their own formatting.
|
4
|
-
Helium:Console is to make
|
6
|
+
Helium:Console is an attempt to make your development console more readable by:
|
7
|
+
* limiting displayed nesting levels to 3
|
8
|
+
* limiting data displayed for nested objects
|
9
|
+
* using nested table layout
|
10
|
+
* automatically dividing and wrapping long strings
|
5
11
|
|
6
12
|
## Installation
|
7
13
|
|
@@ -21,24 +27,74 @@ Or install it yourself as:
|
|
21
27
|
|
22
28
|
## Usage
|
23
29
|
|
24
|
-
|
30
|
+
You can start helium console same way as you would start Pry:
|
31
|
+
|
32
|
+
``` ruby
|
33
|
+
require 'helium/console'
|
34
|
+
Helium::Console.start
|
35
|
+
```
|
36
|
+
|
37
|
+
### Custom formatters
|
38
|
+
|
39
|
+
Helium::Console hooks into pry and brings a number of default formatters. Unlike IRB and Pry, it does not use object's methods for display
|
40
|
+
(so no `inspect` nor `pretty_print`) and replaces them by the collection of inheritable formatters objects stored in its registry.
|
41
|
+
|
42
|
+
Formatter can be any object that conforms to the following interface:
|
43
|
+
* `initialize(object_to_format, format, console_instance, **options)`
|
44
|
+
* `call` method returning any object responding to `lines` (e.g. `String` )
|
45
|
+
|
46
|
+
Formatter bellow will simply return a result of `inspect` call on the object:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class InspectFormatter
|
50
|
+
def initialize(object, _console, **)
|
51
|
+
@object = object
|
52
|
+
end
|
53
|
+
|
54
|
+
def call
|
55
|
+
@object.inspect
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
You can register your formatter in console registry with:
|
25
61
|
|
62
|
+
```ruby
|
63
|
+
Helium::Console.register(Kernel, InspectFormatter)
|
26
64
|
```
|
27
|
-
|
28
|
-
|
29
|
-
|
65
|
+
|
66
|
+
The call above makes `InspectFormatter` available for all the objects that derives from Kernel module.
|
67
|
+
|
68
|
+
To make formatting easier, you can subclass your formatter from `Helium::Console::Registry::Element`. By doing so, the following methods will be available to you inside your formatter class:
|
69
|
+
* `object`, `console` and `options` readers
|
70
|
+
* default `call` implementation, delegating formatting to one
|
71
|
+
* `format(other_object, **options)` - formats some other object **using the exact same options, including nesting level**.
|
72
|
+
* `format_nested(other_object, **options)` - as above, but increases nesting level.
|
73
|
+
* `format_string(string, **options)` - formats string by splitting it into lines of appropriate length and truncating (depending on nesting level).
|
74
|
+
This is different to `format` and `format_nested` as it will not trigger `String` formatter (which by default adds quotes, escapes inner quotes and colors the result light green)
|
75
|
+
* `red(string)`, `light_red(string)`, `yellow(string)`, etc - returns colorized string when `Pry.color` is set to true.
|
76
|
+
* `length_of(string)` - utility option returning the length of displayed string, handling both colorized and non-colorized strings.
|
77
|
+
|
78
|
+
### Displaying as a table
|
79
|
+
|
80
|
+
To display object in a form of a table, format instance of `Helium::Console::Table`:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class MyFormatter < Helium::Console::Registry::Element
|
84
|
+
def call
|
85
|
+
table = Helium::Console::Table.new(runner: '--@', after_key: '--@--', format_keys: false)
|
86
|
+
table.row magenta("property 1"), object.prop1
|
87
|
+
table.row magenta("property 2"), object.instance_variable_get(:@prop2)
|
88
|
+
|
89
|
+
format table
|
90
|
+
end
|
91
|
+
end
|
30
92
|
```
|
31
93
|
|
32
|
-
|
94
|
+
Table will automatically format all the right-hand values with an increased nesting level. By default, it will also format the left-hand keys, however this is controlled with `format_keys` option.
|
33
95
|
|
34
|
-
|
96
|
+
Other options: `runner` is a string to be displayed at the beginning of each line, and `after_key` is a string to be injected between left and right values.
|
35
97
|
|
36
|
-
* `indent` - specifies the amount of spaces added to each new line. Also accepts hash `{first:, other:}`. Defaults to 0.
|
37
|
-
* `overflow` - specifies how to handle lines longer than console line width.
|
38
|
-
* `:wrap` - splits the long line into few lines and applies the required indent.
|
39
|
-
* `:wrap_words` - similar to wrap, but will try to avoid breaking the words.
|
40
|
-
* `:none` - does not modify long strings.
|
41
|
-
* `max-lines` - specifies how many lines to display. Last line will be truncated with `...`. Defaults to `nil`
|
42
98
|
|
43
99
|
## Development
|
44
100
|
|
data/bin/console
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'colorized_string'
|
4
|
+
|
5
|
+
module Helium
|
6
|
+
class Console
|
7
|
+
class ColorizedString < ColorizedString
|
8
|
+
def length
|
9
|
+
uncolorize.to_s.length
|
10
|
+
end
|
11
|
+
|
12
|
+
def colorize(*)
|
13
|
+
return self unless Pry.color
|
14
|
+
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Helium
|
4
|
+
class Console
|
5
|
+
class Formatter
|
6
|
+
DEFAULT_STYLES = {
|
7
|
+
1 => [:full, {}],
|
8
|
+
2 => [:partial, {}],
|
9
|
+
3 => [:partial, { max_lines: 1 }]
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
class LazyStringEvaluator
|
13
|
+
def initialize(&block)
|
14
|
+
@lines = Enumerator.new { |y| block.(y) }
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :lines
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
lines.to_a.join
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(object, style, console, **options)
|
25
|
+
@object = object
|
26
|
+
@options = options
|
27
|
+
@style = style
|
28
|
+
@console = console
|
29
|
+
end
|
30
|
+
|
31
|
+
def call
|
32
|
+
method_name = [:render, @style].compact.join('_')
|
33
|
+
public_send(method_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def optimal_format
|
37
|
+
DEFAULT_STYLES.fetch(level) { [:compact, {}] }
|
38
|
+
end
|
39
|
+
|
40
|
+
def render
|
41
|
+
format(object, *optimal_format)
|
42
|
+
end
|
43
|
+
|
44
|
+
def render_full
|
45
|
+
render_partial
|
46
|
+
end
|
47
|
+
|
48
|
+
def render_partial
|
49
|
+
format_string(render_inline, max_width: max_width, indent: indent)
|
50
|
+
end
|
51
|
+
|
52
|
+
def render_inline
|
53
|
+
render_compact
|
54
|
+
end
|
55
|
+
|
56
|
+
def render_compact
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :object, :options
|
61
|
+
|
62
|
+
def format_nested(other_object, style = nil, **options)
|
63
|
+
@console.format(other_object, style, **nested_opts(options))
|
64
|
+
end
|
65
|
+
|
66
|
+
def format(other_object, style = nil, **options)
|
67
|
+
@console.format(other_object, style, **nested_opts(options, increase_level: false))
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_string(string, **options)
|
71
|
+
@console.format_string(string, **options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def simple?
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
ColorizedString.colors.each do |color|
|
79
|
+
define_method color do |string|
|
80
|
+
ColorizedString.new(string).colorize(color)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def method_missing(name, *args)
|
85
|
+
return @options[name] if @options.key?(name)
|
86
|
+
|
87
|
+
super
|
88
|
+
end
|
89
|
+
|
90
|
+
def respond_to_missing?(name, private = false)
|
91
|
+
@options.key?(name) || super
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def nested_objects
|
97
|
+
[]
|
98
|
+
end
|
99
|
+
|
100
|
+
def nested_opts(new_options, increase_level: true)
|
101
|
+
new_options = options.merge(new_options)
|
102
|
+
new_options[:level] += 1 if increase_level
|
103
|
+
new_options[:ignore_objects] = nested_objects
|
104
|
+
new_options
|
105
|
+
end
|
106
|
+
|
107
|
+
def length_of(string)
|
108
|
+
ColorizedString.new(string).length
|
109
|
+
end
|
110
|
+
|
111
|
+
def yield_lines(&block)
|
112
|
+
LazyStringEvaluator.new(&block)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -11,15 +11,22 @@ module Helium
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def pp(object)
|
14
|
-
formatted = Helium::Console.format(object)
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
formatted = Helium::Console.format(object, max_width: maxwidth)
|
15
|
+
start_new_line = formatted.is_a?(Formatter::LazyStringEvaluator)
|
16
|
+
byebug if !formatted
|
17
|
+
start_new_line ||= formatted.lines.count > 1
|
18
|
+
start_new_line ||= length_of(formatted.chomp) >= maxwidth - 2
|
19
|
+
output << "\n" if start_new_line
|
20
|
+
|
21
|
+
formatted.lines.each.with_index do |line, index|
|
22
|
+
output << "\n" unless index.zero?
|
23
|
+
output << line.chomp
|
18
24
|
end
|
19
|
-
output << "\n"
|
20
25
|
end
|
21
26
|
|
22
|
-
|
27
|
+
def length_of(str)
|
28
|
+
ColorizedString.new(str).uncolorize.length
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
25
|
-
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Helium
|
2
|
+
class Console
|
3
|
+
class Prompt
|
4
|
+
def initialize
|
5
|
+
@line = 0
|
6
|
+
end
|
7
|
+
|
8
|
+
def pry_prompt
|
9
|
+
Pry::Prompt.new(
|
10
|
+
'helium',
|
11
|
+
'Default prompt for helium',
|
12
|
+
[
|
13
|
+
method(:active_prompt),
|
14
|
+
method(:wait_prompt)
|
15
|
+
]
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def active_prompt(context, _nesting, _pry)
|
22
|
+
@line += 1
|
23
|
+
str = [
|
24
|
+
ColorizedString.new("[#{@line}]").light_black,
|
25
|
+
ColorizedString.new("He\u269B").light_blue,
|
26
|
+
ColorizedString.new("(#{context.inspect})").magenta
|
27
|
+
].join(' ')
|
28
|
+
"#{str}> "
|
29
|
+
end
|
30
|
+
|
31
|
+
def wait_prompt(context, nesting, pry)
|
32
|
+
@line += 1
|
33
|
+
str = [
|
34
|
+
ColorizedString.new("[#{@line}]").light_black,
|
35
|
+
' ',
|
36
|
+
ColorizedString.new("(#{context.inspect})").magenta
|
37
|
+
].join(' ')
|
38
|
+
"#{str}> "
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -3,13 +3,23 @@
|
|
3
3
|
module Helium
|
4
4
|
class Console
|
5
5
|
define_formatter_for Array do
|
6
|
-
def
|
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
|
|
10
16
|
inline_without_truncation || format_as_table
|
11
17
|
end
|
12
18
|
|
19
|
+
def render_inline
|
20
|
+
inline_with_truncation
|
21
|
+
end
|
22
|
+
|
13
23
|
def simple?
|
14
24
|
object.none?
|
15
25
|
end
|
@@ -32,7 +42,7 @@ module Helium
|
|
32
42
|
def inline_with_truncation
|
33
43
|
formatted = formatted_elements.with_index.inject([]) do |joined, (element, index)|
|
34
44
|
new_joined = [*joined[0..-2], element, trunc_message(object_size - index - 1, all_truncated: index.zero?)]
|
35
|
-
break joined if too_long?(new_joined, max_width: max_width - 4)
|
45
|
+
break joined if max_width && too_long?(new_joined, max_width: max_width - 4)
|
36
46
|
|
37
47
|
new_joined
|
38
48
|
end
|
@@ -65,7 +75,7 @@ module Helium
|
|
65
75
|
def trunc_message(count, all_truncated: false)
|
66
76
|
return if count < 1
|
67
77
|
|
68
|
-
"(#{count} #{all_truncated ? 'elements' : 'more'})"
|
78
|
+
light_black "(#{count} #{all_truncated ? 'elements' : 'more'})"
|
69
79
|
end
|
70
80
|
|
71
81
|
def object_size
|
@@ -3,7 +3,13 @@
|
|
3
3
|
module Helium
|
4
4
|
class Console
|
5
5
|
define_formatter_for Hash do
|
6
|
-
def
|
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
|
|
@@ -29,7 +35,7 @@ module Helium
|
|
29
35
|
def inline_with_truncation
|
30
36
|
truncated = formatted_inline_elements.with_index.inject([]) do |collected, (formatted, index)|
|
31
37
|
new_collected = [*collected[0..-2], formatted, trunc_text(index + 1)].compact
|
32
|
-
break collected if new_collected.join(', ')
|
38
|
+
break collected if length_of(new_collected.join(', ')) > max_width - 4
|
33
39
|
|
34
40
|
new_collected
|
35
41
|
end
|
@@ -55,9 +61,10 @@ module Helium
|
|
55
61
|
end
|
56
62
|
|
57
63
|
def formatted_inline_elements
|
64
|
+
max_width = 15 unless level == 1
|
58
65
|
object.each.lazy.map do |key, value|
|
59
|
-
formatted_key = format_key(key, max_lines: 1, nesting: 1, max_with:
|
60
|
-
formatted_value = format_nested(value, max_lines: 1, nesting: 1, max_width:
|
66
|
+
formatted_key = format_key(key, max_lines: 1, nesting: 1, max_with: max_width)
|
67
|
+
formatted_value = format_nested(value, max_lines: 1, nesting: 1, max_width: max_width)
|
61
68
|
[formatted_key, after_key, formatted_value].join
|
62
69
|
end
|
63
70
|
end
|
@@ -81,6 +88,8 @@ module Helium
|
|
81
88
|
|
82
89
|
def trunc_text(count)
|
83
90
|
truncated_elements = total_elements - count
|
91
|
+
return if truncated_elements.zero?
|
92
|
+
|
84
93
|
light_black("(#{truncated_elements} #{count.zero? ? 'elements' : 'more'})")
|
85
94
|
end
|
86
95
|
|
@@ -0,0 +1,53 @@
|
|
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
|
+
def as_table(source:)
|
21
|
+
table = Table.new(runner: light_black('| '), format_keys: false, after_key: light_black(': '))
|
22
|
+
table.row(magenta('receiver'), object.receiver)
|
23
|
+
table.row(magenta('location'), object.source_location&.join(':'))
|
24
|
+
table.row(magenta('source'), trimmed_source, :full) if source && object.source_location
|
25
|
+
|
26
|
+
yield_lines do |y|
|
27
|
+
y << "#{light_black '#'} #{render_compact}"
|
28
|
+
format(table).lines.each { |line| y << line }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def title
|
33
|
+
owner = object.owner
|
34
|
+
singleton = owner.singleton_class?
|
35
|
+
|
36
|
+
if singleton
|
37
|
+
owner = object.receiver
|
38
|
+
owner = owner.ancestors.find { |ancestor| ancestor.singleton_class == object.owner } if owner.is_a? Class
|
39
|
+
end
|
40
|
+
|
41
|
+
formatted_owner = format(owner, short: true, max_length: 20)
|
42
|
+
formatted_owner = "(#{formatted_owner})" unless owner.is_a? Module
|
43
|
+
|
44
|
+
"#{formatted_owner}#{yellow(singleton ? '.' : '#')}#{yellow object.name.to_s}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def trimmed_source
|
48
|
+
indent = object.source.lines.map { |line| line =~ /[^ ]/ }.min
|
49
|
+
object.source.lines.map { |line| line[indent..-1] }.join.chomp
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -2,22 +2,34 @@
|
|
2
2
|
|
3
3
|
module Helium
|
4
4
|
class Console
|
5
|
-
|
6
|
-
def
|
7
|
-
|
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
|
-
|
31
|
+
|
32
|
+
"#{light_yellow '('}#{signature})#{light_yellow ')'}"
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
@@ -3,28 +3,17 @@
|
|
3
3
|
module Helium
|
4
4
|
class Console
|
5
5
|
define_formatter_for Object do
|
6
|
-
def
|
7
|
-
return
|
6
|
+
def optimal_format
|
7
|
+
return [:compact, {}] if object.instance_variables.none?
|
8
8
|
|
9
|
-
|
9
|
+
super
|
10
10
|
end
|
11
11
|
|
12
|
-
|
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
|
-
yield_lines do |y|
|
22
|
-
y << "#{light_black '#'} #{class_name}"
|
23
|
-
format(table).lines.each {|line| y << line }
|
24
|
-
end
|
12
|
+
def render_compact
|
13
|
+
"#{format object.class, :compact}#{light_black "##{object.object_id}"}"
|
25
14
|
end
|
26
15
|
|
27
|
-
def
|
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,14 +27,22 @@ module Helium
|
|
38
27
|
[class_name, formatted_vars].compact.join
|
39
28
|
end
|
40
29
|
|
41
|
-
def force_inline?
|
42
|
-
level > 2
|
43
|
-
end
|
44
30
|
|
45
|
-
def
|
46
|
-
|
31
|
+
def render_partial
|
32
|
+
table = Table.new(runner: light_black('| '), after_key: light_black(': '), format_keys: false)
|
33
|
+
|
34
|
+
object.instance_variables.each do |inst|
|
35
|
+
table.row(magenta(inst.to_s), object.instance_variable_get(inst))
|
36
|
+
end
|
37
|
+
|
38
|
+
yield_lines do |y|
|
39
|
+
y << "#{light_black '#'} #{class_name}"
|
40
|
+
format(table).lines.each { |line| y << line }
|
41
|
+
end
|
47
42
|
end
|
48
43
|
|
44
|
+
private
|
45
|
+
|
49
46
|
def formatted_instance_variables(**options)
|
50
47
|
object.instance_variables.sort.each.lazy.map do |var_name|
|
51
48
|
value = object.instance_variable_get(var_name)
|
@@ -54,7 +51,7 @@ module Helium
|
|
54
51
|
end
|
55
52
|
|
56
53
|
def class_name(short: false)
|
57
|
-
formatted = format(object.class,
|
54
|
+
formatted = format(object.class, :compact)
|
58
55
|
short ? "##{formatted}" : "#{formatted} instance"
|
59
56
|
end
|
60
57
|
end
|
@@ -3,9 +3,15 @@
|
|
3
3
|
module Helium
|
4
4
|
class Console
|
5
5
|
define_formatter_for Set do
|
6
|
-
def
|
6
|
+
def render_compact
|
7
|
+
return rendr_empty if object.none?
|
8
|
+
|
9
|
+
"#{light_magenta('Set:')} #{trunc_message(object.count, all_truncated: true)}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def render_partial
|
7
13
|
return "#{light_magenta('Set:')} #{red 'empty'}" if object.none?
|
8
|
-
return inline_with_truncation if
|
14
|
+
return inline_with_truncation if options[:max_lines] == 1
|
9
15
|
|
10
16
|
inline_without_truncation || format_as_table
|
11
17
|
end
|
@@ -16,17 +22,21 @@ module Helium
|
|
16
22
|
|
17
23
|
private
|
18
24
|
|
25
|
+
def render_empty
|
26
|
+
"#{light_magenta('Set:')} #{red 'empty'}" if object.none?
|
27
|
+
end
|
28
|
+
|
19
29
|
def format_as_table
|
20
30
|
table = Table.new(runner: '', format_keys: false)
|
21
31
|
object.each do |element|
|
22
|
-
table.row(
|
32
|
+
table.row(light_black('-'), element)
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
light_magenta('Set: {')
|
27
|
-
format(table)
|
28
|
-
light_magenta('}')
|
29
|
-
|
35
|
+
yield_lines do |y|
|
36
|
+
y << light_magenta('Set: {')
|
37
|
+
format(table).lines.each { |line| y << line }
|
38
|
+
y << light_magenta('}')
|
39
|
+
end
|
30
40
|
end
|
31
41
|
|
32
42
|
def inline_with_truncation
|
@@ -59,7 +69,8 @@ module Helium
|
|
59
69
|
end
|
60
70
|
|
61
71
|
def formatted_elements(**options)
|
62
|
-
object.sort
|
72
|
+
sorted = object.sort rescue object
|
73
|
+
sorted.each.lazy.map { |element| format_nested(element, **options) }
|
63
74
|
end
|
64
75
|
|
65
76
|
def trunc_message(count, all_truncated: false)
|
@@ -71,10 +82,6 @@ module Helium
|
|
71
82
|
def object_size
|
72
83
|
@object_size ||= object.size
|
73
84
|
end
|
74
|
-
|
75
|
-
def force_inline?
|
76
|
-
level > 2
|
77
|
-
end
|
78
85
|
end
|
79
86
|
end
|
80
87
|
end
|
@@ -3,26 +3,46 @@
|
|
3
3
|
module Helium
|
4
4
|
class Console
|
5
5
|
define_formatter_for String do
|
6
|
-
def
|
7
|
-
|
8
|
-
|
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
|
-
|
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
|
@@ -5,8 +5,8 @@ module Helium
|
|
5
5
|
define_formatter_for Table do
|
6
6
|
def call
|
7
7
|
yield_lines do |y|
|
8
|
-
rows.each do |key, value, options = {}|
|
9
|
-
format_pair(key, value, **options) do |line|
|
8
|
+
rows.each do |key, value, style, options = {}|
|
9
|
+
format_pair(key, value, style, **options) do |line|
|
10
10
|
y << line
|
11
11
|
end
|
12
12
|
end
|
@@ -16,8 +16,8 @@ module Helium
|
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
def format_pair(key, value, **options)
|
20
|
-
formatted_value = format_nested(value, max_width: max_value_width, **options)
|
19
|
+
def format_pair(key, value, style, **options)
|
20
|
+
formatted_value = format_nested(value, style, max_width: max_value_width, **options)
|
21
21
|
|
22
22
|
formatted_value.lines.each.with_index.map do |line, index|
|
23
23
|
yield [
|
@@ -1,100 +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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@lines = Enumerator.new { |y| block.(y) }
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_reader :lines
|
15
|
-
|
16
|
-
def to_s
|
17
|
-
lines.to_a.join
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(object, **options)
|
22
|
-
@object = object
|
23
|
-
@options = options
|
24
|
-
end
|
25
|
-
|
26
|
-
def call
|
27
|
-
end
|
28
|
-
|
29
|
-
attr_reader :object, :options
|
30
|
-
|
31
|
-
def format_nested(other_object, **options)
|
32
|
-
Helium::Console.format(other_object, **nested_opts(options))
|
33
|
-
end
|
34
|
-
|
35
|
-
def format(other_object, **options)
|
36
|
-
Helium::Console.format(other_object, **nested_opts(options, increase_level: false))
|
37
|
-
end
|
38
|
-
|
39
|
-
def format_string(string, **options)
|
40
|
-
Helium::Console.format_string(string, **options)
|
41
|
-
end
|
42
|
-
|
43
|
-
def simple?
|
44
|
-
false
|
45
|
-
end
|
46
|
-
|
47
|
-
def method_missing(name, *args)
|
48
|
-
return @options[name] if @options.key?(name)
|
49
|
-
return ColorizedString.new(*args).colorize(name) if ColorizedString.colors.include?(name)
|
50
|
-
|
51
|
-
super
|
52
|
-
end
|
53
|
-
|
54
|
-
def respond_to_missing?(name, private = false)
|
55
|
-
@options.key?(name) || ColorizedString.colors.include?(name) || super
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def nested_objects
|
61
|
-
[]
|
62
|
-
end
|
63
|
-
|
64
|
-
def nested_opts(new_options, increase_level: true)
|
65
|
-
new_options = options.merge(new_options)
|
66
|
-
new_options[:level] += 1 if increase_level
|
67
|
-
new_options[:ignore_objects] = nested_objects
|
68
|
-
new_options
|
69
|
-
end
|
70
|
-
|
71
|
-
def length_of(string)
|
72
|
-
ColorizedString.new(string).uncolorize.length
|
73
|
-
end
|
9
|
+
def self.instance_formatters
|
10
|
+
@instance_formatters ||= new
|
11
|
+
end
|
74
12
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
13
|
+
def self.class_formatters
|
14
|
+
@class_formatters ||= new
|
78
15
|
end
|
79
16
|
|
80
|
-
def add(
|
81
|
-
|
82
|
-
define_method(:call, &handler)
|
83
|
-
end
|
17
|
+
def add(mod, formatter)
|
18
|
+
handlers[mod] = formatter
|
84
19
|
end
|
85
20
|
|
86
|
-
def define(
|
87
|
-
|
21
|
+
def define(mod, &block)
|
22
|
+
add(mod, Class.new(Formatter, &block))
|
88
23
|
end
|
89
24
|
|
90
|
-
def handler_for(
|
91
|
-
|
92
|
-
|
93
|
-
|
25
|
+
def handler_for(klass)
|
26
|
+
klass.ancestors.each do |ancestor|
|
27
|
+
result = handlers[ancestor] || handlers[ancestor.name]
|
28
|
+
return result if result
|
94
29
|
end
|
95
|
-
|
96
|
-
|
97
|
-
element_class.new(object, **options)
|
30
|
+
handlers[BasicObject]
|
98
31
|
end
|
99
32
|
|
100
33
|
private
|
data/lib/helium/console/table.rb
CHANGED
data/lib/helium/console.rb
CHANGED
@@ -10,6 +10,7 @@ require 'helium/console/table'
|
|
10
10
|
require 'helium/console/registry'
|
11
11
|
|
12
12
|
require 'helium/console/printer'
|
13
|
+
require 'helium/console/prompt'
|
13
14
|
|
14
15
|
module Helium
|
15
16
|
class Console
|
@@ -23,9 +24,30 @@ module Helium
|
|
23
24
|
Symbol
|
24
25
|
].freeze
|
25
26
|
|
27
|
+
def self.start(target = nil, options = {})
|
28
|
+
prompt = ColorizedString.new("He\u269B").light_blue
|
29
|
+
line = 0
|
30
|
+
|
31
|
+
options = {
|
32
|
+
print: ColorPrinter.method(:default),
|
33
|
+
prompt: Prompt.new.pry_prompt
|
34
|
+
}.merge(options)
|
35
|
+
|
36
|
+
Pry.start(target, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.define_formatter_for(klass, &handler)
|
40
|
+
Registry.instance_formatters.define(klass, &handler)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.define_class_formatter_for(klass, &handler)
|
44
|
+
Registry.class_formatters.define(klass, &handler)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
26
48
|
class << self
|
27
49
|
def instance
|
28
|
-
@instance ||= new
|
50
|
+
@instance ||= new
|
29
51
|
end
|
30
52
|
|
31
53
|
def method_missing(name, *args, &block)
|
@@ -39,51 +61,31 @@ module Helium
|
|
39
61
|
end
|
40
62
|
end
|
41
63
|
|
42
|
-
def
|
43
|
-
@registry = registry
|
44
|
-
end
|
45
|
-
|
46
|
-
def format(object, **options)
|
64
|
+
def format(object, style = nil, **options)
|
47
65
|
options = default_options.merge(options)
|
48
66
|
return '(...)' if options[:ignore_objects].include?(object.object_id)
|
49
67
|
|
50
|
-
|
51
|
-
|
52
|
-
if handler
|
53
|
-
handler.()
|
54
|
-
else
|
55
|
-
format(object.inspect, **options)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def register(klass, &handler)
|
60
|
-
registry.add(klass, &handler)
|
61
|
-
end
|
62
|
-
|
63
|
-
def define_formatter_for(klass, &handler)
|
64
|
-
registry.define(klass, &handler)
|
68
|
+
handler_for(object, style, **options).()
|
65
69
|
end
|
66
70
|
|
67
|
-
def simple?(object)
|
71
|
+
def simple?(object, style = nil, **options)
|
68
72
|
SIMPLE_OBJECTS.any? { |simple_obj_class| object.is_a? simple_obj_class } ||
|
69
|
-
|
73
|
+
handler_for(object, style, **options).simple?
|
70
74
|
end
|
71
75
|
|
72
76
|
def default_options
|
73
77
|
{
|
74
78
|
overflow: :wrap,
|
75
79
|
indent: 0,
|
76
|
-
max_width: `tput cols`.chomp.to_i,
|
77
80
|
level: 1,
|
78
|
-
ignore_objects: []
|
81
|
+
ignore_objects: [],
|
82
|
+
short: false
|
79
83
|
}
|
80
84
|
end
|
81
85
|
|
82
86
|
def format_string(string, ellipses: '...', **options)
|
83
87
|
options = default_options.merge(options)
|
84
|
-
|
85
88
|
formatters = [
|
86
|
-
Formatters::Overflow.get(options[:overflow]).new(max_width: options[:max_width] - options[:indent]),
|
87
89
|
Formatters::Indent.new(options[:indent]),
|
88
90
|
Formatters::MaxLines.new(
|
89
91
|
max_lines: options[:max_lines],
|
@@ -91,6 +93,11 @@ module Helium
|
|
91
93
|
ellipses: ellipses
|
92
94
|
)
|
93
95
|
]
|
96
|
+
if options[:max_width]
|
97
|
+
formatters.unshift(
|
98
|
+
Formatters::Overflow.get(options[:overflow]).new(max_width: options[:max_width] - options[:indent]),
|
99
|
+
)
|
100
|
+
end
|
94
101
|
|
95
102
|
formatters.inject(string) do |str, formatter|
|
96
103
|
formatter.(str)
|
@@ -99,7 +106,15 @@ module Helium
|
|
99
106
|
|
100
107
|
private
|
101
108
|
|
102
|
-
|
109
|
+
# TODO: Injection instead of hard dependency!
|
110
|
+
def handler_for(object, style, **options)
|
111
|
+
formatter_class = if object.is_a? Module
|
112
|
+
Registry.class_formatters.handler_for(object)
|
113
|
+
else
|
114
|
+
Registry.instance_formatters.handler_for(object.class)
|
115
|
+
end
|
116
|
+
formatter_class&.new(object, style, self, **options)
|
117
|
+
end
|
103
118
|
end
|
104
119
|
end
|
105
120
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: helium-console
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stanislaw Klajn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09
|
11
|
+
date: 2021-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -59,16 +59,20 @@ files:
|
|
59
59
|
- bin/setup
|
60
60
|
- helium-console.gemspec
|
61
61
|
- lib/helium/console.rb
|
62
|
+
- lib/helium/console/colorized_string.rb
|
63
|
+
- lib/helium/console/formatter.rb
|
62
64
|
- lib/helium/console/formatters/indent.rb
|
63
65
|
- lib/helium/console/formatters/max_lines.rb
|
64
66
|
- lib/helium/console/formatters/overflow.rb
|
65
67
|
- lib/helium/console/formatters/overflow/wrap.rb
|
66
68
|
- lib/helium/console/printer.rb
|
69
|
+
- lib/helium/console/prompt.rb
|
67
70
|
- lib/helium/console/registry.rb
|
68
71
|
- lib/helium/console/registry/array.rb
|
69
72
|
- lib/helium/console/registry/booleans.rb
|
70
73
|
- lib/helium/console/registry/date.rb
|
71
74
|
- lib/helium/console/registry/hash.rb
|
75
|
+
- lib/helium/console/registry/method.rb
|
72
76
|
- lib/helium/console/registry/module.rb
|
73
77
|
- lib/helium/console/registry/nil.rb
|
74
78
|
- lib/helium/console/registry/numeric.rb
|
@@ -102,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
106
|
- !ruby/object:Gem::Version
|
103
107
|
version: '0'
|
104
108
|
requirements: []
|
105
|
-
rubygems_version: 3.
|
109
|
+
rubygems_version: 3.0.8
|
106
110
|
signing_key:
|
107
111
|
specification_version: 4
|
108
112
|
summary: Collection of tools for smooth integration with console
|