output_mode 1.0.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -0
- data/LICENSE.txt +0 -9
- data/README.md +1 -1
- data/bin/demo +122 -10
- data/lib/output_mode/builder_dsl.rb +3 -1
- data/lib/output_mode/callable.rb +84 -20
- data/lib/output_mode/output.rb +16 -52
- data/lib/output_mode/outputs/delimited.rb +6 -1
- data/lib/output_mode/outputs/tabulated.rb +55 -10
- data/lib/output_mode/outputs/templated.rb +37 -9
- data/lib/output_mode/tldr/index.rb +82 -11
- data/lib/output_mode/tldr/show.rb +78 -10
- data/lib/output_mode/version.rb +1 -1
- data/output_mode.gemspec +4 -3
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33db72e9e5872a974df80e11a0d4bae3735c13d49d3be4d4ab1366b7e461551f
|
4
|
+
data.tar.gz: f1ac7923d6cb9beda1f3af36ebaa41b84cdb6567d5fb71db4f2d1a2503ee731b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f12f87485cdad45ceb4fba9b9b26c405366009b1ad39e87c223fc246424bd0501421a75570caf48c351523d55483f4ea1d705659a3e6185ae8213c6147d9ad96
|
7
|
+
data.tar.gz: cafd82a58648d5e4900c91d242a1128b2b1c5d1123716385160801a3d85959324df691ecd7c8443e038612e4c2b2afb221745da598483e239a15a7ef9a701c0a
|
data/Gemfile
CHANGED
@@ -28,3 +28,10 @@ source "https://rubygems.org"
|
|
28
28
|
|
29
29
|
# Specify your gem's dependencies in output_mode.gemspec
|
30
30
|
gemspec
|
31
|
+
|
32
|
+
# NOTE: Checks out the openflight version of tty-table with the 'rotate' flag
|
33
|
+
# fix. This should eventually become part of the mainline version of TTY::Table
|
34
|
+
#
|
35
|
+
# This is intentionally not part of the gemspec so older versions of TTY::Table
|
36
|
+
# can still be used
|
37
|
+
gem 'tty-table', github: 'openflighthpc/tty-table', branch: '9b326fcbe04968463da58c000fbb1dd5ce178243'
|
data/LICENSE.txt
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
This project is partially dual licensed under BSD-2-Clause OR 0BSD. Source code originating from a BSD-2-Clause licensed file must comply with terms contained within the license header block. Source code originating from files without a license header block maybe redistributed under either license.
|
2
|
-
|
3
|
-
The following is a copy of the BSD-2-Clause license:
|
4
|
-
|
5
1
|
Copyright 2020 William McCumstie
|
6
2
|
|
7
3
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
@@ -11,8 +7,3 @@ Redistribution and use in source and binary forms, with or without modification,
|
|
11
7
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
12
8
|
|
13
9
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
14
|
-
|
15
|
-
The following is a copy of the 0BSD license:
|
16
|
-
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
18
|
-
|
data/README.md
CHANGED
data/bin/demo
CHANGED
@@ -1,22 +1,57 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#==============================================================================
|
3
|
-
#
|
3
|
+
# Copyright 2020 William McCumstie
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
16
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
19
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
20
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
21
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
22
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
23
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
24
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
25
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
4
26
|
#==============================================================================
|
5
27
|
|
6
|
-
|
7
28
|
require "bundler/setup"
|
8
29
|
require "output_mode"
|
30
|
+
require 'erb'
|
9
31
|
|
10
32
|
module DemoIndex
|
11
33
|
extend OutputMode::TLDR::Index
|
12
34
|
|
13
|
-
register_callable(header: 'Integer') { |i| i }
|
14
|
-
register_callable(header: 'Standard') { 'always visible' }
|
35
|
+
register_callable(header: 'Integer', row_color: [:yellow, :bold]) { |i| i }
|
36
|
+
register_callable(header: 'Standard', header_color: [:strikethrough] ) { 'always visible' }
|
15
37
|
register_callable(header: 'Verbose', verbose: true) { 'verbose visible' }
|
16
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' }
|
17
41
|
register_callable(header: 'Yes/True') { true }
|
18
|
-
register_callable(header: 'No/False') { false }
|
42
|
+
register_callable(header: 'No/False', row_color: [:clear]) { false }
|
19
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'
|
51
|
+
else
|
52
|
+
'non-interactive-simplified'
|
53
|
+
end
|
54
|
+
end
|
20
55
|
end
|
21
56
|
|
22
57
|
module DemoShow
|
@@ -26,14 +61,42 @@ module DemoShow
|
|
26
61
|
register_callable(header: 'Standard') { 'always visible' }
|
27
62
|
register_callable(header: 'Verbose', verbose: true) { 'verbose visible' }
|
28
63
|
register_callable(header: 'Simplified', verbose: false) { 'simplified visible' }
|
29
|
-
register_callable(header: '
|
30
|
-
register_callable(header: '
|
64
|
+
register_callable(header: 'Interactive', interactive: true) { 'interactive visible' }
|
65
|
+
register_callable(header: 'Non Interactive', interactive: false) { 'non-interactive visible' }
|
66
|
+
register_callable(header: 'Yes/True', section: :boolean) { true }
|
67
|
+
register_callable(header: 'No/False', section: :boolean) { false }
|
31
68
|
register_callable(header: 'Missing') { nil }
|
69
|
+
register_callable(header: 'Tab') { "tab1\ttab2" }
|
70
|
+
register_callable(header: 'New line') { "line1\nline2" }
|
32
71
|
end
|
33
72
|
|
34
73
|
data = [1, 2, 3]
|
35
74
|
|
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
|
+
|
36
87
|
puts <<~EOF
|
88
|
+
#==============================================================================
|
89
|
+
#==============================================================================
|
90
|
+
# INDEX OUTPUTS
|
91
|
+
#==============================================================================
|
92
|
+
#==============================================================================
|
93
|
+
|
94
|
+
#==============================================================================
|
95
|
+
# Default Demo Index
|
96
|
+
# Simplified in interactive shells, verbose in non-interactive
|
97
|
+
#==============================================================================
|
98
|
+
#{DemoIndex.build_output.render(*data)}
|
99
|
+
|
37
100
|
#==============================================================================
|
38
101
|
# Demo Verbose Index
|
39
102
|
#==============================================================================
|
@@ -41,10 +104,38 @@ puts <<~EOF
|
|
41
104
|
|
42
105
|
#==============================================================================
|
43
106
|
# Demo "Simplified" Index
|
44
|
-
# NOTE: Disabled for non-interactive shell, shows the verbose output instead
|
45
107
|
#==============================================================================
|
46
108
|
#{DemoIndex.build_output(verbose: false).render(*data)}
|
47
109
|
|
110
|
+
#==============================================================================
|
111
|
+
# Force Interactive
|
112
|
+
# Always print as if the shell is interactive
|
113
|
+
#==============================================================================
|
114
|
+
#{DemoIndex.build_output(interactive: true).render(*data)}
|
115
|
+
|
116
|
+
#==============================================================================
|
117
|
+
# Force Non-Interactive
|
118
|
+
# Always print as if the shell is non-interactive
|
119
|
+
#==============================================================================
|
120
|
+
#{DemoIndex.build_output(interactive: false).render(*data)}
|
121
|
+
|
122
|
+
#==============================================================================
|
123
|
+
# Demo ASCII Index
|
124
|
+
#==============================================================================
|
125
|
+
#{DemoIndex.build_output(ascii: true).render(*data)}
|
126
|
+
|
127
|
+
#==============================================================================
|
128
|
+
#==============================================================================
|
129
|
+
# SHOW OUTPUTS
|
130
|
+
#==============================================================================
|
131
|
+
#==============================================================================
|
132
|
+
|
133
|
+
#==============================================================================
|
134
|
+
# Default Settings
|
135
|
+
# Simplified in interactive shells, verbose in non-interactive
|
136
|
+
#==============================================================================
|
137
|
+
#{DemoShow.build_output.render(*data)}
|
138
|
+
|
48
139
|
#==============================================================================
|
49
140
|
# Demo Verbose Show
|
50
141
|
#==============================================================================
|
@@ -52,9 +143,30 @@ puts <<~EOF
|
|
52
143
|
|
53
144
|
#==============================================================================
|
54
145
|
# Demo "Simplified" Show
|
55
|
-
# NOTE: Disabled for non-interactive shell, shows the verbose output instead
|
56
146
|
#==============================================================================
|
57
147
|
#{DemoShow.build_output(verbose: false).render(*data)}
|
58
|
-
EOF
|
59
148
|
|
149
|
+
#==============================================================================
|
150
|
+
# Force Interactive
|
151
|
+
# Always print as if the shell is interactive
|
152
|
+
#==============================================================================
|
153
|
+
#{DemoShow.build_output(interactive: true).render(*data)}
|
154
|
+
|
155
|
+
#==============================================================================
|
156
|
+
# Force Non-Interactive
|
157
|
+
# Always print as if the shell is non-interactive
|
158
|
+
#==============================================================================
|
159
|
+
#{DemoShow.build_output(interactive: false).render(*data)}
|
160
|
+
|
161
|
+
#==============================================================================
|
162
|
+
# Demo ASCII Index
|
163
|
+
#==============================================================================
|
164
|
+
#{DemoShow.build_output(ascii: true).render(*data)}
|
60
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)}
|
172
|
+
EOF
|
@@ -36,7 +36,9 @@ module OutputMode
|
|
36
36
|
# @param config Directly provided to {OutputMode::Callable#initialize}
|
37
37
|
# @yield Directly provided to {OutputMode::Callable#initialize}
|
38
38
|
def register_callable(**config, &b)
|
39
|
-
|
39
|
+
Callable.new(**config, &b).tap do |c|
|
40
|
+
output_callables << c
|
41
|
+
end
|
40
42
|
end
|
41
43
|
|
42
44
|
# Provides the base method signature
|
data/lib/output_mode/callable.rb
CHANGED
@@ -26,16 +26,17 @@
|
|
26
26
|
|
27
27
|
module OutputMode
|
28
28
|
# Internal array like object that will convert procs to Callable
|
29
|
-
class Callables
|
29
|
+
class Callables
|
30
|
+
include Enumerable
|
31
|
+
|
30
32
|
# @api private
|
31
33
|
def initialize(callables = nil)
|
34
|
+
@callables = []
|
32
35
|
case callables
|
33
|
-
when Array
|
34
|
-
|
35
|
-
callables.each { |c| all << c }
|
36
|
-
end
|
36
|
+
when Array, Callables
|
37
|
+
callables.each { |c| @callables << c }
|
37
38
|
when nil
|
38
|
-
|
39
|
+
# NOOP
|
39
40
|
else
|
40
41
|
raise "Can not convert #{callables.class} into a #{self.class}"
|
41
42
|
end
|
@@ -43,13 +44,45 @@ module OutputMode
|
|
43
44
|
|
44
45
|
def <<(item)
|
45
46
|
if item.is_a? Callable
|
46
|
-
|
47
|
+
@callables << item
|
47
48
|
elsif item.respond_to?(:call)
|
48
|
-
|
49
|
+
@callables << Callable.new(&item)
|
49
50
|
else
|
50
51
|
raise Error, "#{item.class} is not callable"
|
51
52
|
end
|
52
53
|
end
|
54
|
+
|
55
|
+
def each(&block)
|
56
|
+
@callables.each(&block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def pad_each(key = :header)
|
60
|
+
max_length = self.map { |c| c.config[key].to_s.length }
|
61
|
+
.max
|
62
|
+
|
63
|
+
pads = self.map do |callable|
|
64
|
+
length = max_length - callable.config[key].to_s.length
|
65
|
+
[callable, { padding: ' ' * length }]
|
66
|
+
end
|
67
|
+
|
68
|
+
if block_given?
|
69
|
+
pads.each { |*args| yield(*args) }
|
70
|
+
else
|
71
|
+
pads.each
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def config_select(key, *values)
|
76
|
+
selected = self.select do |callable|
|
77
|
+
conf = callable.config[key]
|
78
|
+
if conf.is_a? Array
|
79
|
+
!(conf & values).empty?
|
80
|
+
else
|
81
|
+
values.include?(conf)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
Callables.new(selected)
|
85
|
+
end
|
53
86
|
end
|
54
87
|
|
55
88
|
class Callable
|
@@ -83,28 +116,36 @@ module OutputMode
|
|
83
116
|
|
84
117
|
# Handles the dynamic +<query>?+ and +<explicit-negation>!+ methods
|
85
118
|
#
|
86
|
-
# The +<query>?+ methods check if the mode has been set on the object. If
|
87
|
-
# +query+ is a defined mode, then the value is directly pulled from #{modes}.
|
88
|
-
# Undefined modes will return +false+.
|
89
|
-
#
|
90
|
-
# The +<explicit-negation>!+ methods are similar to queries, but undefined modes
|
91
|
-
# will return +true+. This means +<explicit-negation>!+ methods only return +false+
|
92
|
-
# if the +explicit-negation+ mode has been set to +false+ in {#modes}.
|
93
|
-
#
|
94
119
|
# @return [Boolean] The result of the query or explicit-negation
|
95
|
-
# @
|
96
|
-
def method_missing(s, *
|
120
|
+
# @raise [NoMethodError] All other method calls
|
121
|
+
def method_missing(s, *args, &b)
|
97
122
|
mode = s[0..-2].to_sym
|
98
123
|
case method_char(s)
|
99
124
|
when '?'
|
100
|
-
|
125
|
+
ifnone = (args.length > 0 ? args.first : false)
|
126
|
+
modes.fetch(mode, ifnone)
|
101
127
|
when '!'
|
102
|
-
|
128
|
+
send(:"#{mode}?", true)
|
103
129
|
else
|
104
130
|
super
|
105
131
|
end
|
106
132
|
end
|
107
133
|
|
134
|
+
# @!method mode?(ifnone = false)
|
135
|
+
# This is a dynamic method for check if an arbitrary +mode+ has been set. It will
|
136
|
+
# return the associated value if the +mode+ has been defined in {#modes}.
|
137
|
+
#
|
138
|
+
# Otherwise it will return the +ifnone+ value
|
139
|
+
# @return [Boolean] the associated value if +mode+ has been defined
|
140
|
+
# @return otherwise return the +ifnone+ value
|
141
|
+
#
|
142
|
+
# @!method mode!
|
143
|
+
# Older syntax that returns +true+ if the +mode+ has not been defined. Otherwise
|
144
|
+
# the same as {#mode?}
|
145
|
+
#
|
146
|
+
# @return [Boolean]
|
147
|
+
# @deprecated Please use the newer +mode?(true)+ syntax
|
148
|
+
|
108
149
|
# Responds +true+ for valid dynamic methods
|
109
150
|
# @param [Symbol] s The method to be tested
|
110
151
|
# @return [Boolean] The truthiness of the underlining call to {#method_char}
|
@@ -133,6 +174,29 @@ module OutputMode
|
|
133
174
|
def call(*a)
|
134
175
|
callable.call(*a)
|
135
176
|
end
|
177
|
+
|
178
|
+
def generator(output)
|
179
|
+
->(*a) do
|
180
|
+
# Implicitly determine which parts of the context can be passed through
|
181
|
+
ctx = if callable.parameters.any? { |type, _| type == :keyrest }
|
182
|
+
output.context
|
183
|
+
else
|
184
|
+
keys = callable.parameters.select { |type, _| [:key, :keyreq].include?(type) }
|
185
|
+
.map { |_, k| k }
|
186
|
+
output.context.slice(*keys)
|
187
|
+
end
|
188
|
+
raw = call(*a, **ctx)
|
189
|
+
if raw == true
|
190
|
+
config[:yes] || output.yes
|
191
|
+
elsif raw == false
|
192
|
+
config[:no] || output.no
|
193
|
+
elsif [nil, ''].include?(raw)
|
194
|
+
config[:default] || output.default
|
195
|
+
else
|
196
|
+
raw
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
136
200
|
end
|
137
201
|
end
|
138
202
|
|
data/lib/output_mode/output.rb
CHANGED
@@ -36,45 +36,41 @@ module OutputMode
|
|
36
36
|
# @!attribute [r] config
|
37
37
|
# @return [Hash] additional key-values to modify the render
|
38
38
|
# @!attribute [r] default
|
39
|
-
# @return either a static default
|
39
|
+
# @return either a static default
|
40
40
|
# @!attribute [r] yes
|
41
|
-
# @return either a static yes value
|
41
|
+
# @return either a static yes value
|
42
42
|
# @!attribute [r] no
|
43
|
-
# @return either a static no value
|
44
|
-
|
43
|
+
# @return either a static no value
|
44
|
+
# @!attribute [r] context
|
45
|
+
# @return a hash of keys to be provided to the callables
|
46
|
+
attr_reader :procs, :config, :yes, :no, :default, :context
|
45
47
|
|
46
48
|
# Creates a new outputting instance from an array of procs
|
47
49
|
#
|
48
50
|
# @param *procs [Array<#call>] an array of procs (or callable objects)
|
49
51
|
# @param default: [String] replaces _blanks_ with a static string
|
50
|
-
# @param default: [Array] replace _blanks_ on a per column basis. The last value is repeated if the +procs+ are longer.
|
51
52
|
# @param yes: [String] replaces +true+ with a static string
|
52
|
-
# @param yes: [Array] replaces +true+ on a per column basis. The last value is repeated if the +procs+ are longer.
|
53
53
|
# @param no: [String] replaces +false+ with a static string
|
54
|
-
# @param
|
54
|
+
# @param context: [Hash] of keys to be provided to the callables
|
55
55
|
# @param **config [Hash] a hash of additional keys to be stored
|
56
|
-
def initialize(*procs, default: nil, yes: 'true', no: 'false', **config)
|
57
|
-
@procs = procs
|
56
|
+
def initialize(*procs, default: nil, yes: 'true', no: 'false', context: {}, **config)
|
57
|
+
@procs = Callables.new(procs)
|
58
58
|
@config = config
|
59
59
|
@yes = yes
|
60
60
|
@no = no
|
61
61
|
@default = default
|
62
|
+
@context = context
|
63
|
+
end
|
64
|
+
|
65
|
+
def callables
|
66
|
+
procs
|
62
67
|
end
|
63
68
|
|
64
69
|
# Returns the results of the +procs+ for a particular +object+. It will apply the
|
65
70
|
# +default+, +yes+, and +no+ values.
|
66
71
|
def generate(object)
|
67
|
-
procs.
|
68
|
-
|
69
|
-
if raw == true
|
70
|
-
index_selector(:yes, idx)
|
71
|
-
elsif raw == false
|
72
|
-
index_selector(:no, idx)
|
73
|
-
elsif !default.nil? && (raw.nil? || raw == '')
|
74
|
-
index_selector(:default, idx)
|
75
|
-
else
|
76
|
-
raw
|
77
|
-
end
|
72
|
+
procs.map do |callable|
|
73
|
+
callable.generator(self).call(object)
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
@@ -91,37 +87,5 @@ module OutputMode
|
|
91
87
|
def render(*data)
|
92
88
|
raise NotImplementedError
|
93
89
|
end
|
94
|
-
|
95
|
-
# A helper method for selecting elements from a source array or return
|
96
|
-
# a static value.
|
97
|
-
#
|
98
|
-
# @param [Symbol] method The source method on the +output+
|
99
|
-
# @param [Integer] index The index to lookup
|
100
|
-
#
|
101
|
-
# @overload index_selector(array_method, valid_index)
|
102
|
-
# @param array_method A method that returns an array
|
103
|
-
# @param valid_index An index that is less than the array's length
|
104
|
-
# @return the value at the index
|
105
|
-
#
|
106
|
-
# @overload index_selector(array_method, out_of_bounds)
|
107
|
-
# @param array_method A method that returns an array
|
108
|
-
# @param out_of_bounds An index greater than the maximum array length
|
109
|
-
# @return the last element of the array
|
110
|
-
#
|
111
|
-
# @overload index_selector(non_array_method, _)
|
112
|
-
# @param non_array_method A method that does not return an array
|
113
|
-
# @param _ The index is ignored
|
114
|
-
# @return the result of the non_array_method
|
115
|
-
def index_selector(method, index)
|
116
|
-
source = public_send(method)
|
117
|
-
is_array = source.is_a? Array
|
118
|
-
if is_array && source.length > index
|
119
|
-
source[index]
|
120
|
-
elsif is_array
|
121
|
-
source.last
|
122
|
-
else
|
123
|
-
source
|
124
|
-
end
|
125
|
-
end
|
126
90
|
end
|
127
91
|
end
|
@@ -40,7 +40,12 @@ module OutputMode
|
|
40
40
|
def render(*data)
|
41
41
|
io = StringIO.new
|
42
42
|
csv = CSV.new(io, **config)
|
43
|
-
data.each
|
43
|
+
data.each do |datum|
|
44
|
+
csv << generate(datum).map do |value|
|
45
|
+
next nil if value.nil?
|
46
|
+
value.to_s.dump[1...-1]
|
47
|
+
end
|
48
|
+
end
|
44
49
|
io.tap(&:rewind).read
|
45
50
|
end
|
46
51
|
end
|
@@ -29,33 +29,40 @@ require 'tty-table'
|
|
29
29
|
module OutputMode
|
30
30
|
module Outputs
|
31
31
|
class Tabulated < Output
|
32
|
-
attr_reader :renderer, :header, :default, :block, :yes, :no
|
33
|
-
|
34
32
|
# @!attribute [r] renderer
|
35
33
|
# @return [Symbol] the renderer type, see: https://github.com/piotrmurach/tty-table#32-renderer
|
36
|
-
# @!attribute [r] header
|
37
|
-
# @return [Array] An optional header row for the table
|
38
34
|
# @!attribute [r] block
|
39
35
|
# @return [#call] an optional block of code that configures the renderer
|
36
|
+
# @!attribute [r] colorize
|
37
|
+
# @return [Boolean] enable or disabled the colorization
|
38
|
+
# @!attribute [r] header_color
|
39
|
+
# @return An optional header color or array of colors
|
40
|
+
# @!attribute [r] row_color
|
41
|
+
# @return An optional data color or array of colors
|
42
|
+
attr_reader :renderer, :default, :block, :yes, :no,
|
43
|
+
:header_color, :row_color, :colorize
|
40
44
|
|
41
45
|
# @return [Hash] additional options to +TTY::Table+ renderer
|
42
46
|
# @see https://github.com/piotrmurach/tty-table#33-options
|
43
47
|
def config; super; end
|
44
48
|
|
45
|
-
# @overload initialize(*procs, renderer: nil,
|
49
|
+
# @overload initialize(*procs, renderer: nil, **config)
|
46
50
|
# @param [Array] *procs see {OutputMode::Outputs::Base#initialize}
|
47
51
|
# @param [Symbol] :renderer override the default renderer
|
48
|
-
# @param [Array<String>] :header the header row of the table
|
49
52
|
# @param [Hash] **config additional options to the renderer
|
50
53
|
# @yieldparam tty_table_renderer [TTY::Table::Renderer::Base] optional access the underlining TTY::Table renderer
|
51
54
|
def initialize(*procs,
|
52
55
|
renderer: :unicode,
|
53
|
-
|
56
|
+
colorize: false,
|
57
|
+
header_color: nil,
|
58
|
+
row_color: nil,
|
54
59
|
**config,
|
55
60
|
&block)
|
56
|
-
@header = header
|
57
61
|
@renderer = renderer
|
58
62
|
@block = block
|
63
|
+
@header_color = header_color
|
64
|
+
@row_color = row_color
|
65
|
+
@colorize = colorize
|
59
66
|
super(*procs, **config)
|
60
67
|
end
|
61
68
|
|
@@ -63,10 +70,48 @@ module OutputMode
|
|
63
70
|
# @see OutputMode::Outputs::Base#render
|
64
71
|
# @see https://github.com/piotrmurach/tty-table
|
65
72
|
def render(*data)
|
66
|
-
table = TTY::Table.new header:
|
67
|
-
data.each { |d| table <<
|
73
|
+
table = TTY::Table.new header: processed_header
|
74
|
+
data.each { |d| table << process_row(d) }
|
68
75
|
table.render(renderer, **config, &block) || ''
|
69
76
|
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Colorizes the header when requested
|
81
|
+
def processed_header
|
82
|
+
callables.map do |callable|
|
83
|
+
header = callable.config.fetch(:header, '')
|
84
|
+
color = callable.config.fetch(:header_color) || header_color
|
85
|
+
case color
|
86
|
+
when nil
|
87
|
+
header.to_s
|
88
|
+
when Array
|
89
|
+
pastel.decorate(header.to_s, *color)
|
90
|
+
else
|
91
|
+
pastel.decorate(header.to_s, color)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Colorizes the row when requested
|
97
|
+
def process_row(model)
|
98
|
+
callables.map do |callable|
|
99
|
+
d = callable.generator(self).call(model)
|
100
|
+
color = callable.config[:row_color] || row_color
|
101
|
+
case color
|
102
|
+
when NilClass
|
103
|
+
d.to_s
|
104
|
+
when Array
|
105
|
+
pastel.decorate(d.to_s, *color)
|
106
|
+
else
|
107
|
+
pastel.decorate(d.to_s, color)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def pastel
|
113
|
+
@pastel ||= Pastel::Color.new(enabled: colorize)
|
114
|
+
end
|
70
115
|
end
|
71
116
|
end
|
72
117
|
end
|
@@ -38,13 +38,25 @@ module OutputMode
|
|
38
38
|
# @yieldparam field: An optional field header for the value
|
39
39
|
# @yieldparam padding: A padding string which will right align the +field+
|
40
40
|
# @yieldparam **config TBA
|
41
|
-
def each
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
def each(section = nil, &block)
|
42
|
+
# Select the callable objects
|
43
|
+
callables = if section == nil
|
44
|
+
output.callables
|
45
|
+
elsif section == :default
|
46
|
+
output.callables.config_select(:section, :default, nil)
|
47
|
+
else
|
48
|
+
output.callables.config_select(:section, section)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Yield each selected attribute
|
52
|
+
objs = callables.pad_each.map do |callable, padding:|
|
53
|
+
value = callable.generator(output).call(model)
|
54
|
+
field = callable.config[:header]
|
55
|
+
[value, {field: field, padding: padding }]
|
47
56
|
end
|
57
|
+
|
58
|
+
# Runs the provided block
|
59
|
+
objs.each(&block)
|
48
60
|
end
|
49
61
|
|
50
62
|
# Renders an ERB object within the entry's context. This provides access to the
|
@@ -61,6 +73,12 @@ module OutputMode
|
|
61
73
|
def pastel
|
62
74
|
@pastel ||= Pastel.new(enabled: colorize)
|
63
75
|
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def generated
|
80
|
+
@generated ||= output.generate(model)
|
81
|
+
end
|
64
82
|
end
|
65
83
|
|
66
84
|
# @!attribute [r] erb
|
@@ -68,7 +86,8 @@ module OutputMode
|
|
68
86
|
# @!attribute [r] separator
|
69
87
|
# @!attribute [r] fields
|
70
88
|
# @!attribute [r] colorize
|
71
|
-
|
89
|
+
# @!attribute [r] sections
|
90
|
+
attr_reader :erb, :fields, :separator, :colorize, :sections
|
72
91
|
|
73
92
|
# Create a new +output+ which will render using +ERB+. The provided +template+ should
|
74
93
|
# only render the +output+ for a single +entry+ (aka model, record, data object, etc).
|
@@ -84,23 +103,32 @@ module OutputMode
|
|
84
103
|
#
|
85
104
|
# @overload initialize(*procs, template: nil, fields: nil, seperator: "\n", yes: 'true', no: 'false', **config)
|
86
105
|
# @param [Array] *procs see {OutputMode::Output#initialize}
|
87
|
-
# @param [String] template: A string to be converted into +ERB+
|
88
106
|
# @param [ERB] template: The +template+ object used by the renderer
|
89
107
|
# @param [Array] fields: An optional array of field headers that map to the procs, repeating the last value if required
|
90
108
|
# @param fields: A static value to use as all field headers
|
91
109
|
# @param separator: The character(s) used to join the "entries" together
|
92
110
|
# @param colorize: Flags if the caller wants the colorized version, this maybe ignored by +template+
|
111
|
+
# @param sections: An optional array that groups the procs into sections. This is ignored by default
|
93
112
|
# @param [Hash] **config see {OutputMode::Output#initialize}
|
94
113
|
def initialize(*procs,
|
95
114
|
template: nil,
|
96
115
|
fields: nil,
|
97
116
|
separator: "\n",
|
98
117
|
colorize: false,
|
118
|
+
sections: nil,
|
99
119
|
**config)
|
100
|
-
@erb =
|
120
|
+
@erb = case template
|
121
|
+
when String
|
122
|
+
ERB.new(template, nil, '-')
|
123
|
+
when ERB
|
124
|
+
template
|
125
|
+
else
|
126
|
+
DEFAULT_ERB
|
127
|
+
end
|
101
128
|
@fields = fields
|
102
129
|
@separator = separator
|
103
130
|
@colorize = colorize
|
131
|
+
@sections = sections
|
104
132
|
super(*procs, **config)
|
105
133
|
end
|
106
134
|
|
@@ -1,7 +1,31 @@
|
|
1
1
|
#==============================================================================
|
2
|
-
#
|
2
|
+
# Copyright 2020 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.
|
3
25
|
#==============================================================================
|
4
26
|
|
27
|
+
require 'tty-color'
|
28
|
+
|
5
29
|
module OutputMode
|
6
30
|
module TLDR
|
7
31
|
module Index
|
@@ -11,15 +35,31 @@ module OutputMode
|
|
11
35
|
# @overload register_callable(header:, verbose: true)
|
12
36
|
# @param header: The column's header field when displaying to humans
|
13
37
|
# @param verbose: Whether the column will be shown in the verbose output
|
38
|
+
# @param interactive: Whether the field will be show in the interactive output
|
39
|
+
# @param header_color: Override the default color for the header
|
40
|
+
# @param row_color: Override the default color for the row
|
41
|
+
# @param modes: Additional modes flags for the callable
|
14
42
|
# @yieldparam model The subject the column is describing, some sort of data model
|
15
|
-
def register_callable(header:, verbose: nil, &b)
|
16
|
-
|
43
|
+
def register_callable(modes: {}, header:, verbose: nil, interactive: nil, header_color: nil, row_color: nil, &b)
|
44
|
+
modes = modes.map { |m| [m, true] }.to_h if modes.is_a? Array
|
45
|
+
super(modes: modes.merge(verbose: verbose, interactive: interactive),
|
46
|
+
header: header,
|
47
|
+
header_color: header_color,
|
48
|
+
row_color: row_color,
|
49
|
+
&b)
|
17
50
|
end
|
51
|
+
alias_method :register_column, :register_callable
|
18
52
|
|
19
53
|
# Creates an new +output+ from the verbosity flag. This method only uses
|
20
54
|
# +$stdout+ as part of it's output class discovery logic. It does not
|
21
55
|
# print to the output directly
|
22
56
|
#
|
57
|
+
# The +ascii+ flag disables the unicode formatting in interactive shells.
|
58
|
+
# Non interactive shells use ASCII by default.
|
59
|
+
#
|
60
|
+
# The +verbose+ flag toggles the simplified and verbose outputs in the
|
61
|
+
# interactive output. Non-interactive outputs are always verbose
|
62
|
+
#
|
23
63
|
# If +$stdout+ is an interactive shell (aka a TTY), then it will display using
|
24
64
|
# {OutputMode::Outputs::Tabulated}. This is intended for human consumption
|
25
65
|
# and will obey the provided +verbose+ flag.
|
@@ -28,26 +68,57 @@ module OutputMode
|
|
28
68
|
# {OutputMode::Outputs::Delimited} using tab delimiters. This is intended
|
29
69
|
# for consumption by machines. This output ignores the provided +verbose+
|
30
70
|
# flag as it is always verbose.
|
31
|
-
|
32
|
-
|
71
|
+
#
|
72
|
+
# An interative/ non-interactive output can be forced by setting the
|
73
|
+
# +interactive+ flag to +true+/+false+ respectively
|
74
|
+
def build_output(verbose: nil, ascii: nil, interactive: nil, header_color: [:blue, :bold], row_color: :green, context: {})
|
75
|
+
# Set the interactive and verbose flags if not provided
|
76
|
+
interactive = $stdout.tty? if interactive.nil?
|
77
|
+
verbose = !interactive if verbose.nil?
|
78
|
+
ascii = !interactive if ascii.nil?
|
79
|
+
|
80
|
+
# Update the rendering context with the verbosity/interactive settings
|
81
|
+
context = context.merge(interactive: interactive, verbose: verbose, ascii: ascii)
|
82
|
+
|
83
|
+
callables = if verbose
|
33
84
|
# Filter out columns that are explicitly not verbose
|
34
|
-
output_callables.select(
|
85
|
+
output_callables.select { |o| o.verbose?(true) }
|
35
86
|
else
|
36
87
|
# Filter out columns that are explicitly verbose
|
37
88
|
output_callables.reject(&:verbose?)
|
38
89
|
end
|
39
90
|
|
40
|
-
if
|
91
|
+
callables = if interactive
|
92
|
+
# Filter out columns that are explicitly not interactive
|
93
|
+
callables.select { |o| o.interactive?(true) }
|
94
|
+
else
|
95
|
+
# Filter out columns that are explicitly interactive
|
96
|
+
callables.reject { |o| o.interactive? }
|
97
|
+
end
|
98
|
+
|
99
|
+
if interactive
|
41
100
|
# Creates the human readable output
|
101
|
+
opts = if ascii
|
102
|
+
{ yes: 'yes', no: 'no', renderer: :ascii }
|
103
|
+
else
|
104
|
+
{
|
105
|
+
yes: '✓', no: '✕', renderer: :unicode, colorize: TTY::Color.color?,
|
106
|
+
header_color: header_color,
|
107
|
+
row_color: row_color
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
42
111
|
Outputs::Tabulated.new(*callables,
|
43
|
-
|
44
|
-
renderer: :unicode,
|
112
|
+
rotate: false,
|
45
113
|
padding: [0,1],
|
46
114
|
default: '(none)',
|
47
|
-
|
115
|
+
context: context,
|
116
|
+
**opts
|
117
|
+
)
|
48
118
|
else
|
49
119
|
# Creates the machine readable output
|
50
|
-
Outputs::Delimited.new(*callables, col_sep: "\t", yes: '
|
120
|
+
Outputs::Delimited.new(*callables, col_sep: "\t", yes: 'yes', no: 'no', default: nil,
|
121
|
+
context: context)
|
51
122
|
end
|
52
123
|
end
|
53
124
|
end
|
@@ -1,5 +1,27 @@
|
|
1
1
|
#==============================================================================
|
2
|
-
#
|
2
|
+
# Copyright 2020 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.
|
3
25
|
#==============================================================================
|
4
26
|
|
5
27
|
require 'tty-color'
|
@@ -13,15 +35,29 @@ module OutputMode
|
|
13
35
|
# @overload register_callable(header:, verbose: true)
|
14
36
|
# @param header: The human readable key to the field, uses the term 'header' for consistency
|
15
37
|
# @param verbose: Whether the field will be shown in the verbose output
|
38
|
+
# @param interactive: Whether the field will be show in the interactive output
|
39
|
+
# @param section: Define the grouping a callable belongs to. Ignored by default
|
40
|
+
# @param modes: Additional modes flags for the callable
|
16
41
|
# @yieldparam model The subject the column is describing, some sort of data model
|
17
|
-
def register_callable(header:, verbose: nil, &b)
|
18
|
-
|
42
|
+
def register_callable(modes: {}, header:, verbose: nil, interactive: nil, section: :other, &b)
|
43
|
+
modes = modes.map { |m| [m, true] }.to_h if modes.is_a? Array
|
44
|
+
super(modes: modes.merge(verbose: verbose, interactive: interactive),
|
45
|
+
header: header,
|
46
|
+
section: section,
|
47
|
+
&b)
|
19
48
|
end
|
49
|
+
alias_method :register_attribute, :register_callable
|
20
50
|
|
21
51
|
# Creates an new +output+ from the verbosity flag. This method only uses
|
22
52
|
# +$stdout+ as part of it's output class discovery logic. It does not
|
23
53
|
# print to the io directly
|
24
54
|
#
|
55
|
+
# The +ascii+ flag disables the unicode formatting in interactive shells.
|
56
|
+
# Non interactive shells use ASCII by default.
|
57
|
+
#
|
58
|
+
# The +verbose+ flag toggles the simplified and verbose outputs in the
|
59
|
+
# interactive output. Non-interactive outputs are always verbose
|
60
|
+
#
|
25
61
|
# If +$stdout+ is an interactive shell (aka a TTY), then it will display using
|
26
62
|
# {OutputMode::Outputs::Templated}. This is intended for human consumption
|
27
63
|
# and will obey the provided +verbose+ flag.
|
@@ -30,25 +66,57 @@ module OutputMode
|
|
30
66
|
# {OutputMode::Outputs::Delimited} using tab delimiters. This is intended
|
31
67
|
# for consumption by machines. This output ignores the provided +verbose+
|
32
68
|
# flag as it is always verbose.
|
33
|
-
|
34
|
-
|
69
|
+
#
|
70
|
+
# The +template+ overrides the default erb template for the output
|
71
|
+
#
|
72
|
+
# An interative/ non-interactive output can be forced by setting the
|
73
|
+
# +interactive+ flag to +true+/+false+ respectively
|
74
|
+
def build_output(verbose: nil, ascii: nil, interactive: nil, template: nil, context: {})
|
75
|
+
# Set the interactive and verbose flags if not provided
|
76
|
+
interactive = $stdout.tty? if interactive.nil?
|
77
|
+
verbose = !interactive if verbose.nil?
|
78
|
+
ascii = !interactive if ascii.nil?
|
79
|
+
|
80
|
+
# Update the rendering context with the verbosity/interactive settings
|
81
|
+
context = context.merge(interactive: interactive, verbose: verbose, ascii: ascii)
|
82
|
+
|
83
|
+
callables = if verbose
|
35
84
|
# Filter out columns that are explicitly not verbose
|
36
|
-
output_callables.select(
|
85
|
+
output_callables.select { |o| o.verbose?(true) }
|
37
86
|
else
|
38
87
|
# Filter out columns that are explicitly verbose
|
39
88
|
output_callables.reject(&:verbose?)
|
40
89
|
end
|
41
90
|
|
42
|
-
if
|
91
|
+
callables = if interactive
|
92
|
+
# Filter out columns that are explicitly not interactive
|
93
|
+
callables.select { |o| o.interactive?(true) }
|
94
|
+
else
|
95
|
+
# Filter out columns that are explicitly interactive
|
96
|
+
callables.reject { |o| o.interactive? }
|
97
|
+
end
|
98
|
+
|
99
|
+
if interactive
|
43
100
|
# Creates the human readable output
|
101
|
+
opts = if ascii
|
102
|
+
{ yes: 'yes', no: 'no', colorize: false }
|
103
|
+
else
|
104
|
+
{ yes: '✓', no: '✕', colorize: TTY::Color.color? }
|
105
|
+
end
|
106
|
+
|
107
|
+
sections = callables.map { |o| o.config[:section] }
|
108
|
+
|
44
109
|
Outputs::Templated.new(*callables,
|
45
110
|
fields: callables.map { |c| c.config.fetch(:header, 'missing') },
|
46
|
-
colorize: TTY::Color.color?,
|
47
111
|
default: '(none)',
|
48
|
-
|
112
|
+
sections: sections,
|
113
|
+
template: template,
|
114
|
+
context: context,
|
115
|
+
**opts)
|
49
116
|
else
|
50
117
|
# Creates the machine readable output
|
51
|
-
Outputs::Delimited.new(*callables, col_sep: "\t", yes: '
|
118
|
+
Outputs::Delimited.new(*callables, col_sep: "\t", yes: 'yes', no: 'no', default: nil,
|
119
|
+
context: context)
|
52
120
|
end
|
53
121
|
end
|
54
122
|
end
|
data/lib/output_mode/version.rb
CHANGED
data/output_mode.gemspec
CHANGED
@@ -31,6 +31,7 @@ require "output_mode/version"
|
|
31
31
|
Gem::Specification.new do |spec|
|
32
32
|
spec.name = "output_mode"
|
33
33
|
spec.version = OutputMode::VERSION
|
34
|
+
spec.licenses = ['BSD-2-Clause']
|
34
35
|
spec.authors = ["William McCumsite"]
|
35
36
|
spec.email = ["openlicense.williams@gmail.com"]
|
36
37
|
|
@@ -48,9 +49,9 @@ Gem::Specification.new do |spec|
|
|
48
49
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
49
50
|
spec.require_paths = ["lib"]
|
50
51
|
|
51
|
-
spec.add_runtime_dependency 'tty-table', '
|
52
|
-
spec.add_runtime_dependency 'pastel', '
|
53
|
-
spec.add_runtime_dependency 'tty-color', '
|
52
|
+
spec.add_runtime_dependency 'tty-table', '>= 0.11'
|
53
|
+
spec.add_runtime_dependency 'pastel', '>= 0.7'
|
54
|
+
spec.add_runtime_dependency 'tty-color', '>= 0.5'
|
54
55
|
|
55
56
|
spec.add_development_dependency "bundler", "~> 2.0"
|
56
57
|
spec.add_development_dependency "rake", ">= 12.3.3"
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: output_mode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.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:
|
11
|
+
date: 2021-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tty-table
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0.11'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.11'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pastel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0.7'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.7'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: tty-color
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0.5'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -141,7 +141,8 @@ files:
|
|
141
141
|
- lib/output_mode/version.rb
|
142
142
|
- output_mode.gemspec
|
143
143
|
homepage: https://github.com/WilliamMcCumstie/output_mode
|
144
|
-
licenses:
|
144
|
+
licenses:
|
145
|
+
- BSD-2-Clause
|
145
146
|
metadata:
|
146
147
|
homepage_uri: https://github.com/WilliamMcCumstie/output_mode
|
147
148
|
post_install_message:
|