youplot 0.3.4 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39029ea73cd1233a1ad890343381986b5fcf46e1e7619708cd0329269d07135c
4
- data.tar.gz: '08662eaab8c28351e57727c69f2f5479e1950d3cbbad7d65ab61ec8994830fec'
3
+ metadata.gz: 83145e216c0d124d537c8a01d63f9203730a74191fefcb9de5743b08e0e504bd
4
+ data.tar.gz: a246eab22f11ab8c526cc838d9f2fbf7d249721b4782287087c08a5410f8647b
5
5
  SHA512:
6
- metadata.gz: 7f24fc609bf6501d9b9f6a6452db84d015cfbea7fe6c3a86f4d69ab31043c5a99d9907fe8dbf34f2672589fbfa99e51cde6cfab578c1ef570552e649a7ebfb10
7
- data.tar.gz: 6fb46f5492480a385dec175d022e693442c43cdead3b5bd948dfdc0030a81d661ea5363cb386c9c9f7da5e25329cdc11c286d78985cc9383f7032a3a56a8435a
6
+ metadata.gz: d9138c26fade36d7d0ca19100b47dcb8e65c8c884d13b74d258dcae9ea304ced2fc783b08e871d76607e57e394e6b861c81f1f5030caba53493b2f4740a05cd2
7
+ data.tar.gz: f293d686791ba1481948877e534c9085e99c24ab9c36026979002ecaa9ee2ece6f12ad7193cda936c62e472e2f94008466cc666e9405157bfcc348c4c21c4579
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  <p align="center">
2
- <img src="https://user-images.githubusercontent.com/5798442/103439598-9e952a00-4c81-11eb-881f-67c593bb7861.png" width="75%" height="75%" />
2
+ <img src="logo.svg" width="60%" height="60%" />
3
3
  </p>
4
4
 
5
5
  ![Build Status](https://github.com/kojix2/youplot/workflows/test/badge.svg)
6
6
  [![Gem Version](https://badge.fury.io/rb/youplot.svg)](https://badge.fury.io/rb/youplot)
7
- [![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://rubydoc.info/gems/youplot)
7
+ [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://rubydoc.info/gems/youplot)
8
8
  [![The MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.txt)
9
9
  [![DOI](https://zenodo.org/badge/283230219.svg)](https://zenodo.org/badge/latestdoi/283230219)
10
10
 
@@ -106,8 +106,8 @@ In this example, YouPlot counts the number of chromosomes where the gene is loca
106
106
 
107
107
  ```sh
108
108
  cat gencode.v35.annotation.gff3 \
109
- | grep -v '#' | grep 'gene' | cut -f1 | \
110
- uplot count -t "The number of human gene annotations per chromosome" -c blue
109
+ | grep -v '#' | grep 'gene' | cut -f1 \
110
+ | uplot count -t "The number of human gene annotations per chromosome" -c blue
111
111
  ```
112
112
 
113
113
  <p align="center">
@@ -119,7 +119,7 @@ This is fine in most cases, as long as the data size is small. If you want to vi
119
119
 
120
120
  ```sh
121
121
  cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
122
- |sort | uniq -c | sort -nrk2 | awk '{print $2,$1}' \
122
+ | sort | uniq -c | sort -nrk2 | awk '{print $2,$1}' \
123
123
  | uplot bar -d ' ' -t "The number of human gene annotations per chromosome" -c blue
124
124
  ```
125
125
 
@@ -130,15 +130,15 @@ cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
130
130
  Wouldn't it be a pain to have to run R, Python, Julia, gnuplot or whatever REPL just to check your data?
131
131
  YouPlot is a command line tool for this purpose. With YouPlot, you can continue working without leaving your terminal and shell.
132
132
 
133
- ### how to use YouPlot?
133
+ ### How to use YouPlot?
134
134
 
135
135
  `uplot` is the shortened form of `youplot`. You can use either.
136
136
 
137
- | | |
138
- |-----------------------------------|------------------------------------------------|
139
- | Reads data from standard input | `cat data.tsv \| uplot <command> [options]` |
140
- | Reads data from files | `uplot <command> [options] data.tsv ...` |
141
- | Outputs data from stdin to stdout | `pipeline1 \| uplot <command> -O \| pipeline2` |
137
+ | Command | Description |
138
+ |------------------------------------------------|-----------------------------------|
139
+ | `cat data.tsv \| uplot <command> [options]` | Take input from stdin |
140
+ | `uplot <command> [options] data.tsv ...` | Take input from files |
141
+ | `pipeline1 \| uplot <command> -O \| pipeline2` | Outputs data from stdin to stdout |
142
142
 
143
143
  ### Where to output the plot?
144
144
 
@@ -148,7 +148,8 @@ The output file or stream for the plot can be specified with the `-o` option.
148
148
  ### Where to output the input data?
149
149
 
150
150
  By default, the input data is not shown anywhere.
151
- The `-O` option, with no arguments, outputs the input data directly to the standard output. This is useful when passing data to a subsequent pipeline.
151
+ The `-O` option, with no arguments, outputs the input data directly to the standard output.
152
+ This is useful when passing data to a subsequent pipeline.
152
153
 
153
154
  ### What types of plots are available?
154
155
 
@@ -176,11 +177,21 @@ If your input data contains a header line, you need to specify the `-H` option.
176
177
 
177
178
  ### How to specify the delimiter?
178
179
 
179
- Use the `-d` option. To specify a blank space, you can use `uplot bar -d ' ' data.txt`. You do not need to use `-d` option for tab-delimited text since the default value is tab.
180
+ Use the `-d` option. To specify a blank space, you can use `uplot bar -d ' ' data.txt`.
181
+ You do not need to use `-d` option for tab-delimited text since the default value is tab.
180
182
 
181
183
  ### Is there a way to specify a column as the x-axis or y-axis?
182
184
 
183
- Not yet. In principle, YouPlot treats the first column as the X axis and the second column as the Y axis. When working with multiple series, the first row is the X axis, the second row is series 1, the third row is series 2, and so on. If you pass only one column of data for `line` and `bar`, YouPlot will automatically use a sequential number starting from 1 as the X-axis. The `--fmt xyy`, `--fmt xyxy` and `--fmt yx` options give you a few more choices. See `youplot <command> --help` for more details. YouPlot has limited functionalities, but you can use shell scripts such as `awk '{print $2, $1}'` to swap lines.
185
+ Not yet.
186
+ YouPlot treats the first column as the X axis and the second column as the Y axis.
187
+ When working with multiple series, the first column is the X axis, the second column is series Y1, the third column is series Y2, and so on.
188
+ If you pass only one column of data for `line` and `bar`, YouPlot will automatically use a sequential number starting from 1 as the X-axis.
189
+
190
+ * `--fmt xyy` `--fmt xyxy` `--fmt yx` options give you a few more choices.
191
+ See `youplot <command> --help` for more details.
192
+
193
+ * Use `awk '{print $2, $1}'` to swap lines.
194
+ * Use `paste` to concatenate series.
184
195
 
185
196
  ### How to plot real-time data?
186
197
 
@@ -216,18 +227,21 @@ uplot colors
216
227
 
217
228
  ## Contributing
218
229
 
230
+ YouPlot is a library under development, so even small improvements like typofix are welcome!
231
+ Please feel free to send us your pull requests.
232
+
219
233
  * [Report bugs](https://github.com/kojix2/youplot/issues)
220
234
  * Fix bugs and [submit pull requests](https://github.com/kojix2/youplot/pulls)
221
235
  * Write, clarify, or fix documentation
222
236
  * English corrections by native speakers are welcome.
223
237
  * Suggest or add new features
224
-
238
+ * Make a donation
225
239
 
226
240
  ### Development
227
241
 
228
242
  ```sh
229
- git clone https://github.com/your_name/GR.rb # Clone the Git repo
230
- cd GR.rb
243
+ # fork the main repository by clicking the Fork button.
244
+ git clone https://github.com/your_name/YouPlot
231
245
  bundle install # Install the gem dependencies
232
246
  bundle exec rake test # Run the test
233
247
  bundle exec rake install # Installation from source code
@@ -11,12 +11,16 @@ module YouPlot
11
11
  if tally && Enumerable.method_defined?(:tally)
12
12
  arr.tally
13
13
  else
14
- # https://github.com/marcandre/backports
15
- arr.each_with_object(Hash.new(0)) { |item, res| res[item] += 1 }
16
- .tap { |h| h.default = nil }
14
+ # value_counts Enumerable::Statistics
15
+ arr.value_counts(dropna: false)
17
16
  end
18
- .sort { |a, b| a[1] <=> b[1] }
19
- .reverse
17
+ .sort do |a, b|
18
+ # compare values
19
+ r = b[1] <=> a[1]
20
+ # If the values are the same, compare by name
21
+ r = a[0] <=> b[0] if r == 0
22
+ r
23
+ end
20
24
  .transpose
21
25
  end
22
26
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # UnicodePlot - Plot your data by Unicode characters
4
+ # https://github.com/red-data-tools/unicode_plot.rb
5
+
3
6
  require_relative 'processing'
4
7
  require 'unicode_plot'
5
8
 
6
9
  module YouPlot
7
10
  # plotting functions.
8
11
  module Backends
9
- module UnicodePlotBackend
12
+ module UnicodePlot
10
13
  class Error < StandardError; end
11
14
 
12
15
  module_function
@@ -39,19 +42,7 @@ module YouPlot
39
42
  labels = series[x_col]
40
43
  values = series[y_col].map(&:to_f)
41
44
  end
42
- begin
43
- UnicodePlot.barplot(labels, values, **params.to_hc)
44
- # UnicodePlot error:
45
- # All values have to be positive. Negative bars are not supported.
46
- rescue ArgumentError => e
47
- if YouPlot.run_as_executable?
48
- warn e.backtrace[0]
49
- warn "\e[35m#{e}\e[0m"
50
- exit 1
51
- else
52
- raise e
53
- end
54
- end
45
+ ::UnicodePlot.barplot(labels, values, **params.to_hc)
55
46
  end
56
47
 
57
48
  def histogram(data, params)
@@ -59,7 +50,7 @@ module YouPlot
59
50
  series = data.series
60
51
  params.title ||= data.headers[0] if headers
61
52
  values = series[0].map(&:to_f)
62
- UnicodePlot.histogram(values, **params.to_hc)
53
+ ::UnicodePlot.histogram(values, **params.to_hc)
63
54
  end
64
55
 
65
56
  def line(data, params, fmt = nil)
@@ -69,7 +60,7 @@ module YouPlot
69
60
  # If there is only one series, it is assumed to be sequential data.
70
61
  params.ylabel ||= headers[0] if headers
71
62
  y = series[0].map(&:to_f)
72
- UnicodePlot.lineplot(y, **params.to_hc)
63
+ ::UnicodePlot.lineplot(y, **params.to_hc)
73
64
  else
74
65
  # If there are 2 or more series...
75
66
  if fmt == 'yx'
@@ -87,7 +78,7 @@ module YouPlot
87
78
  end
88
79
  x = series[x_col].map(&:to_f)
89
80
  y = series[y_col].map(&:to_f)
90
- UnicodePlot.lineplot(x, y, **params.to_hc)
81
+ ::UnicodePlot.lineplot(x, y, **params.to_hc)
91
82
  end
92
83
  end
93
84
 
@@ -106,9 +97,9 @@ module YouPlot
106
97
  end
107
98
  params.xlim ||= series[0].flatten.minmax # why need?
108
99
  params.ylim ||= series[1..-1].flatten.minmax # why need?
109
- plot = UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
100
+ plot = ::UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
110
101
  2.upto(series.size - 1) do |i|
111
- UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
102
+ ::UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
112
103
  end
113
104
  plot
114
105
  end
@@ -124,9 +115,9 @@ module YouPlot
124
115
  params.xlim ||= series2.map(&:first).flatten.minmax # why need?
125
116
  params.ylim ||= series2.map(&:last).flatten.minmax # why need?
126
117
  x1, y1 = series2.shift
127
- plot = UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
118
+ plot = ::UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
128
119
  series2.each_with_index do |(xi, yi), i|
129
- UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
120
+ ::UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
130
121
  end
131
122
  plot
132
123
  end
@@ -164,13 +155,13 @@ module YouPlot
164
155
  series = data.series
165
156
  headers ||= (1..series.size).map(&:to_s)
166
157
  series.map! { |s| s.map(&:to_f) }
167
- UnicodePlot.boxplot(headers, series, **params.to_hc)
158
+ ::UnicodePlot.boxplot(headers, series, **params.to_hc)
168
159
  end
169
160
 
170
161
  def colors(color_names = false)
171
162
  # FIXME
172
163
  s = String.new
173
- UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
164
+ ::UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
174
165
  s << v
175
166
  s << k.to_s
176
167
  unless color_names
@@ -190,18 +181,24 @@ module YouPlot
190
181
  def check_series_size(data, fmt)
191
182
  series = data.series
192
183
  if series.size == 1
193
- warn 'youplot: There is only one series of input data. Please check the delimiter.'
194
- warn ''
195
- warn " Headers: \e[35m#{data.headers.inspect}\e[0m"
196
- warn " The first item is: \e[35m\"#{series[0][0]}\"\e[0m"
197
- warn " The last item is : \e[35m\"#{series[0][-1]}\"\e[0m"
184
+ warn <<~EOS
185
+ youplot: There is only one series of input data. Please check the delimiter.
186
+
187
+ Headers: \e[35m#{data.headers.inspect}\e[0m
188
+ The first item is: \e[35m\"#{series[0][0]}\"\e[0m
189
+ The last item is : \e[35m\"#{series[0][-1]}\"\e[0m
190
+ EOS
191
+ # NOTE: Error messages cannot be colored.
198
192
  YouPlot.run_as_executable ? exit(1) : raise(Error)
199
193
  end
200
194
  if fmt == 'xyxy' && series.size.odd?
201
- warn 'YouPlot: In the xyxy format, the number of series must be even.'
202
- warn ''
203
- warn " Number of series: \e[35m#{series.size}\e[0m"
204
- warn " Headers: \e[35m#{data.headers.inspect}\e[0m"
195
+ warn <<~EOS
196
+ YouPlot: In the xyxy format, the number of series must be even.
197
+
198
+ Number of series: \e[35m#{series.size}\e[0m
199
+ Headers: \e[35m#{data.headers.inspect}\e[0m
200
+ EOS
201
+ # NOTE: Error messages cannot be colored.
205
202
  YouPlot.run_as_executable ? exit(1) : raise(Error)
206
203
  end
207
204
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'dsv'
4
- require_relative 'command/parser'
4
+ require_relative 'parser'
5
5
 
6
6
  # FIXME
7
- require_relative 'backends/unicode_plot_backend'
7
+ require_relative 'backends/unicode_plot'
8
8
 
9
9
  module YouPlot
10
10
  Data = Struct.new(:headers, :series)
@@ -19,7 +19,7 @@ module YouPlot
19
19
  @command = nil
20
20
  @params = nil
21
21
  @options = nil
22
- @backend = YouPlot::Backends::UnicodePlotBackend
22
+ @backend = YouPlot::Backends::UnicodePlot
23
23
  end
24
24
 
25
25
  def run_as_executable
@@ -33,21 +33,34 @@ module YouPlot
33
33
  @options ||= parser.options
34
34
  @params ||= parser.params
35
35
 
36
+ # color command
36
37
  if %i[colors color colours colour].include? @command
37
38
  plot = create_plot
38
39
  output_plot(plot)
39
- elsif options[:progressive]
40
+ return
41
+ end
42
+
43
+ # progressive mode
44
+ if options[:progressive]
40
45
  stop = false
41
46
  Signal.trap(:INT) { stop = true }
42
- options[:output].print "\e[?25l" # make cursor invisible
47
+
48
+ # make cursor invisible
49
+ options[:output].print "\e[?25l"
50
+
51
+ # mainloop
43
52
  while (input = Kernel.gets)
44
53
  n = main_progressive(input)
45
54
  break if stop
46
55
 
47
56
  options[:output].print "\e[#{n}F"
48
57
  end
58
+
49
59
  options[:output].print "\e[0J"
50
- options[:output].print "\e[?25h" # make cursor visible
60
+ # make cursor visible
61
+ options[:output].print "\e[?25h"
62
+
63
+ # normal mode
51
64
  else
52
65
  # Sometimes the input file does not end with a newline code.
53
66
  while (input = Kernel.gets(nil))
@@ -59,13 +72,32 @@ module YouPlot
59
72
  private
60
73
 
61
74
  def main(input)
75
+ # Outputs input data to a file or stdout.
62
76
  output_data(input)
63
77
 
64
- @data = read_dsv(input)
78
+ @data = parse_dsv(input)
65
79
 
80
+ # Debug mode, show parsed results
66
81
  pp @data if options[:debug]
67
82
 
68
- plot = create_plot
83
+ # When run as a program instead of a library
84
+ if YouPlot.run_as_executable?
85
+ begin
86
+ plot = create_plot
87
+ rescue ArgumentError => e
88
+ # Show only one line of error.
89
+ warn e.backtrace[0]
90
+ # Show error message in purple
91
+ warn "\e[35m#{e}\e[0m"
92
+ # Explicitly terminated with exit code: 1
93
+ exit 1
94
+ end
95
+
96
+ # When running YouPlot as a library (e.g. for testing)
97
+ else
98
+ plot = create_plot
99
+ end
100
+
69
101
  output_plot(plot)
70
102
  end
71
103
 
@@ -85,15 +117,28 @@ module YouPlot
85
117
  @raw_data << input
86
118
 
87
119
  # FIXME
88
- @data = read_dsv(@raw_data)
120
+ @data = parse_dsv(@raw_data)
89
121
 
90
122
  plot = create_plot
91
123
  output_plot_progressive(plot)
92
124
  end
93
125
 
94
- def read_dsv(input)
95
- input = input.dup.force_encoding(options[:encoding]).encode('utf-8') if options[:encoding]
96
- DSV.parse(input, options[:delimiter], options[:headers], options[:transpose])
126
+ def parse_dsv(input)
127
+ # If encoding is specified, convert to UTF-8
128
+ if options[:encoding]
129
+ input.force_encoding(options[:encoding])
130
+ .encode!('utf-8')
131
+ end
132
+
133
+ begin
134
+ data = DSV.parse(input, options[:delimiter], options[:headers], options[:transpose])
135
+ rescue CSV::MalformedCSVError => e
136
+ warn 'Failed to parse the text. '
137
+ warn 'Please try to set the correct character encoding with --encoding option.'
138
+ raise e
139
+ end
140
+
141
+ data
97
142
  end
98
143
 
99
144
  def create_plot
@@ -137,9 +182,9 @@ module YouPlot
137
182
 
138
183
  def output_plot(plot)
139
184
  case options[:output]
140
- when IO
185
+ when IO, StringIO
141
186
  plot.render(options[:output])
142
- else
187
+ when String, Tempfile
143
188
  File.open(options[:output], 'w') do |f|
144
189
  plot.render(f)
145
190
  end
@@ -148,7 +193,7 @@ module YouPlot
148
193
 
149
194
  def output_plot_progressive(plot)
150
195
  case options[:output]
151
- when IO
196
+ when IO, StringIO
152
197
  # RefactorMe
153
198
  out = StringIO.new(String.new)
154
199
  def out.tty?
data/lib/youplot/dsv.rb CHANGED
@@ -3,41 +3,49 @@
3
3
  require 'csv'
4
4
 
5
5
  module YouPlot
6
- # Read and interpret Delimiter-separated values format file or stream.
6
+ # Module to handle DSV (Delimiter-separated values) format.
7
+ # Extract header and series.
7
8
  module DSV
8
9
  module_function
9
10
 
10
11
  def parse(input, delimiter, headers, transpose)
11
- arr = parse_as_csv(input, delimiter)
12
+ # Parse as CSV
13
+ arr = CSV.parse(input, col_sep: delimiter)
14
+
15
+ # Remove blank lines
16
+ arr.delete_if do |i|
17
+ i == [] or i.all? nil
18
+ end
19
+
20
+ # get header
12
21
  headers = get_headers(arr, headers, transpose)
22
+
23
+ # get series
13
24
  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 if YouPlot.run_as_executable?
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 if YouPlot.run_as_executable?
32
- end
25
+
26
+ # Return if No header
27
+ return Data.new(headers, series) if headers.nil?
28
+
29
+ # Warn if header contains nil
30
+ warn "\e[35mHeaders contains nil in it.\e[0m" if headers.include?(nil)
31
+
32
+ # Warn if header contains ''
33
+ warn "\e[35mHeaders contains \"\" in it.\e[0m" if headers.include? ''
34
+
35
+ # Make sure the number of elements in the header matches the number of series.
36
+ h_size = headers.size
37
+ s_size = series.size
38
+
39
+ if h_size > s_size
40
+ warn "\e[35mThe number of headers is greater than the number of series.\e[0m"
41
+ exit 1 if YouPlot.run_as_executable?
42
+
43
+ elsif h_size < s_size
44
+ warn "\e[35mThe number of headers is less than the number of series.\e[0m"
45
+ exit 1 if YouPlot.run_as_executable?
33
46
  end
34
- end
35
47
 
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
48
+ Data.new(headers, series) if h_size == s_size
41
49
  end
42
50
 
43
51
  # Transpose different sized ruby arrays
@@ -47,31 +55,33 @@ module YouPlot
47
55
  end
48
56
 
49
57
  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
58
+ # header(-)
59
+ return nil unless headers
60
+
61
+ # header(+) trenspose(+)
62
+ return arr.map(&:first) if transpose
63
+
64
+ # header(+) transpose(-)
65
+ arr[0]
57
66
  end
58
67
 
59
68
  def get_series(arr, headers, transpose)
60
- if headers
61
- if arr.size > 1
62
- if transpose
63
- arr.map { |row| row[1..-1] }
64
- else
65
- transpose2(arr[1..-1])
66
- end
67
- else
68
- Array.new(arr[0].size, [])
69
- end
70
- elsif transpose
71
- arr
72
- else
73
- transpose2(arr)
69
+ # header(-)
70
+ unless headers
71
+ return arr if transpose
72
+
73
+ return transpose2(arr)
74
74
  end
75
+
76
+ # header(+) but no element in the series.
77
+ # TODO: should raise error?
78
+ return Array.new(arr[0].size, []) if arr.size == 1
79
+
80
+ # header(+) transpose(+)
81
+ return arr.map { |row| row[1..-1] } if transpose
82
+
83
+ # header(+) transpose(-)
84
+ transpose2(arr[1..-1])
75
85
  end
76
86
  end
77
87
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YouPlot
4
+ # Command line options that are not Plot parameters
5
+ Options = Struct.new(
6
+ :delimiter,
7
+ :transpose,
8
+ :headers,
9
+ :pass,
10
+ :output,
11
+ :fmt,
12
+ :progressive,
13
+ :encoding,
14
+ :color_names,
15
+ :debug,
16
+ keyword_init: true
17
+ )
18
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YouPlot
4
+ # UnicodePlot parameters.
5
+ # Why Struct, not Hash?
6
+ # * The keys are static in Struct.
7
+ # * Struct does not conflict with keyword arguments. Hash dose.
8
+ Parameters = Struct.new(
9
+ # Sort me!
10
+ :title,
11
+ :width,
12
+ :height,
13
+ :border,
14
+ :margin,
15
+ :padding,
16
+ :color,
17
+ :xlabel,
18
+ :ylabel,
19
+ :labels,
20
+ :symbol,
21
+ :xscale,
22
+ :nbins,
23
+ :closed,
24
+ :canvas,
25
+ :xlim,
26
+ :ylim,
27
+ :grid,
28
+ :name
29
+ ) do
30
+ def to_hc
31
+ to_h.compact
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,306 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+ require_relative 'options'
5
+
6
+ module YouPlot
7
+ # Class for parsing command line options
8
+ class Parser
9
+ class Error < StandardError; end
10
+
11
+ attr_reader :command, :options, :params,
12
+ :main_parser, :sub_parser
13
+
14
+ def initialize
15
+ @command = nil
16
+
17
+ @options = Options.new(
18
+ delimiter: "\t",
19
+ transpose: false,
20
+ headers: nil,
21
+ pass: false,
22
+ output: $stderr,
23
+ fmt: 'xyy',
24
+ progressive: false,
25
+ encoding: nil,
26
+ color_names: false,
27
+ debug: false
28
+ )
29
+
30
+ @params = Parameters.new
31
+ end
32
+
33
+ def create_base_parser
34
+ OptionParser.new do |parser|
35
+ parser.program_name = 'YouPlot'
36
+ parser.version = YouPlot::VERSION
37
+ parser.summary_width = 23
38
+ parser.on_tail('') # Add a blank line at the end
39
+ parser.separator('')
40
+ parser.on('Common options:')
41
+ parser.on('-O', '--pass [FILE]', 'file to output input data to [stdout]',
42
+ 'for inserting YouPlot in the middle of Unix pipes') do |v|
43
+ options[:pass] = v || $stdout
44
+ end
45
+ parser.on('-o', '--output [FILE]', 'file to output plots to [stdout]',
46
+ 'If no option is specified, plot will print to stderr') do |v|
47
+ options[:output] = v || $stdout
48
+ end
49
+ parser.on('-d', '--delimiter DELIM', String, 'use DELIM instead of [TAB] for field delimiter') do |v|
50
+ options[:delimiter] = v
51
+ end
52
+ parser.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
53
+ options[:headers] = v
54
+ end
55
+ parser.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
56
+ options[:transpose] = v
57
+ end
58
+ parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v|
59
+ params.title = v
60
+ end
61
+ parser.on('-x', '--xlabel STR', String, 'print string on the bottom of the plot') do |v|
62
+ params.xlabel = v
63
+ end
64
+ parser.on('-y', '--ylabel STR', String, 'print string on the far left of the plot') do |v|
65
+ params.ylabel = v
66
+ end
67
+ parser.on('-w', '--width INT', Integer, 'number of characters per row') do |v|
68
+ params.width = v
69
+ end
70
+ parser.on('-h', '--height INT', Numeric, 'number of rows') do |v|
71
+ params.height = v
72
+ end
73
+ border_options = UnicodePlot::BORDER_MAP.keys.join(', ')
74
+ parser.on('-b', '--border STR', String, 'specify the style of the bounding box', "(#{border_options})") do |v|
75
+ params.border = v.to_sym
76
+ end
77
+ parser.on('-m', '--margin INT', Numeric, 'number of spaces to the left of the plot') do |v|
78
+ params.margin = v
79
+ end
80
+ parser.on('--padding INT', Numeric, 'space of the left and right of the plot') do |v|
81
+ params.padding = v
82
+ end
83
+ parser.on('-c', '--color VAL', String, 'color of the drawing') do |v|
84
+ params.color = v =~ /\A[0-9]+\z/ ? v.to_i : v.to_sym
85
+ end
86
+ parser.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
87
+ params.labels = v
88
+ end
89
+ parser.on('-p', '--progress', TrueClass, 'progressive mode [experimental]') do |v|
90
+ options[:progressive] = v
91
+ end
92
+ parser.on('-C', '--color-output', TrueClass, 'colorize even if writing to a pipe') do |_v|
93
+ UnicodePlot::IOContext.define_method(:color?) { true } # FIXME
94
+ end
95
+ parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |_v|
96
+ UnicodePlot::IOContext.define_method(:color?) { false } # FIXME
97
+ end
98
+ parser.on('--encoding STR', String, 'Specify the input encoding') do |v|
99
+ options[:encoding] = v
100
+ end
101
+ # Optparse adds the help option, but it doesn't show up in usage.
102
+ # This is why you need the code below.
103
+ parser.on('--help', 'print sub-command help menu') do
104
+ puts parser.help
105
+ exit if YouPlot.run_as_executable?
106
+ end
107
+ parser.on('--debug', TrueClass, 'print preprocessed data') do |v|
108
+ options[:debug] = v
109
+ end
110
+ # yield opt if block_given?
111
+ end
112
+ end
113
+
114
+ def create_main_parser
115
+ @main_parser = create_base_parser
116
+ main_parser.banner = \
117
+ <<~MSG
118
+
119
+ Program: YouPlot (Tools for plotting on the terminal)
120
+ Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
121
+ Source: https://github.com/kojix2/youplot
122
+
123
+ Usage: uplot <command> [options] <in.tsv>
124
+
125
+ Commands:
126
+ barplot bar draw a horizontal barplot
127
+ histogram hist draw a horizontal histogram
128
+ lineplot line draw a line chart
129
+ lineplots lines draw a line chart with multiple series
130
+ scatter s draw a scatter plot
131
+ density d draw a density plot
132
+ boxplot box draw a horizontal boxplot
133
+ colors color show the list of available colors
134
+
135
+ count c draw a baplot based on the number of
136
+ occurrences (slow)
137
+
138
+ General options:
139
+ --help print command specific help menu
140
+ --version print the version of YouPlot
141
+ MSG
142
+
143
+ # Help for the main parser is simple.
144
+ # Simply show the banner above.
145
+ main_parser.on('--help', 'print sub-command help menu') do
146
+ puts main_parser.banner
147
+ puts
148
+ exit if YouPlot.run_as_executable?
149
+ end
150
+ end
151
+
152
+ def sub_parser_add_symbol
153
+ sub_parser.on_head('--symbol STR', String, 'character to be used to plot the bars') do |v|
154
+ params.symbol = v
155
+ end
156
+ end
157
+
158
+ def sub_parser_add_xscale
159
+ xscale_options = UnicodePlot::ValueTransformer::PREDEFINED_TRANSFORM_FUNCTIONS.keys.join(', ')
160
+ sub_parser.on_head('--xscale STR', String, "axis scaling (#{xscale_options})") do |v|
161
+ params.xscale = v.to_sym
162
+ end
163
+ end
164
+
165
+ def sub_parser_add_canvas
166
+ sub_parser.on_head('--canvas STR', String, 'type of canvas') do |v|
167
+ params.canvas = v.to_sym
168
+ end
169
+ end
170
+
171
+ def sub_parser_add_xlim
172
+ sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v|
173
+ params.xlim = v
174
+ end
175
+ end
176
+
177
+ def sub_parser_add_ylim
178
+ sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v|
179
+ params.ylim = v
180
+ end
181
+ end
182
+
183
+ def sub_parser_add_grid
184
+ sub_parser.on_head('--[no-]grid', TrueClass, 'draws grid-lines at the origin') do |v|
185
+ params.grid = v
186
+ end
187
+ end
188
+
189
+ def sub_parser_add_fmt_xyxy
190
+ sub_parser.on_head('--fmt STR', String,
191
+ 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
192
+ 'xyy : header is like x, y1, y2, y2, y3...') do |v|
193
+ options[:fmt] = v
194
+ end
195
+ end
196
+
197
+ def sub_parser_add_fmt_yx
198
+ sub_parser.on_head('--fmt STR', String,
199
+ 'xy : header is like x, y...',
200
+ 'yx : header is like y, x...') do |v|
201
+ options[:fmt] = v
202
+ end
203
+ end
204
+
205
+ def create_sub_parser
206
+ @sub_parser = create_base_parser
207
+ sub_parser.banner = \
208
+ <<~MSG
209
+
210
+ Usage: YouPlot #{command} [options] <in.tsv>
211
+
212
+ Options for #{command}:
213
+ MSG
214
+
215
+ case command
216
+
217
+ # If you type only `uplot` in the terminal.
218
+ when nil
219
+ warn main_parser.banner
220
+ warn "\n"
221
+ exit 1 if YouPlot.run_as_executable?
222
+
223
+ when :barplot, :bar
224
+ sub_parser_add_symbol
225
+ sub_parser_add_fmt_yx
226
+ sub_parser_add_xscale
227
+
228
+ when :count, :c
229
+ sub_parser_add_symbol
230
+ sub_parser_add_xscale
231
+
232
+ when :histogram, :hist
233
+ sub_parser_add_symbol
234
+ sub_parser.on_head('--closed STR', String, 'side of the intervals to be closed [left]') do |v|
235
+ params.closed = v
236
+ end
237
+ sub_parser.on_head('-n', '--nbins INT', Numeric, 'approximate number of bins') do |v|
238
+ params.nbins = v
239
+ end
240
+
241
+ when :lineplot, :line
242
+ sub_parser_add_canvas
243
+ sub_parser_add_grid
244
+ sub_parser_add_fmt_yx
245
+ sub_parser_add_ylim
246
+ sub_parser_add_xlim
247
+
248
+ when :lineplots, :lines
249
+ sub_parser_add_canvas
250
+ sub_parser_add_grid
251
+ sub_parser_add_fmt_xyxy
252
+ sub_parser_add_ylim
253
+ sub_parser_add_xlim
254
+
255
+ when :scatter, :s
256
+ sub_parser_add_canvas
257
+ sub_parser_add_grid
258
+ sub_parser_add_fmt_xyxy
259
+ sub_parser_add_ylim
260
+ sub_parser_add_xlim
261
+
262
+ when :density, :d
263
+ sub_parser_add_canvas
264
+ sub_parser_add_grid
265
+ sub_parser_add_fmt_xyxy
266
+ sub_parser_add_ylim
267
+ sub_parser_add_xlim
268
+
269
+ when :boxplot, :box
270
+ sub_parser_add_xlim
271
+
272
+ when :colors, :color, :colours, :colour
273
+ sub_parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
274
+ options[:color_names] = v
275
+ end
276
+
277
+ else
278
+ error_message = "uplot: unrecognized command '#{command}'"
279
+ if YouPlot.run_as_executable?
280
+ warn error_message
281
+ exit 1
282
+ else
283
+ raise Error, error_message
284
+ end
285
+ end
286
+ end
287
+
288
+ def parse_options(argv = ARGV)
289
+ begin
290
+ create_main_parser.order!(argv)
291
+ rescue OptionParser::ParseError => e
292
+ warn "uplot: #{e.message}"
293
+ exit 1 if YouPlot.run_as_executable?
294
+ end
295
+
296
+ @command = argv.shift&.to_sym
297
+
298
+ begin
299
+ create_sub_parser&.parse!(argv)
300
+ rescue OptionParser::ParseError => e
301
+ warn "uplot: #{e.message}"
302
+ exit 1 if YouPlot.run_as_executable?
303
+ end
304
+ end
305
+ end
306
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module YouPlot
4
- VERSION = '0.3.4'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/youplot.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'unicode_plot'
4
- require 'youplot/version'
5
- require 'youplot/dsv'
6
- require 'youplot/command'
3
+ require_relative 'youplot/version'
4
+ require_relative 'youplot/dsv'
5
+ require_relative 'youplot/parameters'
6
+ require_relative 'youplot/command'
7
7
 
8
8
  module YouPlot
9
9
  class << self
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.4
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: 2021-01-20 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
@@ -109,12 +109,12 @@ files:
109
109
  - exe/youplot
110
110
  - lib/youplot.rb
111
111
  - lib/youplot/backends/processing.rb
112
- - lib/youplot/backends/unicode_plot_backend.rb
112
+ - lib/youplot/backends/unicode_plot.rb
113
113
  - lib/youplot/command.rb
114
- - lib/youplot/command/options.rb
115
- - lib/youplot/command/parser.rb
116
- - lib/youplot/command/plot_params.rb
117
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,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  - !ruby/object:Gem::Version
136
136
  version: '0'
137
137
  requirements: []
138
- rubygems_version: 3.2.3
138
+ rubygems_version: 3.2.15
139
139
  signing_key:
140
140
  specification_version: 4
141
141
  summary: A command line tool for Unicode Plotting
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module YouPlot
4
- class Command
5
- Options = Struct.new(
6
- :delimiter,
7
- :transpose,
8
- :headers,
9
- :pass,
10
- :progressive,
11
- :output,
12
- :fmt,
13
- :encoding,
14
- :color_names,
15
- :debug,
16
- keyword_init: true
17
- )
18
- end
19
- end
@@ -1,297 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'optparse'
4
- require_relative 'options'
5
- require_relative 'plot_params'
6
-
7
- module YouPlot
8
- class Command
9
- class Parser
10
- class Error < StandardError; end
11
-
12
- attr_reader :command, :options, :params,
13
- :main_parser, :sub_parser
14
-
15
- def initialize
16
- @command = nil
17
-
18
- @options = Options.new(
19
- delimiter: "\t",
20
- transpose: false,
21
- headers: nil,
22
- pass: false,
23
- output: $stderr,
24
- fmt: 'xyy',
25
- encoding: nil,
26
- color_names: false,
27
- debug: false
28
- )
29
-
30
- @params = PlotParams.new
31
- end
32
-
33
- def create_default_parser
34
- OptionParser.new do |parser|
35
- parser.program_name = 'YouPlot'
36
- parser.version = YouPlot::VERSION
37
- parser.summary_width = 24
38
- parser.on_tail('') # Add a blank line at the end
39
- parser.separator('')
40
- parser.on('Common options:')
41
- parser.on('-O', '--pass [FILE]', 'file to output input data to [stdout]',
42
- 'for inserting YouPlot in the middle of Unix pipes') do |v|
43
- options[:pass] = v || $stdout
44
- end
45
- parser.on('-o', '--output [FILE]', 'file to output plots to [stdout]',
46
- 'If no option is specified, plot will print to stderr') do |v|
47
- options[:output] = v || $stdout
48
- end
49
- parser.on('-d', '--delimiter DELIM', String, 'use DELIM instead of [TAB] for field delimiter') do |v|
50
- options[:delimiter] = v
51
- end
52
- parser.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
53
- options[:headers] = v
54
- end
55
- parser.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
56
- options[:transpose] = v
57
- end
58
- parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v|
59
- params.title = v
60
- end
61
- parser.on('-x', '--xlabel STR', String, 'print string on the bottom of the plot') do |v|
62
- params.xlabel = v
63
- end
64
- parser.on('-y', '--ylabel STR', String, 'print string on the far left of the plot') do |v|
65
- params.ylabel = v
66
- end
67
- parser.on('-w', '--width INT', Integer, 'number of characters per row') do |v|
68
- params.width = v
69
- end
70
- parser.on('-h', '--height INT', Numeric, 'number of rows') do |v|
71
- params.height = v
72
- end
73
- parser.on('-b', '--border STR', String, 'specify the style of the bounding box') do |v|
74
- params.border = v.to_sym
75
- end
76
- parser.on('-m', '--margin INT', Numeric, 'number of spaces to the left of the plot') do |v|
77
- params.margin = v
78
- end
79
- parser.on('--padding INT', Numeric, 'space of the left and right of the plot') do |v|
80
- params.padding = v
81
- end
82
- parser.on('-c', '--color VAL', String, 'color of the drawing') do |v|
83
- params.color = v =~ /\A[0-9]+\z/ ? v.to_i : v.to_sym
84
- end
85
- parser.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
86
- params.labels = v
87
- end
88
- parser.on('-p', '--progress', TrueClass, 'progressive mode [experimental]') do |v|
89
- options[:progressive] = v
90
- end
91
- parser.on('--encoding STR', String, 'Specify the input encoding') do |v|
92
- options[:encoding] = v
93
- end
94
- # Optparse adds the help option, but it doesn't show up in usage.
95
- # This is why you need the code below.
96
- parser.on('--help', 'print sub-command help menu') do
97
- puts parser.help
98
- exit if YouPlot.run_as_executable?
99
- end
100
- parser.on('--debug', TrueClass, 'print preprocessed data') do |v|
101
- options[:debug] = v
102
- end
103
- # yield opt if block_given?
104
- end
105
- end
106
-
107
- def create_main_parser
108
- @main_parser = create_default_parser
109
- main_parser.banner = \
110
- <<~MSG
111
-
112
- Program: YouPlot (Tools for plotting on the terminal)
113
- Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
114
- Source: https://github.com/kojix2/youplot
115
-
116
- Usage: uplot <command> [options] <in.tsv>
117
-
118
- Commands:
119
- barplot bar draw a horizontal barplot
120
- histogram hist draw a horizontal histogram
121
- lineplot line draw a line chart
122
- lineplots lines draw a line chart with multiple series
123
- scatter s draw a scatter plot
124
- density d draw a density plot
125
- boxplot box draw a horizontal boxplot
126
- colors color show the list of available colors
127
-
128
- count c draw a baplot based on the number of
129
- occurrences (slow)
130
-
131
- General options:
132
- --help print command specific help menu
133
- --version print the version of YouPlot
134
- MSG
135
-
136
- # Help for the main parser is simple.
137
- # Simply show the banner above.
138
- main_parser.on('--help', 'print sub-command help menu') do
139
- puts main_parser.banner
140
- puts
141
- exit if YouPlot.run_as_executable?
142
- end
143
- end
144
-
145
- def sub_parser_add_symbol
146
- sub_parser.on_head('--symbol STR', String, 'character to be used to plot the bars') do |v|
147
- params.symbol = v
148
- end
149
- end
150
-
151
- def sub_parser_add_xscale
152
- xscale_options = UnicodePlot::ValueTransformer::PREDEFINED_TRANSFORM_FUNCTIONS.keys.join(', ')
153
- sub_parser.on_head('--xscale STR', String, "axis scaling (#{xscale_options})") do |v|
154
- params.xscale = v
155
- end
156
- end
157
-
158
- def sub_parser_add_canvas
159
- sub_parser.on_head('--canvas STR', String, 'type of canvas') do |v|
160
- params.canvas = v.to_sym
161
- end
162
- end
163
-
164
- def sub_parser_add_xlim
165
- sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v|
166
- params.xlim = v.take(2)
167
- end
168
- end
169
-
170
- def sub_parser_add_ylim
171
- sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v|
172
- params.ylim = v.take(2)
173
- end
174
- end
175
-
176
- def sub_parser_add_grid
177
- sub_parser.on_head('--[no-]grid', TrueClass, 'draws grid-lines at the origin') do |v|
178
- params.grid = v
179
- end
180
- end
181
-
182
- def create_sub_parser
183
- @sub_parser = create_default_parser
184
- sub_parser.banner = \
185
- <<~MSG
186
-
187
- Usage: YouPlot #{command} [options] <in.tsv>
188
-
189
- Options for #{command}:
190
- MSG
191
-
192
- case command
193
-
194
- # If you type only `uplot` in the terminal.
195
- when nil
196
- warn main_parser.banner
197
- warn "\n"
198
- exit 1 if YouPlot.run_as_executable?
199
-
200
- when :barplot, :bar
201
- sub_parser_add_symbol
202
- sub_parser.on_head('--fmt STR', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
203
- options[:fmt] = v
204
- end
205
- sub_parser_add_xscale
206
-
207
- when :count, :c
208
- sub_parser_add_symbol
209
- sub_parser_add_xscale
210
-
211
- when :histogram, :hist
212
- sub_parser_add_symbol
213
- sub_parser.on_head('--closed STR', String, 'side of the intervals to be closed [left]') do |v|
214
- params.closed = v
215
- end
216
- sub_parser.on_head('-n', '--nbins INT', Numeric, 'approximate number of bins') do |v|
217
- params.nbins = v
218
- end
219
-
220
- when :lineplot, :line
221
- sub_parser_add_canvas
222
- sub_parser_add_grid
223
- sub_parser.on_head('--fmt STR', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
224
- options[:fmt] = v
225
- end
226
- sub_parser_add_ylim
227
- sub_parser_add_xlim
228
-
229
- when :lineplots, :lines
230
- sub_parser_add_canvas
231
- sub_parser_add_grid
232
- sub_parser.on_head('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
233
- 'xyy : header is like x, y1, y2, y2, y3...') do |v|
234
- options[:fmt] = v
235
- end
236
- sub_parser_add_ylim
237
- sub_parser_add_xlim
238
-
239
- when :scatter, :s
240
- sub_parser_add_canvas
241
- sub_parser_add_grid
242
- sub_parser.on_head('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
243
- 'xyy : header is like x, y1, y2, y2, y3...') do |v|
244
- options[:fmt] = v
245
- end
246
- sub_parser_add_ylim
247
- sub_parser_add_xlim
248
-
249
- when :density, :d
250
- sub_parser_add_canvas
251
- sub_parser_add_grid
252
- sub_parser.on('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
253
- 'xyy : header is like x, y1, y2, y2, y3...') do |v|
254
- options[:fmt] = v
255
- end
256
- sub_parser_add_ylim
257
- sub_parser_add_xlim
258
-
259
- when :boxplot, :box
260
- sub_parser_add_xlim
261
-
262
- when :colors, :color, :colours, :colour
263
- sub_parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
264
- options[:color_names] = v
265
- end
266
-
267
- else
268
- error_message = "uplot: unrecognized command '#{command}'"
269
- if YouPlot.run_as_executable?
270
- warn error_message
271
- exit 1
272
- else
273
- raise Error, error_message
274
- end
275
- end
276
- end
277
-
278
- def parse_options(argv = ARGV)
279
- begin
280
- create_main_parser.order!(argv)
281
- rescue OptionParser::ParseError => e
282
- warn "uplot: #{e.message}"
283
- exit 1 if YouPlot.run_as_executable?
284
- end
285
-
286
- @command = argv.shift&.to_sym
287
-
288
- begin
289
- create_sub_parser&.parse!(argv)
290
- rescue OptionParser::ParseError => e
291
- warn "uplot: #{e.message}"
292
- exit 1 if YouPlot.run_as_executable?
293
- end
294
- end
295
- end
296
- end
297
- end
@@ -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
- PlotParams = 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