youplot 0.3.1 → 0.4.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/README.md +177 -67
- data/exe/uplot +1 -1
- data/exe/youplot +1 -1
- data/lib/youplot.rb +12 -4
- data/lib/youplot/backends/processing.rb +11 -7
- data/lib/youplot/backends/{unicode_plot_backend.rb → unicode_plot.rb} +53 -34
- data/lib/youplot/command.rb +189 -70
- data/lib/youplot/dsv.rb +87 -0
- data/lib/youplot/options.rb +18 -0
- data/lib/youplot/parameters.rb +34 -0
- data/lib/youplot/parser.rb +306 -0
- data/lib/youplot/version.rb +1 -1
- metadata +10 -10
- data/lib/youplot/command/params.rb +0 -37
- data/lib/youplot/command/parser.rb +0 -277
- data/lib/youplot/dsv_reader.rb +0 -73
data/lib/youplot/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: youplot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kojix2
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: unicode_plot
|
@@ -94,8 +94,7 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
description:
|
98
|
-
in the \npipeline. \n"
|
97
|
+
description: A command line tool for Unicode Plotting
|
99
98
|
email:
|
100
99
|
- 2xijok@gmail.com
|
101
100
|
executables:
|
@@ -110,11 +109,12 @@ files:
|
|
110
109
|
- exe/youplot
|
111
110
|
- lib/youplot.rb
|
112
111
|
- lib/youplot/backends/processing.rb
|
113
|
-
- lib/youplot/backends/
|
112
|
+
- lib/youplot/backends/unicode_plot.rb
|
114
113
|
- lib/youplot/command.rb
|
115
|
-
- lib/youplot/
|
116
|
-
- lib/youplot/
|
117
|
-
- lib/youplot/
|
114
|
+
- lib/youplot/dsv.rb
|
115
|
+
- lib/youplot/options.rb
|
116
|
+
- lib/youplot/parameters.rb
|
117
|
+
- lib/youplot/parser.rb
|
118
118
|
- lib/youplot/version.rb
|
119
119
|
homepage: https://github.com/kojix2/youplot
|
120
120
|
licenses:
|
@@ -135,8 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '0'
|
137
137
|
requirements: []
|
138
|
-
rubygems_version: 3.
|
138
|
+
rubygems_version: 3.2.15
|
139
139
|
signing_key:
|
140
140
|
specification_version: 4
|
141
|
-
summary:
|
141
|
+
summary: A command line tool for Unicode Plotting
|
142
142
|
test_files: []
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module YouPlot
|
4
|
-
class Command
|
5
|
-
# UnicodePlot parameters.
|
6
|
-
# * Normally in a Ruby program, you might use hash for the parameter object.
|
7
|
-
# * Here, I use Struct for 2 safety reason.
|
8
|
-
# * The keys are static in Struct.
|
9
|
-
# * Struct does not conflict with keyword arguments. Hash dose.
|
10
|
-
Params = Struct.new(
|
11
|
-
# Sort me!
|
12
|
-
:title,
|
13
|
-
:width,
|
14
|
-
:height,
|
15
|
-
:border,
|
16
|
-
:margin,
|
17
|
-
:padding,
|
18
|
-
:color,
|
19
|
-
:xlabel,
|
20
|
-
:ylabel,
|
21
|
-
:labels,
|
22
|
-
:symbol,
|
23
|
-
:xscale,
|
24
|
-
:nbins,
|
25
|
-
:closed,
|
26
|
-
:canvas,
|
27
|
-
:xlim,
|
28
|
-
:ylim,
|
29
|
-
:grid,
|
30
|
-
:name
|
31
|
-
) do
|
32
|
-
def to_hc
|
33
|
-
to_h.compact
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,277 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
require_relative 'params'
|
5
|
-
|
6
|
-
module YouPlot
|
7
|
-
class Command
|
8
|
-
class Parser
|
9
|
-
attr_reader :command, :params,
|
10
|
-
:delimiter, :transpose, :headers, :pass, :output, :fmt,
|
11
|
-
:color_names, :encoding, :debug
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@command = nil
|
15
|
-
@params = Params.new
|
16
|
-
|
17
|
-
@delimiter = "\t"
|
18
|
-
@transpose = false
|
19
|
-
@headers = nil
|
20
|
-
@pass = false
|
21
|
-
@output = $stderr
|
22
|
-
@fmt = 'xyy'
|
23
|
-
@encoding = nil
|
24
|
-
@debug = false
|
25
|
-
@color_names = false
|
26
|
-
end
|
27
|
-
|
28
|
-
def create_default_parser
|
29
|
-
OptionParser.new do |opt|
|
30
|
-
opt.program_name = 'YouPlot'
|
31
|
-
opt.version = YouPlot::VERSION
|
32
|
-
opt.summary_width = 24
|
33
|
-
opt.on_tail('') # Add a blank line at the end
|
34
|
-
opt.separator('')
|
35
|
-
opt.on('Common options:')
|
36
|
-
opt.on('-O', '--pass [VAL]', 'file to output standard input data to [stdout]',
|
37
|
-
'for inserting YouPlot in the middle of Unix pipes') do |v|
|
38
|
-
@pass = v || $stdout
|
39
|
-
end
|
40
|
-
opt.on('-o', '--output VAL', 'file to output results to [stderr]') do |v|
|
41
|
-
@output = v
|
42
|
-
end
|
43
|
-
opt.on('-d', '--delimiter VAL', String, 'use DELIM instead of TAB for field delimiter') do |v|
|
44
|
-
@delimiter = v
|
45
|
-
end
|
46
|
-
opt.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
|
47
|
-
@headers = v
|
48
|
-
end
|
49
|
-
opt.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
|
50
|
-
@transpose = v
|
51
|
-
end
|
52
|
-
opt.on('-t', '--title VAL', String, 'print string on the top of plot') do |v|
|
53
|
-
params.title = v
|
54
|
-
end
|
55
|
-
opt.on('-x', '--xlabel VAL', String, 'print string on the bottom of the plot') do |v|
|
56
|
-
params.xlabel = v
|
57
|
-
end
|
58
|
-
opt.on('-y', '--ylabel VAL', String, 'print string on the far left of the plot') do |v|
|
59
|
-
params.ylabel = v
|
60
|
-
end
|
61
|
-
opt.on('-w', '--width VAL', Integer, 'number of characters per row') do |v|
|
62
|
-
params.width = v
|
63
|
-
end
|
64
|
-
opt.on('-h', '--height VAL', Numeric, 'number of rows') do |v|
|
65
|
-
params.height = v
|
66
|
-
end
|
67
|
-
opt.on('-b', '--border VAL', String, 'specify the style of the bounding box') do |v|
|
68
|
-
params.border = v.to_sym
|
69
|
-
end
|
70
|
-
opt.on('-m', '--margin VAL', Numeric, 'number of spaces to the left of the plot') do |v|
|
71
|
-
params.margin = v
|
72
|
-
end
|
73
|
-
opt.on('-p', '--padding VAL', Numeric, 'space of the left and right of the plot') do |v|
|
74
|
-
params.padding = v
|
75
|
-
end
|
76
|
-
opt.on('-c', '--color VAL', String, 'color of the drawing') do |v|
|
77
|
-
params.color = v =~ /\A[0-9]+\z/ ? v.to_i : v.to_sym
|
78
|
-
end
|
79
|
-
opt.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
|
80
|
-
params.labels = v
|
81
|
-
end
|
82
|
-
opt.on('--encoding VAL', String, 'Specify the input encoding') do |v|
|
83
|
-
@encoding = v
|
84
|
-
end
|
85
|
-
# Optparse adds the help option, but it doesn't show up in usage.
|
86
|
-
# This is why you need the code below.
|
87
|
-
opt.on('--help', 'print sub-command help menu') do
|
88
|
-
puts opt.help
|
89
|
-
exit
|
90
|
-
end
|
91
|
-
opt.on('--debug', TrueClass, 'print preprocessed data') do |v|
|
92
|
-
@debug = v
|
93
|
-
end
|
94
|
-
yield opt if block_given?
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def main_parser
|
99
|
-
@main_parser ||= create_default_parser do |main_parser|
|
100
|
-
# Here, help message is stored in the banner.
|
101
|
-
# Because help of main_parser may be referred by `sub_parser`.
|
102
|
-
|
103
|
-
main_parser.banner = \
|
104
|
-
<<~MSG
|
105
|
-
|
106
|
-
Program: YouPlot (Tools for plotting on the terminal)
|
107
|
-
Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
|
108
|
-
Source: https://github.com/kojix2/youplot
|
109
|
-
|
110
|
-
Usage: uplot <command> [options] <in.tsv>
|
111
|
-
|
112
|
-
Commands:
|
113
|
-
barplot bar draw a horizontal barplot
|
114
|
-
histogram hist draw a horizontal histogram
|
115
|
-
lineplot line draw a line chart
|
116
|
-
lineplots lines draw a line chart with multiple series
|
117
|
-
scatter s draw a scatter plot
|
118
|
-
density d draw a density plot
|
119
|
-
boxplot box draw a horizontal boxplot
|
120
|
-
colors show the list of available colors
|
121
|
-
|
122
|
-
count c draw a baplot based on the number of
|
123
|
-
occurrences (slow)
|
124
|
-
|
125
|
-
General options:
|
126
|
-
--help print command specific help menu
|
127
|
-
--version print the version of YouPlot
|
128
|
-
MSG
|
129
|
-
|
130
|
-
# Actually, main_parser can take common optional arguments.
|
131
|
-
# However, these options dose not be shown in the help menu.
|
132
|
-
# I think the main help should be simple.
|
133
|
-
main_parser.on('--help', 'print sub-command help menu') do
|
134
|
-
puts main_parser.banner
|
135
|
-
puts
|
136
|
-
exit
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def sub_parser
|
142
|
-
@sub_parser ||= create_default_parser do |parser|
|
143
|
-
parser.banner = <<~MSG
|
144
|
-
|
145
|
-
Usage: YouPlot #{command} [options] <in.tsv>
|
146
|
-
|
147
|
-
Options for #{command}:
|
148
|
-
MSG
|
149
|
-
|
150
|
-
case command
|
151
|
-
|
152
|
-
# If you type only `uplot` in the terminal.
|
153
|
-
when nil
|
154
|
-
warn main_parser.banner
|
155
|
-
warn "\n"
|
156
|
-
exit 1
|
157
|
-
|
158
|
-
when :barplot, :bar
|
159
|
-
parser.on_head('--symbol VAL', String, 'character to be used to plot the bars') do |v|
|
160
|
-
params.symbol = v
|
161
|
-
end
|
162
|
-
parser.on_head('--xscale VAL', String, 'axis scaling') do |v|
|
163
|
-
params.xscale = v
|
164
|
-
end
|
165
|
-
parser.on_head('--fmt VAL', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
|
166
|
-
@fmt = v
|
167
|
-
end
|
168
|
-
|
169
|
-
when :count, :c
|
170
|
-
parser.on_head('--symbol VAL', String, 'character to be used to plot the bars') do |v|
|
171
|
-
params.symbol = v
|
172
|
-
end
|
173
|
-
|
174
|
-
when :histogram, :hist
|
175
|
-
parser.on_head('-n', '--nbins VAL', Numeric, 'approximate number of bins') do |v|
|
176
|
-
params.nbins = v
|
177
|
-
end
|
178
|
-
parser.on_head('--closed VAL', String) do |v|
|
179
|
-
params.closed = v
|
180
|
-
end
|
181
|
-
parser.on_head('--symbol VAL', String, 'character to be used to plot the bars') do |v|
|
182
|
-
params.symbol = v
|
183
|
-
end
|
184
|
-
|
185
|
-
when :lineplot, :line
|
186
|
-
parser.on_head('--canvas VAL', String, 'type of canvas') do |v|
|
187
|
-
params.canvas = v
|
188
|
-
end
|
189
|
-
parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
|
190
|
-
params.xlim = v.take(2)
|
191
|
-
end
|
192
|
-
parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
|
193
|
-
params.ylim = v.take(2)
|
194
|
-
end
|
195
|
-
parser.on_head('--fmt VAL', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
|
196
|
-
@fmt = v
|
197
|
-
end
|
198
|
-
|
199
|
-
when :lineplots, :lines
|
200
|
-
parser.on_head('--canvas VAL', String) do |v|
|
201
|
-
params.canvas = v
|
202
|
-
end
|
203
|
-
parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
|
204
|
-
params.xlim = v.take(2)
|
205
|
-
end
|
206
|
-
parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
|
207
|
-
params.ylim = v.take(2)
|
208
|
-
end
|
209
|
-
parser.on_head('--fmt VAL', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...', 'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
210
|
-
@fmt = v
|
211
|
-
end
|
212
|
-
|
213
|
-
when :scatter, :s
|
214
|
-
parser.on_head('--canvas VAL', String) do |v|
|
215
|
-
params.canvas = v
|
216
|
-
end
|
217
|
-
parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
|
218
|
-
params.xlim = v.take(2)
|
219
|
-
end
|
220
|
-
parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
|
221
|
-
params.ylim = v.take(2)
|
222
|
-
end
|
223
|
-
parser.on_head('--fmt VAL', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...', 'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
224
|
-
@fmt = v
|
225
|
-
end
|
226
|
-
|
227
|
-
when :density, :d
|
228
|
-
parser.on_head('--grid', TrueClass) do |v|
|
229
|
-
params.grid = v
|
230
|
-
end
|
231
|
-
parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
|
232
|
-
params.xlim = v.take(2)
|
233
|
-
end
|
234
|
-
parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
|
235
|
-
params.ylim = v.take(2)
|
236
|
-
end
|
237
|
-
parser.on('--fmt VAL', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...', 'xyy : header is like x, y1, y2, y2, y3...') do |v|
|
238
|
-
@fmt = v
|
239
|
-
end
|
240
|
-
|
241
|
-
when :boxplot, :box
|
242
|
-
parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
|
243
|
-
params.xlim = v.take(2)
|
244
|
-
end
|
245
|
-
|
246
|
-
when :colors
|
247
|
-
parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
|
248
|
-
@color_names = v
|
249
|
-
end
|
250
|
-
|
251
|
-
else
|
252
|
-
warn "uplot: unrecognized command '#{command}'"
|
253
|
-
exit 1
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def parse_options(argv = ARGV)
|
259
|
-
begin
|
260
|
-
main_parser.order!(argv)
|
261
|
-
rescue OptionParser::ParseError => e
|
262
|
-
warn "uplot: #{e.message}"
|
263
|
-
exit 1
|
264
|
-
end
|
265
|
-
|
266
|
-
@command = argv.shift&.to_sym
|
267
|
-
|
268
|
-
begin
|
269
|
-
sub_parser.parse!(argv)
|
270
|
-
rescue OptionParser::ParseError => e
|
271
|
-
warn "uplot: #{e.message}"
|
272
|
-
exit 1
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
data/lib/youplot/dsv_reader.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'csv'
|
4
|
-
|
5
|
-
module YouPlot
|
6
|
-
# Read and interpret Delimiter-separated values format file or stream.
|
7
|
-
module DSVReader
|
8
|
-
module_function
|
9
|
-
|
10
|
-
def input(input, delimiter, headers, transpose)
|
11
|
-
arr = parse_as_csv(input, delimiter)
|
12
|
-
headers = get_headers(arr, headers, transpose)
|
13
|
-
series = get_series(arr, headers, transpose)
|
14
|
-
if headers.nil?
|
15
|
-
Data.new(headers, series)
|
16
|
-
else
|
17
|
-
if headers.include?(nil)
|
18
|
-
warn "\e[35mHeaders contains nil in it.\e[0m"
|
19
|
-
elsif headers.include? ''
|
20
|
-
warn "\e[35mHeaders contains \"\" in it.\e[0m"
|
21
|
-
end
|
22
|
-
h_size = headers.size
|
23
|
-
s_size = series.size
|
24
|
-
if h_size == s_size
|
25
|
-
Data.new(headers, series)
|
26
|
-
elsif h_size > s_size
|
27
|
-
warn "\e[35mThe number of headers is greater than the number of series.\e[0m"
|
28
|
-
exit 1
|
29
|
-
elsif h_size < s_size
|
30
|
-
warn "\e[35mThe number of headers is less than the number of series.\e[0m"
|
31
|
-
exit 1
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def parse_as_csv(input, delimiter)
|
37
|
-
CSV.parse(input, col_sep: delimiter)
|
38
|
-
.delete_if do |i|
|
39
|
-
i == [] or i.all? nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Transpose different sized ruby arrays
|
44
|
-
# https://stackoverflow.com/q/26016632
|
45
|
-
def transpose2(arr)
|
46
|
-
Array.new(arr.map(&:length).max) { |i| arr.map { |e| e[i] } }
|
47
|
-
end
|
48
|
-
|
49
|
-
def get_headers(arr, headers, transpose)
|
50
|
-
if headers
|
51
|
-
if transpose
|
52
|
-
arr.map(&:first)
|
53
|
-
else
|
54
|
-
arr[0]
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def get_series(arr, headers, transpose)
|
60
|
-
if transpose
|
61
|
-
if headers
|
62
|
-
arr.map { |row| row[1..-1] }
|
63
|
-
else
|
64
|
-
arr
|
65
|
-
end
|
66
|
-
elsif headers
|
67
|
-
transpose2(arr[1..-1])
|
68
|
-
else
|
69
|
-
transpose2(arr)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|