youplot 0.3.0 → 0.3.5

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.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'preprocessing'
3
+ require_relative 'dsv'
4
4
  require_relative 'command/parser'
5
5
 
6
6
  # FIXME
@@ -10,79 +10,173 @@ module YouPlot
10
10
  Data = Struct.new(:headers, :series)
11
11
 
12
12
  class Command
13
- attr_accessor :params
14
- attr_reader :data, :fmt, :parser
13
+ attr_accessor :command, :params, :options
14
+ attr_reader :data, :parser
15
15
 
16
16
  def initialize(argv = ARGV)
17
17
  @argv = argv
18
- @params = Params.new
19
18
  @parser = Parser.new
19
+ @command = nil
20
+ @params = nil
21
+ @options = nil
20
22
  @backend = YouPlot::Backends::UnicodePlotBackend
21
23
  end
22
24
 
25
+ def run_as_executable
26
+ YouPlot.run_as_executable = true
27
+ run
28
+ end
29
+
23
30
  def run
24
31
  parser.parse_options(@argv)
25
- command = parser.command
26
- params = parser.params
27
- delimiter = parser.delimiter
28
- transpose = parser.transpose
29
- headers = parser.headers
30
- pass = parser.pass
31
- output = parser.output
32
- fmt = parser.fmt
33
- @debug = parser.debug
34
-
35
- if command == :colors
36
- @backend.colors(parser.color_names)
37
- exit
32
+ @command ||= parser.command
33
+ @options ||= parser.options
34
+ @params ||= parser.params
35
+
36
+ if %i[colors color colours colour].include? @command
37
+ plot = create_plot
38
+ output_plot(plot)
39
+ elsif options[:progressive]
40
+ stop = false
41
+ Signal.trap(:INT) { stop = true }
42
+ options[:output].print "\e[?25l" # make cursor invisible
43
+ while (input = Kernel.gets)
44
+ n = main_progressive(input)
45
+ break if stop
46
+
47
+ options[:output].print "\e[#{n}F"
48
+ end
49
+ options[:output].print "\e[0J"
50
+ options[:output].print "\e[?25h" # make cursor visible
51
+ else
52
+ # Sometimes the input file does not end with a newline code.
53
+ while (input = Kernel.gets(nil))
54
+ main(input)
55
+ end
38
56
  end
57
+ end
39
58
 
40
- # Sometimes the input file does not end with a newline code.
41
- while (input = Kernel.gets(nil))
42
- input.freeze
43
- @data = Preprocessing.input(input, delimiter, headers, transpose)
44
- pp @data if @debug
45
- plot = case command
46
- when :bar, :barplot
47
- @backend.barplot(data, params)
48
- when :count, :c
49
- @backend.barplot(data, params, count: true)
50
- when :hist, :histogram
51
- @backend.histogram(data, params)
52
- when :line, :lineplot
53
- @backend.line(data, params)
54
- when :lines, :lineplots
55
- @backend.lines(data, params, fmt)
56
- when :scatter, :s
57
- @backend.scatter(data, params, fmt)
58
- when :density, :d
59
- @backend.density(data, params, fmt)
60
- when :box, :boxplot
61
- @backend.boxplot(data, params)
62
- else
63
- raise "unrecognized plot_type: #{command}"
64
- end
65
-
66
- case output
67
- when IO
68
- plot.render(output)
69
- else
70
- File.open(output, 'w') do |f|
71
- plot.render(f)
72
- end
59
+ private
60
+
61
+ def main(input)
62
+ output_data(input)
63
+
64
+ @data = read_dsv(input)
65
+
66
+ pp @data if options[:debug]
67
+
68
+ if YouPlot.run_as_executable?
69
+ begin
70
+ plot = create_plot
71
+ rescue ArgumentError => e
72
+ warn e.backtrace[0]
73
+ warn "\e[35m#{e}\e[0m"
74
+ exit 1
73
75
  end
76
+ else
77
+ plot = create_plot
78
+ end
79
+ output_plot(plot)
80
+ end
81
+
82
+ def main_progressive(input)
83
+ output_data(input)
84
+
85
+ # FIXME
86
+ # Worked around the problem of not being able to draw
87
+ # plots when there is only one header line.
88
+ if @raw_data.nil?
89
+ @raw_data = String.new
90
+ if options[:headers]
91
+ @raw_data << input
92
+ return
93
+ end
94
+ end
95
+ @raw_data << input
74
96
 
75
- case pass
76
- when IO
77
- pass.print(input)
78
- else
79
- if pass
80
- File.open(pass, 'w') do |f|
81
- f.print(input)
82
- end
97
+ # FIXME
98
+ @data = read_dsv(@raw_data)
99
+
100
+ plot = create_plot
101
+ output_plot_progressive(plot)
102
+ end
103
+
104
+ def read_dsv(input)
105
+ input = input.dup.force_encoding(options[:encoding]).encode('utf-8') if options[:encoding]
106
+ DSV.parse(input, options[:delimiter], options[:headers], options[:transpose])
107
+ end
108
+
109
+ def create_plot
110
+ case command
111
+ when :bar, :barplot
112
+ @backend.barplot(data, params, options[:fmt])
113
+ when :count, :c
114
+ @backend.barplot(data, params, count: true)
115
+ when :hist, :histogram
116
+ @backend.histogram(data, params)
117
+ when :line, :lineplot
118
+ @backend.line(data, params, options[:fmt])
119
+ when :lines, :lineplots
120
+ @backend.lines(data, params, options[:fmt])
121
+ when :scatter, :s
122
+ @backend.scatter(data, params, options[:fmt])
123
+ when :density, :d
124
+ @backend.density(data, params, options[:fmt])
125
+ when :box, :boxplot
126
+ @backend.boxplot(data, params)
127
+ when :colors, :color, :colours, :colour
128
+ @backend.colors(options[:color_names])
129
+ else
130
+ raise "unrecognized plot_type: #{command}"
131
+ end
132
+ end
133
+
134
+ def output_data(input)
135
+ # Pass the input to subsequent pipelines
136
+ case options[:pass]
137
+ when IO
138
+ options[:pass].print(input)
139
+ else
140
+ if options[:pass]
141
+ File.open(options[:pass], 'w') do |f|
142
+ f.print(input)
83
143
  end
84
144
  end
85
145
  end
86
146
  end
147
+
148
+ def output_plot(plot)
149
+ case options[:output]
150
+ when IO
151
+ plot.render(options[:output])
152
+ else
153
+ File.open(options[:output], 'w') do |f|
154
+ plot.render(f)
155
+ end
156
+ end
157
+ end
158
+
159
+ def output_plot_progressive(plot)
160
+ case options[:output]
161
+ when IO
162
+ # RefactorMe
163
+ out = StringIO.new(String.new)
164
+ def out.tty?
165
+ true
166
+ end
167
+ plot.render(out)
168
+ lines = out.string.lines
169
+ lines.each do |line|
170
+ options[:output].print line.chomp
171
+ options[:output].print "\e[0K"
172
+ options[:output].puts
173
+ end
174
+ options[:output].print "\e[0J"
175
+ options[:output].flush
176
+ out.string.lines.size
177
+ else
178
+ raise 'In progressive mode, output to a file is not possible.'
179
+ end
180
+ end
87
181
  end
88
182
  end
@@ -0,0 +1,19 @@
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
+ :output,
11
+ :fmt,
12
+ :progressive,
13
+ :encoding,
14
+ :color_names,
15
+ :debug,
16
+ keyword_init: true
17
+ )
18
+ end
19
+ end
@@ -1,259 +1,303 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
- require_relative 'params'
4
+ require_relative 'options'
5
+ require_relative 'plot_params'
5
6
 
6
7
  module YouPlot
7
8
  class Command
8
9
  class Parser
9
- attr_reader :command, :params,
10
- :delimiter, :transpose, :headers, :pass, :output, :fmt,
11
- :color_names, :debug
10
+ class Error < StandardError; end
11
+
12
+ attr_reader :command, :options, :params,
13
+ :main_parser, :sub_parser
12
14
 
13
15
  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
- @debug = false
24
- @color_names = false
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
+ progressive: false,
26
+ encoding: nil,
27
+ color_names: false,
28
+ debug: false
29
+ )
30
+
31
+ @params = PlotParams.new
25
32
  end
26
33
 
27
34
  def create_default_parser
28
- OptionParser.new do |opt|
29
- opt.program_name = 'YouPlot'
30
- opt.version = YouPlot::VERSION
31
- opt.summary_width = 24
32
- opt.on_tail('') # Add a blank line at the end
33
- opt.separator('')
34
- opt.on('Common options:')
35
- opt.on('-O', '--pass [VAL]', 'file to output standard input data to [stdout]',
36
- 'for inserting YouPlot in the middle of Unix pipes') do |v|
37
- @pass = v || $stdout
35
+ OptionParser.new do |parser|
36
+ parser.program_name = 'YouPlot'
37
+ parser.version = YouPlot::VERSION
38
+ parser.summary_width = 24
39
+ parser.on_tail('') # Add a blank line at the end
40
+ parser.separator('')
41
+ parser.on('Common options:')
42
+ parser.on('-O', '--pass [FILE]', 'file to output input data to [stdout]',
43
+ 'for inserting YouPlot in the middle of Unix pipes') do |v|
44
+ options[:pass] = v || $stdout
38
45
  end
39
- opt.on('-o', '--output VAL', 'file to output results to [stderr]') do |v|
40
- @output = v
46
+ parser.on('-o', '--output [FILE]', 'file to output plots to [stdout]',
47
+ 'If no option is specified, plot will print to stderr') do |v|
48
+ options[:output] = v || $stdout
41
49
  end
42
- opt.on('-d', '--delimiter VAL', String, 'use DELIM instead of TAB for field delimiter') do |v|
43
- @delimiter = v
50
+ parser.on('-d', '--delimiter DELIM', String, 'use DELIM instead of [TAB] for field delimiter') do |v|
51
+ options[:delimiter] = v
44
52
  end
45
- opt.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
46
- @headers = v
53
+ parser.on('-H', '--headers', TrueClass, 'specify that the input has header row') do |v|
54
+ options[:headers] = v
47
55
  end
48
- opt.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
49
- @transpose = v
56
+ parser.on('-T', '--transpose', TrueClass, 'transpose the axes of the input data') do |v|
57
+ options[:transpose] = v
50
58
  end
51
- opt.on('-t', '--title VAL', String, 'print string on the top of plot') do |v|
59
+ parser.on('-t', '--title STR', String, 'print string on the top of plot') do |v|
52
60
  params.title = v
53
61
  end
54
- opt.on('-x', '--xlabel VAL', String, 'print string on the bottom of the plot') do |v|
62
+ parser.on('-x', '--xlabel STR', String, 'print string on the bottom of the plot') do |v|
55
63
  params.xlabel = v
56
64
  end
57
- opt.on('-y', '--ylabel VAL', String, 'print string on the far left of the plot') do |v|
65
+ parser.on('-y', '--ylabel STR', String, 'print string on the far left of the plot') do |v|
58
66
  params.ylabel = v
59
67
  end
60
- opt.on('-w', '--width VAL', Integer, 'number of characters per row') do |v|
68
+ parser.on('-w', '--width INT', Integer, 'number of characters per row') do |v|
61
69
  params.width = v
62
70
  end
63
- opt.on('-h', '--height VAL', Numeric, 'number of rows') do |v|
71
+ parser.on('-h', '--height INT', Numeric, 'number of rows') do |v|
64
72
  params.height = v
65
73
  end
66
- opt.on('-b', '--border VAL', String, 'specify the style of the bounding box') do |v|
74
+ border_options = UnicodePlot::BORDER_MAP.keys.join(', ')
75
+ parser.on('-b', '--border STR', String, 'specify the style of the bounding box', "(#{border_options})") do |v|
67
76
  params.border = v.to_sym
68
77
  end
69
- opt.on('-m', '--margin VAL', Numeric, 'number of spaces to the left of the plot') do |v|
78
+ parser.on('-m', '--margin INT', Numeric, 'number of spaces to the left of the plot') do |v|
70
79
  params.margin = v
71
80
  end
72
- opt.on('-p', '--padding VAL', Numeric, 'space of the left and right of the plot') do |v|
81
+ parser.on('--padding INT', Numeric, 'space of the left and right of the plot') do |v|
73
82
  params.padding = v
74
83
  end
75
- opt.on('-c', '--color VAL', String, 'color of the drawing') do |v|
84
+ parser.on('-c', '--color VAL', String, 'color of the drawing') do |v|
76
85
  params.color = v =~ /\A[0-9]+\z/ ? v.to_i : v.to_sym
77
86
  end
78
- opt.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
87
+ parser.on('--[no-]labels', TrueClass, 'hide the labels') do |v|
79
88
  params.labels = v
80
89
  end
81
- opt.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|
82
- @fmt = v
90
+ parser.on('-p', '--progress', TrueClass, 'progressive mode [experimental]') do |v|
91
+ options[:progressive] = v
92
+ end
93
+ parser.on('-C', '--color-output', TrueClass, 'colorize even if writing to a pipe') do |v|
94
+ UnicodePlot::StyledPrinter.define_method(:color?){ |o| true }
95
+ end
96
+ parser.on('-M', '--monochrome', TrueClass, 'no colouring even if writing to a tty') do |v|
97
+ UnicodePlot::StyledPrinter.define_method(:color?){ |o| false }
98
+ end
99
+ parser.on('--encoding STR', String, 'Specify the input encoding') do |v|
100
+ options[:encoding] = v
83
101
  end
84
102
  # Optparse adds the help option, but it doesn't show up in usage.
85
103
  # This is why you need the code below.
86
- opt.on('--help', 'print sub-command help menu') do
87
- puts opt.help
88
- exit
104
+ parser.on('--help', 'print sub-command help menu') do
105
+ puts parser.help
106
+ exit if YouPlot.run_as_executable?
89
107
  end
90
- opt.on('--debug', TrueClass, 'print preprocessed data') do |v|
91
- @debug = v
108
+ parser.on('--debug', TrueClass, 'print preprocessed data') do |v|
109
+ options[:debug] = v
92
110
  end
93
- yield opt if block_given?
111
+ # yield opt if block_given?
94
112
  end
95
113
  end
96
114
 
97
- def main_parser
98
- @main_parser ||= create_default_parser do |main_parser|
99
- # Here, help message is stored in the banner.
100
- # Because help of main_parser may be referred by `sub_parser`.
101
-
102
- main_parser.banner = \
103
- <<~MSG
104
-
105
- Program: YouPlot (Tools for plotting on the terminal)
106
- Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
107
- Source: https://github.com/kojix2/youplot
108
-
109
- Usage: uplot <command> [options] <in.tsv>
110
-
111
- Commands:
112
- barplot bar draw a horizontal barplot
113
- histogram hist draw a horizontal histogram
114
- lineplot line draw a line chart
115
- lineplots lines draw a line chart with multiple series
116
- scatter s draw a scatter plot
117
- density d draw a density plot
118
- boxplot box draw a horizontal boxplot
119
- colors show the list of available colors
120
-
121
- count c draw a baplot based on the number of
122
- occurrences (slow)
123
-
124
- General options:
125
- --help print command specific help menu
126
- --version print the version of YouPlot
127
- MSG
128
-
129
- # Actually, main_parser can take common optional arguments.
130
- # However, these options dose not be shown in the help menu.
131
- # I think the main help should be simple.
132
- main_parser.on('--help', 'print sub-command help menu') do
133
- puts main_parser.banner
134
- puts
135
- exit
136
- end
115
+ def create_main_parser
116
+ @main_parser = create_default_parser
117
+ main_parser.banner = \
118
+ <<~MSG
119
+
120
+ Program: YouPlot (Tools for plotting on the terminal)
121
+ Version: #{YouPlot::VERSION} (using UnicodePlot #{UnicodePlot::VERSION})
122
+ Source: https://github.com/kojix2/youplot
123
+
124
+ Usage: uplot <command> [options] <in.tsv>
125
+
126
+ Commands:
127
+ barplot bar draw a horizontal barplot
128
+ histogram hist draw a horizontal histogram
129
+ lineplot line draw a line chart
130
+ lineplots lines draw a line chart with multiple series
131
+ scatter s draw a scatter plot
132
+ density d draw a density plot
133
+ boxplot box draw a horizontal boxplot
134
+ colors color show the list of available colors
135
+
136
+ count c draw a baplot based on the number of
137
+ occurrences (slow)
138
+
139
+ General options:
140
+ --help print command specific help menu
141
+ --version print the version of YouPlot
142
+ MSG
143
+
144
+ # Help for the main parser is simple.
145
+ # Simply show the banner above.
146
+ main_parser.on('--help', 'print sub-command help menu') do
147
+ puts main_parser.banner
148
+ puts
149
+ exit if YouPlot.run_as_executable?
137
150
  end
138
151
  end
139
152
 
140
- def sub_parser
141
- @sub_parser ||= create_default_parser do |parser|
142
- parser.banner = <<~MSG
153
+ def sub_parser_add_symbol
154
+ sub_parser.on_head('--symbol STR', String, 'character to be used to plot the bars') do |v|
155
+ params.symbol = v
156
+ end
157
+ end
158
+
159
+ def sub_parser_add_xscale
160
+ xscale_options = UnicodePlot::ValueTransformer::PREDEFINED_TRANSFORM_FUNCTIONS.keys.join(', ')
161
+ sub_parser.on_head('--xscale STR', String, "axis scaling (#{xscale_options})") do |v|
162
+ params.xscale = v.to_sym
163
+ end
164
+ end
165
+
166
+ def sub_parser_add_canvas
167
+ sub_parser.on_head('--canvas STR', String, 'type of canvas') do |v|
168
+ params.canvas = v.to_sym
169
+ end
170
+ end
171
+
172
+ def sub_parser_add_xlim
173
+ sub_parser.on_head('--xlim FLOAT,FLOAT', Array, 'plotting range for the x coordinate') do |v|
174
+ params.xlim = v
175
+ end
176
+ end
177
+
178
+ def sub_parser_add_ylim
179
+ sub_parser.on_head('--ylim FLOAT,FLOAT', Array, 'plotting range for the y coordinate') do |v|
180
+ params.ylim = v
181
+ end
182
+ end
183
+
184
+ def sub_parser_add_grid
185
+ sub_parser.on_head('--[no-]grid', TrueClass, 'draws grid-lines at the origin') do |v|
186
+ params.grid = v
187
+ end
188
+ end
189
+
190
+ def create_sub_parser
191
+ @sub_parser = create_default_parser
192
+ sub_parser.banner = \
193
+ <<~MSG
143
194
 
144
195
  Usage: YouPlot #{command} [options] <in.tsv>
145
196
 
146
197
  Options for #{command}:
147
198
  MSG
148
199
 
149
- case command
200
+ case command
150
201
 
151
- # If you type only `uplot` in the terminal.
152
- when nil
153
- warn main_parser.banner
154
- warn "\n"
155
- exit 1
202
+ # If you type only `uplot` in the terminal.
203
+ when nil
204
+ warn main_parser.banner
205
+ warn "\n"
206
+ exit 1 if YouPlot.run_as_executable?
156
207
 
157
- when :barplot, :bar
158
- parser.on_head('--symbol VAL', String, 'character to be used to plot the bars') do |v|
159
- params.symbol = v
160
- end
161
- parser.on_head('--xscale VAL', String, 'axis scaling') do |v|
162
- params.xscale = v
163
- end
164
-
165
- when :count, :c
166
- parser.on_head('--symbol VAL', String, 'character to be used to plot the bars') do |v|
167
- params.symbol = v
168
- end
169
-
170
- when :histogram, :hist
171
- parser.on_head('-n', '--nbins VAL', Numeric, 'approximate number of bins') do |v|
172
- params.nbins = v
173
- end
174
- parser.on_head('--closed VAL', String) do |v|
175
- params.closed = v
176
- end
177
- parser.on_head('--symbol VAL', String, 'character to be used to plot the bars') do |v|
178
- params.symbol = v
179
- end
180
-
181
- when :lineplot, :line
182
- parser.on_head('--canvas VAL', String, 'type of canvas') do |v|
183
- params.canvas = v
184
- end
185
- parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
186
- params.xlim = v.take(2)
187
- end
188
- parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
189
- params.ylim = v.take(2)
190
- end
191
-
192
- when :lineplots, :lines
193
- parser.on_head('--canvas VAL', String) do |v|
194
- params.canvas = v
195
- end
196
- parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
197
- params.xlim = v.take(2)
198
- end
199
- parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
200
- params.ylim = v.take(2)
201
- end
202
-
203
- when :scatter, :s
204
- parser.on_head('--canvas VAL', String) do |v|
205
- params.canvas = v
206
- end
207
- parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
208
- params.xlim = v.take(2)
209
- end
210
- parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
211
- params.ylim = v.take(2)
212
- end
213
-
214
- when :density, :d
215
- parser.on_head('--grid', TrueClass) do |v|
216
- params.grid = v
217
- end
218
- parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
219
- params.xlim = v.take(2)
220
- end
221
- parser.on_head('--ylim VAL', Array, 'plotting range for the y coordinate') do |v|
222
- params.ylim = v.take(2)
223
- end
224
-
225
- when :boxplot, :box
226
- parser.on_head('--xlim VAL', Array, 'plotting range for the x coordinate') do |v|
227
- params.xlim = v.take(2)
228
- end
229
-
230
- when :colors
231
- parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
232
- @color_names = v
233
- end
208
+ when :barplot, :bar
209
+ sub_parser_add_symbol
210
+ sub_parser.on_head('--fmt STR', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
211
+ options[:fmt] = v
212
+ end
213
+ sub_parser_add_xscale
234
214
 
235
- else
236
- warn "uplot: unrecognized command '#{command}'"
215
+ when :count, :c
216
+ sub_parser_add_symbol
217
+ sub_parser_add_xscale
218
+
219
+ when :histogram, :hist
220
+ sub_parser_add_symbol
221
+ sub_parser.on_head('--closed STR', String, 'side of the intervals to be closed [left]') do |v|
222
+ params.closed = v
223
+ end
224
+ sub_parser.on_head('-n', '--nbins INT', Numeric, 'approximate number of bins') do |v|
225
+ params.nbins = v
226
+ end
227
+
228
+ when :lineplot, :line
229
+ sub_parser_add_canvas
230
+ sub_parser_add_grid
231
+ sub_parser.on_head('--fmt STR', String, 'xy : header is like x, y...', 'yx : header is like y, x...') do |v|
232
+ options[:fmt] = v
233
+ end
234
+ sub_parser_add_ylim
235
+ sub_parser_add_xlim
236
+
237
+ when :lineplots, :lines
238
+ sub_parser_add_canvas
239
+ sub_parser_add_grid
240
+ sub_parser.on_head('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
241
+ 'xyy : header is like x, y1, y2, y2, y3...') do |v|
242
+ options[:fmt] = v
243
+ end
244
+ sub_parser_add_ylim
245
+ sub_parser_add_xlim
246
+
247
+ when :scatter, :s
248
+ sub_parser_add_canvas
249
+ sub_parser_add_grid
250
+ sub_parser.on_head('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
251
+ 'xyy : header is like x, y1, y2, y2, y3...') do |v|
252
+ options[:fmt] = v
253
+ end
254
+ sub_parser_add_ylim
255
+ sub_parser_add_xlim
256
+
257
+ when :density, :d
258
+ sub_parser_add_canvas
259
+ sub_parser_add_grid
260
+ sub_parser.on('--fmt STR', String, 'xyxy : header is like x1, y1, x2, y2, x3, y3...',
261
+ 'xyy : header is like x, y1, y2, y2, y3...') do |v|
262
+ options[:fmt] = v
263
+ end
264
+ sub_parser_add_ylim
265
+ sub_parser_add_xlim
266
+
267
+ when :boxplot, :box
268
+ sub_parser_add_xlim
269
+
270
+ when :colors, :color, :colours, :colour
271
+ sub_parser.on_head('-n', '--names', 'show color names only', TrueClass) do |v|
272
+ options[:color_names] = v
273
+ end
274
+
275
+ else
276
+ error_message = "uplot: unrecognized command '#{command}'"
277
+ if YouPlot.run_as_executable?
278
+ warn error_message
237
279
  exit 1
280
+ else
281
+ raise Error, error_message
238
282
  end
239
283
  end
240
284
  end
241
285
 
242
286
  def parse_options(argv = ARGV)
243
287
  begin
244
- main_parser.order!(argv)
288
+ create_main_parser.order!(argv)
245
289
  rescue OptionParser::ParseError => e
246
290
  warn "uplot: #{e.message}"
247
- exit 1
291
+ exit 1 if YouPlot.run_as_executable?
248
292
  end
249
293
 
250
294
  @command = argv.shift&.to_sym
251
295
 
252
296
  begin
253
- sub_parser.parse!(argv)
297
+ create_sub_parser&.parse!(argv)
254
298
  rescue OptionParser::ParseError => e
255
299
  warn "uplot: #{e.message}"
256
- exit 1
300
+ exit 1 if YouPlot.run_as_executable?
257
301
  end
258
302
  end
259
303
  end