youplot 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YouPlot
4
- VERSION = '0.3.1'
4
+ VERSION = '0.4.0'
5
5
  end
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.3.1
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: 2020-12-04 00:00:00.000000000 Z
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: "Create ASCII charts on the terminal with data from standard streams
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/unicode_plot_backend.rb
112
+ - lib/youplot/backends/unicode_plot.rb
114
113
  - lib/youplot/command.rb
115
- - lib/youplot/command/params.rb
116
- - lib/youplot/command/parser.rb
117
- - lib/youplot/dsv_reader.rb
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.1.4
138
+ rubygems_version: 3.2.15
139
139
  signing_key:
140
140
  specification_version: 4
141
- summary: Create Ascii charts on your terminal.
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
@@ -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