youplot 0.3.5 → 0.4.3
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 +87 -82
- data/lib/youplot/backends/processing.rb +22 -10
- data/lib/youplot/backends/{unicode_plot_backend.rb → unicode_plot.rb} +41 -18
- data/lib/youplot/command.rb +51 -16
- data/lib/youplot/dsv.rb +58 -48
- data/lib/youplot/options.rb +18 -0
- data/lib/youplot/parameters.rb +34 -0
- data/lib/youplot/parser.rb +309 -0
- data/lib/youplot/version.rb +1 -1
- data/lib/youplot.rb +10 -5
- metadata +10 -80
- data/lib/youplot/command/options.rb +0 -19
- data/lib/youplot/command/parser.rb +0 -305
- data/lib/youplot/command/plot_params.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b3b1cbdabc0a74b4010d13fa59fe9724ac9c07783414a7a7584f8cab27b49ec
|
4
|
+
data.tar.gz: f5cf98b592a248c4d74e06078d97050e85c892e94c0dd78ec17e92f6bdc856d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aebe50c600b66e9cb8e3a64da3ddafff70472f495d51b812987cc835017ca19fd1347fbe2ee88fac66e111837ffef59bf6c271f2f6515ae7e60a526050ded5b3
|
7
|
+
data.tar.gz: b37e2a5a2d8eb33700690d28b6e6f5851fbefb0e88ae10bcb6d9f65f06f966c31b81c7587135c6d296bde0caefbc81239046ec06535cefa9329f2ac6d8a8788f
|
data/README.md
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
<
|
2
|
-
<img src="logo.svg"
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
<div align="center">
|
2
|
+
<img src="logo.svg">
|
3
|
+
<hr>
|
4
|
+
<img alt="Build Status" src="https://github.com/red-data-tools/YouPlot/workflows/test/badge.svg">
|
5
|
+
<a href="https://rubygems.org/gems/youplot/"><img alt="Gem Version" src="https://badge.fury.io/rb/youplot.svg"></a>
|
6
|
+
<a href="https://zenodo.org/badge/latestdoi/283230219"><img alt="DOI" src="https://zenodo.org/badge/283230219.svg"></a>
|
7
|
+
<a href="https://rubydoc.info/gems/youplot/"><img alt="Docs Stable" src="https://img.shields.io/badge/docs-stable-blue.svg"></a>
|
8
|
+
<a href="LICENSE.txt"><img alt="The MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
|
9
|
+
|
10
|
+
YouPlot is a command line tool that draws plots on the terminal.
|
11
|
+
|
12
|
+
:bar_chart: Powered by [UnicodePlot](https://github.com/red-data-tools/unicode_plot.rb)
|
13
|
+
</div>
|
14
14
|
|
15
15
|
## Installation
|
16
16
|
|
@@ -20,8 +20,9 @@ gem install youplot
|
|
20
20
|
|
21
21
|
## Quick Start
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
<img alt="barplot" src="https://user-images.githubusercontent.com/5798442/101999903-d36a2d00-3d24-11eb-9361-b89116f44122.png" width=160> <img alt="histogram" src="https://user-images.githubusercontent.com/5798442/101999820-21cafc00-3d24-11eb-86db-e410d19b07df.png" width=160> <img alt="scatter" src="https://user-images.githubusercontent.com/5798442/101999827-27284680-3d24-11eb-9903-551857eaa69c.png" width=160> <img alt="density" src="https://user-images.githubusercontent.com/5798442/101999828-2abbcd80-3d24-11eb-902c-2f44266fa6ae.png" width=160> <img alt="boxplot" src="https://user-images.githubusercontent.com/5798442/101999830-2e4f5480-3d24-11eb-8891-728c18bf5b35.png" width=160>
|
24
|
+
|
25
|
+
`uplot <command> [options] <data.tsv>`
|
25
26
|
|
26
27
|
### barplot
|
27
28
|
|
@@ -33,7 +34,7 @@ curl -sL https://git.io/ISLANDScsv \
|
|
33
34
|
```
|
34
35
|
|
35
36
|
<p align="center">
|
36
|
-
<img alt="barplot" src="https://user-images.githubusercontent.com/5798442/101999903-d36a2d00-3d24-11eb-9361-b89116f44122.png">
|
37
|
+
<img alt="barplot" src="https://user-images.githubusercontent.com/5798442/101999903-d36a2d00-3d24-11eb-9361-b89116f44122.png">
|
37
38
|
</p>
|
38
39
|
|
39
40
|
### histogram
|
@@ -100,57 +101,41 @@ curl -sL https://git.io/IRIStsv \
|
|
100
101
|
|
101
102
|
### count
|
102
103
|
|
103
|
-
In this example, YouPlot counts the number of chromosomes where the gene is located from the human gene annotation file and it creates a bar chart. The human gene annotation file can be downloaded from the following website.
|
104
|
-
|
105
|
-
* https://www.gencodegenes.org/human/
|
106
|
-
|
107
104
|
```sh
|
108
105
|
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
|
106
|
+
| grep -v '#' | grep 'gene' | cut -f1 \
|
107
|
+
| uplot count -t "The number of human gene annotations per chromosome" -c blue
|
111
108
|
```
|
112
109
|
|
113
110
|
<p align="center">
|
114
111
|
<img alt="count" src="https://user-images.githubusercontent.com/5798442/101999832-30b1ae80-3d24-11eb-96fe-e5000bed1f5c.png">
|
115
112
|
</p>
|
116
113
|
|
114
|
+
In this example, YouPlot counts the number of chromosomes where genes are located.
|
115
|
+
* [GENCODE - Human Release](https://www.gencodegenes.org/human/)
|
116
|
+
|
117
117
|
Note: `count` is not very fast because it runs in a Ruby script.
|
118
118
|
This is fine in most cases, as long as the data size is small. If you want to visualize huge data, it is faster to use a combination of common Unix commands as shown below.
|
119
119
|
|
120
120
|
```sh
|
121
121
|
cat gencode.v35.annotation.gff3 | grep -v '#' | grep 'gene' | cut -f1 \
|
122
|
-
|sort | uniq -c | sort -
|
123
|
-
| uplot bar -d ' ' -t "The number of human gene annotations per chromosome" -c blue
|
122
|
+
| sort | uniq -c | sort -nrk1 \
|
123
|
+
| uplot bar --fmt yx -d ' ' -t "The number of human gene annotations per chromosome" -c blue
|
124
124
|
```
|
125
125
|
|
126
126
|
## Usage
|
127
127
|
|
128
|
-
###
|
129
|
-
|
130
|
-
Wouldn't it be a pain to have to run R, Python, Julia, gnuplot or whatever REPL just to check your data?
|
131
|
-
YouPlot is a command line tool for this purpose. With YouPlot, you can continue working without leaving your terminal and shell.
|
132
|
-
|
133
|
-
### how to use YouPlot?
|
128
|
+
### Commands
|
134
129
|
|
135
130
|
`uplot` is the shortened form of `youplot`. You can use either.
|
136
131
|
|
137
|
-
|
|
138
|
-
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
143
|
-
### Where to output the plot?
|
144
|
-
|
145
|
-
By default, the plot is output to *standard error output*.
|
146
|
-
The output file or stream for the plot can be specified with the `-o` option.
|
132
|
+
| Command | Description |
|
133
|
+
|------------------------------------------------|-----------------------------------|
|
134
|
+
| `cat data.tsv \| uplot <command> [options]` | Take input from stdin |
|
135
|
+
| `uplot <command> [options] data.tsv ...` | Take input from files |
|
136
|
+
| `pipeline1 \| uplot <command> -O \| pipeline2` | Outputs data from stdin to stdout |
|
147
137
|
|
148
|
-
###
|
149
|
-
|
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.
|
152
|
-
|
153
|
-
### What types of plots are available?
|
138
|
+
### Subcommands
|
154
139
|
|
155
140
|
The following sub-commands are available.
|
156
141
|
|
@@ -163,67 +148,87 @@ The following sub-commands are available.
|
|
163
148
|
| scatter | s | draw a scatter plot |
|
164
149
|
| density | d | draw a density plot |
|
165
150
|
| boxplot | box | draw a horizontal boxplot |
|
151
|
+
| | | |
|
152
|
+
| count | c | draw a barplot based on the number of occurrences (slow) |
|
153
|
+
| | | |
|
154
|
+
| colors | color | show the list of available colors |
|
166
155
|
|
167
|
-
|
156
|
+
### Output the plot
|
168
157
|
|
169
|
-
|
170
|
-
|
171
|
-
|
158
|
+
* `-o`
|
159
|
+
* By default, the plot is output to **standard error output**.
|
160
|
+
* If you want to output to standard input, Use hyphen ` -o -` or no argument `uplot s -o | `.
|
172
161
|
|
173
|
-
###
|
162
|
+
### Output the input data
|
174
163
|
|
175
|
-
|
164
|
+
* `-O`
|
165
|
+
* By default, the input data is not shown anywhere.
|
166
|
+
* If you want to pass the input data directly to the standard output, Use hyphen `-O -` or no argument `uplot s -O |`.
|
167
|
+
* This is useful when passing data to a subsequent pipeline.
|
176
168
|
|
177
|
-
###
|
169
|
+
### Header
|
178
170
|
|
179
|
-
|
171
|
+
* `-H`
|
172
|
+
* If input data contains a header line, you need to specify the `-H` option.
|
180
173
|
|
181
|
-
###
|
174
|
+
### Delimiter
|
182
175
|
|
183
|
-
|
176
|
+
* `-d`
|
177
|
+
* You do not need to use `-d` option for tab-delimited text since the default value is tab.
|
178
|
+
* To specify a blank space, you can use `uplot bar -d ' ' data.txt`.
|
184
179
|
|
185
|
-
###
|
180
|
+
### Real-time data
|
186
181
|
|
187
|
-
|
182
|
+
* `-p` `--progress`
|
183
|
+
* Experimental progressive mode is currently under development.
|
184
|
+
* `ruby -e 'loop{puts rand(100)}' | uplot line --progress`
|
188
185
|
|
189
|
-
|
190
|
-
ruby -e 'loop{puts rand(100)}' | uplot line --progress
|
191
|
-
```
|
186
|
+
### Show detailed options for subcommands
|
192
187
|
|
193
|
-
|
188
|
+
* `--help`
|
189
|
+
* The `--help` option will show more detailed options for each subcommand.
|
190
|
+
* `uplot hist --help`
|
194
191
|
|
195
|
-
|
192
|
+
### Set columns as x-axis or y-axis
|
196
193
|
|
197
|
-
|
194
|
+
* YouPlot treats the first column as the X axis and the second column as the Y axis. 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.
|
195
|
+
* 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.
|
198
196
|
|
199
|
-
|
200
|
-
|
197
|
+
* `--fmt`
|
198
|
+
* `--fmt xyy` `--fmt xyxy` `--fmt yx` options give you a few more choices. See `youplot <command> --help` for more details.
|
199
|
+
* The fmt option may be renamed in the future.
|
200
|
+
* The `-x` and `-y` options might be used to specify columns in the future.
|
201
201
|
|
202
|
-
|
203
|
-
--symbol VAL character to be used to plot the bars
|
204
|
-
--closed VAL side of the intervals to be closed [left]
|
205
|
-
-n, --nbins VAL approximate number of bins
|
202
|
+
* Use `awk '{print $2, $1}'` to swap columns. Use `paste` to concatenate series.
|
206
203
|
|
207
|
-
|
208
|
-
...
|
209
|
-
```
|
204
|
+
### Categorical data
|
210
205
|
|
211
|
-
|
206
|
+
* With GNU datamash, you can manage to handle categorized data.
|
207
|
+
* `cat test/fixtures/iris.csv | sed '/^$/d' | datamash --header-in --output-delimiter=: -t, -g5 collapse 3,4 | cut -f2-3 -d: | sed 's/:/\n/g' | uplot s -d, -T --fmt xyxy`
|
208
|
+
* This is not so easy...
|
212
209
|
|
213
|
-
|
214
|
-
|
215
|
-
|
210
|
+
### Time series
|
211
|
+
|
212
|
+
* Not yet supported.
|
213
|
+
|
214
|
+
## Tools that are useful to use with YouPlot
|
215
|
+
|
216
|
+
* [csvtk](https://github.com/shenwei356/csvtk)
|
217
|
+
* [GNU datamash](https://www.gnu.org/software/datamash/)
|
218
|
+
* [awk](https://www.gnu.org/software/gawk/)
|
219
|
+
* [xsv](https://github.com/BurntSushi/xsv)
|
216
220
|
|
217
221
|
## Contributing
|
218
222
|
|
219
|
-
YouPlot is a library under development, so even small improvements like typofix are welcome!
|
223
|
+
YouPlot is a library under development, so even small improvements like typofix are welcome!
|
224
|
+
Please feel free to send us your pull requests.
|
220
225
|
|
221
|
-
* [Report bugs](https://github.com/
|
222
|
-
* Fix bugs and [submit pull requests](https://github.com/
|
226
|
+
* [Report bugs](https://github.com/red-data-tools/YouPlot/issues)
|
227
|
+
* Fix bugs and [submit pull requests](https://github.com/red-data-tools/YouPlot/pulls)
|
223
228
|
* Write, clarify, or fix documentation
|
224
229
|
* English corrections by native speakers are welcome.
|
225
230
|
* Suggest or add new features
|
226
|
-
|
231
|
+
* Make a donation
|
227
232
|
|
228
233
|
### Development
|
229
234
|
|
@@ -233,11 +238,11 @@ git clone https://github.com/your_name/YouPlot
|
|
233
238
|
bundle install # Install the gem dependencies
|
234
239
|
bundle exec rake test # Run the test
|
235
240
|
bundle exec rake install # Installation from source code
|
241
|
+
bundle exec exe/uplot # Run youplot (Try out the edited code)
|
236
242
|
```
|
237
243
|
|
238
244
|
### Acknowledgements
|
239
245
|
|
240
|
-
* [Red Data Tools](https://github.com/red-data-tools) - Technical support
|
241
246
|
* [sampo grafiikka](https://jypg.net/sampo_grafiikka) - Project logo creation
|
242
247
|
* [yutaas](https://github.com/yutaas) - English proofreading
|
243
248
|
|
@@ -6,18 +6,30 @@ module YouPlot
|
|
6
6
|
module Processing
|
7
7
|
module_function
|
8
8
|
|
9
|
-
def count_values(arr, tally: true)
|
9
|
+
def count_values(arr, tally: true, reverse: false)
|
10
10
|
# tally was added in Ruby 2.7
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
result = \
|
12
|
+
if tally && Enumerable.method_defined?(:tally)
|
13
|
+
arr.tally
|
14
|
+
else
|
15
|
+
# value_counts Enumerable::Statistics
|
16
|
+
arr.value_counts(dropna: false)
|
17
|
+
end
|
18
|
+
|
19
|
+
# sorting
|
20
|
+
result = result.sort do |a, b|
|
21
|
+
# compare values
|
22
|
+
r = b[1] <=> a[1]
|
23
|
+
# If the values are the same, compare by name
|
24
|
+
r = a[0] <=> b[0] if r.zero?
|
25
|
+
r
|
17
26
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
27
|
+
|
28
|
+
# --reverse option
|
29
|
+
result.reverse! if reverse
|
30
|
+
|
31
|
+
# prepare for barplot
|
32
|
+
result.transpose
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
@@ -1,22 +1,46 @@
|
|
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
|
|
9
|
+
# If the line color is specified as a number, the program will display an error
|
10
|
+
# message to the user and exit. Remove this patch when UnicodePlot is improved.
|
11
|
+
|
12
|
+
module UnicodePlot
|
13
|
+
class << self
|
14
|
+
alias lineplot_original lineplot
|
15
|
+
def lineplot(*args, **kw)
|
16
|
+
if kw[:color].is_a? Numeric
|
17
|
+
warn <<~EOS
|
18
|
+
YouPlot: Line colors cannot be specified by numerical values.
|
19
|
+
|
20
|
+
For more information, please see the following issue.
|
21
|
+
https://github.com/red-data-tools/unicode_plot.rb/issues/34
|
22
|
+
EOS
|
23
|
+
YouPlot.run_as_executable ? exit(1) : raise(Error)
|
24
|
+
end
|
25
|
+
lineplot_original(*args, **kw)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
6
30
|
module YouPlot
|
7
31
|
# plotting functions.
|
8
32
|
module Backends
|
9
|
-
module
|
33
|
+
module UnicodePlot
|
10
34
|
class Error < StandardError; end
|
11
35
|
|
12
36
|
module_function
|
13
37
|
|
14
|
-
def barplot(data, params, fmt = nil, count: false)
|
38
|
+
def barplot(data, params, fmt = nil, count: false, reverse: false)
|
15
39
|
headers = data.headers
|
16
40
|
series = data.series
|
17
41
|
# `uplot count`
|
18
42
|
if count
|
19
|
-
series = Processing.count_values(series[0])
|
43
|
+
series = Processing.count_values(series[0], reverse: reverse)
|
20
44
|
params.title = headers[0] if headers
|
21
45
|
end
|
22
46
|
if series.size == 1
|
@@ -39,7 +63,7 @@ module YouPlot
|
|
39
63
|
labels = series[x_col]
|
40
64
|
values = series[y_col].map(&:to_f)
|
41
65
|
end
|
42
|
-
UnicodePlot.barplot(labels, values, **params.to_hc)
|
66
|
+
::UnicodePlot.barplot(labels, values, **params.to_hc)
|
43
67
|
end
|
44
68
|
|
45
69
|
def histogram(data, params)
|
@@ -47,7 +71,7 @@ module YouPlot
|
|
47
71
|
series = data.series
|
48
72
|
params.title ||= data.headers[0] if headers
|
49
73
|
values = series[0].map(&:to_f)
|
50
|
-
UnicodePlot.histogram(values, **params.to_hc)
|
74
|
+
::UnicodePlot.histogram(values, **params.to_hc)
|
51
75
|
end
|
52
76
|
|
53
77
|
def line(data, params, fmt = nil)
|
@@ -57,7 +81,7 @@ module YouPlot
|
|
57
81
|
# If there is only one series, it is assumed to be sequential data.
|
58
82
|
params.ylabel ||= headers[0] if headers
|
59
83
|
y = series[0].map(&:to_f)
|
60
|
-
UnicodePlot.lineplot(y, **params.to_hc)
|
84
|
+
::UnicodePlot.lineplot(y, **params.to_hc)
|
61
85
|
else
|
62
86
|
# If there are 2 or more series...
|
63
87
|
if fmt == 'yx'
|
@@ -75,7 +99,7 @@ module YouPlot
|
|
75
99
|
end
|
76
100
|
x = series[x_col].map(&:to_f)
|
77
101
|
y = series[y_col].map(&:to_f)
|
78
|
-
UnicodePlot.lineplot(x, y, **params.to_hc)
|
102
|
+
::UnicodePlot.lineplot(x, y, **params.to_hc)
|
79
103
|
end
|
80
104
|
end
|
81
105
|
|
@@ -94,27 +118,26 @@ module YouPlot
|
|
94
118
|
end
|
95
119
|
params.xlim ||= series[0].flatten.minmax # why need?
|
96
120
|
params.ylim ||= series[1..-1].flatten.minmax # why need?
|
97
|
-
plot = UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
|
121
|
+
plot = ::UnicodePlot.public_send(method1, series[0], series[1], **params.to_hc)
|
98
122
|
2.upto(series.size - 1) do |i|
|
99
|
-
UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
|
123
|
+
::UnicodePlot.public_send(method2, plot, series[0], series[i], name: headers&.[](i))
|
100
124
|
end
|
101
125
|
plot
|
102
126
|
end
|
103
127
|
|
104
128
|
def plot_xyxy(data, method1, params)
|
105
129
|
headers = data.headers
|
106
|
-
|
130
|
+
series2 = data.series
|
131
|
+
.map { |s| s.map(&:to_f) }
|
132
|
+
.each_slice(2).to_a
|
107
133
|
method2 = get_method2(method1)
|
108
|
-
series.map! { |s| s.map(&:to_f) }
|
109
|
-
series2 = series.each_slice(2).to_a
|
110
|
-
series = nil
|
111
134
|
params.name ||= headers[0] if headers
|
112
135
|
params.xlim ||= series2.map(&:first).flatten.minmax # why need?
|
113
136
|
params.ylim ||= series2.map(&:last).flatten.minmax # why need?
|
114
137
|
x1, y1 = series2.shift
|
115
|
-
plot = UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
|
138
|
+
plot = ::UnicodePlot.public_send(method1, x1, y1, **params.to_hc)
|
116
139
|
series2.each_with_index do |(xi, yi), i|
|
117
|
-
UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
|
140
|
+
::UnicodePlot.public_send(method2, plot, xi, yi, name: headers&.[]((i + 1) * 2))
|
118
141
|
end
|
119
142
|
plot
|
120
143
|
end
|
@@ -152,13 +175,13 @@ module YouPlot
|
|
152
175
|
series = data.series
|
153
176
|
headers ||= (1..series.size).map(&:to_s)
|
154
177
|
series.map! { |s| s.map(&:to_f) }
|
155
|
-
UnicodePlot.boxplot(headers, series, **params.to_hc)
|
178
|
+
::UnicodePlot.boxplot(headers, series, **params.to_hc)
|
156
179
|
end
|
157
180
|
|
158
181
|
def colors(color_names = false)
|
159
182
|
# FIXME
|
160
183
|
s = String.new
|
161
|
-
UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
|
184
|
+
::UnicodePlot::StyledPrinter::TEXT_COLORS.each do |k, v|
|
162
185
|
s << v
|
163
186
|
s << k.to_s
|
164
187
|
unless color_names
|
@@ -179,7 +202,7 @@ module YouPlot
|
|
179
202
|
series = data.series
|
180
203
|
if series.size == 1
|
181
204
|
warn <<~EOS
|
182
|
-
|
205
|
+
YouPlot: There is only one series of input data. Please check the delimiter.
|
183
206
|
|
184
207
|
Headers: \e[35m#{data.headers.inspect}\e[0m
|
185
208
|
The first item is: \e[35m\"#{series[0][0]}\"\e[0m
|
data/lib/youplot/command.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'dsv'
|
4
|
-
require_relative '
|
4
|
+
require_relative 'parser'
|
5
5
|
|
6
6
|
# FIXME
|
7
|
-
require_relative 'backends/
|
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::
|
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
|
-
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
# progressive mode
|
44
|
+
if options[:progressive]
|
40
45
|
stop = false
|
41
46
|
Signal.trap(:INT) { stop = true }
|
42
|
-
|
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
|
-
|
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,23 +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 =
|
78
|
+
@data = parse_dsv(input)
|
65
79
|
|
80
|
+
# Debug mode, show parsed results
|
66
81
|
pp @data if options[:debug]
|
67
82
|
|
83
|
+
# When run as a program instead of a library
|
68
84
|
if YouPlot.run_as_executable?
|
69
85
|
begin
|
70
86
|
plot = create_plot
|
71
87
|
rescue ArgumentError => e
|
88
|
+
# Show only one line of error.
|
72
89
|
warn e.backtrace[0]
|
90
|
+
# Show error message in purple
|
73
91
|
warn "\e[35m#{e}\e[0m"
|
92
|
+
# Explicitly terminated with exit code: 1
|
74
93
|
exit 1
|
75
94
|
end
|
95
|
+
|
96
|
+
# When running YouPlot as a library (e.g. for testing)
|
76
97
|
else
|
77
98
|
plot = create_plot
|
78
99
|
end
|
100
|
+
|
79
101
|
output_plot(plot)
|
80
102
|
end
|
81
103
|
|
@@ -95,15 +117,28 @@ module YouPlot
|
|
95
117
|
@raw_data << input
|
96
118
|
|
97
119
|
# FIXME
|
98
|
-
@data =
|
120
|
+
@data = parse_dsv(@raw_data)
|
99
121
|
|
100
122
|
plot = create_plot
|
101
123
|
output_plot_progressive(plot)
|
102
124
|
end
|
103
125
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
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
|
107
142
|
end
|
108
143
|
|
109
144
|
def create_plot
|
@@ -111,7 +146,7 @@ module YouPlot
|
|
111
146
|
when :bar, :barplot
|
112
147
|
@backend.barplot(data, params, options[:fmt])
|
113
148
|
when :count, :c
|
114
|
-
@backend.barplot(data, params, count: true)
|
149
|
+
@backend.barplot(data, params, count: true, reverse: options[:reverse])
|
115
150
|
when :hist, :histogram
|
116
151
|
@backend.histogram(data, params)
|
117
152
|
when :line, :lineplot
|
@@ -134,7 +169,7 @@ module YouPlot
|
|
134
169
|
def output_data(input)
|
135
170
|
# Pass the input to subsequent pipelines
|
136
171
|
case options[:pass]
|
137
|
-
when IO
|
172
|
+
when IO, StringIO
|
138
173
|
options[:pass].print(input)
|
139
174
|
else
|
140
175
|
if options[:pass]
|
@@ -147,9 +182,9 @@ module YouPlot
|
|
147
182
|
|
148
183
|
def output_plot(plot)
|
149
184
|
case options[:output]
|
150
|
-
when IO
|
185
|
+
when IO, StringIO
|
151
186
|
plot.render(options[:output])
|
152
|
-
|
187
|
+
when String, Tempfile
|
153
188
|
File.open(options[:output], 'w') do |f|
|
154
189
|
plot.render(f)
|
155
190
|
end
|
@@ -158,7 +193,7 @@ module YouPlot
|
|
158
193
|
|
159
194
|
def output_plot_progressive(plot)
|
160
195
|
case options[:output]
|
161
|
-
when IO
|
196
|
+
when IO, StringIO
|
162
197
|
# RefactorMe
|
163
198
|
out = StringIO.new(String.new)
|
164
199
|
def out.tty?
|