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
@@ -1,26 +1,30 @@
1
- # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
1
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
- # modification, are permitted provided that the following conditions are met:
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
5
6
  #
6
- # 1. Redistributions of source code must retain the above copyright notice, this
7
- # list of conditions and the following disclaimer.
8
- # 2. Redistributions in binary form must reproduce the above copyright notice,
9
- # this list of conditions and the following disclaimer in the documentation
10
- # and/or other materials provided with the distribution.
11
- # 3. The name of the author may not be used to endorse or promote products
12
- # derived from this software without specific prior written permission.
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above
10
+ # copyright notice, this list of conditions and the following
11
+ # disclaimer in the documentation and/or other materials provided
12
+ # with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote
14
+ # products derived from this software without specific prior
15
+ # written permission.
13
16
  #
14
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
19
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
23
- # OF SUCH DAMAGE.
17
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
28
 
25
29
  Tb::Cmd.subcommands << 'mheader'
26
30
 
@@ -28,7 +32,8 @@ Tb::Cmd.default_option[:opt_mheader_count] = nil
28
32
 
29
33
  def (Tb::Cmd).op_mheader
30
34
  op = OptionParser.new
31
- op.banner = 'Usage: tb mheader [OPTS] [TABLE]'
35
+ op.banner = "Usage: tb mheader [OPTS] [TABLE]\n" +
36
+ "Collapse multi rows header."
32
37
  define_common_option(op, "ho", "--no-pager")
33
38
  op.def_option('-c N', 'number of header records') {|arg| Tb::Cmd.opt_mheader_count = arg.to_i }
34
39
  op
@@ -51,27 +56,32 @@ def (Tb::Cmd).main_mheader(argv)
51
56
  header.length == h2.length ? h2 : nil
52
57
  }
53
58
  end
54
- with_table_stream_output {|gen|
55
- Tb::CatReader.open(argv, true) {|tblreader|
56
- tblreader.each {|ary|
57
- if header
58
- ary.each_with_index {|v,i|
59
- header[i] ||= []
60
- header[i] << v if header[i].empty? || header[i].last != v
61
- }
62
- h2 = header_end_p.call
63
- if h2
64
- gen << h2
65
- header = nil
66
- end
67
- else
68
- gen << ary
59
+ creader = Tb::CatReader.open(argv, true)
60
+ er = Tb::Enumerator.new {|y|
61
+ creader.each {|pairs|
62
+ if header
63
+ ary = []
64
+ pairs.each {|f, v| ary[f.to_i-1] = v }
65
+ ary.each_with_index {|v,i|
66
+ header[i] ||= []
67
+ header[i] << v if header[i].empty? || header[i].last != v
68
+ }
69
+ h2 = header_end_p.call
70
+ if h2
71
+ pairs2 = Tb::Pairs.new(h2.map.with_index {|v, i| ["#{i+1}", v] })
72
+ y.yield pairs2
73
+ header = nil
69
74
  end
70
- }
75
+ else
76
+ y.yield pairs
77
+ end
71
78
  }
72
79
  }
80
+ with_output {|out|
81
+ er.write_to_csv(out, false)
82
+ }
73
83
  if header
74
- warn "no header found."
84
+ warn "unique header fields not recognized."
75
85
  end
76
86
  end
77
87
 
@@ -0,0 +1,94 @@
1
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
2
+ #
3
+ # Redistribution and use in source and binary forms, with or without
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
6
+ #
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above
10
+ # copyright notice, this list of conditions and the following
11
+ # disclaimer in the documentation and/or other materials provided
12
+ # with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote
14
+ # products derived from this software without specific prior
15
+ # written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ Tb::Cmd.subcommands << 'nest'
30
+
31
+ def (Tb::Cmd).op_nest
32
+ op = OptionParser.new
33
+ op.banner = "Usage: tb nest [OPTS] NEWFIELD,OLDFIELD1,OLDFIELD2,... [TABLE ...]\n" +
34
+ "Nest fields."
35
+ define_common_option(op, "hNo", "--no-pager")
36
+ op
37
+ end
38
+
39
+ def (Tb::Cmd).main_nest(argv)
40
+ op_nest.parse!(argv)
41
+ exit_if_help('nest')
42
+ err('no fields given.') if argv.empty?
43
+ fields = split_field_list_argument(argv.shift)
44
+ newfield, *oldfields = fields
45
+ oldfields_hash = {}
46
+ oldfields.each {|f| oldfields_hash[f] = true }
47
+ argv = ['-'] if argv.empty?
48
+ creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N)
49
+ er = Tb::Enumerator.new {|y|
50
+ sorted = creader.with_header {|header0|
51
+ oldfields.each {|f|
52
+ if !header0.include?(f)
53
+ err("field not found: #{f.inspect}")
54
+ end
55
+ }
56
+ y.set_header(header0.reject {|f| oldfields_hash[f] } + [newfield])
57
+ }.map {|pairs|
58
+ cv = pairs.reject {|f, v|
59
+ oldfields_hash[f]
60
+ }.map {|f, v|
61
+ [smart_cmp_value(f), smart_cmp_value(v)]
62
+ }.sort
63
+ [cv, pairs]
64
+ }
65
+
66
+ nested = nil
67
+ boundary_p = lambda {|(cv1, _), (cv2, _)|
68
+ cv1 != cv2
69
+ }
70
+ before_group = lambda {|(_, _)|
71
+ nested = []
72
+ }
73
+ body = lambda {|(_, pairs)|
74
+ nested << pairs.reject {|f, v| !oldfields_hash[f] }
75
+ }
76
+ after_group = lambda {|(_, last_pairs)|
77
+ Tb.csv_stream_output(nested_csv="") {|ngen|
78
+ ngen << oldfields
79
+ nested.each {|npairs|
80
+ ngen << oldfields.map {|of| npairs[of] }
81
+ }
82
+ }
83
+ assoc = last_pairs.reject {|f, v| oldfields_hash[f] }.to_a
84
+ assoc << [newfield, nested_csv]
85
+ pairs = Tb::Pairs.new(assoc)
86
+ y.yield pairs
87
+ }
88
+ sorted.each_group_element(boundary_p, before_group, body, after_group)
89
+ }
90
+ with_output {|out|
91
+ er.write_to_csv(out, !Tb::Cmd.opt_N)
92
+ }
93
+ end
94
+
@@ -1,32 +1,37 @@
1
- # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
1
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
- # modification, are permitted provided that the following conditions are met:
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
5
6
  #
6
- # 1. Redistributions of source code must retain the above copyright notice, this
7
- # list of conditions and the following disclaimer.
8
- # 2. Redistributions in binary form must reproduce the above copyright notice,
9
- # this list of conditions and the following disclaimer in the documentation
10
- # and/or other materials provided with the distribution.
11
- # 3. The name of the author may not be used to endorse or promote products
12
- # derived from this software without specific prior written permission.
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above
10
+ # copyright notice, this list of conditions and the following
11
+ # disclaimer in the documentation and/or other materials provided
12
+ # with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote
14
+ # products derived from this software without specific prior
15
+ # written permission.
13
16
  #
14
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
19
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
23
- # OF SUCH DAMAGE.
17
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
28
 
25
29
  Tb::Cmd.subcommands << 'newfield'
26
30
 
27
31
  def (Tb::Cmd).op_newfield
28
32
  op = OptionParser.new
29
- op.banner = 'Usage: tb newfield [OPTS] FIELD RUBY-EXP [TABLE]'
33
+ op.banner = "Usage: tb newfield [OPTS] FIELD RUBY-EXP [TABLE]\n" +
34
+ "Add a field."
30
35
  define_common_option(op, "ho", "--no-pager")
31
36
  op
32
37
  end
@@ -40,19 +45,10 @@ def (Tb::Cmd).main_newfield(argv)
40
45
  rubyexp = argv.shift
41
46
  pr = eval("lambda {|_| #{rubyexp} }")
42
47
  argv = ['-'] if argv.empty?
43
- Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader|
44
- renamed_header = [field] + tblreader.header
45
- with_table_stream_output {|gen|
46
- gen.output_header(renamed_header)
47
- tblreader.each {|ary|
48
- h = {}
49
- ary.each_with_index {|str, i|
50
- f = tblreader.field_from_index_ex(i)
51
- h[f] = str
52
- }
53
- gen << [pr.call(h), *ary]
54
- }
55
- }
48
+ creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N)
49
+ er = creader.newfield(field) {|pairs| pr.call(pairs) }
50
+ with_output {|out|
51
+ er.write_to_csv(out, !Tb::Cmd.opt_N)
56
52
  }
57
53
  end
58
54
 
data/lib/tb/cmd_rename.rb CHANGED
@@ -1,32 +1,37 @@
1
- # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
1
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
- # modification, are permitted provided that the following conditions are met:
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
5
6
  #
6
- # 1. Redistributions of source code must retain the above copyright notice, this
7
- # list of conditions and the following disclaimer.
8
- # 2. Redistributions in binary form must reproduce the above copyright notice,
9
- # this list of conditions and the following disclaimer in the documentation
10
- # and/or other materials provided with the distribution.
11
- # 3. The name of the author may not be used to endorse or promote products
12
- # derived from this software without specific prior written permission.
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above
10
+ # copyright notice, this list of conditions and the following
11
+ # disclaimer in the documentation and/or other materials provided
12
+ # with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote
14
+ # products derived from this software without specific prior
15
+ # written permission.
13
16
  #
14
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
19
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
23
- # OF SUCH DAMAGE.
17
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
28
 
25
29
  Tb::Cmd.subcommands << 'rename'
26
30
 
27
31
  def (Tb::Cmd).op_rename
28
32
  op = OptionParser.new
29
- op.banner = 'Usage: tb rename [OPTS] SRC,DST,... [TABLE]'
33
+ op.banner = "Usage: tb rename [OPTS] SRC,DST,... [TABLE]\n" +
34
+ "Rename field names."
30
35
  define_common_option(op, "ho", "--no-pager")
31
36
  op
32
37
  end
@@ -39,20 +44,23 @@ def (Tb::Cmd).main_rename(argv)
39
44
  argv = ['-'] if argv.empty?
40
45
  h = {}
41
46
  fs.each_slice(2) {|sf, df| h[sf] = df }
42
- Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader|
43
- header = tblreader.header
44
- h.each {|sf, df|
45
- unless header.include? sf
46
- err "field not found: #{sf.inspect}"
47
- end
48
- }
49
- renamed_header = tblreader.header.map {|f| h.fetch(f, f) }
50
- with_table_stream_output {|gen|
51
- gen.output_header(renamed_header)
52
- tblreader.each {|ary|
53
- gen << ary
47
+ creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N)
48
+ er = Tb::Enumerator.new {|y|
49
+ header = nil
50
+ creader.with_header {|header0|
51
+ header = header0
52
+ h.each {|sf, df|
53
+ unless header.include? sf
54
+ err "field not found: #{sf.inspect}"
55
+ end
54
56
  }
57
+ y.set_header header.map {|f| h.fetch(f, f) }
58
+ }.each {|pairs|
59
+ y.yield Tb::Pairs.new(pairs.map {|f, v| [h.fetch(f, f), v] })
55
60
  }
56
61
  }
62
+ with_output {|out|
63
+ er.write_to_csv(out, !Tb::Cmd.opt_N)
64
+ }
57
65
  end
58
66
 
data/lib/tb/cmd_shape.rb CHANGED
@@ -1,32 +1,37 @@
1
- # Copyright (C) 2011 Tanaka Akira <akr@fsij.org>
1
+ # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
- # modification, are permitted provided that the following conditions are met:
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
5
6
  #
6
- # 1. Redistributions of source code must retain the above copyright notice, this
7
- # list of conditions and the following disclaimer.
8
- # 2. Redistributions in binary form must reproduce the above copyright notice,
9
- # this list of conditions and the following disclaimer in the documentation
10
- # and/or other materials provided with the distribution.
11
- # 3. The name of the author may not be used to endorse or promote products
12
- # derived from this software without specific prior written permission.
7
+ # 1. Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above
10
+ # copyright notice, this list of conditions and the following
11
+ # disclaimer in the documentation and/or other materials provided
12
+ # with the distribution.
13
+ # 3. The name of the author may not be used to endorse or promote
14
+ # products derived from this software without specific prior
15
+ # written permission.
13
16
  #
14
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
19
- # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22
- # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
23
- # OF SUCH DAMAGE.
17
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23
+ # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
+ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
28
 
25
29
  Tb::Cmd.subcommands << 'shape'
26
30
 
27
31
  def (Tb::Cmd).op_shape
28
32
  op = OptionParser.new
29
- op.banner = 'Usage: tb shape [OPTS] [TABLE ...]'
33
+ op.banner = "Usage: tb shape [OPTS] [TABLE ...]\n" +
34
+ "Show table size."
30
35
  define_common_option(op, "hNo", "--no-pager")
31
36
  op
32
37
  end
@@ -38,11 +43,14 @@ def (Tb::Cmd).main_shape(argv)
38
43
  result = Tb.new(%w[header_fields min_fields max_fields records filename])
39
44
  filenames.each {|filename|
40
45
  tablereader_open(filename) {|tblreader|
41
- num_header_fields = tblreader.header.length
42
46
  min_num_fields = nil
43
47
  max_num_fields = nil
44
48
  num_records = 0
45
- tblreader.each {|ary|
49
+ num_header_fields = nil
50
+ tblreader.with_header {|header|
51
+ num_header_fields = header.length
52
+ }.each {|pairs|
53
+ ary = pairs.values
46
54
  num_records += 1
47
55
  n = ary.length
48
56
  if min_num_fields.nil?
@@ -60,8 +68,7 @@ def (Tb::Cmd).main_shape(argv)
60
68
  }
61
69
  }
62
70
  with_output {|out|
63
- # don't use tbl_generate_csv() because the header should always outputted.
64
- result.generate_csv(out)
71
+ result.write_to_csv(out, true)
65
72
  }
66
73
  end
67
74