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
data/lib/tb/cmd_join.rb CHANGED
@@ -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 << 'join'
26
30
 
@@ -30,7 +34,8 @@ Tb::Cmd.default_option[:opt_join_retain_right] = nil
30
34
 
31
35
  def (Tb::Cmd).op_join
32
36
  op = OptionParser.new
33
- op.banner = 'Usage: tb join [OPTS] [TABLE1 TABLE2 ...]'
37
+ op.banner = "Usage: tb join [OPTS] [TABLE1 TABLE2 ...]\n" +
38
+ "Concatenate tables horizontally as left/right/full natural join."
34
39
  define_common_option(op, 'hNod', '--no-pager', '--debug')
35
40
  op.def_option('--outer', 'outer join') {
36
41
  Tb::Cmd.opt_join_retain_left = true
@@ -60,22 +65,14 @@ def (Tb::Cmd).main_join(argv)
60
65
  retain_left = Tb::Cmd.opt_join_retain_left
61
66
  retain_right = Tb::Cmd.opt_join_retain_right
62
67
  err('two tables required at least.') if argv.length < 2
63
- result = load_table(argv.shift)
64
- if retain_left || retain_right
65
- argv.each {|filename|
66
- tbl = load_table(filename)
67
- STDERR.puts "shared keys: #{(result.list_fields & tbl.list_fields).inspect}" if 1 <= Tb::Cmd.opt_debug
68
- result = result.natjoin2_outer(tbl, Tb::Cmd.opt_join_outer_missing, retain_left, retain_right)
69
- }
70
- else
71
- argv.each {|filename|
72
- tbl = load_table(filename)
73
- STDERR.puts "shared keys: #{(result.list_fields & tbl.list_fields).inspect}" if 1 <= Tb::Cmd.opt_debug
74
- result = result.natjoin2(tbl)
75
- }
76
- end
68
+ result = tablereader_open(argv.shift)
69
+ argv.each {|filename|
70
+ tbl = tablereader_open(filename)
71
+ $stderr.puts "shared keys: #{(result.list_fields & tbl.list_fields).inspect}" if 1 <= Tb::Cmd.opt_debug
72
+ result = result.natjoin2_outer(tbl, Tb::Cmd.opt_join_outer_missing, retain_left, retain_right)
73
+ }
77
74
  with_output {|out|
78
- tbl_generate_csv(result, out)
75
+ result.write_to_csv(out, !Tb::Cmd.opt_N)
79
76
  }
80
77
  end
81
78
 
data/lib/tb/cmd_ls.rb CHANGED
@@ -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 << 'ls'
26
30
 
@@ -31,7 +35,8 @@ Tb::Cmd.default_option[:opt_ls_R] = nil
31
35
 
32
36
  def (Tb::Cmd).op_ls
33
37
  op = OptionParser.new
34
- op.banner = 'Usage: tb ls [OPTS] [FILE ...]'
38
+ op.banner = "Usage: tb ls [OPTS] [FILE ...]\n" +
39
+ "List directory entries as a table."
35
40
  define_common_option(op, "hNo", "--no-pager")
36
41
  op.def_option('-a', 'don\'t ignore filenames beginning with a period.') {|fs| Tb::Cmd.opt_ls_a = true }
37
42
  op.def_option('-A', 'don\'t ignore filenames beginning with a period, except "." and "..".') {|fs| Tb::Cmd.opt_ls_A = true }
@@ -44,230 +49,253 @@ def (Tb::Cmd).main_ls(argv)
44
49
  op_ls.parse!(argv)
45
50
  exit_if_help('ls')
46
51
  argv = ['.'] if argv.empty?
47
- @fail = false
48
- with_table_stream_output {|gen|
49
- if Tb::Cmd.opt_ls_l == 0
50
- gen.output_header ['filename'] # don't generate the header when -N.
51
- else
52
- gen.output_header(ls_long_header()) # don't generate the header when -N.
53
- end
52
+ opts = {
53
+ :a => Tb::Cmd.opt_ls_a,
54
+ :A => Tb::Cmd.opt_ls_A,
55
+ :l => Tb::Cmd.opt_ls_l,
56
+ :R => Tb::Cmd.opt_ls_R,
57
+ }
58
+ ls = nil
59
+ er = Tb::Enumerator.new {|y|
60
+ ls = Tb::Cmd::Ls.new(y, opts)
61
+ ls.set_header
54
62
  argv.each {|arg|
55
- ls_run(gen, Pathname(real_pathname_string(arg)))
63
+ ls.ls_run(Pathname(ls.real_pathname_string(arg)))
56
64
  }
57
65
  }
58
- if @fail
66
+ with_output {|out|
67
+ er.write_to_csv(out, !Tb::Cmd.opt_N)
68
+ }
69
+ if ls.fail
59
70
  exit false
60
71
  end
61
72
  end
62
73
 
63
- def (Tb::Cmd).ls_run(gen, path)
64
- st = ls_get_stat(path)
65
- return if !st
66
- if st.directory?
67
- ls_dir(gen, path, st)
68
- else
69
- ls_file(gen, path, st)
74
+ class Tb::Cmd::Ls
75
+ def initialize(y, opts)
76
+ @y = y
77
+ @opts = opts
78
+ @fail = false
70
79
  end
71
- end
80
+ attr_reader :fail
72
81
 
73
- def (Tb::Cmd).ls_dir(gen, dir, st)
74
- begin
75
- entries = Dir.entries(dir)
76
- rescue SystemCallError
77
- @fail = true
78
- warn "tb: #{$!}: #{dir}"
79
- return
82
+ def set_header
83
+ if @opts[:l] == 0
84
+ @y.set_header ['filename']
85
+ else
86
+ @y.set_header(ls_long_header())
87
+ end
80
88
  end
81
- entries.map! {|filename| real_pathname_string(filename) }
82
- entries = entries.sort_by {|filename| smart_cmp_value(filename) }
83
- if Tb::Cmd.opt_ls_a || Tb::Cmd.opt_ls_A
84
- entries1, entries2 = entries.partition {|filename| /\A\./ =~ filename }
85
- entries0, entries1 = entries1.partition {|filename| filename == '.' || filename == '..' }
86
- entries0.sort!
87
- if Tb::Cmd.opt_ls_A
88
- entries = entries1 + entries2
89
+
90
+ def ls_run(path)
91
+ st = ls_get_stat(path)
92
+ return if !st
93
+ if st.directory?
94
+ ls_dir(path, st)
89
95
  else
90
- entries = entries0 + entries1 + entries2
96
+ ls_file(path, st)
91
97
  end
92
- else
93
- entries.reject! {|filename| /\A\./ =~ filename }
94
98
  end
95
- if !Tb::Cmd.opt_ls_R
96
- entries.each {|filename|
97
- ls_file(gen, dir + filename, nil)
98
- }
99
- else
100
- dirs = []
101
- entries.each {|filename|
102
- path = dir + filename
103
- st2 = ls_get_stat(path)
104
- next if !st2
105
- if filename == '.' || filename == '..'
106
- if dir.to_s != '.'
107
- path = Pathname(dir.to_s + "/" + filename)
108
- end
109
- ls_file(gen, path, st2)
110
- elsif st2.directory?
111
- dirs << [path, st2]
99
+
100
+ def ls_dir(dir, st)
101
+ begin
102
+ entries = Dir.entries(dir)
103
+ rescue SystemCallError
104
+ @fail = true
105
+ warn "tb: #{$!}: #{dir}"
106
+ return
107
+ end
108
+ entries.map! {|filename| real_pathname_string(filename) }
109
+ entries = entries.sort_by {|filename| smart_cmp_value(filename) }
110
+ if @opts[:a] || @opts[:A]
111
+ entries1, entries2 = entries.partition {|filename| /\A\./ =~ filename }
112
+ entries0, entries1 = entries1.partition {|filename| filename == '.' || filename == '..' }
113
+ entries0.sort!
114
+ if @opts[:A]
115
+ entries = entries1 + entries2
112
116
  else
113
- ls_file(gen, path, st2)
117
+ entries = entries0 + entries1 + entries2
114
118
  end
115
- }
116
- dirs.each {|path, st2|
117
- ls_file(gen, path, st2)
118
- ls_dir(gen, path, st2)
119
- }
119
+ else
120
+ entries.reject! {|filename| /\A\./ =~ filename }
121
+ end
122
+ if !@opts[:R]
123
+ entries.each {|filename|
124
+ ls_file(dir + filename, nil)
125
+ }
126
+ else
127
+ dirs = []
128
+ entries.each {|filename|
129
+ path = dir + filename
130
+ st2 = ls_get_stat(path)
131
+ next if !st2
132
+ if filename == '.' || filename == '..'
133
+ if dir.to_s != '.'
134
+ path = Pathname(dir.to_s + "/" + filename)
135
+ end
136
+ ls_file(path, st2)
137
+ elsif st2.directory?
138
+ dirs << [path, st2]
139
+ else
140
+ ls_file(path, st2)
141
+ end
142
+ }
143
+ dirs.each {|path, st2|
144
+ ls_file(path, st2)
145
+ ls_dir(path, st2)
146
+ }
147
+ end
120
148
  end
121
- end
122
149
 
123
- def (Tb::Cmd).ls_file(gen, path, st)
124
- if 0 < Tb::Cmd.opt_ls_l
125
- if !st
126
- st = ls_get_stat(path)
127
- return if !st
150
+ def ls_file(path, st)
151
+ if 0 < @opts[:l]
152
+ if !st
153
+ st = ls_get_stat(path)
154
+ return if !st
155
+ end
156
+ @y.yield ls_long_info(path, st)
157
+ else
158
+ @y.yield Tb::Pairs.new([['filename', path.to_s]])
128
159
  end
129
- gen << ls_long_info(path, st)
130
- else
131
- gen << [path.to_s]
132
160
  end
133
- end
134
161
 
135
- def (Tb::Cmd).ls_get_stat(path)
136
- begin
137
- st = path.lstat
138
- rescue SystemCallError
139
- @fail = true
140
- warn "tb: #{$!}: #{path}"
141
- return nil
162
+ def ls_get_stat(path)
163
+ begin
164
+ st = path.lstat
165
+ rescue SystemCallError
166
+ @fail = true
167
+ warn "tb: #{$!}: #{path}"
168
+ return nil
169
+ end
170
+ st
142
171
  end
143
- st
144
- end
145
172
 
146
- def (Tb::Cmd).ls_long_header
147
- if 1 < Tb::Cmd.opt_ls_l
148
- %w[dev ino mode filemode nlink uid user gid group rdev size blksize blocks atime mtime ctime filename symlink]
149
- else
150
- %w[filemode nlink user group size mtime filename symlink]
173
+ def ls_long_header
174
+ if 1 < @opts[:l]
175
+ %w[dev ino mode filemode nlink uid user gid group rdev size blksize blocks atime mtime ctime filename symlink]
176
+ else
177
+ %w[filemode nlink user group size mtime filename symlink]
178
+ end
151
179
  end
152
- end
153
-
154
- def (Tb::Cmd).ls_long_info(path, st)
155
- ls_long_header.map {|info_type|
156
- self.send("ls_info_#{info_type}", path, st)
157
- }
158
- end
159
180
 
160
- def (Tb::Cmd).ls_info_dev(path, st) sprintf("0x%x", st.dev) end
161
- def (Tb::Cmd).ls_info_ino(path, st) st.ino end
162
- def (Tb::Cmd).ls_info_mode(path, st) sprintf("0%o", st.mode) end
163
- def (Tb::Cmd).ls_info_nlink(path, st) st.nlink end
164
- def (Tb::Cmd).ls_info_uid(path, st) st.uid end
165
- def (Tb::Cmd).ls_info_gid(path, st) st.gid end
166
- def (Tb::Cmd).ls_info_rdev(path, st) sprintf("0x%x", st.rdev) end
167
- def (Tb::Cmd).ls_info_size(path, st) st.size end
168
- def (Tb::Cmd).ls_info_blksize(path, st) st.blksize end
169
- def (Tb::Cmd).ls_info_blocks(path, st) st.blocks end
181
+ def ls_long_info(path, st)
182
+ Tb::Pairs.new(ls_long_header.map {|info_type|
183
+ [info_type, self.send("ls_info_#{info_type}", path, st)]
184
+ })
185
+ end
170
186
 
171
- def (Tb::Cmd).ls_info_filemode(path, st)
172
- entry_type =
173
- case st.ftype
174
- when "file" then '-'
175
- when "directory" then 'd'
176
- when "characterSpecial" then 'c'
177
- when "blockSpecial" then 'b'
178
- when "fifo" then 'p'
179
- when "link" then 'l'
180
- when "socket" then 's'
181
- when "unknown" then '?'
182
- else '?'
183
- end
184
- m = st.mode
185
- sprintf("%s%c%c%c%c%c%c%c%c%c",
186
- entry_type,
187
- (m & 0400 == 0 ? ?- : ?r),
188
- (m & 0200 == 0 ? ?- : ?w),
189
- (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
190
- (m & 04000 == 0 ? ?x : ?s)),
191
- (m & 0040 == 0 ? ?- : ?r),
192
- (m & 0020 == 0 ? ?- : ?w),
193
- (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
194
- (m & 02000 == 0 ? ?x : ?s)),
195
- (m & 0004 == 0 ? ?- : ?r),
196
- (m & 0002 == 0 ? ?- : ?w),
197
- (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
198
- (m & 01000 == 0 ? ?x : ?t)))
199
- end
187
+ def ls_info_dev(path, st) sprintf("0x%x", st.dev) end
188
+ def ls_info_ino(path, st) st.ino end
189
+ def ls_info_mode(path, st) sprintf("0%o", st.mode) end
190
+ def ls_info_nlink(path, st) st.nlink end
191
+ def ls_info_uid(path, st) st.uid end
192
+ def ls_info_gid(path, st) st.gid end
193
+ def ls_info_rdev(path, st) sprintf("0x%x", st.rdev) end
194
+ def ls_info_size(path, st) st.size end
195
+ def ls_info_blksize(path, st) st.blksize end
196
+ def ls_info_blocks(path, st) st.blocks end
200
197
 
201
- def (Tb::Cmd).ls_info_user(path, st)
202
- uid = st.uid
203
- begin
204
- pw = Etc.getpwuid(uid)
205
- rescue ArgumentError
206
- end
207
- if pw
208
- pw.name
209
- else
210
- uid
198
+ def ls_info_filemode(path, st)
199
+ entry_type =
200
+ case st.ftype
201
+ when "file" then '-'
202
+ when "directory" then 'd'
203
+ when "characterSpecial" then 'c'
204
+ when "blockSpecial" then 'b'
205
+ when "fifo" then 'p'
206
+ when "link" then 'l'
207
+ when "socket" then 's'
208
+ when "unknown" then '?'
209
+ else '?'
210
+ end
211
+ m = st.mode
212
+ sprintf("%s%c%c%c%c%c%c%c%c%c",
213
+ entry_type,
214
+ (m & 0400 == 0 ? ?- : ?r),
215
+ (m & 0200 == 0 ? ?- : ?w),
216
+ (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
217
+ (m & 04000 == 0 ? ?x : ?s)),
218
+ (m & 0040 == 0 ? ?- : ?r),
219
+ (m & 0020 == 0 ? ?- : ?w),
220
+ (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
221
+ (m & 02000 == 0 ? ?x : ?s)),
222
+ (m & 0004 == 0 ? ?- : ?r),
223
+ (m & 0002 == 0 ? ?- : ?w),
224
+ (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
225
+ (m & 01000 == 0 ? ?x : ?t)))
211
226
  end
212
- end
213
227
 
214
- def (Tb::Cmd).ls_info_group(path, st)
215
- gid = st.gid
216
- begin
217
- gr = Etc.getgrgid(gid)
218
- rescue ArgumentError
228
+ def ls_info_user(path, st)
229
+ uid = st.uid
230
+ begin
231
+ pw = Etc.getpwuid(uid)
232
+ rescue ArgumentError
233
+ end
234
+ if pw
235
+ pw.name
236
+ else
237
+ uid
238
+ end
219
239
  end
220
- if gr
221
- gr.name
222
- else
223
- gid
240
+
241
+ def ls_info_group(path, st)
242
+ gid = st.gid
243
+ begin
244
+ gr = Etc.getgrgid(gid)
245
+ rescue ArgumentError
246
+ end
247
+ if gr
248
+ gr.name
249
+ else
250
+ gid
251
+ end
224
252
  end
225
- end
226
253
 
227
- def (Tb::Cmd).ls_info_atime(path, st)
228
- if 1 < Tb::Cmd.opt_ls_l
229
- st.atime.iso8601(9)
230
- else
231
- st.atime.iso8601
254
+ def ls_info_atime(path, st)
255
+ if 1 < @opts[:l]
256
+ st.atime.iso8601(9)
257
+ else
258
+ st.atime.iso8601
259
+ end
232
260
  end
233
- end
234
261
 
235
- def (Tb::Cmd).ls_info_mtime(path, st)
236
- if 1 < Tb::Cmd.opt_ls_l
237
- st.mtime.iso8601(9)
238
- else
239
- st.mtime.iso8601
262
+ def ls_info_mtime(path, st)
263
+ if 1 < @opts[:l]
264
+ st.mtime.iso8601(9)
265
+ else
266
+ st.mtime.iso8601
267
+ end
240
268
  end
241
- end
242
269
 
243
- def (Tb::Cmd).ls_info_ctime(path, st)
244
- if 1 < Tb::Cmd.opt_ls_l
245
- st.ctime.iso8601(9)
246
- else
247
- st.ctime.iso8601
270
+ def ls_info_ctime(path, st)
271
+ if 1 < @opts[:l]
272
+ st.ctime.iso8601(9)
273
+ else
274
+ st.ctime.iso8601
275
+ end
248
276
  end
249
- end
250
277
 
251
- def (Tb::Cmd).ls_info_filename(path, st)
252
- path
253
- end
278
+ def ls_info_filename(path, st)
279
+ path
280
+ end
254
281
 
255
- def (Tb::Cmd).ls_info_symlink(path, st)
256
- return nil if !st.symlink?
257
- begin
258
- File.readlink(path)
259
- rescue SystemCallError
260
- @fail = true
261
- warn "tb: #{$!}: #{path}"
262
- return nil
282
+ def ls_info_symlink(path, st)
283
+ return nil if !st.symlink?
284
+ begin
285
+ File.readlink(path)
286
+ rescue SystemCallError
287
+ @fail = true
288
+ warn "tb: #{$!}: #{path}"
289
+ return nil
290
+ end
263
291
  end
264
- end
265
292
 
266
- def (Tb::Cmd).real_pathname_string(str)
267
- if str.respond_to? :force_encoding
268
- # pathname is a sequence of bytes on Unix.
269
- str.dup.force_encoding("ASCII-8BIT")
270
- else
271
- str
293
+ def real_pathname_string(str)
294
+ if str.respond_to? :force_encoding
295
+ # pathname is a sequence of bytes on Unix.
296
+ str.dup.force_encoding("ASCII-8BIT")
297
+ else
298
+ str
299
+ end
272
300
  end
273
301
  end