unicode_plot 0.0.4 → 0.0.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.
@@ -58,7 +58,7 @@ module UnicodePlot
58
58
  COLOR_DECODE = COLOR_ENCODE.map {|k, v| [v, k] }.to_h.freeze
59
59
 
60
60
  def print_styled(out, *args, bold: false, color: :normal)
61
- return out.print(*args) unless color?(out)
61
+ return out.print(*args) unless out.color?
62
62
 
63
63
  str = StringIO.open {|sio| sio.print(*args); sio.close; sio.string }
64
64
  color = :nothing if bold && color == :bold
@@ -83,9 +83,5 @@ module UnicodePlot
83
83
  color = COLOR_DECODE[color]
84
84
  print_styled(out, *args, color: color)
85
85
  end
86
-
87
- def color?(out)
88
- out&.tty? || false
89
- end
90
86
  end
91
87
  end
@@ -1,5 +1,5 @@
1
1
  module UnicodePlot
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
 
4
4
  module Version
5
5
  numbers, TAG = VERSION.split("-", 2)
@@ -2,22 +2,28 @@ require 'stringio'
2
2
 
3
3
  module Helper
4
4
  module WithTerm
5
- def with_term(tty=true)
5
+ def with_sio(tty: true)
6
6
  sio = StringIO.new
7
7
  def sio.tty?; true; end if tty
8
8
 
9
- orig_stdout, $stdout = $stdout, sio
10
- orig_env = ENV.to_h.dup
11
- ENV['TERM'] = 'xterm-256color'
12
-
13
- result = yield
9
+ result = yield(sio)
14
10
  sio.close
15
11
 
16
12
  [result, sio.string]
17
- ensure
18
- $stdout.close
19
- $stdout = orig_stdout
20
- ENV.replace(orig_env) if orig_env
13
+ end
14
+
15
+ def with_term(tty=true)
16
+ with_sio(tty: tty) do |sio|
17
+ begin
18
+ orig_stdout, $stdout = $stdout, sio
19
+ orig_env = ENV.to_h.dup
20
+ ENV['TERM'] = 'xterm-256color'
21
+ yield
22
+ ensure
23
+ $stdout = orig_stdout
24
+ ENV.replace(orig_env) if orig_env
25
+ end
26
+ end
21
27
  end
22
28
  end
23
29
  end
data/test/test-barplot.rb CHANGED
@@ -12,6 +12,14 @@ class BarplotTest < Test::Unit::TestCase
12
12
  end
13
13
  end
14
14
 
15
+ sub_test_case("with invalid arguments") do
16
+ test("unknown border type") do
17
+ assert_raise(ArgumentError.new("unknown border type: invalid_border_name")) do
18
+ UnicodePlot.barplot(data: {bar: 23, foo: 37}, border: :invalid_border_name)
19
+ end
20
+ end
21
+ end
22
+
15
23
  test("colored") do
16
24
  data = { bar: 23, foo: 37 }
17
25
  plot = UnicodePlot.barplot(data: data)
data/test/test-boxplot.rb CHANGED
@@ -3,6 +3,14 @@ class BoxplotTest < Test::Unit::TestCase
3
3
  include Helper::WithTerm
4
4
 
5
5
  sub_test_case("UnicodePlot.boxplot") do
6
+ sub_test_case("with invalid arguments") do
7
+ test("unknown border type") do
8
+ assert_raise(ArgumentError.new("unknown border type: invalid_border_name")) do
9
+ UnicodePlot.boxplot([1, 2, 3, 4, 5], border: :invalid_border_name)
10
+ end
11
+ end
12
+ end
13
+
6
14
  sub_test_case("print to tty") do
7
15
  test("without name") do
8
16
  plot = UnicodePlot.boxplot([1, 2, 3, 4, 5])
data/test/test-canvas.rb CHANGED
@@ -6,7 +6,8 @@ module CanvasTestCases
6
6
  ascii: UnicodePlot::AsciiCanvas,
7
7
  braille: UnicodePlot::BrailleCanvas,
8
8
  density: UnicodePlot::DensityCanvas,
9
- dot: UnicodePlot::DotCanvas
9
+ dot: UnicodePlot::DotCanvas,
10
+ block: UnicodePlot::BlockCanvas
10
11
  }.freeze
11
12
 
12
13
  def self.included(mod)
@@ -54,11 +55,11 @@ module CanvasTestCases
54
55
 
55
56
  test("empty") do
56
57
  if self.class::CANVAS_NAME == :braille
57
- _, output = with_term { @canvas.show($stdout) }
58
+ _, output = with_term { @canvas.show(UnicodePlot::IOContext.new($stdout)) }
58
59
  assert_equal(fixture_path("canvas/empty_braille_show.txt").read,
59
60
  output)
60
61
  else
61
- _, output = with_term { @canvas.show($stdout) }
62
+ _, output = with_term { @canvas.show(UnicodePlot::IOContext.new($stdout)) }
62
63
  assert_equal(fixture_path("canvas/empty_show.txt").read,
63
64
  output)
64
65
  end
@@ -80,31 +81,31 @@ module CanvasTestCases
80
81
  end
81
82
 
82
83
  test("print_row") do
83
- _, output = with_term { @canvas.print_row($stdout, 2) }
84
+ _, output = with_term { @canvas.print_row(UnicodePlot::IOContext.new($stdout), 2) }
84
85
  assert_equal(fixture_path("canvas/#{self.class::CANVAS_NAME}_printrow.txt").read,
85
86
  output)
86
87
  end
87
88
 
88
89
  test("print") do
89
- _, output = with_term { @canvas.print($stdout) }
90
+ _, output = with_term { @canvas.print(UnicodePlot::IOContext.new($stdout)) }
90
91
  assert_equal(fixture_path("canvas/#{self.class::CANVAS_NAME}_print.txt").read,
91
92
  output)
92
93
  end
93
94
 
94
95
  test("print_nocolor") do
95
- _, output = with_term(false) { @canvas.print($stdout) }
96
+ _, output = with_term(false) { @canvas.print(UnicodePlot::IOContext.new($stdout)) }
96
97
  assert_equal(fixture_path("canvas/#{self.class::CANVAS_NAME}_print_nocolor.txt").read,
97
98
  output)
98
99
  end
99
100
 
100
101
  test("sow") do
101
- _, output = with_term { @canvas.show($stdout) }
102
+ _, output = with_term { @canvas.show(UnicodePlot::IOContext.new($stdout)) }
102
103
  assert_equal(fixture_path("canvas/#{self.class::CANVAS_NAME}_show.txt").read,
103
104
  output)
104
105
  end
105
106
 
106
107
  test("show_nocolor") do
107
- _, output = with_term(false) { @canvas.show($stdout) }
108
+ _, output = with_term(false) { @canvas.show(UnicodePlot::IOContext.new($stdout)) }
108
109
  assert_equal(fixture_path("canvas/#{self.class::CANVAS_NAME}_show_nocolor.txt").read,
109
110
  output)
110
111
  end
@@ -136,3 +137,9 @@ class DotCanvasTest < Test::Unit::TestCase
136
137
 
137
138
  include CanvasTestCases
138
139
  end
140
+
141
+ class BlockCanvasTest < Test::Unit::TestCase
142
+ CANVAS_NAME = :block
143
+
144
+ include CanvasTestCases
145
+ end
@@ -10,6 +10,14 @@ class DensityplotTest < Test::Unit::TestCase
10
10
  assert_equal(1000, @dy.length)
11
11
  end
12
12
 
13
+ sub_test_case("with invalid arguments") do
14
+ test("unknown border type") do
15
+ assert_raise(ArgumentError.new("unknown border type: invalid_border_name")) do
16
+ UnicodePlot.densityplot(@dx, @dy, border: :invalid_border_name)
17
+ end
18
+ end
19
+ end
20
+
13
21
  test("default") do
14
22
  plot = UnicodePlot.densityplot(@dx, @dy)
15
23
  dx2 = @dx.map {|x| x + 2 }
@@ -7,6 +7,14 @@ class HistogramTest < Test::Unit::TestCase
7
7
  @x = fixture_path("randn.txt").read.lines.map(&:to_f)
8
8
  end
9
9
 
10
+ sub_test_case("with invalid arguments") do
11
+ test("unknown border type") do
12
+ assert_raise(ArgumentError.new("unknown border type: invalid_border_name")) do
13
+ UnicodePlot.histogram(@x, border: :invalid_border_name)
14
+ end
15
+ end
16
+ end
17
+
10
18
  test("default") do
11
19
  plot = UnicodePlot.histogram(@x)
12
20
  _, output = with_term { plot.render($stdout) }
@@ -23,6 +23,14 @@ class LineplotTest < Test::Unit::TestCase
23
23
  assert_raise(ArgumentError) { UnicodePlot.lineplot(1..3, 1..2) }
24
24
  end
25
25
 
26
+ sub_test_case("with invalid arguments") do
27
+ test("unknown border type") do
28
+ assert_raise(ArgumentError.new("unknown border type: invalid_border_name")) do
29
+ UnicodePlot.lineplot(@x, @y, border: :invalid_border_name)
30
+ end
31
+ end
32
+ end
33
+
26
34
  sub_test_case("with numeric array") do
27
35
  test("default") do
28
36
  plot = UnicodePlot.lineplot(@x, @y)
@@ -192,8 +200,84 @@ class LineplotTest < Test::Unit::TestCase
192
200
  output)
193
201
  end
194
202
 
203
+ test("fixed line y-interpolation bug (issue 32)") do
204
+ ys = [261, 272, 277, 283, 289, 294, 298, 305, 309, 314, 319, 320, 322, 323, 324]
205
+ xs = ys.size.times.to_a
206
+ plot = UnicodePlot.lineplot(xs, ys, height: 26, ylim: [0, 700])
207
+ _, output = with_term { plot.render($stdout, newline: false) }
208
+ assert_equal(fixture_path("lineplot/issue32_fix.txt").read,
209
+ output)
210
+ end
211
+
195
212
  # TODO: functions
196
213
 
197
- # TODO: stairs
214
+ sub_test_case("stairs") do
215
+ def setup
216
+ @sx = [1, 2, 4, 7, 8]
217
+ @sy = [1, 3, 4, 2, 7]
218
+ end
219
+
220
+ test("pre") do
221
+ plot = UnicodePlot.stairs(@sx, @sy, style: :pre)
222
+ _, output = with_term { plot.render($stdout, newline: false) }
223
+ assert_equal(fixture_path("lineplot/stairs_pre.txt").read, output)
224
+ end
225
+
226
+ test("post") do
227
+ # inferred post
228
+ plot = UnicodePlot.stairs(@sx, @sy)
229
+ _, output = with_term { plot.render($stdout, newline: false) }
230
+ assert_equal(fixture_path("lineplot/stairs_post.txt").read, output)
231
+ # explicit post
232
+ plot = UnicodePlot.stairs(@sx, @sy, style: :post)
233
+ _, output = with_term { plot.render($stdout, newline: false) }
234
+ assert_equal(fixture_path("lineplot/stairs_post.txt").read, output)
235
+ end
236
+
237
+ test("with parameters") do
238
+ plot = UnicodePlot.stairs(@sx, @sy, title: "Foo", color: :red, xlabel: "x", name: "1")
239
+ sx2 = @sx.map { |val| val - 0.2 }
240
+ sy2 = @sy.map { |val| val + 1.5 }
241
+ plot2 = UnicodePlot.stairs!(plot, sx2, sy2, name: "2")
242
+ assert_equal(plot.class, plot2.class)
243
+ _, output = with_term { plot.render($stdout, newline: false) }
244
+ assert_equal(fixture_path("lineplot/stairs_parameters.txt").read, output)
245
+
246
+ # add a 3rd staircase and check again
247
+ plot3 = UnicodePlot.stairs!(plot, @sx, @sy, name: "3", style: :pre)
248
+ assert_equal(plot.class, plot3.class)
249
+ _, output = with_term { plot.render($stdout, newline: false) }
250
+ assert_equal(fixture_path("lineplot/stairs_parameters2.txt").read, output)
251
+
252
+ # check with color disabled
253
+ output = StringIO.open do |sio|
254
+ plot.render(sio)
255
+ sio.close
256
+ sio.string
257
+ end
258
+ assert_equal("\n", output[-1])
259
+ assert_equal(fixture_path("lineplot/stairs_parameters2_nocolor.txt").read,
260
+ output.chomp)
261
+ end
262
+
263
+ test("special weird case") do
264
+ plot = UnicodePlot.stairs(@sx, [1, 3, 4, 2, 7000])
265
+ _, output = with_term { plot.render($stdout, newline: false) }
266
+ assert_equal(fixture_path("lineplot/stairs_edgecase.txt").read, output)
267
+ end
268
+
269
+ test("annotations") do
270
+ plot = UnicodePlot.stairs(@sx, @sy, width: 10, padding: 3)
271
+ plot.annotate!(:tl, "Hello")
272
+ plot.annotate!(:t, "how are")
273
+ plot.annotate!(:tr, "you?")
274
+ plot.annotate!(:bl, "Hello")
275
+ plot.annotate!(:b, "how are")
276
+ plot.annotate!(:br, "you?")
277
+ UnicodePlot.lineplot!(plot, 1, 0.5)
278
+ _, output = with_term { plot.render($stdout, newline: false) }
279
+ assert_equal(fixture_path("lineplot/squeeze_annotations.txt").read, output)
280
+ end
281
+ end
198
282
  end
199
283
  end
data/test/test-plot.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'stringio'
2
2
 
3
3
  class TestPlot < Test::Unit::TestCase
4
+ include Helper::WithTerm
5
+
4
6
  sub_test_case("#render") do
5
7
  test("render to $stdout when no arguments") do
6
8
  sio = StringIO.new
@@ -16,5 +18,19 @@ class TestPlot < Test::Unit::TestCase
16
18
  $stdout = save_stdout
17
19
  end
18
20
  end
21
+
22
+ test("color: true") do
23
+ _, tty_output = with_sio(tty: true) {|sio| UnicodePlot.barplot(data: {a: 23, b: 37}).render(sio) }
24
+ _, notty_output = with_sio(tty: false) {|sio| UnicodePlot.barplot(data: {a: 23, b: 37}).render(sio, color: true) }
25
+
26
+ assert_equal(tty_output, notty_output)
27
+ end
28
+
29
+ test("color: false") do
30
+ _, tty_output = with_sio(tty: true) {|sio| UnicodePlot.barplot(data: {a: 23, b: 37}).render(sio, color: false) }
31
+ _, notty_output = with_sio(tty: false) {|sio| UnicodePlot.barplot(data: {a: 23, b: 37}).render(sio) }
32
+
33
+ assert_equal(tty_output, notty_output)
34
+ end
19
35
  end
20
36
  end
@@ -22,6 +22,14 @@ class ScatterplotTest < Test::Unit::TestCase
22
22
  end
23
23
  end
24
24
 
25
+ sub_test_case("with invalid arguments") do
26
+ test("unknown border type") do
27
+ assert_raise(ArgumentError.new("unknown border type: invalid_border_name")) do
28
+ UnicodePlot.scatterplot(@x, @y, border: :invalid_border_name)
29
+ end
30
+ end
31
+ end
32
+
25
33
  test("default") do
26
34
  plot = UnicodePlot.scatterplot(@x, @y)
27
35
  _, output = with_term { plot.render($stdout, newline: false) }
@@ -0,0 +1,95 @@
1
+ # coding: utf-8
2
+ class HistogramTest < Test::Unit::TestCase
3
+ include Helper::Fixture
4
+ include Helper::WithTerm
5
+
6
+ sub_test_case("UnicodePlot.stemplot") do
7
+ def setup
8
+ @randoms = fixture_path("randn.txt").read.lines.take(50).map(&:to_f)
9
+
10
+ @int80a = [40, 53, 33, 8, 30, 78, 68, 63, 80, 75, 73, 75, 61, 24, 84, 84, 51, 31, 94, 63, 72, 9, 80, 1, 84, 1, 13, 55, 46, 41, 99, 100, 39, 41, 10, 70, 67, 21, 50, 41, 49, 24, 32, 42, 32, 37, 44, 10, 48, 64, 41, 46, 94, 15, 15, 5, 6, 97, 48, 14, 2, 92, 10, 2, 91, 89, 20, 98, 19, 66, 43, 95, 90, 34, 71, 42, 31, 92, 95, 30]
11
+
12
+ @int80b = [23, 24, 70, 61, 26, 57, 28, 18, 69, 53, 92, 11, 33, 38, 85, 58, 38, 27, 14, 62, 57, 38, 91, 11, 66, 23, 63, 28, 98, 9, 53, 26, 1, 93, 96, 49, 8, 89, 19, 18, 68, 51, 4, 57, 79, 90, 72, 99, 41, 57, 100, 94, 5, 13, 24, 76, 5, 60, 26, 41, 89, 99, 22, 81, 41, 48, 65, 67, 38, 53, 96, 85, 75, 89, 35, 75, 88, 50, 14, 33]
13
+
14
+ @int300 = [-30, -7, 37, -42, -15, 8, 62, 22, -3, -32, -35, -48, -29, 8, -75, 27, 84, 81, -21, 9, 23, 86, -30, 29, 47, 89, -3, 38, 22, 31, 49, 84, -5, -28, -26, -66, 68, 59, -92, -3, -23, 100, -73, 19, -37, 89, -21, 23, 71, 14, -98, 49, -3, -1, -8, 67, -55, -30, -55, 93, 69, -20, -79, -91, -23, -46, 84, -49, -12, 35, -74, -2, -84, -34, -28, 98, -70, -72, 71, 86, 24, 64, -99, -76, -37, 54, 53, 72, -31, -53, 85, 10, -17, -8, -35, -16, -3, 26, 68, -92, 20, -70, 87, -78, 95, -88, -85, -7, 67, -47, -46, 0, -24, -48, 53, -53, -26, 79, -51, -40, -95, -37, 44, 77, -66, 85, 14, 5, -25, -85, -54, -17, -94, -52, -75, -79, 79, -53, -16, -27, -43, -94, -66, -56, -47, -56, -21, 7, 73, -19, 87, -64, -46, -81, 19, -13, -44, -87, -22, 18, 54, -9, 84, 50, 85, 62, 8, 99, -94, -65, 59, 93, 84, 16, 82, -16, 77, 55, -63, -13, -34, -77, 55, 87, -99, -82, 9, 73, 75, -94, -6, 9, 89, 27, 70, 56, -38, -67, -46, 59, 91, -26, 30, -81, -6, -29, -66, 25, 17, -25, -9, -90, 20, -71, 1, -47, -76, 39, -29, -19, -45, 91, -92, -6, -59, 34, 51, -61, -41, -90, 77, 83, -83, -25, -29, -64, 16, -91, -14, 7, -71, -57, -71, 76, -9, -43, -89, 86, 56, 56, 27, 3, -5, 13, -99, 13, -97, -68, 94, -15, 6, -8, -28, -52, 38, -96, -54, 13, -36, 78, -24, 32, 96, -57, -56, -27, -79, -73, -18, 44, -48, -65, -4, 80, -69, -26, -38, 66, 62, 65, -83, -100, -37, 1, -99, 75, 33, 19, 0, -70]
15
+
16
+ @words_1 = %w[apple junk ant age bee bar baz dog egg a]
17
+ @words_2 = %w[ape flan can cat juice elf gnome child fruit]
18
+
19
+ end
20
+
21
+ test("range input") do
22
+ _, output = with_term { UnicodePlot.stemplot(-100..100) }
23
+ assert_equal(fixture_path("stemplot/range.txt").read, output)
24
+ end
25
+
26
+ test("positive integers") do
27
+ _, output = with_term { UnicodePlot.stemplot(@int80a) }
28
+ assert_equal(fixture_path("stemplot/pos_ints.txt").read, output)
29
+ end
30
+
31
+ test("with happy divider") do
32
+ _, output = with_term { UnicodePlot.stemplot(@int80a, divider: "😄") }
33
+ assert_equal(fixture_path("stemplot/ints_divider.txt").read, output)
34
+ end
35
+
36
+ test("positive and negative integers") do
37
+ _, output = with_term { UnicodePlot.stemplot(@int300) }
38
+ assert_equal(fixture_path("stemplot/posneg_ints.txt").read, output)
39
+ end
40
+
41
+ test("floats") do
42
+ x10 = @randoms.map {|a| a * 10 }
43
+ #p x10.sort
44
+ #UnicodePlot.stemplot(x10)
45
+ _, output = with_term { UnicodePlot.stemplot(x10) }
46
+ assert_equal(fixture_path("stemplot/float.txt").read, output)
47
+ end
48
+
49
+
50
+ test("floats, scale=1") do
51
+ floats = (-8..8).to_a.map { |a| a / 2.0 }
52
+ _, output = with_term { UnicodePlot.stemplot(floats, scale: 1) }
53
+ assert_equal(fixture_path("stemplot/float_scale1.txt").read, output)
54
+ end
55
+
56
+
57
+ test("back-to-back stemplot with integers") do
58
+ _, output = with_term { UnicodePlot.stemplot(@int80a, @int80b) }
59
+ assert_equal(fixture_path("stemplot/b2b_integers.txt").read, output)
60
+ end
61
+
62
+ test("stemplot with strings") do
63
+ _, output = with_term { UnicodePlot.stemplot(@words_1) }
64
+ assert_equal(fixture_path("stemplot/strings.txt").read, output)
65
+ end
66
+
67
+ test("back-to-back stemplot with strings") do
68
+ _, output = with_term { UnicodePlot.stemplot(@words_1, @words_2) }
69
+ assert_equal(fixture_path("stemplot/b2b_strings.txt").read, output)
70
+ end
71
+
72
+ test("stemplot with strings, two-char scale") do
73
+ _, output = with_term { UnicodePlot.stemplot(@words_1, scale: 100, trim: true) }
74
+ assert_equal(fixture_path("stemplot/strings_2c.txt").read, output)
75
+ end
76
+
77
+ test("stemplot with strings, two-char scale, string_padchar") do
78
+ _, output = with_term { UnicodePlot.stemplot(@words_1, string_padchar: '?') }
79
+ assert_equal(fixture_path("stemplot/strings_pad.txt").read, output)
80
+ end
81
+
82
+ test("string stemplot cannot take scale less than 10") do
83
+ assert_raise(ArgumentError) do
84
+ UnicodePlot.stemplot(@words_1, scale: 9)
85
+ end
86
+ end
87
+
88
+ test("cannot mix string/number in back to back stemplot") do
89
+ assert_raise(ArgumentError) do
90
+ UnicodePlot.stemplot(@words_1, @int80a)
91
+ end
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,13 @@
1
+ class UnicodePlotTest < Test::Unit::TestCase
2
+ test("UnicodePlot.canvas_types") do
3
+ available_canvas_types = [:ascii, :block, :braille, :density, :dot]
4
+ assert_equal(available_canvas_types.sort,
5
+ UnicodePlot.canvas_types.sort)
6
+ end
7
+
8
+ test("UnicodePlot.border_types") do
9
+ available_border_types = [:solid, :corners, :barplot]
10
+ assert_equal(available_border_types.sort,
11
+ UnicodePlot.border_types.sort)
12
+ end
13
+ end