tb 0.1 → 0.2

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 (81) hide show
  1. data/README +156 -5
  2. data/bin/tb +2 -1110
  3. data/lib/tb.rb +4 -2
  4. data/lib/tb/catreader.rb +131 -0
  5. data/lib/tb/cmd_cat.rb +65 -0
  6. data/lib/tb/cmd_consecutive.rb +79 -0
  7. data/lib/tb/cmd_crop.rb +105 -0
  8. data/lib/tb/cmd_cross.rb +119 -0
  9. data/lib/tb/cmd_csv.rb +42 -0
  10. data/lib/tb/cmd_cut.rb +77 -0
  11. data/lib/tb/cmd_grep.rb +76 -0
  12. data/lib/tb/cmd_group.rb +82 -0
  13. data/lib/tb/cmd_gsub.rb +77 -0
  14. data/lib/tb/cmd_help.rb +98 -0
  15. data/lib/tb/cmd_join.rb +81 -0
  16. data/lib/tb/cmd_json.rb +60 -0
  17. data/lib/tb/cmd_ls.rb +273 -0
  18. data/lib/tb/cmd_mheader.rb +77 -0
  19. data/lib/tb/cmd_newfield.rb +59 -0
  20. data/lib/tb/cmd_pnm.rb +43 -0
  21. data/lib/tb/cmd_pp.rb +70 -0
  22. data/lib/tb/cmd_rename.rb +58 -0
  23. data/lib/tb/cmd_shape.rb +67 -0
  24. data/lib/tb/cmd_sort.rb +58 -0
  25. data/lib/tb/cmd_svn_log.rb +158 -0
  26. data/lib/tb/cmd_tsv.rb +43 -0
  27. data/lib/tb/cmd_yaml.rb +47 -0
  28. data/lib/tb/cmdmain.rb +45 -0
  29. data/lib/tb/cmdtop.rb +58 -0
  30. data/lib/tb/cmdutil.rb +327 -0
  31. data/lib/tb/csv.rb +30 -6
  32. data/lib/tb/fieldset.rb +39 -41
  33. data/lib/tb/pager.rb +132 -0
  34. data/lib/tb/pnm.rb +357 -0
  35. data/lib/tb/reader.rb +18 -128
  36. data/lib/tb/record.rb +3 -3
  37. data/lib/tb/ropen.rb +70 -0
  38. data/lib/tb/{pathfinder.rb → search.rb} +69 -34
  39. data/lib/tb/tsv.rb +29 -1
  40. data/sample/colors.ppm +0 -0
  41. data/sample/gradation.pgm +0 -0
  42. data/sample/langs.csv +46 -0
  43. data/sample/tbplot +293 -0
  44. data/test-all-cov.rb +65 -0
  45. data/test-all.rb +5 -0
  46. data/test/test_basic.rb +99 -2
  47. data/test/test_catreader.rb +27 -0
  48. data/test/test_cmd_cat.rb +118 -0
  49. data/test/test_cmd_consecutive.rb +90 -0
  50. data/test/test_cmd_crop.rb +101 -0
  51. data/test/test_cmd_cross.rb +113 -0
  52. data/test/test_cmd_csv.rb +129 -0
  53. data/test/test_cmd_cut.rb +100 -0
  54. data/test/test_cmd_grep.rb +89 -0
  55. data/test/test_cmd_group.rb +181 -0
  56. data/test/test_cmd_gsub.rb +103 -0
  57. data/test/test_cmd_help.rb +190 -0
  58. data/test/test_cmd_join.rb +197 -0
  59. data/test/test_cmd_json.rb +75 -0
  60. data/test/test_cmd_ls.rb +203 -0
  61. data/test/test_cmd_mheader.rb +86 -0
  62. data/test/test_cmd_newfield.rb +63 -0
  63. data/test/test_cmd_pnm.rb +35 -0
  64. data/test/test_cmd_pp.rb +62 -0
  65. data/test/test_cmd_rename.rb +91 -0
  66. data/test/test_cmd_shape.rb +50 -0
  67. data/test/test_cmd_sort.rb +105 -0
  68. data/test/test_cmd_tsv.rb +67 -0
  69. data/test/test_cmd_yaml.rb +55 -0
  70. data/test/test_cmdtty.rb +154 -0
  71. data/test/test_cmdutil.rb +43 -0
  72. data/test/test_csv.rb +10 -0
  73. data/test/test_fieldset.rb +42 -0
  74. data/test/test_pager.rb +142 -0
  75. data/test/test_pnm.rb +374 -0
  76. data/test/test_reader.rb +147 -0
  77. data/test/test_record.rb +49 -0
  78. data/test/test_search.rb +575 -0
  79. data/test/test_tsv.rb +7 -0
  80. metadata +108 -5
  81. data/lib/tb/qtsv.rb +0 -93
@@ -0,0 +1,42 @@
1
+ # Copyright (C) 2011 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 are met:
5
+ #
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.
13
+ #
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.
24
+
25
+ Tb::Cmd.subcommands << 'csv'
26
+
27
+ def (Tb::Cmd).op_csv
28
+ op = OptionParser.new
29
+ op.banner = 'Usage: tb csv [OPTS] [TABLE ...]'
30
+ define_common_option(op, "hNo", "--no-pager")
31
+ op
32
+ end
33
+
34
+ def (Tb::Cmd).main_csv(argv)
35
+ op_csv.parse!(argv)
36
+ exit_if_help('csv')
37
+ argv = ['-'] if argv.empty?
38
+ tbl = Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|creader| build_table(creader) }
39
+ with_output {|out|
40
+ tbl_generate_csv(tbl, out)
41
+ }
42
+ end
@@ -0,0 +1,77 @@
1
+ # Copyright (C) 2011 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 are met:
5
+ #
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.
13
+ #
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.
24
+
25
+ Tb::Cmd.subcommands << 'cut'
26
+
27
+ Tb::Cmd.default_option[:opt_cut_v] = nil
28
+
29
+ def (Tb::Cmd).op_cut
30
+ op = OptionParser.new
31
+ op.banner = 'Usage: tb cut [OPTS] FIELD,... [TABLE]'
32
+ define_common_option(op, "hNo", "--no-pager")
33
+ op.def_option('-v', 'invert match') { Tb::Cmd.opt_cut_v = true }
34
+ op
35
+ end
36
+
37
+ def (Tb::Cmd).main_cut(argv)
38
+ op_cut.parse!(argv)
39
+ exit_if_help('cut')
40
+ err('no fields given.') if argv.empty?
41
+ fs = split_field_list_argument(argv.shift)
42
+ argv = ['-'] if argv.empty?
43
+ Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader|
44
+ if Tb::Cmd.opt_cut_v
45
+ h = {}
46
+ fs.each {|f| h[tblreader.index_from_field(f)] = true }
47
+ header = nil
48
+ if !Tb::Cmd.opt_N
49
+ header = []
50
+ tblreader.header.each_with_index {|f, i|
51
+ header << f if !h[i]
52
+ }
53
+ end
54
+ with_table_stream_output {|gen|
55
+ gen.output_header(header)
56
+ tblreader.each {|ary|
57
+ values = []
58
+ ary.each_with_index {|v, i|
59
+ values << v if !h[i]
60
+ }
61
+ gen << values
62
+ }
63
+ }
64
+ else
65
+ header = tblreader.header
66
+ is = []
67
+ is = fs.map {|f| tblreader.index_from_field_ex(f) }
68
+ with_table_stream_output {|gen|
69
+ gen.output_header(is.map {|i| tblreader.field_from_index_ex(i) })
70
+ tblreader.each {|ary|
71
+ gen << ary.values_at(*is)
72
+ }
73
+ }
74
+ end
75
+ }
76
+ end
77
+
@@ -0,0 +1,76 @@
1
+ # Copyright (C) 2011 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 are met:
5
+ #
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.
13
+ #
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.
24
+
25
+ Tb::Cmd.subcommands << 'grep'
26
+
27
+ Tb::Cmd.default_option[:opt_grep_e] = nil
28
+ Tb::Cmd.default_option[:opt_grep_ruby] = nil
29
+ Tb::Cmd.default_option[:opt_grep_f] = nil
30
+ Tb::Cmd.default_option[:opt_grep_v] = nil
31
+
32
+ def (Tb::Cmd).op_grep
33
+ op = OptionParser.new
34
+ op.banner = 'Usage: tb grep [OPTS] REGEXP [TABLE ...]'
35
+ define_common_option(op, "hNo", "--no-pager")
36
+ op.def_option('-f FIELD', 'search field') {|field| Tb::Cmd.opt_grep_f = field }
37
+ op.def_option('-e REGEXP', 'predicate written in ruby. A hash is given as _. no usual regexp argument.') {|pattern| Tb::Cmd.opt_grep_e = pattern }
38
+ op.def_option('--ruby RUBY-EXP', 'specify a regexp. no usual regexp argument.') {|ruby_exp| Tb::Cmd.opt_grep_ruby = ruby_exp }
39
+ op.def_option('-v', 'ouput the records which doesn\'t match') { Tb::Cmd.opt_grep_v = true }
40
+ op
41
+ end
42
+
43
+ def (Tb::Cmd).main_grep(argv)
44
+ op_grep.parse!(argv)
45
+ exit_if_help('grep')
46
+ if Tb::Cmd.opt_grep_ruby
47
+ pred = eval("lambda {|_| #{Tb::Cmd.opt_grep_ruby} }")
48
+ elsif Tb::Cmd.opt_grep_e
49
+ re = Regexp.new(Tb::Cmd.opt_grep_e)
50
+ pred = Tb::Cmd.opt_grep_f ? lambda {|_| re =~ _[Tb::Cmd.opt_grep_f] } :
51
+ lambda {|_| _.any? {|k, v| re =~ v.to_s } }
52
+ else
53
+ err("no regexp given.") if argv.empty?
54
+ re = Regexp.new(argv.shift)
55
+ pred = Tb::Cmd.opt_grep_f ? lambda {|_| re =~ _[Tb::Cmd.opt_grep_f] } :
56
+ lambda {|_| _.any? {|k, v| re =~ v.to_s } }
57
+ end
58
+ opt_v = Tb::Cmd.opt_grep_v ? true : false
59
+ argv = ['-'] if argv.empty?
60
+ Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader|
61
+ with_table_stream_output {|gen|
62
+ gen.output_header tblreader.header
63
+ tblreader.each {|ary|
64
+ h = {}
65
+ ary.each_with_index {|str, i|
66
+ f = tblreader.field_from_index_ex(i)
67
+ h[f] = str
68
+ }
69
+ found = pred.call(h)
70
+ found = opt_v ^ !!(found)
71
+ gen << ary if found
72
+ }
73
+ }
74
+ }
75
+ end
76
+
@@ -0,0 +1,82 @@
1
+ # Copyright (C) 2011 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 are met:
5
+ #
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.
13
+ #
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.
24
+
25
+ Tb::Cmd.subcommands << 'group'
26
+
27
+ Tb::Cmd.default_option[:opt_group_fields] = []
28
+
29
+ def (Tb::Cmd).op_group
30
+ op = OptionParser.new
31
+ op.banner = 'Usage: tb group [OPTS] KEY-FIELD1,... [TABLE ...]'
32
+ define_common_option(op, "hNo", "--no-pager")
33
+ op.def_option('-a AGGREGATION-SPEC[,NEW-FIELD]',
34
+ '--aggregate AGGREGATION-SPEC[,NEW-FIELD]') {|arg| Tb::Cmd.opt_group_fields << arg }
35
+ op.def_option('--no-pager', 'don\'t use pager') { Tb::Cmd.opt_no_pager = true }
36
+ op
37
+ end
38
+
39
+ def (Tb::Cmd).main_group(argv)
40
+ op_group.parse!(argv)
41
+ exit_if_help('group')
42
+ err("no key fields given.") if argv.empty?
43
+ kfs = split_field_list_argument(argv.shift)
44
+ opt_group_fields = Tb::Cmd.opt_group_fields.map {|arg|
45
+ aggregation_spec, new_field = split_field_list_argument(arg)
46
+ new_field ||= aggregation_spec
47
+ [new_field,
48
+ lambda {|fields|
49
+ begin
50
+ make_aggregator(aggregation_spec, fields)
51
+ rescue ArgumentError
52
+ err($!.message)
53
+ end
54
+ }
55
+ ]
56
+ }
57
+ argv = ['-'] if argv.empty?
58
+ h = {}
59
+ Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader|
60
+ kis = kfs.map {|f| tblreader.index_from_field(f) }
61
+ result_fields = kfs + opt_group_fields.map {|nf, maker| nf }
62
+ tblreader.each {|ary|
63
+ kvs = ary.values_at(*kis)
64
+ if !h.include?(kvs)
65
+ h[kvs] = opt_group_fields.map {|nf, maker| ag = maker.call(tblreader.header); ag.update(ary); ag }
66
+ else
67
+ h[kvs].each {|ag|
68
+ ag.update(ary)
69
+ }
70
+ end
71
+ }
72
+ result = Tb.new(result_fields)
73
+ h.keys.sort_by {|k| k.map {|v| smart_cmp_value(v) } }.each {|k|
74
+ a = h[k]
75
+ result.insert_values result_fields, k + a.map {|ag| ag.finish }
76
+ }
77
+ with_output {|out|
78
+ tbl_generate_csv(result, out)
79
+ }
80
+ }
81
+ end
82
+
@@ -0,0 +1,77 @@
1
+ # Copyright (C) 2011 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 are met:
5
+ #
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.
13
+ #
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.
24
+
25
+ Tb::Cmd.subcommands << 'gsub'
26
+
27
+ Tb::Cmd.default_option[:opt_gsub_e] = nil
28
+ Tb::Cmd.default_option[:opt_gsub_f] = nil
29
+
30
+ def (Tb::Cmd).op_gsub
31
+ op = OptionParser.new
32
+ op.banner = 'Usage: tb gsub [OPTS] REGEXP STRING [TABLE ...]'
33
+ define_common_option(op, "hNo", "--no-pager")
34
+ op.def_option('-f FIELD', 'target field') {|field| Tb::Cmd.opt_gsub_f = field }
35
+ op.def_option('-e REGEXP', 'specify regexp, possibly begins with a hyphen') {|pattern| Tb::Cmd.opt_gsub_e = pattern }
36
+ op
37
+ end
38
+
39
+ def (Tb::Cmd).main_gsub(argv)
40
+ op_gsub.parse!(argv)
41
+ exit_if_help('gsub')
42
+ if Tb::Cmd.opt_gsub_e
43
+ re = Regexp.new(Tb::Cmd.opt_gsub_e)
44
+ else
45
+ err('no regexp given.') if argv.empty?
46
+ re = Regexp.new(argv.shift)
47
+ end
48
+ err('no substitution given.') if argv.empty?
49
+ repl = argv.shift
50
+ argv = ['-'] if argv.empty?
51
+ Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader|
52
+ with_table_stream_output {|gen|
53
+ gen.output_header tblreader.header
54
+ tblreader.each {|ary|
55
+ if Tb::Cmd.opt_gsub_f
56
+ ary2 = []
57
+ ary.each_with_index {|str, i|
58
+ f = tblreader.field_from_index_ex(i)
59
+ if f == Tb::Cmd.opt_gsub_f
60
+ str ||= ''
61
+ ary2 << str.gsub(re, repl)
62
+ else
63
+ ary2 << str
64
+ end
65
+ }
66
+ else
67
+ ary2 = ary.map {|s|
68
+ s ||= ''
69
+ s.gsub(re, repl)
70
+ }
71
+ end
72
+ gen << ary2
73
+ }
74
+ }
75
+ }
76
+ end
77
+
@@ -0,0 +1,98 @@
1
+ # Copyright (C) 2011 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 are met:
5
+ #
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.
13
+ #
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.
24
+
25
+ Tb::Cmd.subcommands << 'help'
26
+
27
+ def (Tb::Cmd).usage_list_subcommands
28
+ with_output {|f|
29
+ f.print <<'End'
30
+ Usage:
31
+ End
32
+ Tb::Cmd.subcommands.each {|subcommand|
33
+ f.puts " " + self.subcommand_send("op", subcommand).banner.sub(/\AUsage: /, '')
34
+ }
35
+ }
36
+ end
37
+
38
+ def (Tb::Cmd).op_help
39
+ op = OptionParser.new
40
+ op.banner = 'Usage: tb help [OPTS] [SUBCOMMAND]'
41
+ define_common_option(op, "hvo", "--no-pager")
42
+ op
43
+ end
44
+
45
+ Tb::Cmd.def_vhelp('help', <<'End')
46
+ Example:
47
+
48
+ tb -h : list subcommands
49
+ tb help : list subcommands
50
+
51
+ tb cat -h : succinct help of "cat" subcommand
52
+ tb cat -hh : verbose help of "cat" subcommand
53
+ tb help cat : succinct help of "cat" subcommand
54
+ tb help -h cat : verbose help of "cat" subcommand
55
+
56
+ tb help -h : succinct help of "help" subcommand
57
+ tb help -hh : verbose help of "help" subcommand
58
+ tb help help : succinct help of "help" subcommand
59
+ tb help -h help : verbose help of "help" subcommand
60
+ End
61
+
62
+ def (Tb::Cmd).exit_if_help(subcommand)
63
+ if 0 < Tb::Cmd.opt_help
64
+ show_help(subcommand)
65
+ exit
66
+ end
67
+ end
68
+
69
+ def (Tb::Cmd).show_help(subcommand)
70
+ if Tb::Cmd.subcommands.include?(subcommand)
71
+ with_output {|f|
72
+ f.puts self.subcommand_send("op", subcommand)
73
+ if 2 <= Tb::Cmd.opt_help && Tb::Cmd.verbose_help[subcommand]
74
+ f.puts
75
+ f.puts Tb::Cmd.verbose_help[subcommand]
76
+ end
77
+ }
78
+ true
79
+ else
80
+ err "unexpected subcommand: #{subcommand.inspect}"
81
+ end
82
+ end
83
+
84
+ def (Tb::Cmd).main_help(argv)
85
+ op_help.parse!(argv)
86
+ if argv.empty?
87
+ if Tb::Cmd.opt_help == 0
88
+ usage_list_subcommands
89
+ return true
90
+ else
91
+ argv.unshift 'help'
92
+ Tb::Cmd.opt_help -= 1
93
+ end
94
+ end
95
+ Tb::Cmd.opt_help += 1
96
+ subcommand = argv.shift
97
+ exit_if_help(subcommand)
98
+ end