output_mode 1.6.0 → 1.7.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.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/bin/byebug +29 -0
- data/bin/demo +47 -65
- data/lib/output_mode/callable.rb +11 -5
- data/lib/output_mode/formatter.rb +146 -0
- data/lib/output_mode/formatters/index.rb +59 -0
- data/lib/output_mode/formatters/show.rb +98 -0
- data/lib/output_mode/formatters.rb +36 -0
- data/lib/output_mode/outputs/templated.rb +18 -6
- data/lib/output_mode/version.rb +1 -1
- data/lib/output_mode.rb +1 -0
- data/output_mode.gemspec +1 -0
- metadata +21 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4beed6d9f51548ef131e475bb68aa9c6d6fe079e39672b4691566ff80ffb65c2
|
|
4
|
+
data.tar.gz: df648ec5ee82875c189123dca55bfaabfa3bf4d5ba24e160be1d0f15bb1a624b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e19a13c9e5b0b6e3fa497aadd4d1ed59bb6297fd8063f88d7f6a01bd4dd84f801baae9be8efe46a0e42e63024824d227fa51c0f7b84ad283baec7f5960fb2f6
|
|
7
|
+
data.tar.gz: b9ea560f3b42886ca8baaa04452cc5e4557c82ddf23068b095b544f2649b425b5b30a30212d6ef7955cd1fde41c624b4f9fbe73cfc32a3a2ddb1092f6d16fd54
|
data/.travis.yml
CHANGED
data/bin/byebug
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# This file was generated by Bundler.
|
|
6
|
+
#
|
|
7
|
+
# The application 'byebug' is installed as part of a gem, and
|
|
8
|
+
# this file is here to facilitate running it.
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
require "pathname"
|
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
|
13
|
+
Pathname.new(__FILE__).realpath)
|
|
14
|
+
|
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
|
16
|
+
|
|
17
|
+
if File.file?(bundle_binstub)
|
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
|
19
|
+
load(bundle_binstub)
|
|
20
|
+
else
|
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
require "rubygems"
|
|
27
|
+
require "bundler/setup"
|
|
28
|
+
|
|
29
|
+
load Gem.bin_path("byebug", "byebug")
|
data/bin/demo
CHANGED
|
@@ -29,61 +29,50 @@ require "bundler/setup"
|
|
|
29
29
|
require "output_mode"
|
|
30
30
|
require 'erb'
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
register_callable(header: 'Simplified', verbose: false) { 'simplified visible' }
|
|
39
|
-
register_callable(header: 'Interactive', interactive: true) { 'interactive visible' }
|
|
40
|
-
register_callable(header: 'Non Interactive', interactive: false) { 'non-interactive visible' }
|
|
41
|
-
register_callable(header: 'Yes/True') { true }
|
|
42
|
-
register_callable(header: 'No/False', row_color: [:clear]) { false }
|
|
43
|
-
register_callable(header: 'Missing') { nil }
|
|
44
|
-
register_callable(header: 'Inline') do |interactive:, verbose:|
|
|
45
|
-
if interactive && verbose
|
|
46
|
-
'interactive-verbose'
|
|
47
|
-
elsif interactive
|
|
48
|
-
'interactive-simplified'
|
|
49
|
-
elsif verbose
|
|
50
|
-
'non-interactive-verbose'
|
|
32
|
+
class DemoIndex < OutputMode::Formatters::Index
|
|
33
|
+
constructor do
|
|
34
|
+
register(header: 'Integer', row_color: [:yellow, :bold]) { |i| i }
|
|
35
|
+
register(header: 'Standard', header_color: [:strikethrough] ) { 'always visible' }
|
|
36
|
+
if verbose?
|
|
37
|
+
register(header: 'Verbose') { 'verbose visible' }
|
|
51
38
|
else
|
|
52
|
-
'
|
|
39
|
+
register(header: 'Simplified') { 'simplified visible' }
|
|
53
40
|
end
|
|
41
|
+
if interactive?
|
|
42
|
+
register(header: 'Interactive') { 'interactive visible' }
|
|
43
|
+
else
|
|
44
|
+
register(header: 'Non Interactive') { 'non-interactive visible' }
|
|
45
|
+
end
|
|
46
|
+
register(header: 'Yes/True') { true }
|
|
47
|
+
register(header: 'No/False', row_color: [:clear]) { false }
|
|
48
|
+
register(header: 'Missing') { nil }
|
|
54
49
|
end
|
|
55
50
|
end
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
52
|
+
class DemoShow < OutputMode::Formatters::Show
|
|
53
|
+
constructor do
|
|
54
|
+
register(header: 'Integer') { |i| i }
|
|
55
|
+
register(header: 'Standard') { 'always visible' }
|
|
56
|
+
if verbose?
|
|
57
|
+
register(header: 'Verbose') { 'verbose visible' }
|
|
58
|
+
else
|
|
59
|
+
register(header: 'Simplified') { 'simplified visible' }
|
|
60
|
+
end
|
|
61
|
+
if interactive?
|
|
62
|
+
register(header: 'Interactive') { 'interactive visible' }
|
|
63
|
+
else
|
|
64
|
+
register(header: 'Non Interactive') { 'non-interactive visible' }
|
|
65
|
+
end
|
|
66
|
+
register(header: 'Yes/True', section: :boolean) { true }
|
|
67
|
+
register(header: 'No/False', section: :boolean) { false }
|
|
68
|
+
register(header: 'Missing') { nil }
|
|
69
|
+
register(header: 'Tab') { "tab1\ttab2" }
|
|
70
|
+
register(header: 'New line') { "line1\nline2" }
|
|
71
|
+
end
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
data = [1, 2, 3]
|
|
74
75
|
|
|
75
|
-
other_template = ERB.new(<<~TEMPLATE, nil, '-')
|
|
76
|
-
# Non boolean values
|
|
77
|
-
<% each(:other) do |value, field:, padding:, **_| -%>
|
|
78
|
-
<%= padding -%><%= pastel.blue.bold field -%><%= pastel.bold ':' -%> <%= pastel.green value %>
|
|
79
|
-
<% end -%>
|
|
80
|
-
|
|
81
|
-
# Boolean Values
|
|
82
|
-
<% each(:boolean) do |value, field:, padding:, **_| -%>
|
|
83
|
-
<%= padding -%><%= pastel.blue.bold field -%><%= pastel.bold ':' -%> <%= pastel.green value %>
|
|
84
|
-
<% end -%>
|
|
85
|
-
TEMPLATE
|
|
86
|
-
|
|
87
76
|
puts <<~EOF
|
|
88
77
|
#==============================================================================
|
|
89
78
|
#==============================================================================
|
|
@@ -95,34 +84,34 @@ puts <<~EOF
|
|
|
95
84
|
# Default Demo Index
|
|
96
85
|
# Simplified in interactive shells, verbose in non-interactive
|
|
97
86
|
#==============================================================================
|
|
98
|
-
#{DemoIndex.
|
|
87
|
+
#{DemoIndex.render(*data)}
|
|
99
88
|
|
|
100
89
|
#==============================================================================
|
|
101
90
|
# Demo Verbose Index
|
|
102
91
|
#==============================================================================
|
|
103
|
-
#{DemoIndex.
|
|
92
|
+
#{DemoIndex.render(*data, verbose: true)}
|
|
104
93
|
|
|
105
94
|
#==============================================================================
|
|
106
95
|
# Demo "Simplified" Index
|
|
107
96
|
#==============================================================================
|
|
108
|
-
#{DemoIndex.
|
|
97
|
+
#{DemoIndex.render(*data, verbose: false)}
|
|
109
98
|
|
|
110
99
|
#==============================================================================
|
|
111
100
|
# Force Interactive
|
|
112
101
|
# Always print as if the shell is interactive
|
|
113
102
|
#==============================================================================
|
|
114
|
-
#{DemoIndex.
|
|
103
|
+
#{DemoIndex.render(*data, interactive: true)}
|
|
115
104
|
|
|
116
105
|
#==============================================================================
|
|
117
106
|
# Force Non-Interactive
|
|
118
107
|
# Always print as if the shell is non-interactive
|
|
119
108
|
#==============================================================================
|
|
120
|
-
#{DemoIndex.
|
|
109
|
+
#{DemoIndex.render(*data, interactive: false)}
|
|
121
110
|
|
|
122
111
|
#==============================================================================
|
|
123
112
|
# Demo ASCII Index
|
|
124
113
|
#==============================================================================
|
|
125
|
-
#{DemoIndex.
|
|
114
|
+
#{DemoIndex.render(*data, ascii: true)}
|
|
126
115
|
|
|
127
116
|
#==============================================================================
|
|
128
117
|
#==============================================================================
|
|
@@ -134,39 +123,32 @@ puts <<~EOF
|
|
|
134
123
|
# Default Settings
|
|
135
124
|
# Simplified in interactive shells, verbose in non-interactive
|
|
136
125
|
#==============================================================================
|
|
137
|
-
#{DemoShow.
|
|
126
|
+
#{DemoShow.render(data.first)}
|
|
138
127
|
|
|
139
128
|
#==============================================================================
|
|
140
129
|
# Demo Verbose Show
|
|
141
130
|
#==============================================================================
|
|
142
|
-
#{DemoShow.
|
|
131
|
+
#{DemoShow.render(data.first, verbose: true)}
|
|
143
132
|
|
|
144
133
|
#==============================================================================
|
|
145
134
|
# Demo "Simplified" Show
|
|
146
135
|
#==============================================================================
|
|
147
|
-
#{DemoShow.
|
|
136
|
+
#{DemoShow.render(data.first, verbose: false)}
|
|
148
137
|
|
|
149
138
|
#==============================================================================
|
|
150
139
|
# Force Interactive
|
|
151
140
|
# Always print as if the shell is interactive
|
|
152
141
|
#==============================================================================
|
|
153
|
-
#{DemoShow.
|
|
142
|
+
#{DemoShow.render(data.first, interactive: true)}
|
|
154
143
|
|
|
155
144
|
#==============================================================================
|
|
156
145
|
# Force Non-Interactive
|
|
157
146
|
# Always print as if the shell is non-interactive
|
|
158
147
|
#==============================================================================
|
|
159
|
-
#{DemoShow.
|
|
148
|
+
#{DemoShow.render(data.first, interactive: false)}
|
|
160
149
|
|
|
161
150
|
#==============================================================================
|
|
162
151
|
# Demo ASCII Index
|
|
163
152
|
#==============================================================================
|
|
164
|
-
#{DemoShow.
|
|
165
|
-
|
|
166
|
-
#==============================================================================
|
|
167
|
-
# Group the boolean value separately
|
|
168
|
-
# NOTE: This only occurs in interactive mode
|
|
169
|
-
# Non-Interactive sessions have a fix order
|
|
170
|
-
#==============================================================================
|
|
171
|
-
#{DemoShow.build_output(template: other_template).render(*data)}
|
|
153
|
+
#{DemoShow.render(data.first, ascii: true)}
|
|
172
154
|
EOF
|
data/lib/output_mode/callable.rb
CHANGED
|
@@ -58,7 +58,7 @@ module OutputMode
|
|
|
58
58
|
@callables.each(&block)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
def pad_each(*ctx, **input_opts)
|
|
61
|
+
def pad_each(*ctx, **input_opts, &block)
|
|
62
62
|
fields = self.map do |callables|
|
|
63
63
|
field = callables.config[:header]
|
|
64
64
|
if field.respond_to?(:call)
|
|
@@ -83,11 +83,14 @@ module OutputMode
|
|
|
83
83
|
[callable, { padding: ' ' * length, field: field }]
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
pads.each
|
|
86
|
+
# Generate an enum
|
|
87
|
+
# NOTE: This fixes the double splate deprecation warning
|
|
88
|
+
enum = Enumerator.new do |yielder|
|
|
89
|
+
pads.each do |callable, opts|
|
|
90
|
+
yielder.yield(callable, **opts)
|
|
91
|
+
end
|
|
90
92
|
end
|
|
93
|
+
enum.each(&block)
|
|
91
94
|
end
|
|
92
95
|
|
|
93
96
|
def config_select(key, *values)
|
|
@@ -138,6 +141,8 @@ module OutputMode
|
|
|
138
141
|
|
|
139
142
|
# Handles the dynamic +<query>?+ and +<explicit-negation>!+ methods
|
|
140
143
|
#
|
|
144
|
+
# DEPRECATED: The explicit! negation operator should not be used
|
|
145
|
+
#
|
|
141
146
|
# @return [Boolean] The result of the query or explicit-negation
|
|
142
147
|
# @raise [NoMethodError] All other method calls
|
|
143
148
|
def method_missing(s, *args, &b)
|
|
@@ -197,6 +202,7 @@ module OutputMode
|
|
|
197
202
|
callable.call(*a)
|
|
198
203
|
end
|
|
199
204
|
|
|
205
|
+
# DEPRECATED: Use a Formatter class
|
|
200
206
|
def generator(output)
|
|
201
207
|
->(*a) do
|
|
202
208
|
# Implicitly determine which parts of the context can be passed through
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#==============================================================================
|
|
2
|
+
# Copyright 2021 William McCumstie
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
# this list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
# and/or other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
#==============================================================================
|
|
26
|
+
|
|
27
|
+
require 'tty-color'
|
|
28
|
+
|
|
29
|
+
module OutputMode
|
|
30
|
+
class Formatter
|
|
31
|
+
def self.constructor(&block)
|
|
32
|
+
@constructor ||= block
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.build(*objects, **opts)
|
|
36
|
+
new(*objects, **opts).tap do |policy|
|
|
37
|
+
next unless constructor
|
|
38
|
+
policy.instance_exec(&constructor)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.render(*objects, **opts)
|
|
43
|
+
build(*objects, **opts).render
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def initialize(*objects, verbose: nil, ascii: nil, interactive: nil, color: nil)
|
|
47
|
+
@verbose = verbose
|
|
48
|
+
@ascii = ascii
|
|
49
|
+
@interactive = interactive
|
|
50
|
+
@color = color
|
|
51
|
+
|
|
52
|
+
# NOTE: This is intentionally not exposed on the base class
|
|
53
|
+
# It is up to the individual implementations to expose it
|
|
54
|
+
@objects = objects
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def callables
|
|
58
|
+
@callables ||= Callables.new
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def register(**config, &block)
|
|
62
|
+
callables << Callable.new(**config) do |*args, **opts|
|
|
63
|
+
value = block.call(*args, **opts)
|
|
64
|
+
format(value, **config)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def format(value, **config)
|
|
69
|
+
case value
|
|
70
|
+
when TrueClass
|
|
71
|
+
config[:yes] || yes
|
|
72
|
+
when FalseClass
|
|
73
|
+
config[:no] || no
|
|
74
|
+
when NilClass
|
|
75
|
+
config[:default] || default
|
|
76
|
+
when Time
|
|
77
|
+
format = config[:time] || time
|
|
78
|
+
value.strftime(format)
|
|
79
|
+
else
|
|
80
|
+
value
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def build_output
|
|
85
|
+
raise NotImplementedError
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def render
|
|
89
|
+
build_output.render(*@objects)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def interactive?
|
|
93
|
+
if @interactive.nil?
|
|
94
|
+
$stdout.tty?
|
|
95
|
+
else
|
|
96
|
+
@interactive
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def color?
|
|
101
|
+
if @color.nil? && (ascii? || !interactive?)
|
|
102
|
+
false
|
|
103
|
+
elsif @color.nil?
|
|
104
|
+
TTY::Color.color?
|
|
105
|
+
else
|
|
106
|
+
@color
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def ascii?
|
|
111
|
+
if @ascii.nil?
|
|
112
|
+
!interactive?
|
|
113
|
+
else
|
|
114
|
+
@ascii
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def verbose?
|
|
119
|
+
if @verbose.nil?
|
|
120
|
+
!interactive?
|
|
121
|
+
else
|
|
122
|
+
@verbose
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def yes(value = nil)
|
|
127
|
+
@yes = value unless value.nil?
|
|
128
|
+
@yes ? @yes : (ascii? ? 'yes' : '✓')
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def no(value = nil)
|
|
132
|
+
@no = value unless value.nil?
|
|
133
|
+
@no ? @no : (ascii? ? 'no' : '✕')
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def default(value = nil)
|
|
137
|
+
@default = value unless value.nil?
|
|
138
|
+
@default ? @default : (interactive? ? '(none)' : '')
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def time(value = nil)
|
|
142
|
+
@time = value unless value.nil?
|
|
143
|
+
@time ? @time : (verbose? ? "%Y-%m-%dT%H:%M:%S%:z" : "%d/%m/%y %H:%M")
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#==============================================================================
|
|
2
|
+
# Copyright 2021 William McCumstie
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
# this list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
# and/or other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
#==============================================================================
|
|
26
|
+
|
|
27
|
+
module OutputMode
|
|
28
|
+
module Formatters
|
|
29
|
+
class Index < Formatter
|
|
30
|
+
attr_reader :objects
|
|
31
|
+
|
|
32
|
+
def header_color(value = nil)
|
|
33
|
+
@header_color = value unless value.nil?
|
|
34
|
+
@header_color ? @header_color : :bold
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def row_color(value = nil)
|
|
38
|
+
@row_color = value unless value.nil?
|
|
39
|
+
@row_color ? @row_color : :cyan
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def build_output
|
|
43
|
+
if interactive?
|
|
44
|
+
opts = {
|
|
45
|
+
renderer: ascii? ? :ascii : :unicode,
|
|
46
|
+
header_color: header_color,
|
|
47
|
+
row_color: row_color,
|
|
48
|
+
colorize: color?,
|
|
49
|
+
rotate: false,
|
|
50
|
+
padding: [0, 1]
|
|
51
|
+
}
|
|
52
|
+
Outputs::Tabulated.new(*callables, **opts)
|
|
53
|
+
else
|
|
54
|
+
Outputs::Delimited.new(*callables, col_sep: "\t")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#==============================================================================
|
|
2
|
+
# Copyright 2021 William McCumstie
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
# this list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
# and/or other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
#==============================================================================
|
|
26
|
+
|
|
27
|
+
require 'output_mode/default_erb'
|
|
28
|
+
require 'output_mode/non_interactive_erb'
|
|
29
|
+
|
|
30
|
+
module OutputMode
|
|
31
|
+
module Formatters
|
|
32
|
+
class Show < Formatter
|
|
33
|
+
include Enumerable
|
|
34
|
+
|
|
35
|
+
# Limit the policy to a single object
|
|
36
|
+
def initialize(object, **opts)
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def object
|
|
41
|
+
@objects.first
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def template(value = nil)
|
|
45
|
+
@template = value unless value.nil?
|
|
46
|
+
@template ? @template : (interactive? ? DEFAULT_ERB : NON_INTERACTIVE_ERB)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def scope(value = nil)
|
|
50
|
+
@scope = value unless value.nil?
|
|
51
|
+
@scope ? @scope : self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def build_output
|
|
55
|
+
opts = {
|
|
56
|
+
template: template,
|
|
57
|
+
colorize: color?,
|
|
58
|
+
bind: scope.instance_exec { binding }
|
|
59
|
+
}
|
|
60
|
+
OutputMode::Outputs::Templated.new(*callables, **opts)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @yieldparam value An attribute to be rendered
|
|
64
|
+
# @yieldparam field: An optional field header for the value
|
|
65
|
+
# @yieldparam padding: A padding string which will right align the +field+
|
|
66
|
+
# @yieldparam **config TBA
|
|
67
|
+
def each(section = nil, &block)
|
|
68
|
+
# Select the callable objects
|
|
69
|
+
selected = if section == nil
|
|
70
|
+
callables
|
|
71
|
+
elsif section == :default
|
|
72
|
+
callables.config_select(:section, :default, nil)
|
|
73
|
+
else
|
|
74
|
+
callables.config_select(:section, section)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Yield each selected attribute
|
|
78
|
+
objs = selected.pad_each(object).map do |callable, opts|
|
|
79
|
+
field = opts[:field]
|
|
80
|
+
padding = opts[:padding]
|
|
81
|
+
value = callable.call(object)
|
|
82
|
+
[value, { field: field, padding: padding }]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Runs the provided block
|
|
86
|
+
objs.each do |model, opts|
|
|
87
|
+
block.call(model, **opts)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Library for colorizing the output. It is automatically disabled when the
|
|
92
|
+
# +colorize+ flag is +false+
|
|
93
|
+
def pastel
|
|
94
|
+
@pastel ||= Pastel.new(enabled: color?)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#==============================================================================
|
|
2
|
+
# Copyright 2021 William McCumstie
|
|
3
|
+
#
|
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
|
6
|
+
#
|
|
7
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
# this list of conditions and the following disclaimer.
|
|
9
|
+
#
|
|
10
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
# and/or other materials provided with the distribution.
|
|
13
|
+
#
|
|
14
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
15
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
16
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
17
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
18
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
19
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
20
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
21
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
22
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
23
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
24
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
#==============================================================================
|
|
26
|
+
|
|
27
|
+
module OutputMode
|
|
28
|
+
autoload 'Formatter', File.expand_path('formatter.rb', __dir__)
|
|
29
|
+
|
|
30
|
+
module Formatters
|
|
31
|
+
Dir.glob(File.expand_path('formatters/*.rb', __dir__)).each do |path|
|
|
32
|
+
autoload File.basename(path).chomp('.rb').capitalize, path
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
@@ -55,7 +55,9 @@ module OutputMode
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
# Runs the provided block
|
|
58
|
-
objs.each
|
|
58
|
+
objs.each do |model, opts|
|
|
59
|
+
block.call(model, **opts)
|
|
60
|
+
end
|
|
59
61
|
end
|
|
60
62
|
|
|
61
63
|
# Renders an ERB object within the entry's context. This provides access to the
|
|
@@ -86,7 +88,8 @@ module OutputMode
|
|
|
86
88
|
# @!attribute [r] fields
|
|
87
89
|
# @!attribute [r] colorize
|
|
88
90
|
# @!attribute [r] sections
|
|
89
|
-
|
|
91
|
+
# @!attribute [r] bind
|
|
92
|
+
attr_reader :erb, :fields, :separator, :colorize, :sections, :bind
|
|
90
93
|
|
|
91
94
|
# Create a new +output+ which will render using +ERB+. The provided +template+ should
|
|
92
95
|
# only render the +output+ for a single +entry+ (aka model, record, data object, etc).
|
|
@@ -104,10 +107,11 @@ module OutputMode
|
|
|
104
107
|
# @param [Array] *procs see {OutputMode::Output#initialize}
|
|
105
108
|
# @param [ERB] template: The +template+ object used by the renderer
|
|
106
109
|
# @param [Array] fields: An optional array of field headers that map to the procs, repeating the last value if required
|
|
107
|
-
# @param fields: A static value to use as all field headers
|
|
110
|
+
# @param fields: DEPRECATED A static value to use as all field headers
|
|
108
111
|
# @param separator: The character(s) used to join the "entries" together
|
|
109
112
|
# @param colorize: Flags if the caller wants the colorized version, this maybe ignored by +template+
|
|
110
|
-
# @param sections: An optional array that groups the procs into sections
|
|
113
|
+
# @param sections: DEPRECATED An optional array that groups the procs into sections
|
|
114
|
+
# @param bind: An optional execution context to render the template within
|
|
111
115
|
# @param [Hash] **config see {OutputMode::Output#initialize}
|
|
112
116
|
def initialize(*procs,
|
|
113
117
|
template: nil,
|
|
@@ -115,6 +119,7 @@ module OutputMode
|
|
|
115
119
|
separator: "\n",
|
|
116
120
|
colorize: false,
|
|
117
121
|
sections: nil,
|
|
122
|
+
bind: nil,
|
|
118
123
|
**config)
|
|
119
124
|
@erb = case template
|
|
120
125
|
when String
|
|
@@ -128,6 +133,7 @@ module OutputMode
|
|
|
128
133
|
@separator = separator
|
|
129
134
|
@colorize = colorize
|
|
130
135
|
@sections = sections
|
|
136
|
+
@bind = bind
|
|
131
137
|
super(*procs, **config)
|
|
132
138
|
end
|
|
133
139
|
|
|
@@ -137,11 +143,17 @@ module OutputMode
|
|
|
137
143
|
#
|
|
138
144
|
# @see OutputMode::Output#render
|
|
139
145
|
def render(*data)
|
|
140
|
-
data.map
|
|
141
|
-
|
|
146
|
+
data.map do |datum|
|
|
147
|
+
if bind
|
|
148
|
+
erb.result(bind)
|
|
149
|
+
else
|
|
150
|
+
Entry.new(self, datum, colorize).render(erb)
|
|
151
|
+
end
|
|
152
|
+
end.join(separator)
|
|
142
153
|
end
|
|
143
154
|
|
|
144
155
|
# Returns the length of the maximum field
|
|
156
|
+
# DEPRECATED
|
|
145
157
|
def max_field_length
|
|
146
158
|
if fields.is_a? Array
|
|
147
159
|
fields.map { |f| f.to_s.length }.max
|
data/lib/output_mode/version.rb
CHANGED
data/lib/output_mode.rb
CHANGED
data/output_mode.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: output_mode
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- William McCumsite
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-05
|
|
11
|
+
date: 2021-10-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: tty-table
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - ">"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0.11'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: pry-byebug
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '3.0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '3.0'
|
|
111
125
|
description:
|
|
112
126
|
email:
|
|
113
127
|
- openlicense.williams@gmail.com
|
|
@@ -123,6 +137,7 @@ files:
|
|
|
123
137
|
- README.md
|
|
124
138
|
- Rakefile
|
|
125
139
|
- bin/bundle
|
|
140
|
+
- bin/byebug
|
|
126
141
|
- bin/coderay
|
|
127
142
|
- bin/console
|
|
128
143
|
- bin/demo
|
|
@@ -137,6 +152,10 @@ files:
|
|
|
137
152
|
- lib/output_mode/callable.rb
|
|
138
153
|
- lib/output_mode/default_erb.rb
|
|
139
154
|
- lib/output_mode/errors.rb
|
|
155
|
+
- lib/output_mode/formatter.rb
|
|
156
|
+
- lib/output_mode/formatters.rb
|
|
157
|
+
- lib/output_mode/formatters/index.rb
|
|
158
|
+
- lib/output_mode/formatters/show.rb
|
|
140
159
|
- lib/output_mode/non_interactive_erb.rb
|
|
141
160
|
- lib/output_mode/output.rb
|
|
142
161
|
- lib/output_mode/outputs.rb
|