tb 0.2 → 0.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.
Files changed (95) hide show
  1. data/README +62 -50
  2. data/bin/tb +22 -18
  3. data/lib/tb.rb +35 -19
  4. data/lib/tb/basic.rb +85 -86
  5. data/lib/tb/catreader.rb +33 -116
  6. data/lib/tb/cmd_cat.rb +31 -27
  7. data/lib/tb/cmd_consecutive.rb +45 -35
  8. data/lib/tb/cmd_crop.rb +86 -52
  9. data/lib/tb/cmd_cross.rb +113 -71
  10. data/lib/tb/cmd_cut.rb +49 -44
  11. data/lib/tb/cmd_git_log.rb +193 -0
  12. data/lib/tb/cmd_grep.rb +43 -32
  13. data/lib/tb/cmd_group.rb +63 -39
  14. data/lib/tb/cmd_gsub.rb +53 -43
  15. data/lib/tb/cmd_help.rb +51 -24
  16. data/lib/tb/cmd_join.rb +32 -35
  17. data/lib/tb/cmd_ls.rb +233 -205
  18. data/lib/tb/cmd_mheader.rb +47 -37
  19. data/lib/tb/cmd_nest.rb +94 -0
  20. data/lib/tb/cmd_newfield.rb +29 -33
  21. data/lib/tb/cmd_rename.rb +40 -32
  22. data/lib/tb/cmd_shape.rb +31 -24
  23. data/lib/tb/cmd_sort.rb +46 -25
  24. data/lib/tb/cmd_svn_log.rb +47 -28
  25. data/lib/tb/cmd_tar_tvf.rb +447 -0
  26. data/lib/tb/cmd_to_csv.rb +60 -0
  27. data/lib/tb/cmd_to_json.rb +60 -0
  28. data/lib/tb/cmd_to_pnm.rb +48 -0
  29. data/lib/tb/cmd_to_pp.rb +71 -0
  30. data/lib/tb/cmd_to_tsv.rb +48 -0
  31. data/lib/tb/cmd_to_yaml.rb +52 -0
  32. data/lib/tb/cmd_unnest.rb +118 -0
  33. data/lib/tb/cmdmain.rb +24 -20
  34. data/lib/tb/cmdtop.rb +33 -25
  35. data/lib/tb/cmdutil.rb +26 -66
  36. data/lib/tb/csv.rb +46 -34
  37. data/lib/tb/enum.rb +294 -0
  38. data/lib/tb/enumerable.rb +198 -7
  39. data/lib/tb/enumerator.rb +73 -0
  40. data/lib/tb/fieldset.rb +27 -19
  41. data/lib/tb/fileenumerator.rb +365 -0
  42. data/lib/tb/json.rb +50 -0
  43. data/lib/tb/pager.rb +6 -6
  44. data/lib/tb/pairs.rb +227 -0
  45. data/lib/tb/pnm.rb +23 -22
  46. data/lib/tb/reader.rb +52 -49
  47. data/lib/tb/record.rb +48 -19
  48. data/lib/tb/revcmp.rb +38 -0
  49. data/lib/tb/ropen.rb +74 -57
  50. data/lib/tb/search.rb +25 -21
  51. data/lib/tb/tsv.rb +31 -34
  52. data/sample/excel2csv +24 -20
  53. data/sample/poi-xls2csv.rb +24 -20
  54. data/sample/poi-xls2csv.sh +22 -18
  55. data/sample/tbplot +185 -127
  56. data/test-all-cov.rb +3 -3
  57. data/test-all.rb +1 -1
  58. data/test/test_basic.rb +26 -10
  59. data/test/test_catreader.rb +7 -6
  60. data/test/test_cmd_cat.rb +32 -0
  61. data/test/test_cmd_consecutive.rb +10 -0
  62. data/test/test_cmd_crop.rb +4 -4
  63. data/test/test_cmd_cross.rb +16 -4
  64. data/test/test_cmd_git_log.rb +46 -0
  65. data/test/test_cmd_help.rb +17 -12
  66. data/test/test_cmd_join.rb +21 -1
  67. data/test/test_cmd_ls.rb +3 -4
  68. data/test/test_cmd_mheader.rb +17 -11
  69. data/test/test_cmd_nest.rb +49 -0
  70. data/test/test_cmd_sort.rb +15 -0
  71. data/test/test_cmd_tar_tvf.rb +281 -0
  72. data/test/{test_cmd_csv.rb → test_cmd_to_csv.rb} +35 -21
  73. data/test/{test_cmd_json.rb → test_cmd_to_json.rb} +31 -3
  74. data/test/{test_cmd_pnm.rb → test_cmd_to_pnm.rb} +2 -2
  75. data/test/{test_cmd_pp.rb → test_cmd_to_pp.rb} +4 -4
  76. data/test/{test_cmd_tsv.rb → test_cmd_to_tsv.rb} +4 -4
  77. data/test/{test_cmd_yaml.rb → test_cmd_to_yaml.rb} +3 -3
  78. data/test/test_cmd_unnest.rb +89 -0
  79. data/test/test_cmdtty.rb +19 -13
  80. data/test/test_enumerable.rb +83 -1
  81. data/test/test_fileenumerator.rb +265 -0
  82. data/test/test_json.rb +15 -0
  83. data/test/test_pager.rb +3 -4
  84. data/test/test_pairs.rb +122 -0
  85. data/test/test_pnm.rb +24 -24
  86. data/test/test_reader.rb +35 -13
  87. data/test/test_revcmp.rb +10 -0
  88. data/test/test_tbenum.rb +173 -0
  89. metadata +51 -23
  90. data/lib/tb/cmd_csv.rb +0 -42
  91. data/lib/tb/cmd_json.rb +0 -60
  92. data/lib/tb/cmd_pnm.rb +0 -43
  93. data/lib/tb/cmd_pp.rb +0 -70
  94. data/lib/tb/cmd_tsv.rb +0 -43
  95. data/lib/tb/cmd_yaml.rb +0 -47
@@ -2,29 +2,33 @@
2
2
 
3
3
  # sample/poi-xls2csv.rb - XLS to CSV convert using Apache POI with JRuby.
4
4
  #
5
- # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
5
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
6
6
  #
7
7
  # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
9
10
  #
10
- # 1. Redistributions of source code must retain the above copyright notice, this
11
- # list of conditions and the following disclaimer.
12
- # 2. Redistributions in binary form must reproduce the above copyright notice,
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # 3. The name of the author may not be used to endorse or promote products
16
- # derived from this software without specific prior written permission.
11
+ # 1. Redistributions of source code must retain the above copyright
12
+ # notice, this list of conditions and the following disclaimer.
13
+ # 2. Redistributions in binary form must reproduce the above
14
+ # copyright notice, this list of conditions and the following
15
+ # disclaimer in the documentation and/or other materials provided
16
+ # with the distribution.
17
+ # 3. The name of the author may not be used to endorse or promote
18
+ # products derived from this software without specific prior
19
+ # written permission.
17
20
  #
18
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
23
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27
- # OF SUCH DAMAGE.
21
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
32
 
29
33
  $KCODE = 'u'
30
34
 
@@ -382,7 +386,7 @@ def convert_book(filename, input, csvgen)
382
386
  end
383
387
  end
384
388
 
385
- Tb.csv_stream_output(STDOUT) {|csvgen|
389
+ Tb.csv_stream_output($stdout) {|csvgen|
386
390
  argv = ARGV.empty? ? ['-'] : ARGV
387
391
  argv.each {|filename|
388
392
  if filename == '-'
@@ -5,26 +5,30 @@
5
5
  # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
6
6
  #
7
7
  # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
8
+ # modification, are permitted provided that the following conditions
9
+ # are met:
9
10
  #
10
- # 1. Redistributions of source code must retain the above copyright notice, this
11
- # list of conditions and the following disclaimer.
12
- # 2. Redistributions in binary form must reproduce the above copyright notice,
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # 3. The name of the author may not be used to endorse or promote products
16
- # derived from this software without specific prior written permission.
11
+ # 1. Redistributions of source code must retain the above copyright
12
+ # notice, this list of conditions and the following disclaimer.
13
+ # 2. Redistributions in binary form must reproduce the above
14
+ # copyright notice, this list of conditions and the following
15
+ # disclaimer in the documentation and/or other materials provided
16
+ # with the distribution.
17
+ # 3. The name of the author may not be used to endorse or promote
18
+ # products derived from this software without specific prior
19
+ # written permission.
17
20
  #
18
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
23
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27
- # OF SUCH DAMAGE.
21
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
32
 
29
33
  # Ubuntu libjakarta-poi-java package installs /usr/share/java/jakarta-poi.jar.
30
34
 
data/sample/tbplot CHANGED
@@ -1,45 +1,41 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
- # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
3
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
6
- # modification, are permitted provided that the following conditions are met:
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
7
8
  #
8
- # 1. Redistributions of source code must retain the above copyright notice, this
9
- # list of conditions and the following disclaimer.
10
- # 2. Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- # 3. The name of the author may not be used to endorse or promote products
14
- # derived from this software without specific prior written permission.
9
+ # 1. Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # 2. Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following
13
+ # disclaimer in the documentation and/or other materials provided
14
+ # with the distribution.
15
+ # 3. The name of the author may not be used to endorse or promote
16
+ # products derived from this software without specific prior
17
+ # written permission.
15
18
  #
16
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25
- # OF SUCH DAMAGE.
19
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
30
 
27
31
  # plot a graph using gnuplot.
28
32
 
29
33
  # usage:
30
- # tbplot [-x field] [-y field] [--shape field] [--color field] [--size field] [--facet-x field] [--facet-y field] filename
34
+ # tbplot [-x field,...] [-y field,...] [--shape field] [--color field] [--size field] [--facet-x field] [--facet-y field] filename
31
35
 
32
36
  $:.unshift '/home/akr/ruby/tb/lib'
33
37
 
34
- require 'optparse'
35
- require 'tempfile'
36
- require 'time'
37
- require 'tb'
38
-
39
- def err(msg)
40
- STDERR.puts msg
41
- exit false
42
- end
38
+ require 'tb/cmdtop'
43
39
 
44
40
  def gnuplot_escape_string(string)
45
41
  string = string.dup.force_encoding("ascii-8bit") if string.respond_to? :force_encoding
@@ -123,6 +119,24 @@ class ValueChecker
123
119
  end
124
120
  end
125
121
 
122
+ class AxisScale
123
+ # create an AxisScale object.
124
+ #
125
+ # AxisScale.new("fieldname")
126
+ # AxisScale.new("logscale(fieldname)")
127
+ def initialize(desc)
128
+ @desc = desc
129
+ if /\Alogscale\((.*)\)\z/ =~ desc
130
+ @field = $1
131
+ @logscale = true
132
+ else
133
+ @field = desc
134
+ @logscale = false
135
+ end
136
+ end
137
+ attr_reader :desc, :field, :logscale
138
+ end
139
+
126
140
  $x_field = nil
127
141
  $y_field = nil
128
142
  $shape_field = nil
@@ -132,117 +146,150 @@ $facet_x_field = nil
132
146
  $facet_y_field = nil
133
147
  $max_size = nil
134
148
 
135
- op = OptionParser.new
136
- op.def_option('-x FIELD', 'x-field') {|f| $x_field = f }
137
- op.def_option('-y FIELD', 'y-field') {|f| $y_field = f }
138
- op.def_option('--shape=FIELD', 'shape-field') {|f| $shape_field = f }
139
- op.def_option('--color=FIELD', 'color-field') {|f| $color_field = f }
140
- op.def_option('--size=FIELD', 'size-field') {|f| $size_field = f }
141
- op.def_option('--facet-x=FIELD', 'facet-x-field') {|f| $facet_x_field = f }
142
- op.def_option('--facet-y=FIELD', 'facet-y-field') {|f| $facet_y_field = f }
143
- op.def_option('--shapecolor=FIELD', 'shape-field and color-field') {|f| $shape_field = $color_field = f }
144
- op.def_option('--max-size=MAX-SIZE', 'maximum point size') {|v| $max_size = v.to_f }
149
+ def main_body(argv)
150
+ op = OptionParser.new
151
+ op.def_option('-x FIELD,...', 'x-fields') {|f| $x_field = split_field_list_argument(f).map {|ff| AxisScale.new(ff) } }
152
+ op.def_option('-y FIELD,...', 'y-fields') {|f| $y_field = split_field_list_argument(f).map {|ff| AxisScale.new(ff) } }
153
+ op.def_option('--shape=FIELD', 'shape-field') {|f| $shape_field = f }
154
+ op.def_option('--color=FIELD', 'color-field') {|f| $color_field = f }
155
+ op.def_option('--size=FIELD', 'size-field') {|f| $size_field = f }
156
+ op.def_option('--facet-x=FIELD', 'facet-x-field') {|f| $facet_x_field = f }
157
+ op.def_option('--facet-y=FIELD', 'facet-y-field') {|f| $facet_y_field = f }
158
+ op.def_option('--shapecolor=FIELD', 'shape-field and color-field') {|f| $shape_field = $color_field = f }
159
+ op.def_option('--max-size=MAX-SIZE', 'maximum point size') {|v| $max_size = v.to_f }
145
160
 
146
- op.parse!(ARGV)
161
+ op.parse!(argv)
147
162
 
148
- if !$max_size
149
- if $size_field
150
- $max_size = 100.0
151
- else
152
- $max_size = 1.0
163
+ if !$max_size
164
+ if $size_field
165
+ $max_size = 100.0
166
+ else
167
+ $max_size = 1.0
168
+ end
153
169
  end
154
- end
155
170
 
156
- tmps = {}
171
+ tmps = {}
172
+
173
+ argv = ARGV.empty? ? ['-'] : ARGV
174
+ r = Tb::CatReader.open(argv)
157
175
 
158
- argv = ARGV.empty? ? ['-'] : ARGV
159
- Tb::CatReader.open(argv) {|r|
160
- header0 = r.header
161
- header = header0.dup
162
- [$x_field, $y_field, $shape_field, $color_field, $size_field, $facet_x_field, $facet_y_field].each {|f|
163
- if f && !header.include?(f)
164
- err("field not found: #{f.inspect}")
165
- end
166
- }
167
- header -= [$x_field, $y_field, $shape_field, $color_field, $size_field, $facet_x_field, $facet_y_field].compact
168
- if !$x_field
169
- if header.empty?
170
- err("x-field not found")
171
- end
172
- $x_field = header.shift
173
- end
174
- if !$y_field
175
- if header.empty?
176
- err("y-field not found")
177
- end
178
- $y_field = header.shift
179
- end
180
176
  checkers = {}
181
- uniq_fields = [$x_field, $y_field, $shape_field, $color_field, $size_field, $facet_x_field, $facet_y_field].compact.uniq
182
- r.each {|ary|
183
- next if uniq_fields.any? {|f| ary[r.index_from_field(f)].nil? }
184
- vs = {}
185
- uniq_fields.each {|f|
186
- v = ary[r.index_from_field(f)]
187
- checkers[f] ||= ValueChecker.new
188
- vs[f] = checkers[f].check(v)
177
+ uniq_fields = nil
178
+ r.with_header {|header0|
179
+ header = header0.dup
180
+ fields = [$shape_field, $color_field, $size_field, $facet_x_field, $facet_y_field]
181
+ fields.concat $x_field.map {|as| as.field } if $x_field
182
+ fields.concat $y_field.map {|as| as.field } if $y_field
183
+ fields.each {|f|
184
+ if f && !header.include?(f)
185
+ err("field not found: #{f.inspect}")
186
+ end
189
187
  }
190
- x = vs[$x_field]
191
- y = vs[$y_field]
192
-
193
- shape_value = color_value = nil
194
- size = 1
195
- facet_x_field = facet_y_field = nil
196
- if $shape_field
197
- shape = vs[$shape_field]
198
- end
199
- if $color_field
200
- color = vs[$color_field]
201
- end
202
- if $size_field
203
- size = vs[$size_field]
204
- end
205
- if $facet_x_field
206
- facet_x = vs[$facet_x_field]
188
+ header -= fields.compact
189
+ if !$x_field
190
+ if header.empty?
191
+ err("x-field not found")
192
+ end
193
+ $x_field = [AxisScale.new(header.shift)]
207
194
  end
208
- if $facet_y_field
209
- facet_y = vs[$facet_y_field]
195
+ if !$y_field
196
+ if header.empty?
197
+ err("y-field not found")
198
+ end
199
+ $y_field = [AxisScale.new(header.shift)]
210
200
  end
211
- key1 = [facet_x, facet_y]
212
- key2 = [shape, color]
213
- tmps[key1] ||= {}
214
- tmps[key1][key2] ||= Tempfile.new('tbplot')
215
- tmps[key1][key2].puts "#{x} #{y} #{size}"
201
+ uniq_fields = [$shape_field, $color_field, $size_field, $facet_x_field, $facet_y_field].compact.uniq
202
+ }.each {|pairs|
203
+ $x_field.each {|x_scale|
204
+ x_field = x_scale.field
205
+ $y_field.each {|y_scale|
206
+ y_field = y_scale.field
207
+ next if uniq_fields.any? {|f| pairs[f].nil? }
208
+ next if pairs[x_field].nil?
209
+ vs = {}
210
+ checkers[x_field] ||= ValueChecker.new
211
+ vs[x_field] = checkers[x_field].check(pairs[x_field])
212
+ checkers[y_field] ||= ValueChecker.new
213
+ vs[y_field] = checkers[y_field].check(pairs[y_field])
214
+ uniq_fields.each {|f|
215
+ checkers[f] ||= ValueChecker.new
216
+ vs[f] = checkers[f].check(pairs[f])
217
+ }
218
+ x = vs[x_field]
219
+ y = vs[y_field]
220
+
221
+ size = 1
222
+ if $shape_field
223
+ shape = vs[$shape_field]
224
+ end
225
+ if $color_field
226
+ color = vs[$color_field]
227
+ end
228
+ if $size_field
229
+ size = vs[$size_field]
230
+ end
231
+ if $facet_x_field
232
+ facet_x = vs[$facet_x_field]
233
+ end
234
+ if $facet_y_field
235
+ facet_y = vs[$facet_y_field]
236
+ end
237
+ key1 = [facet_x, facet_y, x_scale, y_scale]
238
+ key2 = [shape, color]
239
+ tmps[key1] ||= {}
240
+ tmps[key1][key2] ||= Tempfile.new('tbplot')
241
+ tmps[key1][key2].puts "#{x} #{y} #{size}"
242
+ }
243
+ }
216
244
  }
245
+
217
246
  tmps.each {|k1, h| h.each {|k2, v| v.close } }
218
247
  gnuplot_command = ''
219
- if 0 < checkers[$x_field].time || 0 < checkers[$y_field].time
220
- gnuplot_command << 'set timefmt "%Y-%m-%dT%H:%M:%SZ"' << "\n"
221
- end
222
- if 0 < checkers[$x_field].time
223
- gnuplot_command << "set xdata time\n"
224
- gnuplot_command << "set format x #{gnuplot_escape_string(checkers[$x_field].tic_format)}\n"
225
- end
226
- if 0 < checkers[$y_field].time
227
- gnuplot_command << "set ydata time\n"
228
- gnuplot_command << "set format y #{gnuplot_escape_string(checkers[$y_field].tic_format)}\n"
229
- end
230
- gnuplot_command << "set xlabel #{gnuplot_escape_string($x_field)}\n"
231
- gnuplot_command << "set ylabel #{gnuplot_escape_string($y_field)}\n"
232
- if $size_field
233
- pointsize = $max_size / checkers[$size_field].numeric_max
234
- gnuplot_command << "set pointsize #{pointsize}\n"
235
- end
236
- if $facet_x_field || $facet_y_field
237
- xsize = $facet_x_field ? 1.0 / checkers[$facet_x_field].values.size : 1.0
238
- ysize = $facet_y_field ? 1.0 / checkers[$facet_y_field].values.size : 1.0
248
+ gnuplot_command << 'set timefmt "%Y-%m-%dT%H:%M:%SZ"' << "\n"
249
+ use_multiplot = false
250
+ if $facet_x_field || $facet_y_field || 1 < $x_field.length || 1 < $y_field.length
251
+ use_multiplot = true
252
+ x_numgraph = ($facet_x_field ? checkers[$facet_x_field].values.size : 1) * $x_field.length
253
+ y_numgraph = ($facet_y_field ? checkers[$facet_y_field].values.size : 1) * $y_field.length
254
+ xsize = 1.0 / x_numgraph
255
+ ysize = 1.0 / y_numgraph
239
256
  gnuplot_command << "set multiplot\n"
240
257
  gnuplot_command << "set size #{xsize},#{ysize}\n"
241
258
  end
242
- tmps.each {|(facet_x, facet_y), h|
243
- if $facet_x_field || $facet_y_field
244
- xorigin = $facet_x_field ? (checkers[$facet_x_field].categorical_index(facet_x)-1.0)/checkers[$facet_x_field].values.size : 0
245
- yorigin = $facet_y_field ? 1.0-(checkers[$facet_y_field].categorical_index(facet_y)-0.0)/checkers[$facet_y_field].values.size : 0
259
+
260
+ tmps.each {|(facet_x, facet_y, x_scale, y_scale), h|
261
+ x_field = x_scale.field
262
+ y_field = y_scale.field
263
+ gnuplot_command << (x_scale.logscale ? "set" : "unset") << " logscale x\n"
264
+ gnuplot_command << (y_scale.logscale ? "set" : "unset") << " logscale y\n"
265
+ if 0 < checkers[x_field].time
266
+ gnuplot_command << "set xdata time\n"
267
+ gnuplot_command << "set format x #{gnuplot_escape_string(checkers[x_field].tic_format)}\n"
268
+ end
269
+ if 0 < checkers[y_field].time
270
+ gnuplot_command << "set ydata time\n"
271
+ gnuplot_command << "set format y #{gnuplot_escape_string(checkers[y_field].tic_format)}\n"
272
+ end
273
+ gnuplot_command << "set xlabel #{gnuplot_escape_string(x_field)}\n"
274
+ gnuplot_command << "set ylabel #{gnuplot_escape_string(y_field)}\n"
275
+ if $size_field
276
+ pointsize = $max_size / checkers[$size_field].numeric_max
277
+ gnuplot_command << "set pointsize #{pointsize}\n"
278
+ end
279
+
280
+ if use_multiplot
281
+ x_graphindex = 0.0
282
+ if $facet_x_field
283
+ x_graphindex += (checkers[$facet_x_field].categorical_index(facet_x)-1) * $x_field.length
284
+ end
285
+ x_graphindex += $x_field.index(x_scale)
286
+ xorigin = x_graphindex / x_numgraph
287
+ y_graphindex = 0.0
288
+ if $facet_y_field
289
+ y_graphindex += (checkers[$facet_y_field].categorical_index(facet_y)-1) * $y_field.length
290
+ end
291
+ y_graphindex += $y_field.index(y_scale)
292
+ yorigin = (y_numgraph - y_graphindex - 1) / y_numgraph
246
293
  gnuplot_command << "set origin #{xorigin},#{yorigin}\n"
247
294
  end
248
295
  gnuplot_command << 'plot '
@@ -282,12 +329,23 @@ Tb::CatReader.open(argv) {|r|
282
329
  }
283
330
  gnuplot_command << "\n"
284
331
  }
285
- if $facet_x_field || $facet_y_field
332
+ if use_multiplot
286
333
  gnuplot_command << "unset multiplot\n"
287
334
  end
288
335
  gnuplot_command << "pause mouse any\n"
289
336
  tmp_gnuplot_command = Tempfile.new(['tbplot', '.gp'])
290
337
  tmp_gnuplot_command << gnuplot_command
291
338
  tmp_gnuplot_command.close
339
+ #puts gnuplot_command; sleep 100
292
340
  system('gnuplot', tmp_gnuplot_command.path)
293
- }
341
+ end
342
+
343
+
344
+ def main(argv)
345
+ main_body(argv)
346
+ rescue SystemExit
347
+ $stderr.puts $!.message if $!.message != 'exit'
348
+ raise
349
+ end
350
+
351
+ main(ARGV)