Top Level Namespace
Defined Under Namespace
Modules: Enumerable, Tb
Class Method Summary collapse
- .decode_a1_addressing_col(str) ⇒ Object
- .exit_if_help(subcommand) ⇒ Object
- .git_each_commit(f) ⇒ Object
- .git_parse_commit(commit_info, files) ⇒ Object
- .git_unescape_filename(filename) ⇒ Object
- .git_with_git_log(dir) ⇒ Object
- .list_summary_of_subcommands ⇒ Object
- .main(argv) ⇒ Object
-
.main_body(argv) ⇒ Object
Copyright © 2011-2012 Tanaka Akira <[email protected]>.
- .main_cat(argv) ⇒ Object
- .main_consecutive(argv) ⇒ Object
- .main_crop(argv) ⇒ Object
- .main_cross(argv) ⇒ Object
- .main_cut(argv) ⇒ Object
- .main_git(argv) ⇒ Object
- .main_group(argv) ⇒ Object
- .main_gsub(argv) ⇒ Object
- .main_help(argv) ⇒ Object
- .main_join(argv) ⇒ Object
- .main_ls(argv) ⇒ Object
- .main_melt(argv) ⇒ Object
- .main_mheader(argv) ⇒ Object
- .main_nest(argv) ⇒ Object
- .main_newfield(argv) ⇒ Object
- .main_rename(argv) ⇒ Object
- .main_search(argv) ⇒ Object
- .main_shape(argv) ⇒ Object
- .main_sort(argv) ⇒ Object
- .main_svn(argv) ⇒ Object
- .main_tar(argv) ⇒ Object
- .main_to_csv(argv) ⇒ Object
- .main_to_json(argv) ⇒ Object
- .main_to_ltsv(argv) ⇒ Object
- .main_to_pnm(argv) ⇒ Object
- .main_to_pp(argv) ⇒ Object
- .main_to_tsv(argv) ⇒ Object
- .main_to_yaml(argv) ⇒ Object
- .main_unmelt(argv) ⇒ Object
- .main_unnest(argv) ⇒ Object
- .op_cat ⇒ Object
- .op_consecutive ⇒ Object
- .op_crop ⇒ Object
- .op_cross ⇒ Object
- .op_cut ⇒ Object
- .op_git ⇒ Object
- .op_group ⇒ Object
- .op_gsub ⇒ Object
- .op_help ⇒ Object
- .op_join ⇒ Object
- .op_ls ⇒ Object
- .op_melt ⇒ Object
- .op_mheader ⇒ Object
- .op_nest ⇒ Object
- .op_newfield ⇒ Object
- .op_rename ⇒ Object
- .op_search ⇒ Object
- .op_shape ⇒ Object
- .op_sort ⇒ Object
- .op_svn ⇒ Object
- .op_tar ⇒ Object
- .op_to_csv ⇒ Object
- .op_to_json ⇒ Object
- .op_to_ltsv ⇒ Object
- .op_to_pnm ⇒ Object
- .op_to_pp ⇒ Object
- .op_to_tsv ⇒ Object
- .op_to_yaml ⇒ Object
- .op_unmelt ⇒ Object
- .op_unnest ⇒ Object
- .show_help(subcommand) ⇒ Object
- .svn_with_svn_log(argv) ⇒ Object
- .tar_check_extension_record(reader, h, content_blocklength) ⇒ Object
- .tar_each(f) ⇒ Object
- .tar_format_filemode(typeflag, mode) ⇒ Object
- .tar_open_with(arg) ⇒ Object
- .tar_open_with0(arg) ⇒ Object
- .tar_parse_header(header_record) ⇒ Object
- .tar_parse_seconds_from_epoch(val) ⇒ Object
- .tar_read_end_of_archive_indicator(reader) ⇒ Object
- .usage_list_subcommands ⇒ Object
Instance Method Summary collapse
- #err(msg) ⇒ Object
- #output_tbenum(te) ⇒ Object
- #parse_aggregator_spec(spec) ⇒ Object
- #parse_aggregator_spec2(spec) ⇒ Object
- #split_csv_argument(arg) ⇒ Object
- #split_field_list_argument(arg) ⇒ Object
- #tablereader_open(filename, &b) ⇒ Object
- #with_output(filename = Tb::Cmd.opt_output) ⇒ Object
Class Method Details
.decode_a1_addressing_col(str) ⇒ Object
58 59 60 |
# File 'lib/tb/cmd_crop.rb', line 58 def (Tb::Cmd).decode_a1_addressing_col(str) (26**str.length-1)/25+str.tr("A-Z", "0-9A-P").to_i(26) end |
.exit_if_help(subcommand) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/tb/cmd_help.rb', line 86 def (Tb::Cmd).exit_if_help(subcommand) if 0 < Tb::Cmd.opt_help show_help(subcommand) exit end end |
.git_each_commit(f) ⇒ Object
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/tb/cmd_git.rb', line 196 def (Tb::Cmd).git_each_commit(f) while chunk = f.gets("\x01commit-separator\x01\n") chunk.chomp!("\x01commit-separator\x01\n") next if chunk.empty? # beginning of the output if /\nend-commit\n/ !~ chunk warn "unexpected git output (end-commit): #{chunk.inspect}" next end commit_info, files = $`, $' files.sub!(/\A\n/, '') h = git_parse_commit(commit_info, files) yield h end end |
.git_parse_commit(commit_info, files) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/tb/cmd_git.rb', line 148 def (Tb::Cmd).git_parse_commit(commit_info, files) commit_info = commit_info.split(/\n(?=[a-z])/) files_raw = {} files_numstat = {} files.split(/\n/).each {|file_line| if /\A:(\d+) (\d+) ([0-9a-f]+) ([0-9a-f]+) (\S+)\t(.+)\z/ =~ file_line mode1, mode2, hash1, hash2, status, filename = $1, $2, $3, $4, $5, $6 filename = git_unescape_filename(filename) files_raw[filename] = [mode1, mode2, hash1, hash2, status] elsif /\A(\d+|-)\t(\d+|-)\t(.+)\z/ =~ file_line add, del, filename = $1, $2, $3 add = add == '-' ? nil : add.to_i del = del == '-' ? nil : del.to_i filename = git_unescape_filename(filename) files_numstat[filename] = [add, del] else warn "unexpected git output (raw/numstat): #{file_line.inspect}" end } files_csv = "" files_csv << %w[mode1 mode2 hash1 hash2 add del status filename].to_csv files_raw.each {|filename, (mode1, mode2, hash1, hash2, status)| add, del = files_numstat[filename] files_csv << [mode1, mode2, hash1, hash2, add, del, status, filename].to_csv } h = {} commit_info.each {|s| if /:/ !~ s warn "unexpected git output (header:value): #{s.inspect}" next end k = $` v = $'.gsub(/\n /, "\n") # remove indent generated by %w(0,0,1) case k when /\A(?:author-date|committer-date)/ v = v.sub(/\A(\d+-\d\d-\d\d) (\d\d:\d\d:\d\d) ([-+]\d\d\d\d)\z/, '\1T\2\3') when /\Aparents\z/ v = ['parent', *v.split(/ /)].map {|c| c + "\n" }.join("") when /\Aref-names\z/ v = v.strip.gsub(/\A\(|\)\z/, '') v = ['ref-name', *v.split(/, /)].map {|c| c + "\n" }.join("") end h[k] = v } h['files'] = files_csv h end |
.git_unescape_filename(filename) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/tb/cmd_git.rb', line 121 def (Tb::Cmd).git_unescape_filename(filename) if /\A"/ =~ filename $'.chomp('"').gsub(/\\((\d\d\d)|[abtnvfr"\\])/) { str = $1 if $2 [str.to_i(8)].pack("C") else case str when 'a' then "\a" when 'b' then "\b" when 't' then "\t" when 'n' then "\n" when 'v' then "\v" when 'f' then "\f" when 'r' then "\r" when '"' then '"' when '\\' then "\\" else warn "unexpected escape: #{str.inspect}" end end } else filename end end |
.git_with_git_log(dir) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/tb/cmd_git.rb', line 86 def (Tb::Cmd).git_with_git_log(dir) if Tb::Cmd.opt_git_debug_input File.open(Tb::Cmd.opt_git_debug_input) {|f| yield f } else git = Tb::Cmd.opt_git_command || 'git' # depends Ruby 1.9. command = [ git, 'log', "--pretty=#{Tb::Cmd::GIT_LOG_PRETTY_FORMAT}", '--decorate=full', '--raw', '--numstat', '--abbrev=40', '.', {:chdir=>dir} ] $stderr.puts "git command line: #{command.inspect}" if 1 <= Tb::Cmd.opt_debug if Tb::Cmd.opt_git_debug_output # File.realdirpath is required before Ruby 2.0. command.last[:out] = File.realdirpath(Tb::Cmd.opt_git_debug_output) system(*command) File.open(Tb::Cmd.opt_git_debug_output) {|f| yield f } else IO.popen(command) {|f| yield f } end end end |
.list_summary_of_subcommands ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/tb/cmd_help.rb', line 46 def (Tb::Cmd).list_summary_of_subcommands with_output {|f| f.print "" subcommand_maxlen = Tb::Cmd.subcommands.map {|subcommand| subcommand.length }.max fmt = "%-#{subcommand_maxlen}s : %s" Tb::Cmd.subcommands.each {|subcommand| = self.subcommand_send("op", subcommand). summary = [/^Usage: (.*)\n(.*)/, 2] f.puts(fmt % [subcommand, summary]) } } end |
.main(argv) ⇒ Object
43 44 45 46 47 48 49 50 |
# File 'lib/tb/cmdmain.rb', line 43 def (Tb::Cmd).main(argv) main_body(argv) rescue SystemExit $stderr.puts $!. if $!. != 'exit' raise rescue Errno::EPIPE exit false end |
.main_body(argv) ⇒ Object
Copyright © 2011-2012 Tanaka Akira <[email protected]>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/tb/cmdmain.rb', line 29 def (Tb::Cmd).main_body(argv) subcommand = argv.shift if subcommand == '-h' || subcommand == '--help' main_help(argv) elsif Tb::Cmd.subcommands.include?(subcommand) self.subcommand_send("main", subcommand, argv) elsif subcommand == nil usage_list_subcommands true else err "unexpected subcommand: #{subcommand.inspect}" end end |
.main_cat(argv) ⇒ Object
61 62 63 64 65 66 67 |
# File 'lib/tb/cmd_cat.rb', line 61 def (Tb::Cmd).main_cat(argv) op_cat.parse!(argv) exit_if_help('cat') argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N, Tb::Cmd.opt_cat_with_filename) output_tbenum(creader) end |
.main_consecutive(argv) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/tb/cmd_consecutive.rb', line 56 def (Tb::Cmd).main_consecutive(argv) op_consecutive.parse!(argv) exit_if_help('consecutive') argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| buf = [] empty = true creader.with_cumulative_header {|header0| if header0 y.set_header header0.map {|f| (1..Tb::Cmd.opt_consecutive_n).map {|i| "#{f}_#{i}" } }.flatten(1) end }.each {|pairs, header| buf << pairs if buf.length == Tb::Cmd.opt_consecutive_n pairs2 = {} header.each {|f| Tb::Cmd.opt_consecutive_n.times {|i| ps = buf[i] next if !ps.has_key?(f) v = ps[f] if Tb::Cmd.opt_N pairs2[((f.to_i-1) * Tb::Cmd.opt_consecutive_n + i + 1).to_s] = v else pairs2["#{f}_#{i+1}"] = v end } } empty = false y.yield pairs2 buf.shift end } } output_tbenum(er) end |
.main_crop(argv) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/tb/cmd_crop.rb', line 62 def (Tb::Cmd).main_crop(argv) op_crop.parse!(argv) exit_if_help('crop') argv = ['-'] if argv.empty? stream = false if Tb::Cmd.opt_crop_range case Tb::Cmd.opt_crop_range when /\AR(\d+)C(\d+):R(\d+)C(\d+)\z/ # 1-based (R1C1 reference style) stream = true range_row1 = $1.to_i range_col1 = $2.to_i range_row2 = $3.to_i range_col2 = $4.to_i when /\A([A-Z]+)(\d+):([A-Z]+)(\d+)\z/ # 1-based (A1 reference style) stream = true range_col1 = decode_a1_addressing_col($1) range_row1 = $2.to_i range_col2 = decode_a1_addressing_col($3) range_row2 = $4.to_i else raise ArgumentError, "unexpected range argument: #{Tb::Cmd.opt_crop_range.inspect}" end end if stream creader = Tb::CatReader.open(argv, true) er = Tb::Enumerator.new {|y| rownum = 1 creader.each {|pairs| if range_row2 < rownum break end if range_row1 <= rownum pairs2 = pairs.reject {|f, v| f = f.to_i f < range_col1 || range_col2 < f } pairs2 = pairs2.map {|f, v| [(f.to_i - range_col1 + 1).to_s, v] } y.yield Hash[pairs2] end rownum += 1 } } Tb::Cmd.opt_N = true output_tbenum(er) else creader = Tb::CatReader.open(argv, true) last_nonempty_row = nil lmargin_min = nil ter = Enumerator.new {|y| numrows = 0 creader.each {|pairs| ary = [] pairs.each {|f, v| ary[f.to_i-1] = v } while !ary.empty? && (ary.last.nil? || ary.last == '') ary.pop end if numrows == 0 && ary.empty? next end if !ary.empty? lmargin = 0 while lmargin < ary.length if !ary[lmargin].nil? && ary[lmargin] != '' break end lmargin += 1 end if lmargin_min.nil? || lmargin < lmargin_min lmargin_min = lmargin end end last_nonempty_row = numrows if !ary.empty? y.yield ary numrows += 1 } }.to_fileenumerator er = Tb::Enumerator.new {|y| ter.each_with_index {|ary, rownum| if last_nonempty_row < rownum break end ary.slice!(0, lmargin_min) pairs = Hash[ary.map.with_index {|v, i| ["#{i+1}", v]}] y.yield pairs } } Tb::Cmd.opt_N = true output_tbenum(er) end end |
.main_cross(argv) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/tb/cmd_cross.rb', line 69 def (Tb::Cmd).main_cross(argv) op_cross.parse!(argv) exit_if_help('cross') err('no vkey-fields given.') if argv.empty? vkfs = split_field_list_argument(argv.shift) err('no hkey-fields given.') if argv.empty? hkfs = split_field_list_argument(argv.shift) vhkfs = vkfs + hkfs if Tb::Cmd.opt_cross_fields.empty? num_aggregate_fields = 1 opt_cross_fields = (vkfs + hkfs).map {|f| [f, Tb::Func::First, f] } + [['count', Tb::Func::Count, nil]] else num_aggregate_fields = Tb::Cmd.opt_cross_fields.length opt_cross_fields = (vkfs + hkfs).map {|f| [f, Tb::Func::First, f] } + Tb::Cmd.opt_cross_fields.map {|arg| agg_spec, new_field = split_field_list_argument(arg) new_field ||= agg_spec begin func_srcf = parse_aggregator_spec2(agg_spec) rescue ArgumentError err($!.) end [new_field, *func_srcf] } end argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| hvs_hash = {} hvs_list = nil aggs_hash = nil op = Tb::Zipper.new(opt_cross_fields.map {|dstf, func, srcf| func }) er = creader.with_header {|header0| vhkfs.each {|f| if !header0.include?(f) err("field not found: #{f}") end } }.extsort_reduce(op) {|pairs| vvs = vkfs.map {|f| pairs[f] } hvs = hkfs.map {|f| pairs[f] } vvsc = vvs.map {|v| Tb::Func.smart_cmp_value(v) } hvsc = hvs.map {|v| Tb::Func.smart_cmp_value(v) } hvs_hash[hvs] = hvsc aggs = opt_cross_fields.map {|dstf, func, srcf| func.start(srcf ? pairs[srcf] : true) } [[vvsc, hvsc], aggs] } all_representative = lambda {|_| 1 } all_before = lambda {|_| hvs_list = hvs_hash.keys.sort_by {|hvs| hvs_hash[hvs] } n = vkfs.length + hvs_list.length * num_aggregate_fields header1 = (1..n).map {|i| i.to_s } y.set_header header1 hkfs.each_with_index {|hkf, i| next if Tb::Cmd.opt_cross_compact && i == hkfs.length - 1 h1 = {} j = vkfs.length h1[j.to_s] = hkf hvs_list.each {|hkvs| num_aggregate_fields.times { j += 1 h1[j.to_s] = hkvs[i] } } y.yield h1 } h2 = {} j = 0 vkfs.each {|vkf| j += 1 h2[j.to_s] = vkf } hvs_list.each {|hkvs| opt_cross_fields.last(num_aggregate_fields).each {|dstf, func, srcf| j += 1 if Tb::Cmd.opt_cross_compact h2[j.to_s] = hkvs[-1] else h2[j.to_s] = dstf end } } y.yield h2 } v_representative = lambda {|((vvsc, _), _)| vvsc } v_before = lambda {|_| aggs_hash = {} } body = lambda {|(_, aggs)| hvs = aggs[vkfs.length, hkfs.length] aggs_hash[hvs] = op.aggregate(aggs) } v_after = lambda {|(_, aggs)| vvs = aggs[0, vkfs.length] ary = vvs hvs_list.each {|hvs| if aggs_hash.has_key? hvs ary.concat(aggs_hash[hvs].last(num_aggregate_fields)) else ary.concat([nil] * num_aggregate_fields) end } pairs = {} ary.each_with_index {|v, i| pairs[(i+1).to_s] = v } y.yield pairs } er.detect_nested_group_by( [[all_representative, all_before], [v_representative, v_before, v_after]]).each(&body) } Tb::Cmd.opt_N = true output_tbenum(er) end |
.main_cut(argv) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/tb/cmd_cut.rb', line 59 def (Tb::Cmd).main_cut(argv) op_cut.parse!(argv) exit_if_help('cut') err('no fields given.') if argv.empty? fs = split_field_list_argument(argv.shift) argv = ['-'] if argv.empty? Tb::CatReader.open(argv, Tb::Cmd.opt_N) {|tblreader| if Tb::Cmd.opt_cut_v er = Tb::Enumerator.new {|y| tblreader.with_header {|header0| if header0 y.set_header header0 - fs end }.each {|pairs| y.yield pairs.reject {|k, v| fs.include? k } } } output_tbenum(er) else er = Tb::Enumerator.new {|y| y.set_header fs tblreader.each {|pairs| y.yield pairs.reject {|k, v| !fs.include?(k) } } } output_tbenum(er) end } end |
.main_git(argv) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/tb/cmd_git.rb', line 212 def (Tb::Cmd).main_git(argv) op_git.parse!(argv) exit_if_help('git') argv = ['.'] if argv.empty? er = Tb::Enumerator.new {|y| y.set_header Tb::Cmd::GIT_LOG_HEADER argv.each {|dir| git_with_git_log(dir) {|f| f.set_encoding("ASCII-8BIT") if f.respond_to? :set_encoding git_each_commit(f) {|h| y.yield h } } } } output_tbenum(er) end |
.main_group(argv) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/tb/cmd_group.rb', line 76 def (Tb::Cmd).main_group(argv) op_group.parse!(argv) exit_if_help('group') err("no key fields given.") if argv.empty? kfs = split_field_list_argument(argv.shift) opt_group_fields = kfs.map {|f| [f, Tb::Func::First, f] } + Tb::Cmd.opt_group_fields.map {|arg| aggregation_spec, new_field = split_field_list_argument(arg) new_field ||= aggregation_spec [new_field, *begin parse_aggregator_spec2(aggregation_spec) rescue ArgumentError err($!.) end ] } argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) result = Tb::Enumerator.new {|y| op = Tb::Zipper.new(opt_group_fields.map {|dstf, func, srcf| func }) er = creader.extsort_reduce(op) {|pairs| [kfs.map {|f| Tb::Func.smart_cmp_value(pairs[f]) }, opt_group_fields.map {|dstf, func, srcf| func.start(srcf ? pairs[srcf] : true) } ] } fields = opt_group_fields.map {|dstf, func, srcf| dstf } y.set_header(fields) er.each {|_, vals| pairs = opt_group_fields.zip(vals).map {|(dstf, func, _), val| [dstf, func.aggregate(val)] } y.yield Hash[pairs] } } output_tbenum(result) end |
.main_gsub(argv) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/tb/cmd_gsub.rb', line 65 def (Tb::Cmd).main_gsub(argv) op_gsub.parse!(argv) exit_if_help('gsub') if Tb::Cmd.opt_gsub_e re = Regexp.new(Tb::Cmd.opt_gsub_e) else err('no regexp given.') if argv.empty? re = Regexp.new(argv.shift) end err('no substitution given.') if argv.empty? repl = argv.shift argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| creader.with_cumulative_header {|header0| if header0 y.set_header header0 end }.each {|pairs, header| fs = header.dup fs.pop while !fs.empty? && !pairs.has_key?(fs.last) if Tb::Cmd.opt_gsub_f pairs2 = pairs.map {|f, v| if f == Tb::Cmd.opt_gsub_f v ||= '' [f, v.gsub(re, repl)] else [f, v] end } else pairs2 = pairs.map {|f, v| v ||= '' [f, v.gsub(re, repl)] } end y.yield Hash[pairs2] } } output_tbenum(er) end |
.main_help(argv) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/tb/cmd_help.rb', line 108 def (Tb::Cmd).main_help(argv) op_help.parse!(argv) if Tb::Cmd.opt_help_s list_summary_of_subcommands exit elsif argv.empty? if Tb::Cmd.opt_help == 0 usage_list_subcommands return true else argv.unshift 'help' Tb::Cmd.opt_help -= 1 end end Tb::Cmd.opt_help += 1 subcommand = argv.shift exit_if_help(subcommand) end |
.main_join(argv) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/tb/cmd_join.rb', line 90 def (Tb::Cmd).main_join(argv) op_join.parse!(argv) exit_if_help('join') retain_left = Tb::Cmd.opt_join_retain_left retain_right = Tb::Cmd.opt_join_retain_right err('two tables required at least.') if argv.length < 2 result = tablereader_open(argv.shift) argv.each {|filename| tbl = tablereader_open(filename) $stderr.puts "shared keys: #{(result.list_fields & tbl.list_fields).inspect}" if 1 <= Tb::Cmd.opt_debug result = result.natjoin2_outer(tbl, Tb::Cmd.opt_join_outer_missing, retain_left, retain_right) } output_tbenum(result) end |
.main_ls(argv) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/tb/cmd_ls.rb', line 57 def (Tb::Cmd).main_ls(argv) op_ls.parse!(argv) exit_if_help('ls') argv = ['.'] if argv.empty? opts = { :a => Tb::Cmd.opt_ls_a, :A => Tb::Cmd.opt_ls_A, :l => Tb::Cmd.opt_ls_l, :R => Tb::Cmd.opt_ls_R, } ls = nil er = Tb::Enumerator.new {|y| ls = Tb::Cmd::Ls.new(y, opts) ls.set_header argv.each {|arg| ls.ls_run(Pathname(ls.real_pathname_string(arg))) } } output_tbenum(er) if ls.fail exit false end end |
.main_melt(argv) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/tb/cmd_melt.rb', line 79 def (Tb::Cmd).main_melt(argv) op_melt.parse!(argv) exit_if_help('melt') err('no key-fields given.') if argv.empty? key_fields = split_field_list_argument(argv.shift) key_fields_hash = Hash[key_fields.map {|f| [f, true] }] if Tb::Cmd.opt_melt_regexps.empty? && Tb::Cmd.opt_melt_list.empty? melt_fields_pattern = // else list = Tb::Cmd.opt_melt_list + Tb::Cmd.opt_melt_regexps melt_fields_pattern = /\A#{Regexp.union(list)}\z/ end argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| header = [] header << Tb::Cmd.opt_melt_recnum if Tb::Cmd.opt_melt_recnum header.concat key_fields header << Tb::Cmd.opt_melt_variable_field header << Tb::Cmd.opt_melt_value_field y.set_header header creader.each_with_index {|pairs, i| recnum = i + 1 h0 = {} h0[Tb::Cmd.opt_melt_recnum] = nil if Tb::Cmd.opt_melt_recnum key_fields.each {|kf| h0[kf] = pairs[kf] } pairs.each {|f, v| next if key_fields_hash[f] next if melt_fields_pattern !~ f h = h0.dup h[Tb::Cmd.opt_melt_recnum] = recnum if Tb::Cmd.opt_melt_recnum h[Tb::Cmd.opt_melt_variable_field] = f h[Tb::Cmd.opt_melt_value_field] = v y.yield h } } } output_tbenum(er) end |
.main_mheader(argv) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/tb/cmd_mheader.rb', line 57 def (Tb::Cmd).main_mheader(argv) op_mheader.parse!(argv) exit_if_help('mheader') argv = ['-'] if argv.empty? header = [] if Tb::Cmd.opt_mheader_count c = Tb::Cmd.opt_mheader_count header_end_p = lambda { c -= 1 c == 0 ? header.map {|a| a.compact.join(' ').strip } : nil } else header_end_p = lambda { h2 = header.map {|a| a.compact.join(' ').strip }.uniq header.length == h2.length ? h2 : nil } end creader = Tb::CatReader.open(argv, true) er = Tb::Enumerator.new {|y| creader.each {|pairs| if header ary = [] pairs.each {|f, v| ary[f.to_i-1] = v } ary.each_with_index {|v,i| header[i] ||= [] header[i] << v if header[i].empty? || header[i].last != v } h2 = header_end_p.call if h2 pairs2 = Hash[h2.map.with_index {|v, i| ["#{i+1}", v] }] y.yield pairs2 header = nil end else y.yield pairs end } } Tb::Cmd.opt_N = true output_tbenum(er) if header warn "unique header fields not recognized." end end |
.main_nest(argv) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/tb/cmd_nest.rb', line 61 def (Tb::Cmd).main_nest(argv) op_nest.parse!(argv) exit_if_help('nest') err('no fields given.') if argv.empty? fields = split_field_list_argument(argv.shift) newfield, *oldfields = fields oldfields_hash = {} oldfields.each {|f| oldfields_hash[f] = true } argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| sorted = creader.with_header {|header0| oldfields.each {|f| if !header0.include?(f) err("field not found: #{f.inspect}") end } y.set_header(header0.reject {|f| oldfields_hash[f] } + [newfield]) }.map {|pairs| cv = pairs.reject {|f, v| oldfields_hash[f] }.map {|f, v| [Tb::Func.smart_cmp_value(f), Tb::Func.smart_cmp_value(v)] }.sort [cv, pairs] } nested = nil before_group = lambda {|(_, _)| nested = [] } body = lambda {|(_, pairs)| nested << pairs.reject {|f, v| !oldfields_hash[f] } } after_group = lambda {|(_, last_pairs)| nested_csv = "" nested_csv << oldfields.to_csv nested.each {|npairs| nested_csv << oldfields.map {|of| npairs[of] }.to_csv } assoc = last_pairs.reject {|f, v| oldfields_hash[f] }.to_a assoc << [newfield, nested_csv] pairs = Hash[assoc] y.yield pairs } sorted.detect_group_by(before_group, after_group) {|cv,| cv }.each(&body) } output_tbenum(er) end |
.main_newfield(argv) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/tb/cmd_newfield.rb', line 61 def (Tb::Cmd).main_newfield(argv) op_newfield.parse!(argv) exit_if_help('newfield') err('no new field name given.') if argv.empty? field = argv.shift if Tb::Cmd.opt_newfield_ruby rubyexp = Tb::Cmd.opt_newfield_ruby pr = eval("lambda {|_| #{rubyexp} }") else err('no value given.') if argv.empty? value = argv.shift pr = lambda {|_| value } end argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = creader.newfield(field) {|pairs| pr.call(pairs) } output_tbenum(er) end |
.main_rename(argv) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/tb/cmd_rename.rb', line 59 def (Tb::Cmd).main_rename(argv) op_rename.parse!(argv) exit_if_help('rename') err('rename fields not given.') if argv.empty? fs = split_field_list_argument(argv.shift) argv = ['-'] if argv.empty? h = {} fs.each_slice(2) {|sf, df| h[sf] = df } creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| header = nil creader.with_header {|header0| header = header0 h.each {|sf, df| unless header.include? sf err "field not found: #{sf.inspect}" end } y.set_header header.map {|f| h.fetch(f, f) } }.each {|pairs| y.yield Hash[pairs.map {|f, v| [h.fetch(f, f), v] }] } } output_tbenum(er) end |
.main_search(argv) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/tb/cmd_search.rb', line 60 def (Tb::Cmd).main_search(argv) op_search.parse!(argv) exit_if_help('search') if Tb::Cmd.opt_search_ruby pred = eval("lambda {|_| #{Tb::Cmd.opt_search_ruby} }") elsif Tb::Cmd.opt_search_e re = Regexp.new(Tb::Cmd.opt_search_e) pred = Tb::Cmd.opt_search_f ? lambda {|_| re =~ _[Tb::Cmd.opt_search_f] } : lambda {|_| _.any? {|k, v| re =~ v.to_s } } else err("no regexp given.") if argv.empty? re = Regexp.new(argv.shift) pred = Tb::Cmd.opt_search_f ? lambda {|_| re =~ _[Tb::Cmd.opt_search_f] } : lambda {|_| _.any? {|k, v| re =~ v.to_s } } end opt_v = Tb::Cmd.opt_search_v ? true : false argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| header = nil creader.with_header {|header0| header = header0 y.set_header header }.each {|pairs| h = {} pairs.each {|f, v| h[f] = v } found = pred.call(h) found = opt_v ^ !!(found) if found y.yield pairs end } } output_tbenum(er) end |
.main_shape(argv) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/tb/cmd_shape.rb', line 61 def (Tb::Cmd).main_shape(argv) op_shape.parse!(argv) exit_if_help('shape') filenames = argv.empty? ? ['-'] : argv ter = Tb::Enumerator.new {|y| filenames.each {|filename| tablereader_open(filename) {|tblreader| tblreader.enable_warning = false if tblreader.respond_to? :enable_warning num_records = 0 num_header_fields = nil min_num_fields = nil max_num_fields = nil if tblreader.respond_to? :header_array_hook tblreader.header_array_hook = lambda {|header| num_header_fields = header.length } end if tblreader.respond_to? :row_array_hook tblreader.row_array_hook = lambda {|ary| n = ary.length if min_num_fields.nil? min_num_fields = max_num_fields = n else min_num_fields = n if n < min_num_fields max_num_fields = n if max_num_fields < n end } end min_num_pairs = nil max_num_pairs = nil tblreader.each {|pairs| num_records += 1 n = pairs.length if min_num_pairs.nil? min_num_pairs = max_num_pairs = n else min_num_pairs = n if n < min_num_pairs max_num_pairs = n if max_num_pairs < n end } h = { 'filename'=>filename, 'records'=>num_records, 'min_pairs'=>min_num_pairs, 'max_pairs'=>max_num_pairs, } h['header_fields'] = num_header_fields if num_header_fields h['min_fields'] = min_num_fields if min_num_fields h['max_fields'] = max_num_fields if max_num_fields y.yield(h) } } } Tb::Cmd.opt_N = false output_tbenum(ter) end |
.main_sort(argv) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/tb/cmd_sort.rb', line 64 def (Tb::Cmd).main_sort(argv) op_sort.parse!(argv) exit_if_help('sort') argv = ['-'] if argv.empty? if Tb::Cmd.opt_sort_f fs = split_field_list_argument(Tb::Cmd.opt_sort_f) else fs = nil end creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) header = [] if fs blk = lambda {|pairs| fs.map {|f| Tb::Func.smart_cmp_value(pairs[f]) } } else blk = lambda {|pairs| header.map {|f| Tb::Func.smart_cmp_value(pairs[f]) } } end if Tb::Cmd.opt_sort_r blk1 = blk blk = lambda {|pairs| Tb::RevCmp.new(blk1.call(pairs)) } end er = Tb::Enumerator.new {|y| creader.with_cumulative_header {|header0| if header0 y.set_header(header0) end }.each {|pairs, header1| header = header1 y.yield pairs } }.extsort_by(&blk) output_tbenum(er) end |
.main_svn(argv) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/tb/cmd_svn.rb', line 173 def (Tb::Cmd).main_svn(argv) op_svn.parse!(argv) exit_if_help('svn') er = Tb::Enumerator.new {|y| svn_with_svn_log(argv) {|f| listener = Tb::Cmd::SVNLOGListener.new(y) REXML::Parsers::StreamParser.new(f, listener).parse } } output_tbenum(er) end |
.main_tar(argv) ⇒ Object
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File 'lib/tb/cmd_tar.rb', line 494 def (Tb::Cmd).main_tar(argv) op_tar.parse!(argv) exit_if_help('tar') if Tb::Cmd.opt_tar_hash.any? {|alg| !Tb::Cmd::TAR_HASH_ALGORITHMS[alg] } STDERR.puts "Unexpected hash algorithm: #{Tb::Cmd.opt_tar_hash.reject {|alg| Tb::Cmd::TAR_HASH_ALGORITHMS[alg] }.join(",")}" exit false end argv = ['-'] if argv.empty? er = Tb::Enumerator.new {|y| if Tb::Cmd.opt_tar_l == 0 header = Tb::Cmd::TAR_CSV_HEADER else header = Tb::Cmd::TAR_CSV_LONG_HEADER end header += Tb::Cmd.opt_tar_hash y.set_header header argv.each {|filename| tar_open_with(filename) {|f| tar_each(f) {|h| formatted = {} formatted["mode"] = sprintf("0%o", h[:mode]) formatted["filemode"] = tar_format_filemode(h[:typeflag], h[:mode]) formatted["uid"] = h[:uid].to_s formatted["gid"] = h[:gid].to_s formatted["size"] = h[:size].to_s formatted["mtime"] = h[:mtime].iso8601(0 < Tb::Cmd.opt_tar_l ? 9 : 0) formatted["atime"] = h[:atime].iso8601(0 < Tb::Cmd.opt_tar_l ? 9 : 0) if h[:atime] formatted["ctime"] = h[:ctime].iso8601(0 < Tb::Cmd.opt_tar_l ? 9 : 0) if h[:ctime] formatted["user"] = h[:uname] formatted["group"] = h[:gname] formatted["devmajor"] = h[:devmajor].to_s formatted["devminor"] = h[:devminor].to_s formatted["path"] = h[:path] formatted["linkname"] = h[:linkname] formatted["size_in_tar"] = h[:size_in_tar] formatted["tar_chksum"] = h[:chksum] formatted["tar_typeflag"] = h[:typeflag] formatted["tar_magic"] = h[:magic] formatted["tar_version"] = h[:version] Tb::Cmd.opt_tar_hash.each {|alg| formatted[alg] = h[alg] } y.yield Hash[header.map {|f2| [f2, formatted[f2]] }] } } } } output_tbenum(er) end |
.main_to_csv(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/tb/cmd_to_csv.rb', line 39 def (Tb::Cmd).main_to_csv(argv) op_to_csv.parse!(argv) exit_if_help('to-csv') argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) header = [] ter = Tb::Enumerator.new {|y| creader.with_cumulative_header.each {|pairs, header1| header = header1 y.yield pairs } }.to_fileenumerator er = Tb::Enumerator.new {|y| y.set_header header ter.each {|pairs| y.yield Hash[header.map {|f| [f, pairs[f]] }] } } with_output {|out| er.write_to_csv(out, !Tb::Cmd.opt_N) } end |
.main_to_json(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/tb/cmd_to_json.rb', line 39 def (Tb::Cmd).main_to_json(argv) require 'json' op_to_json.parse!(argv) exit_if_help('to-json') argv = ['-'] if argv.empty? with_output {|out| out.print "[" sep = nil argv.each {|filename| sep = ",\n\n" if sep tablereader_open(filename) {|tblreader| tblreader.each {|pairs| out.print sep if sep out.print JSON.pretty_generate(pairs) sep = ",\n" } } } out.puts "]" } end |
.main_to_ltsv(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/tb/cmd_to_ltsv.rb', line 39 def (Tb::Cmd).main_to_ltsv(argv) op_to_ltsv.parse!(argv) exit_if_help('to-ltsv') argv = ['-'] if argv.empty? reader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) with_output {|out| reader.write_to_ltsv(out) } end |
.main_to_pnm(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/tb/cmd_to_pnm.rb', line 39 def (Tb::Cmd).main_to_pnm(argv) op_to_pnm.parse!(argv) exit_if_help('to-pnm') argv = ['-'] if argv.empty? reader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) with_output {|out| reader.write_to_pnm(out) } end |
.main_to_pp(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/tb/cmd_to_pp.rb', line 39 def (Tb::Cmd).main_to_pp(argv) op_to_pp.parse!(argv) exit_if_help('to-pp') argv.unshift '-' if argv.empty? with_output {|out| argv.each {|filename| tablereader_open(filename) {|tblreader| tblreader.each {|pairs| a = pairs.reject {|f, v| v.nil? } q = PP.new(out, 79) q.guard_inspect_key { q.group(1, '{', '}') { q.seplist(a, nil, :each) {|kv| k, v = kv q.group { q.pp k q.text '=>' q.group(1) { q.breakable '' q.pp v } } } } } q.flush out << "\n" } } } } end |
.main_to_tsv(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/tb/cmd_to_tsv.rb', line 39 def (Tb::Cmd).main_to_tsv(argv) op_to_tsv.parse!(argv) exit_if_help('to-tsv') argv = ['-'] if argv.empty? reader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) with_output {|out| reader.write_to_tsv(out, !Tb::Cmd.opt_N) } end |
.main_to_yaml(argv) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/tb/cmd_to_yaml.rb', line 39 def (Tb::Cmd).main_to_yaml(argv) require 'yaml' op_to_yaml.parse!(argv) exit_if_help('to-yaml') argv = ['-'] if argv.empty? reader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) ary = reader.to_a with_output {|out| YAML.dump(ary, out) out.puts } end |
.main_unmelt(argv) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/tb/cmd_unmelt.rb', line 76 def (Tb::Cmd).main_unmelt(argv) op_unmelt.parse!(argv) exit_if_help('unmelt') argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) if Tb::Cmd.opt_unmelt_keys.empty? key_fields = nil else if Tb::Cmd.opt_unmelt_recnum key_fields = [Tb::Cmd.opt_unmelt_recnum] else key_fields = [] end key_fields += Tb::Cmd.opt_unmelt_keys end melt_fields_hash = {} er = Tb::Enumerator.new {|y| creader.chunk {|pairs| keys = {} if key_fields key_fields.each {|k| keys[k] = pairs[k] } else pairs.each_key {|k| next if k == Tb::Cmd.opt_unmelt_variable_field || k == Tb::Cmd.opt_unmelt_value_field keys[k] = pairs[k] } end keys }.each {|keys, pairs_ary| if Tb::Cmd.opt_unmelt_recnum keys.delete Tb::Cmd.opt_unmelt_recnum end rec = keys.dup pairs_ary.each {|pairs| var = pairs[Tb::Cmd.opt_unmelt_variable_field] val = pairs[Tb::Cmd.opt_unmelt_value_field] melt_fields_hash[var] = true if rec.has_key? var y.yield rec rec = keys.dup end rec[var] = val } y.yield rec } } if !Tb::Cmd.opt_unmelt_missing_value er2 = er else er2 = Tb::Enumerator.new {|y| er.to_fileenumerator.with_header {|header| y.set_header header }.each {|pairs| melt_fields_hash.each_key {|f| pairs[f] ||= Tb::Cmd.opt_unmelt_missing_value } y.yield pairs } } end output_tbenum(er2) end |
.main_unnest(argv) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/tb/cmd_unnest.rb', line 65 def (Tb::Cmd).main_unnest(argv) op_unnest.parse!(argv) exit_if_help('unnest') err('no field given.') if argv.empty? target_field = argv.shift argv = ['-'] if argv.empty? creader = Tb::CatReader.open(argv, Tb::Cmd.opt_N) er = Tb::Enumerator.new {|y| nested_fields = {} ter = Tb::Enumerator.new {|y2| creader.with_header {|header0| unless header0.include? target_field err("field not found: #{target_field.inspect}") end y2.set_header header0 }.each {|pairs| pairs2 = {} pairs.each {|f, v| if f != target_field pairs2[f] = v elsif v.nil? pairs2[f] = v else aa = CSV.parse(v) reader = Tb::HeaderReader.new(lambda { aa.shift }) nested_tbl_rows = reader.to_a nested_tbl_header = reader.get_named_header nested_tbl_header.each {|f2| unless nested_fields.has_key? f2 nested_fields[f2] = nested_fields.size end } pairs2[f] = [nested_tbl_header, nested_tbl_rows] end } y2.yield pairs2 } }.to_fileenumerator nested_fields_ary = nested_fields.keys if Tb::Cmd.opt_unnest_prefix nested_fields_ary.map! {|f| Tb::Cmd.opt_unnest_prefix + f } end ter.with_header {|header0| header2 = [] header0.each {|f| if f != target_field header2 << f else header2.concat nested_fields_ary end } y.set_header header2 }.each {|pairs| pairs2 = {} pairs.each {|f, v| pairs2[f] = v if f != target_field } ntbl_header, ntbl_rows = pairs[target_field] if ntbl_header.nil? || ntbl_rows.empty? if Tb::Cmd.opt_unnest_outer y.yield pairs2 end else ntbl_rows.each {|npairs| pairs3 = pairs2.dup npairs.each {|nf, nv| if Tb::Cmd.opt_unnest_prefix nf = Tb::Cmd.opt_unnest_prefix + nf end pairs3[nf] = nv } y.yield pairs3 } end } } output_tbenum(er) end |
.op_cat ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/tb/cmd_cat.rb', line 33 def (Tb::Cmd).op_cat op = OptionParser.new op. = "Usage: tb cat [OPTS] [TABLE ...]\n" + "Concatenate tables vertically." define_common_option(op, "hNo", "--no-pager") op.def_option('-H', '--with-filename', 'add filename column') { Tb::Cmd.opt_cat_with_filename = true } op end |
.op_consecutive ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/tb/cmd_consecutive.rb', line 33 def (Tb::Cmd).op_consecutive op = OptionParser.new op. = "Usage: tb consecutive [OPTS] [TABLE ...]\n" + "Concatenate consecutive rows." define_common_option(op, "hNo", "--no-pager") op.def_option('-n NUM', 'gather NUM records. (default: 2)') {|n| Tb::Cmd.opt_consecutive_n = n.to_i } op end |
.op_crop ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/tb/cmd_crop.rb', line 33 def (Tb::Cmd).op_crop op = OptionParser.new op. = "Usage: tb crop [OPTS] [TABLE ...]\n" + "Extract rectangle in a table." define_common_option(op, "ho", "--no-pager") op.def_option('-r RANGE', 'range. i.e. "R2C1:R4C3", "B1:D3"') {|arg| Tb::Cmd.opt_crop_range = arg } op end |
.op_cross ⇒ Object
34 35 36 37 38 39 40 41 42 43 |
# File 'lib/tb/cmd_cross.rb', line 34 def (Tb::Cmd).op_cross op = OptionParser.new op. = "Usage: tb cross [OPTS] VKEY-FIELD1,... HKEY-FIELD1,... [TABLE ...]\n" + "Create a cross table. (a.k.a contingency table, pivot table)" define_common_option(op, "ho", "--no-pager") op.def_option('-a AGGREGATION-SPEC[,NEW-FIELD]', '--aggregate AGGREGATION-SPEC[,NEW-FIELD]') {|arg| Tb::Cmd.opt_cross_fields << arg } op.def_option('-c', '--compact', 'compact format') { Tb::Cmd.opt_cross_compact = true } op end |
.op_cut ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/tb/cmd_cut.rb', line 33 def (Tb::Cmd).op_cut op = OptionParser.new op. = "Usage: tb cut [OPTS] FIELD,... [TABLE]\n" + "Select columns." define_common_option(op, "hNo", "--no-pager") op.def_option('-v', 'invert match') { Tb::Cmd.opt_cut_v = true } op end |
.op_git ⇒ Object
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/tb/cmd_git.rb', line 35 def (Tb::Cmd).op_git op = OptionParser.new op. = "Usage: tb git [OPTS] [GIT-DIR ...]\n" + "Show the GIT log as a table." define_common_option(op, "hNod", "--no-pager", '--debug') op.def_option('--git-command COMMAND', 'specify the git command (default: git)') {|command| Tb::Cmd.opt_git_command = command } op.def_option('--debug-git-output FILE', 'store the raw output of git (for debug)') {|filename| Tb::Cmd.opt_git_debug_output = filename } op.def_option('--debug-git-input FILE', 'use the file as output of git (for debug)') {|filename| Tb::Cmd.opt_git_debug_input = filename } op end |
.op_group ⇒ Object
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/tb/cmd_group.rb', line 33 def (Tb::Cmd).op_group op = OptionParser.new op. = "Usage: tb group [OPTS] KEY-FIELD1,... [TABLE ...]\n" + "Group and aggregate rows." define_common_option(op, "hNo", "--no-pager") op.def_option('-a AGGREGATION-SPEC[,NEW-FIELD]', '--aggregate AGGREGATION-SPEC[,NEW-FIELD]') {|arg| Tb::Cmd.opt_group_fields << arg } op.def_option('--no-pager', 'don\'t use pager') { Tb::Cmd.opt_no_pager = true } op end |
.op_gsub ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/tb/cmd_gsub.rb', line 34 def (Tb::Cmd).op_gsub op = OptionParser.new op. = "Usage: tb gsub [OPTS] REGEXP STRING [TABLE ...]\n" + "Substitute cells." define_common_option(op, "hNo", "--no-pager") op.def_option('-f FIELD', 'target field') {|field| Tb::Cmd.opt_gsub_f = field } op.def_option('-e REGEXP', 'specify regexp, possibly begins with a hyphen') {|pattern| Tb::Cmd.opt_gsub_e = pattern } op end |
.op_help ⇒ Object
60 61 62 63 64 65 66 67 |
# File 'lib/tb/cmd_help.rb', line 60 def (Tb::Cmd).op_help op = OptionParser.new op. = "Usage: tb help [OPTS] [SUBCOMMAND]\n" + "Show help message of tb command." define_common_option(op, "hvo", "--no-pager") op.def_option('-s', 'show summary of subcommands') { Tb::Cmd.opt_help_s = true } op end |
.op_join ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/tb/cmd_join.rb', line 35 def (Tb::Cmd).op_join op = OptionParser.new op. = "Usage: tb join [OPTS] [TABLE1 TABLE2 ...]\n" + "Concatenate tables horizontally as left/right/full natural join." define_common_option(op, 'hNod', '--no-pager', '--debug') op.def_option('--outer', 'outer join') { Tb::Cmd.opt_join_retain_left = true Tb::Cmd.opt_join_retain_right = true } op.def_option('--left', 'left outer join') { Tb::Cmd.opt_join_retain_left = true Tb::Cmd.opt_join_retain_right = false } op.def_option('--right', 'right outer join') { Tb::Cmd.opt_join_retain_left = false Tb::Cmd.opt_join_retain_right = true } op.def_option('--outer-missing=DEFAULT', 'missing value for outer join') {|missing| if Tb::Cmd.opt_join_retain_left == nil Tb::Cmd.opt_join_retain_left = true Tb::Cmd.opt_join_retain_right = true end Tb::Cmd.opt_join_outer_missing = missing } op end |
.op_ls ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/tb/cmd_ls.rb', line 36 def (Tb::Cmd).op_ls op = OptionParser.new op. = "Usage: tb ls [OPTS] [FILE ...]\n" + "List directory entries as a table." define_common_option(op, "hNo", "--no-pager") op.def_option('-a', 'don\'t ignore filenames beginning with a period.') {|fs| Tb::Cmd.opt_ls_a = true } op.def_option('-A', 'don\'t ignore filenames beginning with a period, except "." and "..".') {|fs| Tb::Cmd.opt_ls_A = true } op.def_option('-l', 'show attributes. -ll for more attributes.') {|fs| Tb::Cmd.opt_ls_l += 1 } op.def_option('-R', 'recursive.') {|fs| Tb::Cmd.opt_ls_R = true } op end |
.op_melt ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/tb/cmd_melt.rb', line 37 def (Tb::Cmd).op_melt op = OptionParser.new op. = "Usage: tb melt KEY-FIELDS-LIST [OPTS] [TABLE ...]\n" + "split value fields into records." define_common_option(op, "hNo", "--no-pager") op.def_option('--recnum[=FIELD]', 'add recnum field (default don\'t add)') {|field| Tb::Cmd.opt_melt_recnum = field || 'recnum' } op.def_option('-R REGEXP', '--melt-regexp REGEXP', 'regexp for melt fields') {|regexp| Tb::Cmd.opt_melt_regexps << Regexp.compile(regexp) } op.def_option('--melt-fields FIELD,...', 'list of melt fields') {|fields| Tb::Cmd.opt_melt_list.concat split_field_list_argument(fields) } op.def_option('--variable-field FIELD', 'variable field. (default: variable)') {|field| Tb::Cmd.opt_melt_variable_field = field } op.def_option('--value-field FIELD', 'value field. (default: value)') {|field| Tb::Cmd.opt_melt_value_field = field } op end |
.op_mheader ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/tb/cmd_mheader.rb', line 33 def (Tb::Cmd).op_mheader op = OptionParser.new op. = "Usage: tb mheader [OPTS] [TABLE]\n" + "Collapse multi rows header." define_common_option(op, "ho", "--no-pager") op.def_option('-c N', 'number of header records') {|arg| Tb::Cmd.opt_mheader_count = arg.to_i } op end |
.op_nest ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_nest.rb', line 31 def (Tb::Cmd).op_nest op = OptionParser.new op. = "Usage: tb nest [OPTS] NEWFIELD,OLDFIELD1,OLDFIELD2,... [TABLE ...]\n" + "Nest fields." define_common_option(op, "hNo", "--no-pager") op end |
.op_newfield ⇒ Object
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/tb/cmd_newfield.rb', line 33 def (Tb::Cmd).op_newfield op = OptionParser.new op. = "Usage: tb newfield [OPTS] FIELD VALUE [TABLE]\n" + "Add a field." define_common_option(op, "ho", "--no-pager") op.def_option('--ruby RUBY-EXP', 'ruby expression to generate values. A hash is given as _. no VALUE argument.') {|ruby_exp| Tb::Cmd.opt_newfield_ruby = ruby_exp } op end |
.op_rename ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_rename.rb', line 31 def (Tb::Cmd).op_rename op = OptionParser.new op. = "Usage: tb rename [OPTS] SRC,DST,... [TABLE]\n" + "Rename field names." define_common_option(op, "ho", "--no-pager") op end |
.op_search ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/tb/cmd_search.rb', line 36 def (Tb::Cmd).op_search op = OptionParser.new op. = "Usage: tb search [OPTS] REGEXP [TABLE ...]\n" + "Search rows using regexp or ruby expression." define_common_option(op, "hNo", "--no-pager") op.def_option('-f FIELD', 'search field') {|field| Tb::Cmd.opt_search_f = field } op.def_option('-e REGEXP', 'specify a regexp.') {|pattern| Tb::Cmd.opt_search_e = pattern } op.def_option('--ruby RUBY-EXP', 'predicate written in ruby. A hash is given as _. no usual regexp argument.') {|ruby_exp| Tb::Cmd.opt_search_ruby = ruby_exp } op.def_option('-v', 'ouput the records which doesn\'t match') { Tb::Cmd.opt_search_v = true } op end |
.op_shape ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_shape.rb', line 31 def (Tb::Cmd).op_shape op = OptionParser.new op. = "Usage: tb shape [OPTS] [TABLE ...]\n" + "Show table size." define_common_option(op, "hNo", "--no-pager") op end |
.op_sort ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/tb/cmd_sort.rb', line 34 def (Tb::Cmd).op_sort op = OptionParser.new op. = "Usage: tb sort [OPTS] [TABLE]\n" + "Sort rows." define_common_option(op, "hNo", "--no-pager") op.def_option('-f FIELD,...', 'specify sort keys') {|fs| Tb::Cmd.opt_sort_f = fs } op.def_option('-r', '--reverse', 'reverse order') { Tb::Cmd.opt_sort_r = true } op end |
.op_svn ⇒ Object
36 37 38 39 40 41 42 43 44 |
# File 'lib/tb/cmd_svn.rb', line 36 def (Tb::Cmd).op_svn op = OptionParser.new op. = "Usage: tb svn [OPTS] -- [SVN-LOG-ARGS]\n" + "Show the SVN log as a table." define_common_option(op, "hNo", "--no-pager") op.def_option('--svn-command COMMAND', 'specify the svn command (default: svn)') {|command| Tb::Cmd.opt_svn_command = command } op.def_option('--svn-log-xml FILE', 'specify the result svn log --xml') {|filename| Tb::Cmd.opt_svn_log_xml = filename } op end |
.op_tar ⇒ Object
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/tb/cmd_tar.rb', line 35 def (Tb::Cmd).op_tar op = OptionParser.new op. = "Usage: tb tar [OPTS] [TAR-FILE ...]\n" + "Show the file listing of tar file." define_common_option(op, "hNo", "--no-pager") op.def_option('-l', 'show more attributes.') {|fs| Tb::Cmd.opt_tar_l += 1 } op.def_option('--ustar', 'ustar format (POSIX.1-1988). No GNU and POSIX.1-2001 extension.') {|fs| Tb::Cmd.opt_tar_ustar = true } op.def_option('--hash=ALGORITHMS', 'show the hash of contents. algorithms can be some of md5,sha256,sha384,sha512 (default: none)') {|hs| Tb::Cmd.opt_tar_hash.concat split_field_list_argument(hs) } op end |
.op_to_csv ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_csv.rb', line 31 def (Tb::Cmd).op_to_csv op = OptionParser.new op. = "Usage: tb to-csv [OPTS] [TABLE ...]\n" + "Convert a table to CSV (Comma Separated Values)." define_common_option(op, "hNo", "--no-pager") op end |
.op_to_json ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_json.rb', line 31 def (Tb::Cmd).op_to_json op = OptionParser.new op. = "Usage: tb to-json [OPTS] [TABLE]\n" + "Convert a table to JSON (JavaScript Object Notation)." define_common_option(op, "hNo", "--no-pager") op end |
.op_to_ltsv ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_ltsv.rb', line 31 def (Tb::Cmd).op_to_ltsv op = OptionParser.new op. = "Usage: tb to-ltsv [OPTS] [TABLE]\n" + "Convert a table to LTSV (Labeled Tab Separated Values)." define_common_option(op, "hNo", "--no-pager") op end |
.op_to_pnm ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_pnm.rb', line 31 def (Tb::Cmd).op_to_pnm op = OptionParser.new op. = "Usage: tb to-pnm [OPTS] [TABLE]\n" + "Convert a table to PNM (Portable Anymap: PPM, PGM, PBM)." define_common_option(op, "hNo", "--no-pager") op end |
.op_to_pp ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_pp.rb', line 31 def (Tb::Cmd).op_to_pp op = OptionParser.new op. = "Usage: tb to-pp [OPTS] [TABLE]\n" + "Convert a table to pretty printed format." define_common_option(op, "hNo", "--no-pager") op end |
.op_to_tsv ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_tsv.rb', line 31 def (Tb::Cmd).op_to_tsv op = OptionParser.new op. = "Usage: tb to-tsv [OPTS] [TABLE]\n" + "Convert a table to TSV (Tab Separated Values)." define_common_option(op, "hNo", "--no-pager") op end |
.op_to_yaml ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/tb/cmd_to_yaml.rb', line 31 def (Tb::Cmd).op_to_yaml op = OptionParser.new op. = "Usage: tb to-yaml [OPTS] [TABLE]\n" + "Convert a table to YAML (YAML Ain't a Markup Language)." define_common_option(op, "hNo", "--no-pager") op end |
.op_unmelt ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/tb/cmd_unmelt.rb', line 37 def (Tb::Cmd).op_unmelt op = OptionParser.new op. = "Usage: tb unmelt [OPTS] [TABLE ...]\n" + "merge melted records into a record." define_common_option(op, "hNo", "--no-pager") op.def_option('--recnum[=FIELD]', 'use FIELD as an additional key and remove it from the result. (default: not specified)') {|field| Tb::Cmd.opt_unmelt_recnum = field || 'recnum' } op.def_option('--keys FIELD,...', 'key fields. (default: all fields except variable and value)') {|fields| Tb::Cmd.opt_unmelt_keys.concat split_field_list_argument(fields) } op.def_option('--variable-field FIELD', 'variable field. (default: variable)') {|field| Tb::Cmd.opt_unmelt_variable_field = field } op.def_option('--value-field FIELD', 'value field. (default: value)') {|field| Tb::Cmd.opt_unmelt_value_field = field } op.def_option('--missing-value FIELD', 'used for missing values. (default: not specified)') {|value| Tb::Cmd.opt_unmelt_missing_value = value } op end |
.op_unnest ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/tb/cmd_unnest.rb', line 34 def (Tb::Cmd).op_unnest op = OptionParser.new op. = "Usage: tb unnest [OPTS] FIELD [TABLE ...]\n" + "Unnest a field." define_common_option(op, "hNo", "--no-pager") op.def_option('--prefix PREFIX', 'field prefix') {|prefix| Tb::Cmd.opt_unnest_prefix = prefix } op.def_option('--outer', 'retain rows for empty nested table') { Tb::Cmd.opt_unnest_outer = true } op end |
.show_help(subcommand) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/tb/cmd_help.rb', line 93 def (Tb::Cmd).show_help(subcommand) if Tb::Cmd.subcommands.include?(subcommand) with_output {|f| f.puts self.subcommand_send("op", subcommand) if 2 <= Tb::Cmd.opt_help && Tb::Cmd.verbose_help[subcommand] f.puts f.puts Tb::Cmd.verbose_help[subcommand] end } true else err "unexpected subcommand: #{subcommand.inspect}" end end |
.svn_with_svn_log(argv) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/tb/cmd_svn.rb', line 160 def (Tb::Cmd).svn_with_svn_log(argv) if Tb::Cmd.opt_svn_log_xml File.open(Tb::Cmd.opt_svn_log_xml) {|f| yield f } else svn = Tb::Cmd.opt_svn_command || 'svn' IO.popen([svn, 'log', '--xml', *argv]) {|f| yield f } end end |
.tar_check_extension_record(reader, h, content_blocklength) ⇒ Object
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
# File 'lib/tb/cmd_tar.rb', line 300 def (Tb::Cmd).tar_check_extension_record(reader, h, content_blocklength) prefix_parameters = {} case h[:typeflag] when 'L' # GNU content = reader.read_exactly(content_blocklength, 'GNU long file name')[0, h[:size]][/\A[^\0]*/] prefix_parameters[:path] = content return prefix_parameters when 'K' # GNU content = reader.read_exactly(content_blocklength, 'GNU long link name')[0, h[:size]][/\A[^\0]*/] prefix_parameters[:linkname] = content return prefix_parameters when 'x' # pax (POSIX.1-2001) content = reader.read_exactly(content_blocklength, 'pax Extended Header content')[0, h[:size]] while /\A(\d+) / =~ content lenlen = $&.length len = $1.to_i param = content[lenlen, len-lenlen] content = content[len..-1] if /\n\z/ =~ param param.chomp!("\n") else warn "pax hearder record doesn't end with a newline: #{param.inspect}" end if /=/ !~ param warn "pax hearder record doesn't contain a equal character: #{param.inspect}" else key = $` val = $' if Tb::Cmd::TAR_PAX_KEYWORD_RECOGNIZERS[key] if val == '' prefix_parameters[symkey] = nil else symkey, recognizer = Tb::Cmd::TAR_PAX_KEYWORD_RECOGNIZERS[key] prefix_parameters[symkey] = recognizer.call(val) end end end end return prefix_parameters end nil end |
.tar_each(f) ⇒ Object
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/tb/cmd_tar.rb', line 343 def (Tb::Cmd).tar_each(f) offset = 0 reader = Tb::Cmd::TarReader.new(f) prefix_parameters = {} while true header_record = reader.get_single_record("file header") if !header_record break end if /\A\0*\z/ =~ header_record tar_read_end_of_archive_indicator(reader) break end h = tar_parse_header(header_record) content_numrecords = (h[:size] + Tb::Cmd::TAR_RECORD_LENGTH - 1) / Tb::Cmd::TAR_RECORD_LENGTH content_blocklength = content_numrecords * Tb::Cmd::TAR_RECORD_LENGTH if !Tb::Cmd.opt_tar_ustar extension_params = tar_check_extension_record(reader, h, content_blocklength) if extension_params prefix_parameters.update extension_params next end end prefix_parameters.each {|k, v| if v.nil? h.delete k else h[k] = v end } case Tb::Cmd::TAR_TYPEFLAG[h[:typeflag]] when :link, :symlink, :directory, :character_special, :block_special, :fifo # xxx: hardlink may have contents for posix archive. else if Tb::Cmd.opt_tar_hash.empty? reader.skip(content_blocklength, 'file content') else reader.calculate_hash(content_blocklength, h[:size], Tb::Cmd.opt_tar_hash).each {|alg, result| h[alg] = result } end end h[:size_in_tar] = reader.offset - offset yield h offset = reader.offset prefix_parameters = {} end end |
.tar_format_filemode(typeflag, mode) ⇒ Object
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
# File 'lib/tb/cmd_tar.rb', line 464 def (Tb::Cmd).tar_format_filemode(typeflag, mode) entry_type = case Tb::Cmd::TAR_TYPEFLAG[typeflag] when :regular then '-' when :directory then 'd' when :character_special then 'c' when :block_special then 'b' when :fifo then 'p' when :symlink then 'l' when :link then 'h' when :contiguous then 'C' else '?' end m = mode sprintf("%s%c%c%c%c%c%c%c%c%c", entry_type, (m & 0400 == 0 ? ?- : ?r), (m & 0200 == 0 ? ?- : ?w), (m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) : (m & 04000 == 0 ? ?x : ?s)), (m & 0040 == 0 ? ?- : ?r), (m & 0020 == 0 ? ?- : ?w), (m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) : (m & 02000 == 0 ? ?x : ?s)), (m & 0004 == 0 ? ?- : ?r), (m & 0002 == 0 ? ?- : ?w), (m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) : (m & 01000 == 0 ? ?x : ?t))) end |
.tar_open_with(arg) ⇒ Object
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
# File 'lib/tb/cmd_tar.rb', line 402 def (Tb::Cmd).tar_open_with(arg) tar_open_with0(arg) {|f| magic = f.read(8) case magic when /\A\x1f\x8b/n, /\A\037\235/n # \x1f\x8b is gzip format. \037\235 is "compress" format of old Unix. decompression = ['gzip', '-dc'] when /\ABZh/ decompression = ['bzip2', '-dc'] when /\A\xFD7zXZ\x00/n decompression = ['xz', '-dc'] end begin f.rewind seek_success = true rescue Errno::ESPIPE seek_success = false end # Ruby 1.9 dependent. if decompression if seek_success IO.popen(decompression + [{:in => f}], 'rb') {|pipe| yield pipe } else IO.pipe {|r, w| w.binmode IO.popen(decompression + [{:in => r}], 'rb') {|pipe| w << magic th = Thread.new { IO.copy_stream(f, w) w.close } begin yield pipe ensure th.join end } } end else if seek_success yield f else IO.pipe {|r, w| w.binmode w << magic th = Thread.new { IO.copy_stream(f, w) w.close } begin yield r ensure th.join end } end end } end |
.tar_open_with0(arg) ⇒ Object
392 393 394 395 396 397 398 399 400 |
# File 'lib/tb/cmd_tar.rb', line 392 def (Tb::Cmd).tar_open_with0(arg) if arg == '-' yield $stdin else open(arg, 'rb') {|f| yield f } end end |
.tar_parse_header(header_record) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/tb/cmd_tar.rb', line 157 def (Tb::Cmd).tar_parse_header(header_record) ary = header_record.unpack(Tb::Cmd::TAR_HEADER_TEPMLATE) h = {} Tb::Cmd::TAR_HEADER_STRUCTURE.each_with_index {|(k, _), i| h[k] = ary[i] } [:mode, :uid, :gid, :size, :mtime, :chksum, :devmajor, :devminor].each {|k| h[k] = h[k].to_i(8) } h[:mtime] = Time.at(h[:mtime]) if h[:prefix].empty? h[:path] = h[:name] else h[:path] = h[:prefix] + '/' + h[:name] end header_record_for_chksum = header_record.dup header_record_for_chksum[148, 8] = ' ' * 8 if header_record_for_chksum.sum(0) != h[:chksum] warn "invalid checksum: #{h[:path].inspect}" end h end |
.tar_parse_seconds_from_epoch(val) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/tb/cmd_tar.rb', line 125 def (Tb::Cmd).tar_parse_seconds_from_epoch(val) if /\./ =~ val num = ($` + $').to_i den = 10 ** $'.length t = Rational(num, den) begin Time.at(t) rescue TypeError ti = t.floor Time.at(ti, ((t-ti) * 1000000).floor) end else Time.at(val.to_i) end end |
.tar_read_end_of_archive_indicator(reader) ⇒ Object
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/tb/cmd_tar.rb', line 284 def (Tb::Cmd).tar_read_end_of_archive_indicator(reader) # The end of archive indicator is two consecutive records of NULs. # The first record is already read. second_end_of_archive_indicator_record = reader.get_single_record("second record of the end of archive indicator") if !second_end_of_archive_indicator_record # some tarballs have only one record of NULs. return end if /\A\0*\z/ !~ second_end_of_archive_indicator_record warn "The second record of end of tar archive indicator is not zero" raise Tb::Cmd::TarFormatError end # It is acceptable that there may be garbage after the end of tar # archive indicator. ("ustar Interchange Format" in POSIX) end |
.usage_list_subcommands ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/tb/cmd_help.rb', line 33 def (Tb::Cmd).usage_list_subcommands with_output {|f| f.print "Usage:\n" Tb::Cmd.subcommands.each {|subcommand| = self.subcommand_send("op", subcommand). usage = [/^Usage: (.*)/, 1] f.puts " " + usage } } end |
Instance Method Details
#err(msg) ⇒ Object
95 96 97 |
# File 'lib/tb/cmdutil.rb', line 95 def err(msg) raise SystemExit.new(1, msg) end |
#output_tbenum(te) ⇒ Object
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/tb/cmdutil.rb', line 165 def output_tbenum(te) filename = Tb::Cmd.opt_output || '-' numeric = Tb::Cmd.opt_N filename, fmt = Tb.undecorate_filename(filename, numeric) factory = Tb::FormatHash.fetch(fmt)[:writer] with_output(filename) {|out| writer = factory.new(out) te.write_with(writer) } end |
#parse_aggregator_spec(spec) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/tb/cmdutil.rb', line 99 def parse_aggregator_spec(spec) case spec when 'count' ['count', nil] when /\Asum\((.*)\)\z/ ['sum', $1] when /\Aavg\((.*)\)\z/ ['avg', $1] when /\Amax\((.*)\)\z/ ['max', $1] when /\Amin\((.*)\)\z/ ['min', $1] when /\Avalues\((.*)\)\z/ ['values', $1] when /\Auniquevalues\((.*)\)\z/ ['uniquevalues', $1] else raise ArgumentError, "unexpected aggregation spec: #{spec.inspect}" end end |
#parse_aggregator_spec2(spec) ⇒ Object
120 121 122 123 124 125 126 127 |
# File 'lib/tb/cmdutil.rb', line 120 def parse_aggregator_spec2(spec) name, field = parse_aggregator_spec(spec) func = Tb::Func::AggregationFunctions[name] if !func raise ArgumentError, "unexpected aggregation spec: #{spec.inspect}" end [func, field] end |
#split_csv_argument(arg) ⇒ Object
133 134 135 |
# File 'lib/tb/cmdutil.rb', line 133 def split_csv_argument(arg) return CSV.new(arg).shift || [] end |
#split_field_list_argument(arg) ⇒ Object
129 130 131 |
# File 'lib/tb/cmdutil.rb', line 129 def split_field_list_argument(arg) split_csv_argument(arg).map {|f| f || '' } end |
#tablereader_open(filename, &b) ⇒ Object
137 138 139 |
# File 'lib/tb/cmdutil.rb', line 137 def tablereader_open(filename, &b) Tb.open_reader(filename, Tb::Cmd.opt_N, &b) end |
#with_output(filename = Tb::Cmd.opt_output) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/tb/cmdutil.rb', line 141 def with_output(filename=Tb::Cmd.opt_output) if filename && filename != '-' tmp = filename + ".part" begin File.open(tmp, 'w') {|f| yield f } if File.exist?(filename) && FileUtils.compare_file(filename, tmp) File.unlink tmp else File.rename tmp, filename end ensure File.unlink tmp if File.exist? tmp end elsif $stdout.tty? && !Tb::Cmd.opt_no_pager Tb::Pager.open {|pager| yield pager } else yield $stdout end end |