tb 0.9 → 1.0

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/README +13 -11
  3. data/lib/tb.rb +14 -6
  4. data/lib/tb/catreader.rb +2 -2
  5. data/lib/tb/cmd_consecutive.rb +6 -2
  6. data/lib/tb/cmd_crop.rb +22 -3
  7. data/lib/tb/cmd_cross.rb +24 -0
  8. data/lib/tb/cmd_cut.rb +20 -10
  9. data/lib/tb/cmd_git.rb +20 -7
  10. data/lib/tb/cmd_group.rb +32 -0
  11. data/lib/tb/cmd_gsub.rb +21 -0
  12. data/lib/tb/cmd_join.rb +28 -0
  13. data/lib/tb/cmd_ls.rb +9 -0
  14. data/lib/tb/cmd_melt.rb +15 -0
  15. data/lib/tb/cmd_mheader.rb +15 -0
  16. data/lib/tb/cmd_nest.rb +27 -6
  17. data/lib/tb/cmd_newfield.rb +19 -2
  18. data/lib/tb/cmd_rename.rb +20 -0
  19. data/lib/tb/{cmd_grep.rb → cmd_search.rb} +37 -23
  20. data/lib/tb/cmd_shape.rb +69 -25
  21. data/lib/tb/cmd_sort.rb +20 -0
  22. data/lib/tb/cmd_tar.rb +38 -0
  23. data/lib/tb/cmd_to_json.rb +2 -2
  24. data/lib/tb/cmd_to_ltsv.rb +3 -3
  25. data/lib/tb/cmd_to_pnm.rb +3 -3
  26. data/lib/tb/cmd_to_tsv.rb +3 -3
  27. data/lib/tb/cmd_to_yaml.rb +3 -3
  28. data/lib/tb/cmd_unmelt.rb +15 -0
  29. data/lib/tb/cmd_unnest.rb +31 -7
  30. data/lib/tb/cmdmain.rb +2 -0
  31. data/lib/tb/cmdtop.rb +1 -1
  32. data/lib/tb/cmdutil.rb +9 -62
  33. data/lib/tb/csv.rb +21 -79
  34. data/lib/tb/enumerable.rb +42 -68
  35. data/lib/tb/enumerator.rb +15 -7
  36. data/lib/tb/{fieldset.rb → hashreader.rb} +37 -56
  37. data/lib/tb/hashwriter.rb +54 -0
  38. data/lib/tb/headerreader.rb +108 -0
  39. data/lib/tb/headerwriter.rb +116 -0
  40. data/lib/tb/json.rb +17 -15
  41. data/lib/tb/ltsv.rb +35 -96
  42. data/lib/tb/ndjson.rb +63 -0
  43. data/lib/tb/numericreader.rb +66 -0
  44. data/lib/tb/numericwriter.rb +61 -0
  45. data/lib/tb/pnm.rb +206 -200
  46. data/lib/tb/ropen.rb +54 -59
  47. data/lib/tb/tsv.rb +39 -71
  48. data/sample/excel2csv +24 -25
  49. data/sample/poi-xls2csv.rb +13 -14
  50. data/tb.gemspec +154 -0
  51. data/test/test_cmd_cat.rb +28 -6
  52. data/test/test_cmd_consecutive.rb +8 -3
  53. data/test/test_cmd_cut.rb +14 -4
  54. data/test/test_cmd_git_log.rb +50 -50
  55. data/test/test_cmd_grep.rb +6 -6
  56. data/test/test_cmd_gsub.rb +7 -2
  57. data/test/test_cmd_ls.rb +70 -62
  58. data/test/test_cmd_shape.rb +43 -6
  59. data/test/test_cmd_svn_log.rb +26 -27
  60. data/test/test_cmd_to_csv.rb +10 -5
  61. data/test/test_cmd_to_json.rb +16 -0
  62. data/test/test_cmd_to_ltsv.rb +2 -2
  63. data/test/test_cmd_to_pp.rb +7 -2
  64. data/test/test_csv.rb +74 -62
  65. data/test/test_ex_enumerable.rb +0 -1
  66. data/test/test_fileenumerator.rb +3 -3
  67. data/test/test_headercsv.rb +43 -0
  68. data/test/test_json.rb +2 -2
  69. data/test/test_ltsv.rb +22 -17
  70. data/test/test_ndjson.rb +62 -0
  71. data/test/test_numericcsv.rb +36 -0
  72. data/test/test_pnm.rb +69 -70
  73. data/test/test_reader.rb +27 -124
  74. data/test/test_tbenum.rb +18 -18
  75. data/test/test_tsv.rb +21 -32
  76. data/test/util_tbtest.rb +12 -0
  77. metadata +41 -19
  78. data/lib/tb/basic.rb +0 -1070
  79. data/lib/tb/reader.rb +0 -106
  80. data/lib/tb/record.rb +0 -158
  81. data/test/test_basic.rb +0 -403
  82. data/test/test_fieldset.rb +0 -42
  83. data/test/test_record.rb +0 -61
@@ -1,6 +1,6 @@
1
- # lib/tb/ropen.rb - Tb::Reader.open
1
+ # lib/tb/ropen.rb - Tb.open_reader
2
2
  #
3
- # Copyright (C) 2011-2013 Tanaka Akira <akr@fsij.org>
3
+ # Copyright (C) 2011-2014 Tanaka Akira <akr@fsij.org>
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
6
6
  # modification, are permitted provided that the following conditions
@@ -28,70 +28,65 @@
28
28
  # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29
29
  # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
- def Tb.open_reader(filename, opts={})
32
- opts = opts.dup
33
- case filename
34
- when /\Acsv:/
35
- filename = $'
36
- table_reader_maker = lambda {|io| Tb::CSVReader.new(io) }
37
- when /\Atsv:/
38
- filename = $'
39
- table_reader_maker = lambda {|io| Tb::TSVReader.new(io) }
40
- when /\Altsv:/
41
- filename = $'
42
- pairs_reader_maker = lambda {|io| Tb::LTSVReader.new(io) }
43
- when /\Ap[pgbn]m:/
44
- filename = $'
45
- table_reader_maker = lambda {|io| Tb.pnm_stream_input(io) }
46
- when /\Ajson:/
47
- filename = $'
48
- whole_reader_maker = lambda {|io| Tb::JSONReader.new(io.read) }
49
- when /\.csv\z/
50
- table_reader_maker = lambda {|io| Tb::CSVReader.new(io) }
51
- when /\.tsv\z/
52
- table_reader_maker = lambda {|io| Tb::TSVReader.new(io) }
53
- when /\.ltsv\z/
54
- pairs_reader_maker = lambda {|io| Tb::LTSVReader.new(io) }
55
- when /\.p[pgbn]m\z/
56
- table_reader_maker = lambda {|io| Tb.pnm_stream_input(io) }
57
- when /\.json\z/
58
- whole_reader_maker = lambda {|io| Tb::JSONReader.new(io.read) }
31
+ Tb::FormatHash = {
32
+ 'csv' => { :reader => Tb::HeaderCSVReader, :writer => Tb::HeaderCSVWriter},
33
+ 'ncsv' => { :reader => Tb::NumericCSVReader, :writer => Tb::NumericCSVWriter},
34
+ 'tsv' => { :reader => Tb::HeaderTSVReader, :writer => Tb::HeaderTSVWriter},
35
+ 'ntsv' => { :reader => Tb::NumericTSVReader, :writer => Tb::NumericTSVWriter},
36
+ 'ltsv' => { :reader => Tb::LTSVReader, :writer => Tb::LTSVWriter},
37
+ 'pnm' => { :reader => Tb::PNMReader, :writer => Tb::PNMWriter},
38
+ 'ppm' => { :reader => Tb::PNMReader, :writer => Tb::PNMWriter},
39
+ 'pgm' => { :reader => Tb::PNMReader, :writer => Tb::PNMWriter},
40
+ 'pbm' => { :reader => Tb::PNMReader, :writer => Tb::PNMWriter},
41
+ 'json' => { :reader => Tb::JSONReader, :writer => Tb::JSONWriter},
42
+ 'ndjson' => { :reader => Tb::NDJSONReader, :writer => Tb::NDJSONWriter},
43
+ }
44
+
45
+ def Tb.undecorate_filename(filename, numeric)
46
+ if filename.respond_to?(:to_str)
47
+ filename = filename.to_str
48
+ elsif filename.respond_to?(:to_path)
49
+ filename = filename.to_path
59
50
  else
60
- table_reader_maker = lambda {|io| Tb::CSVReader.new(io) }
61
- end
62
- if !filename.respond_to?(:to_str) && !filename.respond_to?(:to_path)
63
51
  raise ArgumentError, "unexpected filename: #{filename.inspect}"
64
52
  end
65
- if whole_reader_maker
66
- if filename == '-'
67
- reader = whole_reader_maker.call($stdin)
68
- else
69
- reader = File.open(filename) {|io|
70
- whole_reader_maker.call(io)
71
- }
72
- end
73
- elsif pairs_reader_maker
74
- if filename == '-'
75
- reader = pairs_reader_maker.call($stdin)
76
- else
77
- reader = pairs_reader_maker.call(File.open(filename))
53
+ if /\A([a-z0-9]{2,}):/ =~ filename
54
+ fmt = $1
55
+ filename = $'
56
+ err("unexpected format: #{fmt.inspect}") if !Tb::FormatHash.has_key?(fmt)
57
+ elsif /\.([a-z0-9]+{2,})\z/ =~ filename
58
+ fmt = $1
59
+ fmt = 'csv' if !Tb::FormatHash.has_key?(fmt)
60
+ else
61
+ fmt = 'csv'
62
+ end
63
+ if numeric
64
+ case fmt
65
+ when 'csv' then fmt = 'ncsv'
66
+ when 'tsv' then fmt = 'ntsv'
78
67
  end
68
+ end
69
+ return filename, fmt
70
+ end
71
+
72
+ def Tb.open_reader(filename, numeric=false)
73
+ filename, fmt = Tb.undecorate_filename(filename, numeric)
74
+ factory = Tb::FormatHash.fetch(fmt)[:reader]
75
+ io_opened = nil
76
+ if filename == '-'
77
+ reader = factory.new($stdin)
79
78
  else
80
- # table_reader_maker should be available.
81
- reader = Tb::Reader.new(opts) {|body|
82
- if filename == '-'
83
- rawreader = table_reader_maker.call($stdin)
84
- body.call(rawreader)
85
- else
86
- File.open(filename) {|io|
87
- rawreader = table_reader_maker.call(io)
88
- body.call(rawreader)
89
- }
90
- end
91
- }
79
+ io_opened = File.open(filename)
80
+ reader = factory.new(io_opened)
92
81
  end
93
82
  if block_given?
94
- yield reader
83
+ begin
84
+ yield reader
85
+ ensure
86
+ if io_opened && !io_opened.closed?
87
+ io_opened.close
88
+ end
89
+ end
95
90
  else
96
91
  reader
97
92
  end
@@ -1,6 +1,6 @@
1
1
  # lib/tb/tsv.rb - TSV related fetures for table library
2
2
  #
3
- # Copyright (C) 2010-2012 Tanaka Akira <akr@fsij.org>
3
+ # Copyright (C) 2010-2014 Tanaka Akira <akr@fsij.org>
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without
6
6
  # modification, are permitted provided that the following conditions
@@ -30,89 +30,57 @@
30
30
 
31
31
  require 'stringio'
32
32
 
33
- class Tb
34
- def Tb.load_tsv(filename, *header_fields, &block)
35
- Tb.parse_tsv(File.read(filename), *header_fields, &block)
33
+ module Tb
34
+ def Tb.tsv_fields_join(values)
35
+ values.map {|v| v.to_s.gsub(/[\t\r\n]/, ' ') }.join("\t") + "\n"
36
36
  end
37
37
 
38
- def Tb.parse_tsv(tsv, *header_fields)
39
- aa = []
40
- tsv_stream_input(tsv) {|ary|
41
- aa << ary
42
- }
43
- aa = yield aa if block_given?
44
- if header_fields.empty?
45
- reader = Tb::Reader.new {|body| body.call(aa) }
46
- reader.to_tb
47
- else
48
- header = header_fields
49
- arys = aa
50
- t = Tb.new(header)
51
- arys.each {|ary|
52
- ary << nil while ary.length < header.length
53
- t.insert_values header, ary
54
- }
55
- t
56
- end
38
+ def Tb.tsv_fields_split(line)
39
+ line = line.chomp("\n")
40
+ line = line.chomp("\r")
41
+ line.split(/\t/, -1)
57
42
  end
58
43
 
59
- def Tb.tsv_stream_input(tsv)
60
- tsvreader = TSVReader.new(tsv)
61
- while ary = tsvreader.shift
62
- yield ary
44
+ class HeaderTSVReader < HeaderReader
45
+ def initialize(io)
46
+ super lambda {
47
+ line = io.gets
48
+ if line
49
+ Tb.tsv_fields_split(line)
50
+ else
51
+ nil
52
+ end
53
+ }
63
54
  end
64
- nil
65
55
  end
66
56
 
67
- class TSVReader
68
- def initialize(input)
69
- if input.respond_to? :to_str
70
- @input = StringIO.new(input)
71
- else
72
- @input = input
73
- end
74
- end
75
-
76
- def shift
77
- line = @input.gets
78
- return nil if !line
79
- line = line.chomp("\n")
80
- line = line.chomp("\r")
81
- line.split(/\t/, -1)
57
+ class HeaderTSVWriter < HeaderWriter
58
+ # io is an object which has "<<" method.
59
+ def initialize(io)
60
+ super lambda {|ary|
61
+ io << Tb.tsv_fields_join(ary)
62
+ }
82
63
  end
83
64
  end
84
65
 
85
- def Tb.tsv_stream_output(out)
86
- gen = Object.new
87
- gen.instance_variable_set(:@out, out)
88
- def gen.<<(ary)
89
- @out << Tb.tsv_fields_join(ary) << "\n"
66
+ class NumericTSVReader < NumericReader
67
+ def initialize(io)
68
+ super lambda {
69
+ line = io.gets
70
+ if line
71
+ Tb.tsv_fields_split(line)
72
+ else
73
+ nil
74
+ end
75
+ }
90
76
  end
91
- yield gen
92
77
  end
93
78
 
94
- # :call-seq:
95
- # generate_tsv(out='', fields=nil) {|recordids| modified_recordids }
96
- # generate_tsv(out='', fields=nil)
97
- #
98
- def generate_tsv(out='', fields=nil, &block)
99
- if fields.nil?
100
- fields = list_fields
101
- end
102
- recordids = list_recordids
103
- if block_given?
104
- recordids = yield(recordids)
105
- end
106
- Tb.tsv_stream_output(out) {|gen|
107
- gen << fields
108
- recordids.each {|recordid|
109
- gen << get_values(recordid, *fields)
79
+ class NumericTSVWriter < NumericWriter
80
+ def initialize(io)
81
+ super lambda {|ary|
82
+ io << Tb.tsv_fields_join(ary)
110
83
  }
111
- }
112
- out
113
- end
114
-
115
- def Tb.tsv_fields_join(values)
116
- values.map {|v| v.to_s.gsub(/[\t\r\n]/, ' ') }.join("\t")
84
+ end
117
85
  end
118
86
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  # sample/excel2csv - XLS to CSV converter using Microsoft Excel via WIN32OLE.
4
4
  #
5
- # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
5
+ # Copyright (C) 2011-2014 Tanaka Akira <akr@fsij.org>
6
6
  #
7
7
  # Redistribution and use in source and binary forms, with or without
8
8
  # modification, are permitted provided that the following conditions
@@ -205,7 +205,7 @@ end
205
205
  def generate_csv_row(csvgen, row)
206
206
  row = row.dup
207
207
  row.pop while !row.empty? && row.last.nil?
208
- csvgen << row
208
+ csvgen.call(row)
209
209
  end
210
210
 
211
211
  def convert_sheet(filename, sheet, csvgen)
@@ -243,30 +243,29 @@ excel = WIN32OLE.new('Excel.Application')
243
243
  WIN32OLE.const_load(excel,Excel)
244
244
  begin
245
245
  excel.displayAlerts = false
246
- Tb.csv_stream_output($stdout) {|csvgen|
247
- ARGV.each {|excel_filename|
248
- if File.directory? excel_filename
249
- filenames = []
250
- Find.find(excel_filename) {|path| filenames << path if /\.xls\z/ =~ path }
251
- else
252
- filenames = [excel_filename]
253
- end
254
- filenames.each {|ifn0|
255
- ifn = getAbsolutePath(ifn0)
256
- wb = excel.Workbooks.Open(ifn)
257
- begin
258
- if $opt_all_sheets
259
- wb.Worksheets.each {|sheet|
260
- sheetname = sheet.Name
261
- convert_sheet(ifn0, sheet, csvgen)
262
- }
263
- else
264
- convert_sheet(ifn0, wb.Worksheets(1), csvgen)
265
- end
266
- ensure
267
- wb.Close
246
+ csvgen = lambda {|row| $stdout << row.to_csv }
247
+ ARGV.each {|excel_filename|
248
+ if File.directory? excel_filename
249
+ filenames = []
250
+ Find.find(excel_filename) {|path| filenames << path if /\.xls\z/ =~ path }
251
+ else
252
+ filenames = [excel_filename]
253
+ end
254
+ filenames.each {|ifn0|
255
+ ifn = getAbsolutePath(ifn0)
256
+ wb = excel.Workbooks.Open(ifn)
257
+ begin
258
+ if $opt_all_sheets
259
+ wb.Worksheets.each {|sheet|
260
+ sheetname = sheet.Name
261
+ convert_sheet(ifn0, sheet, csvgen)
262
+ }
263
+ else
264
+ convert_sheet(ifn0, wb.Worksheets(1), csvgen)
268
265
  end
269
- }
266
+ ensure
267
+ wb.Close
268
+ end
270
269
  }
271
270
  }
272
271
  ensure
@@ -2,7 +2,7 @@
2
2
 
3
3
  # sample/poi-xls2csv.rb - XLS to CSV convert using Apache POI with JRuby.
4
4
  #
5
- # Copyright (C) 2011-2012 Tanaka Akira <akr@fsij.org>
5
+ # Copyright (C) 2011-2014 Tanaka Akira <akr@fsij.org>
6
6
  #
7
7
  # Redistribution and use in source and binary forms, with or without
8
8
  # modification, are permitted provided that the following conditions
@@ -354,7 +354,7 @@ def convert_sheet(filename, book, i, csvgen)
354
354
  sheetname += ":sheetname" if $opt_type
355
355
  sheet_header << sheetname
356
356
  end
357
- csvgen << (sheet_header + convert_horizontal_borders(sheet, merged, rownums.first-1, min_firstcol)) if $opt_border
357
+ csvgen.call (sheet_header + convert_horizontal_borders(sheet, merged, rownums.first-1, min_firstcol)) if $opt_border
358
358
  rownums.each {|y|
359
359
  record = []
360
360
  row = sheet.getRow(y)
@@ -370,8 +370,8 @@ def convert_sheet(filename, book, i, csvgen)
370
370
  }
371
371
  end
372
372
  end
373
- csvgen << (sheet_header + record)
374
- csvgen << (sheet_header + convert_horizontal_borders(sheet, merged, y, min_firstcol)) if $opt_border
373
+ csvgen.call (sheet_header + record)
374
+ csvgen.call (sheet_header + convert_horizontal_borders(sheet, merged, y, min_firstcol)) if $opt_border
375
375
  }
376
376
  end
377
377
 
@@ -386,16 +386,15 @@ def convert_book(filename, input, csvgen)
386
386
  end
387
387
  end
388
388
 
389
- Tb.csv_stream_output($stdout) {|csvgen|
390
- argv = ARGV.empty? ? ['-'] : ARGV
391
- argv.each {|filename|
392
- if filename == '-'
393
- input = java.lang.System.in
394
- else
395
- input = java.io.FileInputStream.new(filename)
396
- end
397
- convert_book(filename, input, csvgen)
398
- }
389
+ csvgen = lambdas {|row| $stdout << row.to_csv }
390
+ argv = ARGV.empty? ? ['-'] : ARGV
391
+ argv.each {|filename|
392
+ if filename == '-'
393
+ input = java.lang.System.in
394
+ else
395
+ input = java.io.FileInputStream.new(filename)
396
+ end
397
+ convert_book(filename, input, csvgen)
399
398
  }
400
399
 
401
400
  exit true
@@ -0,0 +1,154 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'tb'
3
+ s.version = '1.0'
4
+ s.date = '2014-10-29'
5
+ s.author = 'Tanaka Akira'
6
+ s.email = 'akr@fsij.org'
7
+ s.required_ruby_version = '>= 1.9.2'
8
+ s.add_development_dependency 'test-unit', '~> 2.5.5'
9
+ s.files = %w[
10
+ README
11
+ bin/tb
12
+ lib/tb.rb
13
+ lib/tb/catreader.rb
14
+ lib/tb/cmd_cat.rb
15
+ lib/tb/cmd_consecutive.rb
16
+ lib/tb/cmd_crop.rb
17
+ lib/tb/cmd_cross.rb
18
+ lib/tb/cmd_cut.rb
19
+ lib/tb/cmd_git.rb
20
+ lib/tb/cmd_group.rb
21
+ lib/tb/cmd_gsub.rb
22
+ lib/tb/cmd_help.rb
23
+ lib/tb/cmd_join.rb
24
+ lib/tb/cmd_ls.rb
25
+ lib/tb/cmd_melt.rb
26
+ lib/tb/cmd_mheader.rb
27
+ lib/tb/cmd_nest.rb
28
+ lib/tb/cmd_newfield.rb
29
+ lib/tb/cmd_rename.rb
30
+ lib/tb/cmd_search.rb
31
+ lib/tb/cmd_shape.rb
32
+ lib/tb/cmd_sort.rb
33
+ lib/tb/cmd_svn.rb
34
+ lib/tb/cmd_tar.rb
35
+ lib/tb/cmd_to_csv.rb
36
+ lib/tb/cmd_to_json.rb
37
+ lib/tb/cmd_to_ltsv.rb
38
+ lib/tb/cmd_to_pnm.rb
39
+ lib/tb/cmd_to_pp.rb
40
+ lib/tb/cmd_to_tsv.rb
41
+ lib/tb/cmd_to_yaml.rb
42
+ lib/tb/cmd_unmelt.rb
43
+ lib/tb/cmd_unnest.rb
44
+ lib/tb/cmdmain.rb
45
+ lib/tb/cmdtop.rb
46
+ lib/tb/cmdutil.rb
47
+ lib/tb/csv.rb
48
+ lib/tb/customcmp.rb
49
+ lib/tb/customeq.rb
50
+ lib/tb/enumerable.rb
51
+ lib/tb/enumerator.rb
52
+ lib/tb/ex_enumerable.rb
53
+ lib/tb/ex_enumerator.rb
54
+ lib/tb/fileenumerator.rb
55
+ lib/tb/func.rb
56
+ lib/tb/hashreader.rb
57
+ lib/tb/hashwriter.rb
58
+ lib/tb/headerreader.rb
59
+ lib/tb/headerwriter.rb
60
+ lib/tb/json.rb
61
+ lib/tb/ltsv.rb
62
+ lib/tb/ndjson.rb
63
+ lib/tb/numericreader.rb
64
+ lib/tb/numericwriter.rb
65
+ lib/tb/pager.rb
66
+ lib/tb/pnm.rb
67
+ lib/tb/revcmp.rb
68
+ lib/tb/ropen.rb
69
+ lib/tb/search.rb
70
+ lib/tb/tsv.rb
71
+ lib/tb/zipper.rb
72
+ sample/colors.ppm
73
+ sample/excel2csv
74
+ sample/gradation.pgm
75
+ sample/langs.csv
76
+ sample/poi-xls2csv.rb
77
+ sample/poi-xls2csv.sh
78
+ sample/tbplot
79
+ tb.gemspec
80
+ test-all-cov.rb
81
+ test-all.rb
82
+ ]
83
+ s.test_files = %w[
84
+ test/test_catreader.rb
85
+ test/test_cmd_cat.rb
86
+ test/test_cmd_consecutive.rb
87
+ test/test_cmd_crop.rb
88
+ test/test_cmd_cross.rb
89
+ test/test_cmd_cut.rb
90
+ test/test_cmd_git_log.rb
91
+ test/test_cmd_grep.rb
92
+ test/test_cmd_group.rb
93
+ test/test_cmd_gsub.rb
94
+ test/test_cmd_help.rb
95
+ test/test_cmd_join.rb
96
+ test/test_cmd_ls.rb
97
+ test/test_cmd_melt.rb
98
+ test/test_cmd_mheader.rb
99
+ test/test_cmd_nest.rb
100
+ test/test_cmd_newfield.rb
101
+ test/test_cmd_rename.rb
102
+ test/test_cmd_shape.rb
103
+ test/test_cmd_sort.rb
104
+ test/test_cmd_svn_log.rb
105
+ test/test_cmd_tar_tvf.rb
106
+ test/test_cmd_to_csv.rb
107
+ test/test_cmd_to_json.rb
108
+ test/test_cmd_to_ltsv.rb
109
+ test/test_cmd_to_pnm.rb
110
+ test/test_cmd_to_pp.rb
111
+ test/test_cmd_to_tsv.rb
112
+ test/test_cmd_to_yaml.rb
113
+ test/test_cmd_unmelt.rb
114
+ test/test_cmd_unnest.rb
115
+ test/test_cmdtty.rb
116
+ test/test_cmdutil.rb
117
+ test/test_csv.rb
118
+ test/test_customcmp.rb
119
+ test/test_customeq.rb
120
+ test/test_ex_enumerable.rb
121
+ test/test_fileenumerator.rb
122
+ test/test_headercsv.rb
123
+ test/test_json.rb
124
+ test/test_ltsv.rb
125
+ test/test_ndjson.rb
126
+ test/test_numericcsv.rb
127
+ test/test_pager.rb
128
+ test/test_pnm.rb
129
+ test/test_reader.rb
130
+ test/test_revcmp.rb
131
+ test/test_search.rb
132
+ test/test_tbenum.rb
133
+ test/test_tsv.rb
134
+ test/test_zipper.rb
135
+ test/util_tbtest.rb
136
+ ]
137
+ s.has_rdoc = true
138
+ s.homepage = 'https://github.com/akr/tb'
139
+ s.require_path = 'lib'
140
+ s.executables << 'tb'
141
+ s.summary = 'manipulation tool for tables: CSV, TSV, LTSV, JSON, NDJSON, etc.'
142
+ s.description = <<'End'
143
+ tb is a manipulation tool for tables.
144
+
145
+ tb provides a command and a library for manipulating tables:
146
+ Unix filter like operations (sort, cat, cut, ls, etc.),
147
+ SQL like operations (join, group, etc.),
148
+ other table operations (search, gsub, rename, cross, melt, unmelt, etc.),
149
+ information extractions (git, svn, tar),
150
+ and more.
151
+
152
+ tb supports various table formats: CSV, TSV, JSON, NDJSON, LTSV, etc.
153
+ End
154
+ end