dcm 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/bundle +114 -0
- data/bin/cucumber +29 -0
- data/bin/cucumber-html-formatter +29 -0
- data/bin/dcm +7 -0
- data/bin/gherkin +29 -0
- data/bin/gherkin-ruby +29 -0
- data/bin/htmldiff +29 -0
- data/bin/ldiff +29 -0
- data/bin/protoc-gen-ruby +29 -0
- data/bin/rpc_server +29 -0
- data/bin/rspec +29 -0
- data/bin/thor +29 -0
- data/lib/cli.rb +280 -0
- data/lib/codinginfo.rb +151 -0
- data/lib/core_ext.rb +40 -0
- data/lib/diff_viewer.rb +14 -0
- data/lib/file_reader.rb +16 -0
- data/lib/label_selector.rb +26 -0
- data/lib/list_colorizer.rb +7 -0
- data/lib/selecta.rb +803 -0
- data/lib/tempfile_handler.rb +12 -0
- data/lib/version.rb +3 -0
- metadata +133 -0
data/lib/cli.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
|
4
|
+
require "ecu"
|
5
|
+
require "thor"
|
6
|
+
require "filesize"
|
7
|
+
require "json"
|
8
|
+
|
9
|
+
require_relative "file_reader"
|
10
|
+
require_relative "codinginfo"
|
11
|
+
require_relative "tempfile_handler"
|
12
|
+
require_relative "diff_viewer"
|
13
|
+
require_relative "label_selector"
|
14
|
+
require_relative "core_ext"
|
15
|
+
require_relative "version"
|
16
|
+
|
17
|
+
module Dcm
|
18
|
+
|
19
|
+
class CLI < Thor
|
20
|
+
|
21
|
+
desc "show FILE", "Show all labels in FILE"
|
22
|
+
option :oneline, type: :boolean, aliases: ["-l"]
|
23
|
+
def show(file=nil)
|
24
|
+
display_list(list: parse_file(file), detail: options[:oneline] ? :onelinefull : true)
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "new [SPEC]", "Create a new dcm from scratch"
|
28
|
+
option :indented, aliases: ["-i"], type: :boolean, default: false
|
29
|
+
def new(*spec)
|
30
|
+
list = parse_spec(spec)
|
31
|
+
puts list.to_dcm(option[:indented])
|
32
|
+
rescue RuntimeError => e
|
33
|
+
puts e.message
|
34
|
+
exit 1
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "liveview FILE", "Live search and view labels in FILE"
|
38
|
+
def liveview(file=nil)
|
39
|
+
list = parse_file(file)
|
40
|
+
loop { LabelSelector.choose_from(list) }
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "creta2begu ID CODING FILE", "Convert a hierarchical DCM to a flat DCM"
|
44
|
+
def creta2begu(id, codingpath, file)
|
45
|
+
list = parse_file(file)
|
46
|
+
|
47
|
+
puts Codinginfo.new([id], codingpath)
|
48
|
+
.flatten_list(list)
|
49
|
+
.to_dcm
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "begu2creta IDS CODING FILE", "Convert a flat DCM to a hierarchical DCM"
|
53
|
+
def begu2creta(ids, codingpath, file)
|
54
|
+
list = parse_file(file)
|
55
|
+
|
56
|
+
puts Codinginfo.new(ids.split(","), codingpath)
|
57
|
+
.unflatten_list(list)
|
58
|
+
.to_dcm
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "list FILE", "List all labels in FILE"
|
62
|
+
option :lab, type: :boolean, aliases: ["-l"]
|
63
|
+
def list(file=nil)
|
64
|
+
display_list(list: parse_file(file),
|
65
|
+
detail: false,
|
66
|
+
format: (options[:lab] ? :lab : :tty))
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "summary FILE", "Summarize labels in FILE"
|
70
|
+
option :verbose, type: :boolean, aliases: ["-v"], default: false
|
71
|
+
def summary(file=nil)
|
72
|
+
list = parse_file(file)
|
73
|
+
puts "DCM file with #{list.count.quantify("label")}"
|
74
|
+
if options[:verbose]
|
75
|
+
list.group_by(&:function).each do |function, labels|
|
76
|
+
puts " #{function}: #{labels.count}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "cat FILE", "Output (filtered) dcm content"
|
82
|
+
option :include, aliases: ["-f"], default: ".*"
|
83
|
+
option :reject, aliases: ["-F"], default: "(?!x)x"
|
84
|
+
option :inlab, aliases: ["-l"], default: ""
|
85
|
+
option :notinlab, aliases: ["-L"], default: ""
|
86
|
+
option :indented, aliases: ["-i"], type: :boolean, default: false
|
87
|
+
option :headers, aliases: ["-h"], default: [], type: :array
|
88
|
+
option :subheaders, aliases: ["-H"], default: [], type: :array
|
89
|
+
option :mfile, type: :boolean, aliases: ["-m"]
|
90
|
+
def cat(file=nil)
|
91
|
+
list = parse_file(file)
|
92
|
+
if options[:include] != ".*" || options[:reject] != "(?!x)x"
|
93
|
+
selector = Regexp.new(options[:include], true)
|
94
|
+
rejector = Regexp.new(options[:reject], true)
|
95
|
+
list = list.
|
96
|
+
select { |l| l.match(selector) }.
|
97
|
+
reject { |l| l.match(rejector) }
|
98
|
+
end
|
99
|
+
if options[:inlab].present?
|
100
|
+
labfile = Ecu::LabelList.from_lab(File.read(options[:inlab]))
|
101
|
+
list = list.select { |l| labfile.any? { |s| s.name == l.name } }
|
102
|
+
end
|
103
|
+
if options[:notinlab].present?
|
104
|
+
labfile = Ecu::LabelList.from_lab(File.read(options[:notinlab]))
|
105
|
+
list = list.reject { |l| labfile.any? { |s| s.name == l.name } }
|
106
|
+
end
|
107
|
+
list.headers += options[:headers]
|
108
|
+
list.subheaders += options[:subheaders]
|
109
|
+
if options[:mfile]
|
110
|
+
puts list.to_mfile
|
111
|
+
else
|
112
|
+
puts list.to_dcm(options[:indented])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "rename MAPPING FILE", "Rename dcm content"
|
117
|
+
def rename(mapping=nil, file=nil)
|
118
|
+
list = parse_file(file)
|
119
|
+
mappings = JSON.parse(FileReader.read(mapping))
|
120
|
+
list = list.map_int do |label|
|
121
|
+
label.with \
|
122
|
+
name: mappings.filter_map { |m| m["new"] if m["old"] == label.name }&.first || label.name
|
123
|
+
end
|
124
|
+
puts list.to_dcm(options[:indented])
|
125
|
+
end
|
126
|
+
|
127
|
+
desc "validate FILE", "Validate DCM"
|
128
|
+
def validate(file=nil)
|
129
|
+
parse_file(file)
|
130
|
+
end
|
131
|
+
|
132
|
+
desc "compare FILE1 FILE2", "Compare contents of FILE1 and FILE2"
|
133
|
+
option :left, type: :boolean, aliases: ["-l"]
|
134
|
+
option :right, type: :boolean, aliases: ["-r"]
|
135
|
+
option :comparable, type: :boolean, aliases: ["-c"]
|
136
|
+
option :equal, type: :boolean, aliases: ["-e"]
|
137
|
+
option :unequal, type: :boolean, aliases: ["-u"]
|
138
|
+
option :precision, type: :numeric, aliases: ["-p"], default: 3
|
139
|
+
def compare(file1, file2)
|
140
|
+
comparison = render_comparison(file1, file2, precision: options[:precision])
|
141
|
+
|
142
|
+
if options[:left]
|
143
|
+
puts to_lab(comparison.names(:left_exclusive))
|
144
|
+
elsif options[:right]
|
145
|
+
puts to_lab(comparison.names(:right_exclusive))
|
146
|
+
elsif options[:equal]
|
147
|
+
puts to_lab(comparison.names(:equal))
|
148
|
+
elsif options[:unequal]
|
149
|
+
puts to_lab(comparison.names(:nonequal))
|
150
|
+
elsif options[:comparable]
|
151
|
+
puts (
|
152
|
+
comparison.names(:equal).map { |l| "#{l}: equal".colorize(:green) } +
|
153
|
+
comparison.names(:nonequal).map { |l| "#{l}: unequal".colorize(:red) }
|
154
|
+
)
|
155
|
+
else
|
156
|
+
puts "#{comparison.names(:left_exclusive).size.quantify("label")} exclusive to #{file1}"
|
157
|
+
puts "#{comparison.names(:right_exclusive).size.quantify("label")} exclusive to #{file2}"
|
158
|
+
puts "#{comparison.names(:common).size.quantify("label")} comparable"
|
159
|
+
puts " #{comparison.names(:equal).size.quantify("label")} equal".colorize(:green)
|
160
|
+
puts " #{comparison.names(:nonequal).size.quantify("label")} unequal".colorize(:red)
|
161
|
+
puts "DCMs are identical!".colorize(:green) if comparison.identical?
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
desc "gitdiff [ARGS]", "Provide a wrapper for git diff"
|
166
|
+
def gitdiff(path, file1, hex1, mode1, file2, hex2, mode2)
|
167
|
+
if [file1, file2].all? { |f| File.extname(f).downcase == ".dcm" }
|
168
|
+
invoke(:diff, [file1, file2])
|
169
|
+
else
|
170
|
+
puts DiffViewer.new(File.read(file1), File.read(file2))
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
desc "diff FILE1 FILE2", "Diff contents between FILE1 and FILE2"
|
175
|
+
option :left, type: :boolean, aliases: ["-l"]
|
176
|
+
option :right, type: :boolean, aliases: ["-r"]
|
177
|
+
option :comparable, type: :boolean, aliases: ["-c"]
|
178
|
+
option :precision, type: :numeric, aliases: ["-p"], default: 3
|
179
|
+
def diff(file1, file2)
|
180
|
+
comparison = render_comparison(file1, file2, precision: options[:precision])
|
181
|
+
|
182
|
+
showall = !(options[:left] || options[:comparable] || options[:right])
|
183
|
+
|
184
|
+
puts "-#{file1}".colorize(:red)
|
185
|
+
puts "+#{file2}".colorize(:green)
|
186
|
+
puts ""
|
187
|
+
if options[:left] || showall
|
188
|
+
comparison.left_exclusive.each do |label|
|
189
|
+
puts DiffViewer.new(label.to_s(detail: true), "")
|
190
|
+
end
|
191
|
+
end
|
192
|
+
if options[:comparable] || showall
|
193
|
+
comparison.differences.each do |left, right|
|
194
|
+
puts DiffViewer.new(left.to_s(detail: true), right.to_s(detail: true))
|
195
|
+
end
|
196
|
+
end
|
197
|
+
if options[:right] || showall
|
198
|
+
comparison.right_exclusive.each do |label|
|
199
|
+
puts DiffViewer.new("", label.to_s(detail: true))
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
desc "size FILE", "Guess the size of the labels contained in FILE"
|
205
|
+
def size(file)
|
206
|
+
list = parse_file(file)
|
207
|
+
puts Filesize.new(list.map(&:bytesize).reduce(:+)).pretty
|
208
|
+
end
|
209
|
+
|
210
|
+
desc "merge FILE1 FILE2 [FILE3 ...]", "Merge several files into a single DCM"
|
211
|
+
option :priority, aliases: ["-p"], default: "RIGHT"
|
212
|
+
def merge(*files)
|
213
|
+
baselist = parse_file(files.shift)
|
214
|
+
while not files.empty?
|
215
|
+
mergelist = parse_file(files.shift)
|
216
|
+
baselist = Ecu::LabelListComparison.new(baselist, mergelist).
|
217
|
+
merge(priority: options[:priority].downcase.to_sym)
|
218
|
+
end
|
219
|
+
puts baselist.to_dcm(options[:indented])
|
220
|
+
end
|
221
|
+
|
222
|
+
map %w[--version -v] => :__print_version
|
223
|
+
|
224
|
+
desc "--version, -v", "Print the version"
|
225
|
+
def __print_version
|
226
|
+
puts "v#{Dcm::VERSION}"
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.exit_on_failure?
|
230
|
+
true
|
231
|
+
end
|
232
|
+
|
233
|
+
protected
|
234
|
+
|
235
|
+
def parse_file(file)
|
236
|
+
if file.nil? || file == "-"
|
237
|
+
file = TempfileHandler.create(STDIN.read, filename: ["stdin", ".dcm"])
|
238
|
+
end
|
239
|
+
Ecu::LabelList.from_dcm(FileReader.read(file))
|
240
|
+
rescue Ecu::MalformedDcmError => e
|
241
|
+
puts e.message
|
242
|
+
puts e.context
|
243
|
+
exit 1
|
244
|
+
end
|
245
|
+
|
246
|
+
def parse_spec(spec)
|
247
|
+
return Ecu::LabelList.new if spec.empty?
|
248
|
+
fail "Usage: dcm new TYPE NAME VALUE1 [VALUE2 ...]" if spec.length < 3
|
249
|
+
type, name, value = spec
|
250
|
+
value = Float(value) rescue value
|
251
|
+
label = Ecu::Festwert.new \
|
252
|
+
name: name,
|
253
|
+
value: value
|
254
|
+
Ecu::LabelList.new([label])
|
255
|
+
end
|
256
|
+
|
257
|
+
def display_list(list:, detail:, format: :tty)
|
258
|
+
case format
|
259
|
+
when :tty
|
260
|
+
puts list.map { ListColorizer.call(_1.to_s(detail: detail)) }.join("\n")
|
261
|
+
when :lab
|
262
|
+
puts list.to_lab
|
263
|
+
else
|
264
|
+
error "Unkown format #{format}"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def render_comparison(file1, file2, precision:)
|
269
|
+
lists = [file1, file2]
|
270
|
+
.map { FileReader.read(_1) }
|
271
|
+
.map { Ecu::LabelList.from_dcm(_1) }
|
272
|
+
.map { _1.map_int { |label| label.round_to(precision) } }
|
273
|
+
Ecu::LabelListComparison.new(*lists)
|
274
|
+
end
|
275
|
+
|
276
|
+
def to_lab(ary)
|
277
|
+
ary.unshift("[LABEL]").join("\n")
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
data/lib/codinginfo.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
require "simple_xlsx_reader"
|
2
|
+
|
3
|
+
class Codinginfo
|
4
|
+
CVAR_PREFIX_REGEXP = /^CVAR_[A-Za-z0-9_]+_\d+\./
|
5
|
+
PARAM_ASSIGNMENT_HEADERS = { name: /Parameter/, cvar: /Schalter/, package: /Komponente/ }
|
6
|
+
|
7
|
+
class Cvar
|
8
|
+
|
9
|
+
# The CVAR must have a name and _may_ have a package and value
|
10
|
+
# the package and value can be merged
|
11
|
+
|
12
|
+
attr_reader :name, :value, :package
|
13
|
+
def initialize(name:, package: nil, value: nil)
|
14
|
+
@name = name
|
15
|
+
@package = package
|
16
|
+
@value = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def label_prefix
|
20
|
+
return /^#{name}_(\w+_)?#{value}\./ if package.nil?
|
21
|
+
|
22
|
+
[name, package, value].join("_") + "."
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s = "#{name}=#{value}"
|
26
|
+
def ==(other) = name == other.name
|
27
|
+
|
28
|
+
def merge(other)
|
29
|
+
fail "Cannot merge #{name} with #{other.name}" unless self == other
|
30
|
+
|
31
|
+
self.class.new \
|
32
|
+
name: name,
|
33
|
+
package: package || other.package,
|
34
|
+
value: value || other.value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Variant
|
39
|
+
def initialize(headers, row)
|
40
|
+
@properties = headers.zip(row).to_h
|
41
|
+
end
|
42
|
+
|
43
|
+
def cvars
|
44
|
+
@properties
|
45
|
+
.select { |key, _| key.match?(/^CVAR_/) }
|
46
|
+
.map { Cvar.new(name: _1, value: _2.to_i) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize(ids, filepath)
|
51
|
+
@doc = SimpleXlsxReader.open(filepath)
|
52
|
+
@headers = []
|
53
|
+
@variants = []
|
54
|
+
@assignments = {}
|
55
|
+
|
56
|
+
overview_sheet
|
57
|
+
.rows
|
58
|
+
.each do |row|
|
59
|
+
parse_headers(row) if @headers.empty?
|
60
|
+
next if @headers.empty?
|
61
|
+
next if row[1].nil? || row[3].nil?
|
62
|
+
next unless ids.any? { row[1].match?(/#{_1}/i) }
|
63
|
+
next unless row[3].match?(/CVAR/)
|
64
|
+
|
65
|
+
@variants << Variant.new(@headers, row)
|
66
|
+
end
|
67
|
+
|
68
|
+
param_assignment_sheet
|
69
|
+
.rows
|
70
|
+
.each(headers: PARAM_ASSIGNMENT_HEADERS) do |row|
|
71
|
+
next if row[:cvar].nil?
|
72
|
+
|
73
|
+
@assignments[row[:name]] = Cvar.new(name: row[:cvar], package: row[:package])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def overview_sheet
|
78
|
+
@doc
|
79
|
+
.sheets
|
80
|
+
.find { _1.name == "Gesamtübersicht" }
|
81
|
+
.tap { fail "Cannot find sheet Gesamtübersicht" if _1.nil? }
|
82
|
+
end
|
83
|
+
|
84
|
+
def param_assignment_sheet
|
85
|
+
@doc
|
86
|
+
.sheets
|
87
|
+
.find { _1.name == "Parameterdefinition" }
|
88
|
+
.tap { fail "Cannot find sheet Parameterdefinition" if _1.nil? }
|
89
|
+
end
|
90
|
+
|
91
|
+
def variant
|
92
|
+
fail "No variant matching #{id} found!" if @variants.empty?
|
93
|
+
fail "More than one variant matching #{id} found!" if @variants.size > 1
|
94
|
+
|
95
|
+
@variants.first
|
96
|
+
end
|
97
|
+
|
98
|
+
def unflatten_list(list)
|
99
|
+
Ecu::LabelList.new \
|
100
|
+
list.flat_map { |label|
|
101
|
+
if has_cvar_assignment?(label)
|
102
|
+
@variants.map { label.with(name: add_cvar_prefix(label, _1)) }
|
103
|
+
else
|
104
|
+
label
|
105
|
+
end
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def flatten_list(list)
|
110
|
+
list
|
111
|
+
.select { !cvar_coded?(_1) || has_matching_cvar?(_1) }
|
112
|
+
.map_int { _1.with(name: remove_cvar_prefix(_1.name)) }
|
113
|
+
end
|
114
|
+
|
115
|
+
def cvar_coded?(label)
|
116
|
+
label.name.match?(CVAR_PREFIX_REGEXP)
|
117
|
+
end
|
118
|
+
|
119
|
+
def has_cvar_assignment?(label)
|
120
|
+
@assignments.key?(label.name)
|
121
|
+
end
|
122
|
+
|
123
|
+
def has_matching_cvar?(label)
|
124
|
+
variant.cvars.any? { label.name.match?(_1.label_prefix) }
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_cvar_prefix(label, variant)
|
128
|
+
variant
|
129
|
+
.cvars
|
130
|
+
.find { _1 == @assignments[label.name] }
|
131
|
+
.then { _1.merge(@assignments[label.name]) }
|
132
|
+
.then { _1.label_prefix + label.name }
|
133
|
+
end
|
134
|
+
|
135
|
+
def remove_cvar_prefix(name)
|
136
|
+
name.sub(CVAR_PREFIX_REGEXP, "")
|
137
|
+
end
|
138
|
+
|
139
|
+
def parse_headers(row)
|
140
|
+
return unless row[1]&.match?(/SWFK-ID/)
|
141
|
+
return unless row[1]&.match?(/CVAR_BeguData/)
|
142
|
+
return unless row[2]&.match?(/Kommentar/)
|
143
|
+
|
144
|
+
@headers = row
|
145
|
+
.map(&:chomp)
|
146
|
+
.map(&:lstrip)
|
147
|
+
.map(&:strip)
|
148
|
+
.map { _1.sub(/\n.*/, "") }
|
149
|
+
.tap { _1[0] = "typestr" }
|
150
|
+
end
|
151
|
+
end
|
data/lib/core_ext.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "pastel"
|
2
|
+
|
3
|
+
class Object
|
4
|
+
def as
|
5
|
+
yield self
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Integer
|
10
|
+
def quantify(singular, plural="#{singular}s")
|
11
|
+
"#{to_s} #{self == 1 ? singular : plural}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class String
|
16
|
+
def indent(spaces = 2)
|
17
|
+
lines.map { |line| " " * spaces + line }.join
|
18
|
+
end
|
19
|
+
|
20
|
+
def inline_dcm
|
21
|
+
"KONSERVIERUNG_FORMAT 2.0\n\n" + self
|
22
|
+
end
|
23
|
+
|
24
|
+
def enquote
|
25
|
+
"\"#{to_s}\""
|
26
|
+
end
|
27
|
+
|
28
|
+
def present?
|
29
|
+
!empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def colorize(color)
|
33
|
+
return self if false
|
34
|
+
pastel.decorate(self, color)
|
35
|
+
end
|
36
|
+
|
37
|
+
def pastel
|
38
|
+
@@pastel ||= Pastel.new
|
39
|
+
end
|
40
|
+
end
|
data/lib/diff_viewer.rb
ADDED
data/lib/file_reader.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class FileReader
|
2
|
+
def self.read(file)
|
3
|
+
str = File.read(file)
|
4
|
+
|
5
|
+
# Try it as UTF-8 directly
|
6
|
+
cleaned = str.dup.force_encoding('UTF-8')
|
7
|
+
unless cleaned.valid_encoding?
|
8
|
+
# Some of it might be old Windows code page
|
9
|
+
cleaned = str.encode( 'UTF-8', 'Windows-1252' )
|
10
|
+
end
|
11
|
+
str = cleaned
|
12
|
+
rescue EncodingError
|
13
|
+
# Force it to UTF-8, throwing out invalid bits
|
14
|
+
str.encode!('UTF-8', invalid: :replace, undef: :replace)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "core_ext"
|
2
|
+
require_relative "selecta"
|
3
|
+
require_relative "list_colorizer"
|
4
|
+
|
5
|
+
class LabelSelector
|
6
|
+
def self.choose_from(list)
|
7
|
+
view = selecta(list)
|
8
|
+
print view
|
9
|
+
STDIN.gets
|
10
|
+
rescue Interrupt => e
|
11
|
+
clear_screen
|
12
|
+
exit 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.selecta(list)
|
16
|
+
clear_screen
|
17
|
+
Selecta.new.main_api(keys: list.map(&:name),
|
18
|
+
values: list.map { |e| ListColorizer.call(e.to_s(detail: true)) },
|
19
|
+
options: { height: "full" })
|
20
|
+
clear_screen
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.clear_screen
|
24
|
+
print "\e[2J\e[H"
|
25
|
+
end
|
26
|
+
end
|