tabreader 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '093433817ddd93e79af07604a115964639269b2a'
4
- data.tar.gz: 85d0c1333b75670230133e73f91cda27c1bb68ba
3
+ metadata.gz: 67dbbade5c8b10576053c868e1514c1f87ebb6c7
4
+ data.tar.gz: 2a65adb418fbb89876c47f0427473c0ec7cc3448
5
5
  SHA512:
6
- metadata.gz: 0c254861cd86e97d23b7f020d9a1323314b036964f3b14551da66f8e6f4c2948ea6c6874b3121c82f34070c13606f4631721d532408899a0393064311dcc71ff
7
- data.tar.gz: 9baa9df8979c3eb1923c31ae4344e57926f4c1e431c3d6c4b7567e92cf5bbf9348e55b08756e04cc2a98cfd5978f0c12792d17fb6d713525ab80d008ae2511d5
6
+ metadata.gz: e15ec15bf2e2ee097ef9e58aafca69a68c0796e3ccea125367b47a0ca81497373d7058e4e66c9328e463bc915cc7e6c6c7eb6e105612d6a558e2baecdc4c70ca
7
+ data.tar.gz: a900e51d7b15a509b8457b848c46ffc73fc3c26e41850671d5bc46416a99f45b5b006d6af38f3d23f2c0ee2ff5062ca4f515450d460742dd0551f5183d8f1db4
data/Manifest.txt CHANGED
@@ -5,8 +5,10 @@ README.md
5
5
  Rakefile
6
6
  lib/tabreader.rb
7
7
  lib/tabreader/reader.rb
8
+ lib/tabreader/reader_hash.rb
8
9
  lib/tabreader/version.rb
9
10
  test/data/empty.tab
10
11
  test/data/test.tab
11
12
  test/helper.rb
12
13
  test/test_reader.rb
14
+ test/test_reader_hash.rb
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # tabreader - read in tabular datafiles in text in the tab format
1
+ # tabreader - read in tabular datafiles in text in the tabular (TAB) format
2
2
 
3
- * home :: [github.com/datatxt/tabreader](https://github.com/datatxt/tabreader)
4
- * bugs :: [github.com/datatxt/tabreader/issues](https://github.com/datatxt/tabreader/issues)
3
+ * home :: [github.com/csv11/tabreader](https://github.com/csv11/tabreader)
4
+ * bugs :: [github.com/csv11/tabreader/issues](https://github.com/csv11/tabreader/issues)
5
5
  * gem :: [rubygems.org/gems/tabreader](https://rubygems.org/gems/tabreader)
6
6
  * rdoc :: [rubydoc.info/gems/tabreader](http://rubydoc.info/gems/tabreader)
7
7
  * forum :: [wwwmake](http://groups.google.com/group/wwwmake)
@@ -22,7 +22,7 @@ or the "magic" packaged up in `TabReader`:
22
22
 
23
23
  ``` ruby
24
24
  line = "1\t2\t3"
25
- values = TabReader.parse_line( line )
25
+ values = Tab.parse_line( line ) ## or TAB.parse_line or TabReader.parse_line
26
26
  pp values
27
27
  # => ["1","2","3"]
28
28
  ```
@@ -30,58 +30,84 @@ pp values
30
30
  or use the convenience helpers:
31
31
 
32
32
  ``` ruby
33
- txt <<=TAB
33
+ txt <<=TXT
34
34
  1\t2\t3
35
35
  4\t5\t6
36
- TAB
36
+ TXT
37
37
 
38
- records = TabReader.parse( txt )
38
+ records = Tab.parse( txt ) ## or TAB.parse or TabReader.parse
39
39
  pp records
40
40
  # => [["1","2","3"],
41
- # ["5","6","7"]]
41
+ # ["4","5","6"]]
42
42
 
43
43
  # -or-
44
44
 
45
- records = TabReader.read( "values.tab" )
45
+ records = Tab.read( "values.tab" ) ## or TAB.read or TabReader.read
46
46
  pp records
47
47
  # => [["1","2","3"],
48
- # ["5","6","7"]]
48
+ # ["4","5","6"]]
49
49
 
50
50
  # -or-
51
51
 
52
- TabReader.foreach( "values.tab" ) do |rec|
52
+ Tab.foreach( "values.tab" ) do |rec| ## or TAB.foreach or TabReader.foreach
53
53
  pp rec
54
54
  end
55
55
  # => ["1","2","3"]
56
- # => ["5","6","7"]
56
+ # => ["4","5","6"]
57
+ ```
58
+
59
+
60
+
61
+ ### What about Enumerable?
62
+
63
+ Yes, every reader includes `Enumerable` and runs on `each`.
64
+ Use `new` or `open` without a block
65
+ to get the enumerator (iterator).
66
+ Example:
67
+
68
+
69
+ ``` ruby
70
+ tab = Tab.new( "a\tb\tc" ) ## or TAB.new or TabReader.new
71
+ it = tab.to_enum
72
+ pp it.next
73
+ # => ["a","b","c"]
74
+
75
+ # -or-
76
+
77
+ tab = Tab.open( "values.tab" ) ## or TAB.open or TabReader.open
78
+ it = tab.to_enum
79
+ pp it.next
80
+ # => ["1","2","3"]
81
+ pp it.next
82
+ # => ["4","5","6"]
57
83
  ```
58
84
 
59
85
 
60
86
  ### What about headers?
61
87
 
62
- Use the `TabHashReader`
88
+ Use the `TabHash`
63
89
  if the first line is a header (or if missing pass in the headers
64
90
  as an array) and you want your records as hashes instead of arrays of values.
65
91
  Example:
66
92
 
67
93
  ``` ruby
68
- txt <<=TAB
94
+ txt <<=TXT
69
95
  A\tB\tC
70
96
  1\t2\t3
71
97
  4\t5\t6
72
- TAB
98
+ TXT
73
99
 
74
- records = TabHashReader.parse( txt )
100
+ records = TabHash.parse( txt ) ## or TabHashReader
75
101
  pp records
76
102
 
77
103
  # -or-
78
104
 
79
- txt2 <<=TAB
105
+ txt2 <<=TXT
80
106
  1\t2\t3
81
107
  4\t5\t6
82
- TAB
108
+ TXT
83
109
 
84
- records = TabHashReader.parse( txt2, headers: ["A","B","C"] )
110
+ records = TabHash.parse( txt2, headers: ["A","B","C"] )
85
111
  pp records
86
112
 
87
113
  # => [{"A": "1", "B": "2", "C": "3"},
@@ -89,14 +115,14 @@ pp records
89
115
 
90
116
  # -or-
91
117
 
92
- records = TabHashReader.read( "hash.tab" )
118
+ records = TabHash.read( "hash.tab" )
93
119
  pp records
94
120
  # => [{"A": "1", "B": "2", "C": "3"},
95
121
  # {"A": "4", "B": "5", "C": "6"}]
96
122
 
97
123
  # -or-
98
124
 
99
- TabHashReader.foreach( "hash.tab" ) do |rec|
125
+ TabHash.foreach( "hash.tab" ) do |rec|
100
126
  pp rec
101
127
  end
102
128
  # => {"A": "1", "B": "2", "C": "3"}
@@ -109,11 +135,11 @@ end
109
135
 
110
136
  ## Frequently Asked Questions (FAQ) and Answers
111
137
 
112
- ### Q: Why NOT use `CSV.read( col_sep: "\t", quote_char: "∅" )`?
138
+ ### Q: Why NOT use `Csv.read( sep: "\t" )`?
113
139
 
114
- Tab != CSV
140
+ TAB != CSV
115
141
 
116
- The tab format is an (even) simpler format than
142
+ The tabulator (TAB) format is an (even) simpler format than
117
143
  the comma-separated values (CSV) classic format. How?
118
144
 
119
145
  The tab format has NO escape rules.
@@ -138,23 +164,23 @@ for adding "literal" double quotes in CSV:
138
164
 
139
165
  ```
140
166
  """1""","""2""","""3"""
141
- 4,5,"Six says, ""Hello, World!"""
167
+ 4,5,"Hamlet says, ""Seems,"" madam! Nay it is; I know not ""seems."""
142
168
  ```
143
169
 
144
170
  vs
145
171
 
146
172
  ```
147
173
  "1"→"2"→"3"
148
- 4→5→Six says, "Hello, World!"
174
+ 4→5→Hamlet says, "Seems," madam! Nay it is; I know not "seems."
149
175
  ```
150
176
 
151
177
  Thus, to avoid any surprises, do NOT use
152
- `CSV.read( col_sep: "\t", quote_char: "∅" )` and friends for tab.
178
+ `Csv.read( sep: "\t" )` and friends for tab.
153
179
  Note: Simpler also equals faster :-).
154
180
 
155
181
 
156
182
 
157
- ### Q: What's the tab format?
183
+ ### Q: What's the tabulator (TAB) format?
158
184
 
159
185
  Let's reprint the (complete) tab spec(ification) right here
160
186
  (in an edited simpler version):
data/Rakefile CHANGED
@@ -5,10 +5,10 @@ Hoe.spec 'tabreader' do
5
5
 
6
6
  self.version = TabReader::VERSION
7
7
 
8
- self.summary = "tabreader - read in tabular datafiles in text in the tab format"
8
+ self.summary = "tabreader - read in tabular datafiles in text in the tabular (TAB) format"
9
9
  self.description = summary
10
10
 
11
- self.urls = ['https://github.com/datatext/tabreader']
11
+ self.urls = ['https://github.com/csv11/tabreader']
12
12
 
13
13
  self.author = 'Gerald Bauer'
14
14
  self.email = 'wwwmake@googlegroups.com'
@@ -20,7 +20,7 @@ Hoe.spec 'tabreader' do
20
20
  self.licenses = ['Public Domain']
21
21
 
22
22
  self.spec_extras = {
23
- :required_ruby_version => '>= 2.2.2'
23
+ required_ruby_version: '>= 2.2.2'
24
24
  }
25
25
 
26
26
  end
data/lib/tabreader.rb CHANGED
@@ -2,15 +2,23 @@
2
2
 
3
3
 
4
4
  require 'pp'
5
+ require 'logger'
5
6
 
6
7
 
7
8
  ###
8
9
  # our own code
10
+ # check: use require_relative - why? why not?
9
11
  require 'tabreader/version' # let version always go first
10
12
  require 'tabreader/reader'
13
+ require 'tabreader/reader_hash'
11
14
 
12
15
 
13
16
 
17
+ ## add some "convenience" shortcuts
18
+ TAB = TabReader
19
+ Tab = TabReader
20
+ TabHash = TabHashReader
21
+
14
22
 
15
23
 
16
24
  puts TabReader.banner # say hello
@@ -14,124 +14,164 @@ class TabReader
14
14
  ## todo: add converters: e.g. strip (akk trim / ltrim / rtrim )
15
15
 
16
16
 
17
- def self.read( path, headers: false )
18
- txt = File.open( path, 'r:utf-8' ).read
19
- ## puts "#{path}:"
20
- ## pp txt
21
- parse( txt, headers: headers )
22
- end
23
17
 
24
- def self.parse( txt, headers: false ) ## use parse_rows or parse_lines for array or array results
25
- rows = []
26
-
27
- if headers.is_a?( Array )
28
- columns = headers
29
- else
30
- columns = nil ## header row a.k.a. columns / fields
31
- end
32
-
33
- txt.each_line do |line|
34
- values = parse_line( line )
35
- if headers ## add values as name/value pairs e.g. array of hashes
36
- if columns.nil?
37
- columns = values ## first row is header row
38
- else
39
- ## note: will cut-off values if values.size > columns.size
40
- ## add warning/error - why? why not?
41
- ## if values.size <= columns.size will get filled-up with nil
42
- pairs = columns.zip(values)
43
- ## pp pairs
44
- h = pairs.to_h
45
- ## pp h
46
-
47
- rows << h
48
- end
49
- else ## add values as is e.g. array of array
50
- rows << values
51
- end
52
- end
53
- rows
18
+ ###################################
19
+ ## add simple logger with debug flag/switch
20
+ #
21
+ # use Parser.debug = true # to turn on
22
+ #
23
+ # todo/fix: use logutils instead of std logger - why? why not?
24
+
25
+ def self.build_logger()
26
+ l = Logger.new( STDOUT )
27
+ l.level = :info ## set to :info on start; note: is 0 (debug) by default
28
+ l
54
29
  end
30
+ def self.logger() @@logger ||= build_logger; end
31
+ def logger() self.class.logger; end
55
32
 
56
- def self.foreach( path, headers: false )
57
- if headers.is_a?( Array )
58
- columns = headers
59
- else
60
- columns = nil ## header row a.k.a. columns / fields
61
- end
62
33
 
63
- File.open( path, 'r:utf-8' ).each_line do |line|
64
- pp line
65
- values = parse_line( line )
66
- if headers ## add values as name/value pairs e.g. array of hashes
67
- if columns.nil?
68
- columns = values ## first row is header row
69
- else
70
- pairs = columns.zip(values)
71
- h = pairs.to_h
72
- yield( h )
73
- end
74
- else ## add values as is e.g. array of array
75
- yield( values )
76
- end
77
- end
78
-
79
- # return nil
80
- nil
81
- end
82
34
 
83
35
 
84
36
  def self.parse_line( line )
85
37
  ## check - can handle comments and blank lines too - why? why not?
86
38
  ## remove trailing newlines
87
39
 
40
+ logger.debug "line:" if logger.debug?
41
+ logger.debug line.pretty_inspect if logger.debug?
42
+
43
+
88
44
  ## note: chomp('') if is an empty string,
89
45
  ## it will remove all trailing newlines from the string.
90
- ## use line.sub(/[\n\r]*$/, '') or similar instead - why? why not?
91
- line = line.chomp('')
46
+ ## use line.sub(/[\n\r]*$/, '') or similar instead - why? why not?
47
+ line = line.chomp( '' )
48
+
49
+ ## line = line.strip ## strip leading and trailing whitespaces (space/tab) too
50
+
51
+ logger.debug line.pretty_inspect if logger.debug?
52
+
53
+ # if line.empty? ## skip blank lines
54
+ # logger.debug "skip blank line" if logger.debug?
55
+ # next
56
+ # end
57
+
58
+ # if line.start_with?( "#" ) ## skip comment lines
59
+ # logger.debug "skip comment line" if logger.debug?
60
+ # next
61
+ # end
62
+
63
+ values = line.split( "\t" )
64
+ logger.debug values.pretty_inspect if logger.debug?
92
65
 
93
- values = line.split("\t")
94
66
  values
95
67
  end
96
68
 
97
- def self.header( path )
98
- line = File.open( path, 'r:utf-8' ) do |f|
99
- if f.eof?
100
- ## handle empty file; return empty string; no readline call possible
101
- ## todo/check: return nil from header is no header or [] - why? why not?
102
- ## or throw exception end of file reached (EOFError) - why? why not?
103
- ""
104
- else
105
- f.readline
106
- end
107
- end
108
69
 
109
- ## note: line includes \n or \r\n at the end
110
- ## pp line
111
- parse_line( line )
112
- end
113
70
 
114
- end # class TabReader
115
71
 
72
+ def self.open( path, mode=nil, &block ) ## rename path to filename or name - why? why not?
116
73
 
74
+ ## note: default mode (if nil/not passed in) to 'r:bom|utf-8'
75
+ f = File.open( path, mode ? mode : 'r:bom|utf-8' )
76
+ tab = new( f )
117
77
 
78
+ # handle blocks like Ruby's open()
79
+ if block_given?
80
+ begin
81
+ block.call( tab )
82
+ ensure
83
+ tab.close
84
+ end
85
+ else
86
+ tab
87
+ end
88
+ end # method self.open
118
89
 
119
- class TabHashReader
120
90
 
121
- def self.read( path, headers: true )
122
- TabReader.read( path, headers: headers )
91
+ def self.read( path )
92
+ open( path ) { |tab| tab.read }
123
93
  end
124
94
 
125
- def self.parse( txt, headers: true )
126
- TabReader.parse( txt, headers: headers )
127
- end
128
95
 
129
- def self.foreach( path, headers: true, &block )
130
- TabReader.foreach( path, headers: headers, &block )
96
+ def self.foreach( path, &block )
97
+ tab = open( path )
98
+
99
+ if block_given?
100
+ begin
101
+ tab.each( &block )
102
+ ensure
103
+ tab.close
104
+ end
105
+ else
106
+ tab.to_enum ## note: caller (responsible) must close file!!!
107
+ ## remove version without block given - why? why not?
108
+ ## use Tab.open().to_enum or Tab.open().each
109
+ ## or Tab.new( File.new() ).to_enum or Tab.new( File.new() ).each ???
110
+ end
111
+ end # method self.foreach
112
+
113
+
114
+ def self.parse( data, &block )
115
+ tab = new( data )
116
+
117
+ if block_given?
118
+ tab.each( &block ) ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
119
+ else # slurp contents, if no block is given
120
+ tab.read ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
121
+ end
122
+ end # method self.parse
123
+
124
+
125
+
126
+ ## convenience helper for header (first row with column names)
127
+ def self.header( path ) ## use header or headers - or use both (with alias)?
128
+ # read first lines (only)
129
+
130
+ records = []
131
+ open( path ) do |tab|
132
+ tab.each do |record|
133
+ records << record
134
+ break ## only parse/read first record
135
+ end
136
+ end
137
+
138
+ ## unwrap record if empty return nil - why? why not?
139
+ ## return empty record e.g. [] - why? why not?
140
+ ## returns nil for empty (for now) - why? why not?
141
+ records.size == 0 ? nil : records.first
142
+ end # method self.header
143
+
144
+
145
+
146
+
147
+ def initialize( data )
148
+ if data.is_a?( String )
149
+ @input = data # note: just needs each for each_line
150
+ else ## assume io
151
+ @input = data
152
+ end
131
153
  end
132
154
 
133
- def self.header( path ) ## add header too? why? why not?
134
- TabReader.header( path )
155
+
156
+ include Enumerable
157
+
158
+ def each( &block )
159
+ if block_given?
160
+ @input.each_line do |line|
161
+
162
+ values = self.class.parse_line( line )
163
+
164
+ block.call( values )
165
+ end
166
+ else
167
+ to_enum
168
+ end
169
+ end # method each
170
+
171
+ def read() to_a; end # method read
172
+
173
+ def close
174
+ @input.close if @input.respond_to?(:close) ## note: string needs no close
135
175
  end
136
176
 
137
- end # class TabHashReader
177
+ end # class TabReader
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+
3
+ class TabHashReader
4
+
5
+
6
+ def self.open( path, mode=nil, headers: nil, &block ) ## rename path to filename or name - why? why not?
7
+
8
+ ## note: default mode (if nil/not passed in) to 'r:bom|utf-8'
9
+ f = File.open( path, mode ? mode : 'r:bom|utf-8' )
10
+ tab = new(f, headers: headers )
11
+
12
+ # handle blocks like Ruby's open()
13
+ if block_given?
14
+ begin
15
+ block.call( tab )
16
+ ensure
17
+ tab.close
18
+ end
19
+ else
20
+ tab
21
+ end
22
+ end # method self.open
23
+
24
+
25
+ def self.read( path, headers: nil )
26
+ open( path, headers: headers ) { |tab| tab.read }
27
+ end
28
+
29
+
30
+
31
+ def self.foreach( path, headers: nil, &block )
32
+ tab = open( path, headers: headers)
33
+
34
+ if block_given?
35
+ begin
36
+ tab.each( &block )
37
+ ensure
38
+ tab.close
39
+ end
40
+ else
41
+ tab.to_enum ## note: caller (responsible) must close file!!!
42
+ ## remove version without block given - why? why not?
43
+ ## use Tab.open().to_enum or Tab.open().each
44
+ ## or Tab.new( File.new() ).to_enum or Tab.new( File.new() ).each ???
45
+ end
46
+ end # method self.foreach
47
+
48
+
49
+ def self.parse( data, headers: nil, &block )
50
+ tab = new( data, headers: headers )
51
+
52
+ if block_given?
53
+ tab.each( &block ) ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
54
+ else # slurp contents, if no block is given
55
+ tab.read ## note: caller (responsible) must close file!!! - add autoclose - why? why not?
56
+ end
57
+ end # method self.parse
58
+
59
+
60
+
61
+
62
+ def initialize( data, headers: nil )
63
+ raise ArgumentError.new( "Cannot parse nil as TAB" ) if data.nil?
64
+
65
+ if data.is_a?( String )
66
+ @input = data # note: just needs each for each_line
67
+ else ## assume io
68
+ @input = data
69
+ end
70
+
71
+ ## pass in headers as array e.g. ['A', 'B', 'C']
72
+ @names = headers ? headers : nil
73
+ end
74
+
75
+
76
+
77
+ include Enumerable
78
+
79
+
80
+ def each( &block )
81
+
82
+ ## todo/fix:
83
+ ## add case for headers/names.size != values.size
84
+ ## - add rest option? for if less headers than values (see python csv.DictReader - why? why not?)
85
+ ##
86
+ ## handle case with duplicate and empty header names etc.
87
+
88
+
89
+ if block_given?
90
+ TabReader.parse( @input ) do |values|
91
+ if @names.nil? ## check for (first) headers row
92
+ @names = values ## store header row / a.k.a. field/column names
93
+ else ## "regular" record
94
+ record = @names.zip( values ).to_h ## todo/fix: check for more values than names/headers!!!
95
+ block.call( record )
96
+ end
97
+ end
98
+ else
99
+ to_enum
100
+ end
101
+ end # method each
102
+
103
+ def read() to_a; end # method read
104
+
105
+
106
+ def close
107
+ @input.close if @input.respond_to?(:close) ## note: string needs no close
108
+ end
109
+
110
+
111
+ end # class TabHashReader
@@ -4,8 +4,8 @@
4
4
  ## note: for now TabReader is a class!!! NOT a module - change - why? why not?
5
5
  class TabReader
6
6
 
7
- MAJOR = 0 ## todo: namespace inside version or something - why? why not??
8
- MINOR = 1
7
+ MAJOR = 1 ## todo: namespace inside version or something - why? why not??
8
+ MINOR = 0
9
9
  PATCH = 0
10
10
  VERSION = [MAJOR,MINOR,PATCH].join('.')
11
11
 
data/test/helper.rb CHANGED
@@ -14,3 +14,7 @@ class TabReader
14
14
  "#{root}/test/data"
15
15
  end
16
16
  end
17
+
18
+
19
+
20
+ TabReader.logger.level = :debug ## turn on "global" logging
data/test/test_reader.rb CHANGED
@@ -26,11 +26,9 @@ TXT
26
26
 
27
27
  puts "== parse:"
28
28
  pp TabReader.parse( txt1 )
29
- pp TabReader.parse( txt1, headers: true )
30
29
 
31
30
  puts "== parse:"
32
31
  pp TabReader.parse( txt2 )
33
- pp TabReader.parse( txt2, headers: true )
34
32
 
35
33
  puts "== parse_line:"
36
34
  pp TabReader.parse_line( "1\t2\t3" )
@@ -49,16 +47,12 @@ def test_read
49
47
 
50
48
  puts "== read:"
51
49
  pp TabReader.read( "#{TabReader.test_data_dir}/test.tab" )
52
- pp TabReader.read( "#{TabReader.test_data_dir}/test.tab", headers: true )
53
50
  puts "== header:"
54
51
  pp TabReader.header( "#{TabReader.test_data_dir}/test.tab" )
55
52
  puts "== foreach:"
56
53
  TabReader.foreach( "#{TabReader.test_data_dir}/test.tab" ) do |row|
57
54
  pp row
58
55
  end
59
- TabReader.foreach( "#{TabReader.test_data_dir}/test.tab", headers: true ) do |row|
60
- pp row
61
- end
62
56
  end
63
57
 
64
58
 
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_reader_hash.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestReader < MiniTest::Test
11
+
12
+
13
+ def test_parse
14
+
15
+ txt1 = <<TXT
16
+ a\tb\tc
17
+ 1\t2\t3
18
+ 4\t5\t6
19
+ TXT
20
+
21
+ txt2 = <<TXT
22
+ a b c d
23
+ 1 2 3 4
24
+ 5 6 7 8
25
+ TXT
26
+
27
+ puts "== parse:"
28
+ pp TabHashReader.parse( txt1 )
29
+
30
+ puts "== parse:"
31
+ pp TabHashReader.parse( txt2 )
32
+
33
+ assert true
34
+ end
35
+
36
+
37
+ def test_read
38
+
39
+ puts "== read:"
40
+ pp TabHashReader.read( "#{TabReader.test_data_dir}/test.tab" )
41
+ puts "== foreach:"
42
+ TabHashReader.foreach( "#{TabReader.test_data_dir}/test.tab" ) do |row|
43
+ pp row
44
+ end
45
+ end
46
+
47
+
48
+ def test_read_empty
49
+
50
+ puts "== read (empty):"
51
+ pp TabHashReader.read( "#{TabReader.test_data_dir}/empty.tab" )
52
+ puts "== foreach (empty):"
53
+ TabHashReader.foreach( "#{TabReader.test_data_dir}/empty.tab" ) do |row|
54
+ pp row
55
+ end
56
+ puts "== parse (empty):"
57
+ pp TabHashReader.parse( "" )
58
+ end
59
+
60
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tabreader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-17 00:00:00.000000000 Z
11
+ date: 2018-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.16'
41
- description: tabreader - read in tabular datafiles in text in the tab format
41
+ description: tabreader - read in tabular datafiles in text in the tabular (TAB) format
42
42
  email: wwwmake@googlegroups.com
43
43
  executables: []
44
44
  extensions: []
@@ -55,12 +55,14 @@ files:
55
55
  - Rakefile
56
56
  - lib/tabreader.rb
57
57
  - lib/tabreader/reader.rb
58
+ - lib/tabreader/reader_hash.rb
58
59
  - lib/tabreader/version.rb
59
60
  - test/data/empty.tab
60
61
  - test/data/test.tab
61
62
  - test/helper.rb
62
63
  - test/test_reader.rb
63
- homepage: https://github.com/datatext/tabreader
64
+ - test/test_reader_hash.rb
65
+ homepage: https://github.com/csv11/tabreader
64
66
  licenses:
65
67
  - Public Domain
66
68
  metadata: {}
@@ -85,5 +87,5 @@ rubyforge_project:
85
87
  rubygems_version: 2.5.2
86
88
  signing_key:
87
89
  specification_version: 4
88
- summary: tabreader - read in tabular datafiles in text in the tab format
90
+ summary: tabreader - read in tabular datafiles in text in the tabular (TAB) format
89
91
  test_files: []