tb 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
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
data/README CHANGED
@@ -128,48 +128,56 @@ There are more subcommands.
128
128
  % tb help
129
129
  Usage:
130
130
  tb help [OPTS] [SUBCOMMAND]
131
- tb csv [OPTS] [TABLE]
132
- tb tsv [OPTS] [TABLE]
133
- tb json [OPTS] [TABLE]
134
- tb yaml [OPTS] [TABLE]
135
- tb pp [OPTS] [TABLE]
136
- tb grep [OPTS] REGEXP [TABLE]
137
- tb gsub [OPTS] REGEXP STRING [TABLE]
131
+ tb to-csv [OPTS] [TABLE ...]
132
+ tb to-tsv [OPTS] [TABLE]
133
+ tb to-pnm [OPTS] [TABLE]
134
+ tb to-json [OPTS] [TABLE]
135
+ tb to-yaml [OPTS] [TABLE]
136
+ tb to-pp [OPTS] [TABLE]
137
+ tb grep [OPTS] REGEXP [TABLE ...]
138
+ tb gsub [OPTS] REGEXP STRING [TABLE ...]
138
139
  tb sort [OPTS] [TABLE]
139
140
  tb cut [OPTS] FIELD,... [TABLE]
140
141
  tb rename [OPTS] SRC,DST,... [TABLE]
141
142
  tb newfield [OPTS] FIELD RUBY-EXP [TABLE]
142
143
  tb cat [OPTS] [TABLE ...]
143
- tb join [OPTS] [TABLE ...]
144
- tb group [OPTS] KEY-FIELD1,... [TABLE]
145
- tb cross [OPTS] HKEY-FIELD1,... VKEY-FIELD1,... [TABLE]
144
+ tb join [OPTS] [TABLE1 TABLE2 ...]
145
+ tb consecutive [OPTS] [TABLE ...]
146
+ tb group [OPTS] KEY-FIELD1,... [TABLE ...]
147
+ tb cross [OPTS] HKEY-FIELD1,... VKEY-FIELD1,... [TABLE ...]
146
148
  tb shape [OPTS] [TABLE ...]
147
149
  tb mheader [OPTS] [TABLE]
148
- tb crop [OPTS] [TABLE]
150
+ tb crop [OPTS] [TABLE ...]
151
+ tb ls [OPTS] [FILE ...]
152
+ tb svn-log [OPTS] -- [SVN-LOG-ARGS]
149
153
 
150
154
  == Command Line Tool
151
155
 
152
156
  tb command has many subcommands.
153
157
 
154
- help : show help message of tb command.
155
- csv : convert a table to CSV (Comma Separated Value).
156
- tsv : convert a table to TSV (Tab Separated Value).
157
- json : convert a table to JSON (JavaScript Object Notation).
158
- yaml : convert a table to YAML (YAML Ain't a Markup Language).
159
- pp : convert a table to pretty printed format.
160
- grep : search rows using regexp or ruby expression.
161
- gsub : substitute cells.
162
- sort : sort rows.
163
- cut : select columns.
164
- rename : rename field names.
165
- newfield : add a field.
166
- cat : concatenate tables vertically.
167
- join : concatenate tables horizontally as left/right/full natural join.
168
- group : group and aggregate rows.
169
- cross : create a contingency table.
170
- shape : show table size.
171
- mheader : collapse multi rows header.
172
- crop : extract rectangle in a table.
158
+ help : Show help message of tb command.
159
+ to-csv : Convert a table to CSV (Comma Separated Value).
160
+ to-tsv : Convert a table to TSV (Tab Separated Value).
161
+ to-pnm : Convert a table to PNM (Portable Anymap: PPM, PGM, PBM).
162
+ to-json : Convert a table to JSON (JavaScript Object Notation).
163
+ to-yaml : Convert a table to YAML (YAML Ain't a Markup Language).
164
+ to-pp : Convert a table to pretty printed format.
165
+ grep : Search rows using regexp or ruby expression.
166
+ gsub : Substitute cells.
167
+ sort : Sort rows.
168
+ cut : Select columns.
169
+ rename : Rename field names.
170
+ newfield : Add a field.
171
+ cat : Concatenate tables vertically.
172
+ join : Concatenate tables horizontally as left/right/full natural join.
173
+ consecutive : Concatenate consecutive rows.
174
+ group : Group and aggregate rows.
175
+ cross : Create a contingency table.
176
+ shape : Show table size.
177
+ mheader : Collapse multi rows header.
178
+ crop : Extract rectangle in a table.
179
+ ls : List directory entries as a table.
180
+ svn-log : Show the SVN log as a table.
173
181
 
174
182
  == Install
175
183
 
@@ -187,25 +195,29 @@ Tanaka Akira <akr@fsij.org>
187
195
  == License
188
196
 
189
197
  Redistribution and use in source and binary forms, with or without
190
- modification, are permitted provided that the following conditions are met:
191
-
192
- (1) Redistributions of source code must retain the above copyright notice, this
193
- list of conditions and the following disclaimer.
194
- (2) Redistributions in binary form must reproduce the above copyright notice,
195
- this list of conditions and the following disclaimer in the documentation
196
- and/or other materials provided with the distribution.
197
- (3) The name of the author may not be used to endorse or promote products
198
- derived from this software without specific prior written permission.
199
-
200
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
201
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
202
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
203
- EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
204
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
205
- OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
206
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
207
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
208
- IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
209
- OF SUCH DAMAGE.
198
+ modification, are permitted provided that the following conditions
199
+ are met:
200
+
201
+ 1. Redistributions of source code must retain the above copyright
202
+ notice, this list of conditions and the following disclaimer.
203
+ 2. Redistributions in binary form must reproduce the above
204
+ copyright notice, this list of conditions and the following
205
+ disclaimer in the documentation and/or other materials provided
206
+ with the distribution.
207
+ 3. The name of the author may not be used to endorse or promote
208
+ products derived from this software without specific prior
209
+ written permission.
210
+
211
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
212
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
213
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
214
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
215
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
216
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
217
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
218
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
219
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
220
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
221
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
210
222
 
211
223
  (The modified BSD licence)
data/bin/tb CHANGED
@@ -3,26 +3,30 @@
3
3
  # Copyright (C) 2011 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
  require 'tb/cmdtop'
28
32
 
data/lib/tb.rb CHANGED
@@ -1,37 +1,53 @@
1
1
  # lib/tb.rb - entry file for table library
2
2
  #
3
- # Copyright (C) 2010-2011 Tanaka Akira <akr@fsij.org>
3
+ # Copyright (C) 2010-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
 
31
+ require 'tempfile'
32
+
33
+ class Tb
34
+ end
35
+
36
+ require 'pp'
37
+ require 'tb/enum'
38
+ require 'tb/enumerator'
39
+ require 'tb/pairs'
27
40
  require 'tb/basic'
28
41
  require 'tb/record'
29
42
  require 'tb/csv'
30
43
  require 'tb/tsv'
31
44
  require 'tb/pnm'
45
+ require 'tb/json'
32
46
  require 'tb/reader'
33
47
  require 'tb/ropen'
34
48
  require 'tb/catreader'
35
49
  require 'tb/fieldset'
36
50
  require 'tb/search'
37
51
  require 'tb/enumerable'
52
+ require 'tb/fileenumerator'
53
+ require 'tb/revcmp'
data/lib/tb/basic.rb CHANGED
@@ -1,30 +1,32 @@
1
1
  # lib/tb/basic.rb - basic fetures for table library
2
2
  #
3
- # Copyright (C) 2010-2011 Tanaka Akira <akr@fsij.org>
3
+ # Copyright (C) 2010-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.
26
-
27
- require 'pp'
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.
28
30
 
29
31
  # Tb represents a set of records.
30
32
  # A record contains field values accessed by field names.
@@ -53,7 +55,7 @@ require 'pp'
53
55
  # It is an error to access a record by recordid which is not allocated.
54
56
  #
55
57
  class Tb
56
- include Enumerable
58
+ include Tb::Enum
57
59
 
58
60
  # :call-seq:
59
61
  # Tb.new
@@ -142,7 +144,7 @@ class Tb
142
144
 
143
145
  def check_recordid(recordid)
144
146
  recordid = check_recordid_type(recordid)
145
- if !@recordid2index.include?(recordid)
147
+ if !@recordid2index.has_key?(recordid)
146
148
  raise IndexError, "unexpected recordid: #{recordid.inspect}"
147
149
  end
148
150
  recordid
@@ -159,7 +161,7 @@ class Tb
159
161
 
160
162
  def check_field(field)
161
163
  field = check_field_type(field)
162
- unless @tbl.include? field
164
+ unless @tbl.has_key? field
163
165
  raise ArgumentError, "field not defined: #{field.inspect}"
164
166
  end
165
167
  field
@@ -198,7 +200,7 @@ class Tb
198
200
  if field.start_with?("_")
199
201
  raise ArgumentError, "field begins with underscore: #{field.inspect}"
200
202
  end
201
- if @tbl.include? field
203
+ if @tbl.has_key? field
202
204
  raise ArgumentError, "field already defined: #{field.inspect}"
203
205
  end
204
206
  @tbl[field] = []
@@ -347,6 +349,32 @@ class Tb
347
349
  @recordid2index.size
348
350
  end
349
351
 
352
+ # :call-seq:
353
+ # table.empty?
354
+ #
355
+ # returns true if there is no record.
356
+ #
357
+ # t0 = Tb.new %w[fruit]
358
+ # pp t0
359
+ # #=> #<Tb>
360
+ # p t0.empty?
361
+ # #=> true
362
+ #
363
+ # t3 = Tb.new %w[fruit],
364
+ # %w[apple],
365
+ # %w[banana],
366
+ # %w[orange]
367
+ # pp t3
368
+ # #=> #<Tb
369
+ # # {"_recordid"=>0, "fruit"=>"apple"}
370
+ # # {"_recordid"=>1, "fruit"=>"banana"}
371
+ # # {"_recordid"=>2, "fruit"=>"orange"}>
372
+ # p t3.empty?
373
+ # #=> false
374
+ def empty?
375
+ self.size == 0
376
+ end
377
+
350
378
  # :call-seq:
351
379
  # table.allocate_recordid -> fresh_recordid
352
380
  # table.allocate_recordid(recordid) -> recordid
@@ -398,7 +426,7 @@ class Tb
398
426
  @next_recordid += 1
399
427
  else
400
428
  recordid = check_recordid_type(recordid)
401
- if @recordid2index.include? recordid
429
+ if @recordid2index.has_key? recordid
402
430
  raise ArgumentError, "recordid already used: #{recordid.inspect}"
403
431
  end
404
432
  @next_recordid = recordid + 1 if @next_recordid <= recordid
@@ -886,6 +914,17 @@ class Tb
886
914
  }
887
915
  end
888
916
 
917
+ # :call-seq:
918
+ # table.header_and_each(header_proc) {|record| ... }
919
+ #
920
+ # +header_and_each+ calls _header_proc_ at first.
921
+ # The block is called for each record after that.
922
+ #
923
+ def header_and_each(header_proc, &block)
924
+ header_proc.call(list_fields) if header_proc
925
+ self.each(&block)
926
+ end
927
+
889
928
  # :call-seq:
890
929
  # table.filter {|record| ... }
891
930
  def filter
@@ -898,73 +937,33 @@ class Tb
898
937
  t
899
938
  end
900
939
 
901
- # :call-seq:
902
- # table1.natjoin2(table2)
903
- def natjoin2(table2)
904
- table1 = self
905
- fields1 = table1.list_fields
906
- fields2 = table2.list_fields
907
- common_fields = fields1 & fields2
908
- total_fields = fields1 | fields2
909
- unique_fields2 = fields2 - common_fields
910
- h = {}
911
- table2.each {|rec2|
912
- k = rec2.values_at(*common_fields)
913
- (h[k] ||= []) << rec2
940
+ def natjoin2(table2, missing=nil, retain_left=false, retain_right=false)
941
+ t1 = Tb::Enumerator.new {|y|
942
+ self.with_header {|h0|
943
+ y.set_header h0
944
+ }.each {|record|
945
+ y.yield record.to_h
946
+ }
914
947
  }
915
- result = Tb.new(fields1 | fields2)
916
- table1.each {|rec1|
917
- k = rec1.values_at(*common_fields)
918
- rec2_list = h[k]
919
- next if !rec2_list
920
- values = rec1.values_at(*fields1)
921
- rec2_list.each {|rec2|
922
- result.insert_values total_fields, values + rec2.values_at(*unique_fields2)
948
+ t2 = Tb::Enumerator.new {|y|
949
+ table2.with_header {|h0|
950
+ y.set_header h0
951
+ }.each {|record|
952
+ y.yield record.to_h
923
953
  }
924
954
  }
955
+ er = t1.natjoin2(t2, missing, retain_left, retain_right)
956
+ result = nil
957
+ er.with_header {|header|
958
+ result = Tb.new header
959
+ }.each {|pairs|
960
+ result.insert pairs
961
+ }
925
962
  result
926
963
  end
927
964
 
928
- # :call-seq:
929
- # table1.natjoin2_outer(table2, missing=nil, retain_left=true, retain_right=true)
930
965
  def natjoin2_outer(table2, missing=nil, retain_left=true, retain_right=true)
931
- table1 = self
932
- fields1 = table1.list_fields
933
- fields2 = table2.list_fields
934
- common_fields = fields1 & fields2
935
- total_fields = fields1 | fields2
936
- unique_fields2 = fields2 - common_fields
937
- fields2_extended = total_fields.map {|f| fields2.include?(f) ? f : nil }
938
- h = {}
939
- table2.each {|rec2|
940
- k = rec2.values_at(*common_fields)
941
- (h[k] ||= []) << rec2
942
- }
943
- result = Tb.new(total_fields)
944
- ids2 = {}
945
- table1.each {|rec1|
946
- k = rec1.values_at(*common_fields)
947
- rec2_list = h[k]
948
- values = rec1.values_at(*fields1)
949
- if !rec2_list || rec2_list.empty?
950
- if retain_left
951
- result.insert_values total_fields, values + unique_fields2.map { missing }
952
- end
953
- else
954
- rec2_list.each {|rec2|
955
- ids2[rec2['_recordid']] = true
956
- result.insert_values total_fields, values + rec2.values_at(*unique_fields2)
957
- }
958
- end
959
- }
960
- if retain_right
961
- table2.each {|rec2|
962
- if !ids2[rec2['_recordid']]
963
- result.insert_values total_fields, fields2_extended.map {|f| f ? rec2[f] : missing }
964
- end
965
- }
966
- end
967
- result
966
+ natjoin2(table2, missing, retain_left, retain_right)
968
967
  end
969
968
 
970
969
  # :call-seq: