rio 0.3.3 → 0.3.4

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 (88) hide show
  1. data/ChangeLog +225 -0
  2. data/README +12 -0
  3. data/Rakefile +1 -1
  4. data/VERSION +1 -1
  5. data/doc/ANNOUNCE +160 -71
  6. data/doc/RELEASE_NOTES +71 -2
  7. data/ex/colx.rb +1 -1
  8. data/ex/passwd_report.rb +4 -8
  9. data/ex/riocat +5 -5
  10. data/ex/riogunzip +1 -1
  11. data/ex/riogzip +6 -6
  12. data/ex/rioprompt.rb +6 -0
  13. data/lib/rio.rb +3 -13
  14. data/lib/rio/arycopy.rb +1 -1
  15. data/lib/rio/base.rb +1 -5
  16. data/lib/rio/construct.rb +75 -0
  17. data/lib/rio/constructor.rb +42 -11
  18. data/lib/rio/context.rb +1 -1
  19. data/lib/rio/context/dir.rb +50 -23
  20. data/lib/rio/context/methods.rb +5 -3
  21. data/lib/rio/{cxdir.rb → context/skip.rb} +24 -36
  22. data/lib/rio/context/stream.rb +38 -16
  23. data/lib/rio/cp.rb +24 -5
  24. data/lib/rio/dir.rb +8 -7
  25. data/lib/rio/doc/HOWTO.rb +33 -33
  26. data/lib/rio/doc/INTRO.rb +416 -256
  27. data/lib/rio/doc/MISC.rb +3 -1
  28. data/lib/rio/doc/SYNOPSIS.rb +28 -33
  29. data/lib/rio/entrysel.rb +76 -9
  30. data/lib/rio/file.rb +2 -1
  31. data/lib/rio/filter.rb +95 -0
  32. data/lib/rio/filter/closeoneof.rb +1 -1
  33. data/lib/rio/grande.rb +0 -74
  34. data/lib/rio/if.rb +2 -1
  35. data/lib/rio/if/basic.rb +1 -1
  36. data/lib/rio/if/csv.rb +1 -1
  37. data/lib/rio/if/dir.rb +1 -220
  38. data/lib/rio/if/fileordir.rb +26 -12
  39. data/lib/rio/if/grande.rb +55 -6
  40. data/lib/rio/if/grande_entry.rb +355 -0
  41. data/lib/rio/if/{methods.rb → grande_stream.rb} +69 -88
  42. data/lib/rio/if/path.rb +25 -3
  43. data/lib/rio/if/stream.rb +62 -37
  44. data/lib/rio/if/temp.rb +2 -2
  45. data/lib/rio/if/test.rb +23 -0
  46. data/lib/rio/impl/path.rb +5 -0
  47. data/lib/rio/match.rb +6 -3
  48. data/lib/rio/matchrecord.rb +50 -46
  49. data/lib/rio/{filter/chomp.rb → ops/construct.rb} +12 -20
  50. data/lib/rio/ops/create.rb +3 -0
  51. data/lib/rio/ops/dir.rb +12 -6
  52. data/lib/rio/ops/either.rb +17 -3
  53. data/lib/rio/ops/path.rb +4 -1
  54. data/lib/rio/ops/stream/input.rb +6 -1
  55. data/lib/rio/ops/stream/read.rb +1 -3
  56. data/lib/rio/{context/chomp.rb → prompt.rb} +17 -13
  57. data/lib/rio/rl/base.rb +1 -1
  58. data/lib/rio/rl/builder.rb +3 -1
  59. data/lib/rio/state.rb +7 -13
  60. data/lib/rio/stream.rb +8 -5
  61. data/lib/rio/stream/open.rb +1 -1
  62. data/lib/rio/version.rb +1 -1
  63. data/test/mswin32.rb +1 -1
  64. data/test/runtests_gem.rb +1 -1
  65. data/test/tc/all.rb +3 -0
  66. data/test/tc/copy-from.rb +13 -13
  67. data/test/tc/copy-to.rb +1 -1
  68. data/test/tc/copy.rb +1 -1
  69. data/test/tc/copydir.rb +0 -24
  70. data/test/tc/copysymlink.rb +39 -0
  71. data/test/tc/csv.rb +2 -2
  72. data/test/tc/csv2.rb +4 -4
  73. data/test/tc/misc.rb +16 -16
  74. data/test/tc/nolines.rb +26 -26
  75. data/test/tc/noqae.rb +74 -74
  76. data/test/tc/overload.rb +28 -28
  77. data/test/tc/riorl.rb +36 -0
  78. data/test/tc/selnosel.rb +36 -0
  79. data/test/tc/skip.rb +58 -0
  80. data/test/tc/skiplines.rb +42 -0
  81. data/test/tc/symlink.rb +1 -1
  82. data/test/tc/symlink0.rb +1 -1
  83. data/test/tc/temp.rb +1 -1
  84. data/test/tc/tempdir.rb +1 -1
  85. data/test/tc/testcase.rb +7 -1
  86. metadata +14 -8
  87. data/lib/rio/matchcolumns.rb +0 -266
  88. data/lib/rio/rangemath.rb +0 -44
@@ -0,0 +1,355 @@
1
+ #--
2
+ # ===============================================================================
3
+ # Copyright (c) 2005, Christopher Kleckner
4
+ # All rights reserved
5
+ #
6
+ # This file is part of the Rio library for ruby.
7
+ #
8
+ # Rio is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Rio is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with Rio; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ # ===============================================================================
22
+ #++
23
+ #
24
+ # To create the documentation for Rio run the command
25
+ # rake rdoc
26
+ # from the distribution directory. Then point your browser at the 'doc/rdoc' directory.
27
+ #
28
+ # Suggested Reading
29
+ # * RIO::Doc::SYNOPSIS
30
+ # * RIO::Doc::INTRO
31
+ # * RIO::Doc::HOWTO
32
+ # * RIO::Rio
33
+ #
34
+ # <b>Rio is pre-alpha software.
35
+ # The documented interface and behavior is subject to change without notice.</b>
36
+
37
+
38
+ module RIO
39
+ class Rio
40
+ # Grande Directory Selection Method
41
+ #
42
+ # Sets the rio to return directories. _args_ can be used to select which directories are returned.
43
+ # ario.files(*args) do |f|
44
+ # f.directory? #=> true
45
+ # end
46
+ # No aguments selects all directories.
47
+ # if _args_ are:
48
+ # Regexp:: selects matching directories
49
+ # glob:: selects matching directories
50
+ # Proc:: called for each directory. the directory is processed unless the proc returns false
51
+ # Symbol:: sent to each directory. Each directory is processed unless the symbol returns false
52
+ #
53
+ # If a block is given, behaves like <tt>ario.dirs(*args).each(&block)</tt>
54
+ #
55
+ # See also Rio#files, Rio#entries, Rio#skipdirs
56
+ #
57
+ # rio('adir').dirs { |frio| ... } # process all directories in 'adir'
58
+ # rio('adir').all.dirs { |frio| ... } # same thing recursively
59
+ # rio('adir').dirs(/^\./) { |frio| ...} # process dot directories
60
+ # rio('adir').dirs[/^\./] # return an array of dot directories
61
+ # rio('adir').dirs[:symlink?] # an array of symlinks to directories
62
+ #
63
+ def dirs(*args,&block) target.dirs(*args,&block); self end
64
+
65
+ # Grande Directory Exclude Method
66
+ #
67
+ # If no args are provided selects anything but directories.
68
+ # ario.skipdirs do |el|
69
+ # el.directory? #=> false
70
+ # end
71
+ # If args are provided, sets the rio to select directories as with Rio#dirs, but the arguments are
72
+ # used to determine which directories will *not* be processed
73
+ #
74
+ # If a block is given behaves like
75
+ # ario.skipdirs(*args).each(&block)
76
+ #
77
+ # See Rio#dirs
78
+ #
79
+ # rio('adir').skipdirs { |ent| ... } # iterate through everything except directories
80
+ # rio('adir').skipdirs(/^\./) { |drio| ... } # iterate through directories, skipping dot directories
81
+ #
82
+ #
83
+ def skipdirs(*args,&block) target.skipdirs(*args,&block); self end
84
+
85
+
86
+ # Grande Directory Entry Selection Method
87
+ #
88
+ # No aguments selects all entries.
89
+ #
90
+ # if +args+ are:
91
+ # Regexp:: selects matching entries
92
+ # glob:: selects matching entries
93
+ # Proc:: called for each entry. the entry is processed unless the proc returns false
94
+ # Symbol:: sent to each entry. Each entry is processed unless the symbol returns false
95
+ #
96
+ # If a block is given, behaves like <tt>ario.etries(*args).each(&block)</tt>
97
+ #
98
+ # See also Rio#files, Rio#dirs, Rio#skipentries
99
+ #
100
+ # rio('adir').entries { |frio| ... } # process all entries in 'adir'
101
+ # rio('adir').all.entries { |frio| ... } # same thing recursively
102
+ # rio('adir').entries(/^\./) { |frio| ...} # process entries starting with a dot
103
+ # rio('adir').entries[/^\./] # return an array of all entries starting with a dot
104
+ # rio('adir').entries[:symlink?] # an array of symlinks in 'adir'
105
+ #
106
+ def entries(*args,&block) target.entries(*args,&block); self end
107
+
108
+ # Grande Directory Entry Rejection Method
109
+ #
110
+ # No aguments rejects all entries.
111
+ #
112
+ # Behaves like Rio#entries, except that matching entries are excluded.
113
+ #
114
+ def skipentries(*args,&block) target.skipentries(*args,&block); self end
115
+
116
+
117
+ # Grande File Selection Method
118
+ #
119
+ # Configures the rio to process files. +args+ can be used to select which files are returned.
120
+ # ario.files(*args) do |f|
121
+ # f.file? #=> true
122
+ # end
123
+ # No aguments selects all files.
124
+ #
125
+ # +args+ may be zero or more of the following:
126
+ #
127
+ # Regexp:: selects matching files
128
+ # String:: treated as a glob, and selects matching files
129
+ # Proc:: called for each file. the file is processed unless the proc returns false
130
+ # Symbol:: sent to each file. Each file is processed unless the symbol returns false
131
+ #
132
+ # +files+ returns the Rio which called it. This might seem counter-intuitive at first.
133
+ # One might reasonably assume that
134
+ # rio('adir').files('*.rb')
135
+ # would return files. It does not. It configures the rio to return files and returns
136
+ # the Rio. This enables chaining for further configuration so constructs like
137
+ # rio('adir').all.files('*.rb').norecurse('.svn')
138
+ # are possible.
139
+ #
140
+ # If a block is given, behaves like
141
+ # ario.files(*args).each
142
+ #
143
+ #
144
+ # See also Rio#dirs, Rio#entries, Rio#skipfiles
145
+ #
146
+ # rio('adir').files { |frio| ... } # process all files in 'adir'
147
+ # rio('adir').all.files { |frio| ... } # same thing recursively
148
+ # rio('adir').files('*.rb') { |frio| ...} # process .rb files
149
+ # rio('adir').files['*.rb'] # return an array of .rb files
150
+ # rio('adir').files[/\.rb$/] # same thing using a regular expression
151
+ # rio('adir').files[:symlink?] # an array of symlinks to files
152
+ # rio('adir').files >> rio('other_dir') # copy files to 'other_dir'
153
+ # rio('adir').files('*.rb') >> rio('other_dir') # only copy .rb files
154
+ #
155
+ # For Rios that refer to files, <tt>files(*args)</tt> causes the file to be processed only if
156
+ # it meets the criteria specified by the args.
157
+ #
158
+ # rio('afile.z').files['*.z'] #=> [rio('afile.z')]
159
+ # rio('afile.q').files['*.z'] #=> []
160
+ #
161
+ # === Example Problem
162
+ #
163
+ # Fill the array +ruby_progs+ with all ruby programs in a directory and its subdirectories,
164
+ # skipping those in _subversion_ (.svn) directories.
165
+ #
166
+ # ruby_progs = []
167
+ #
168
+ # For the purposes of this problem, a Ruby program is defined as a file ending with .rb or a file
169
+ # that is executable and whose shebang line contains 'ruby':
170
+ #
171
+ # is_ruby_exe = proc{ |f| f.executable? and f.gets =~ /^#!.+ruby/ }
172
+ #
173
+ # ==== Solution 1. Use the subscript operator.
174
+ #
175
+ # ruby_progs = rio('adir').norecurse('.svn').files['*.rb',is_ruby_exe]
176
+ #
177
+ # Explanation:
178
+ #
179
+ # 1. Create the Rio
180
+ #
181
+ # Create a Rio for a directory
182
+ # rio('adir')
183
+ #
184
+ # 2. Configure the Rio
185
+ #
186
+ # Specify recursion and that '.svn' directories should not be included.
187
+ # rio('adir').norecurse('.svn')
188
+ # Select files
189
+ # rio('adir').norecurse('.svn').files
190
+ # Limit to files ending with '.rb'
191
+ # rio('adir').norecurse('.svn').files('*.rb')
192
+ # Also allow files for whom +is_ruby_exe+ returns true
193
+ # rio('adir').norecurse('.svn').files('*.rb',is_ruby_exe)
194
+ #
195
+ # 3. Do the I/O
196
+ #
197
+ # Return an array rather than iterating thru them
198
+ # ruby_progs = rio('adir').norecurse('.svn').files['*.rb',is_ruby_exe]
199
+ #
200
+ # ==== Solution 2. Use the copy-to operator
201
+ #
202
+ # rio('adir').files('*.rb',is_ruby_exe).norecurse('.svn') > ruby_progs
203
+ #
204
+ # Explanation:
205
+ #
206
+ # 1. Create the Rio
207
+ #
208
+ # Create a Rio for a directory
209
+ # rio('adir')
210
+ #
211
+ # 2. Configure the Rio
212
+ #
213
+ # Select only files
214
+ # rio('adir').files
215
+ # Limit to files ending with '.rb'
216
+ # rio('adir').files('*.rb')
217
+ # Also allow files for whom +is_ruby_exe+ returns true
218
+ # rio('adir').files('*.rb',is_ruby_exe)
219
+ # Specify recursion and that '.svn' directories should not be included.
220
+ # rio('adir').files('*.rb',is_ruby_exe).norecurse('.svn')
221
+ #
222
+ # 3. Do the I/O
223
+ #
224
+ # Copy the Rio to ruby_progs
225
+ # rio('adir').files('*.rb',is_ruby_exe).norecurse('.svn') > ruby_progs
226
+ #
227
+ # ==== Example Discussion
228
+ #
229
+ # Note that the only difference between Step 2 of Solution 1 and that of Solution 2 is
230
+ # the order of the configuration methods. Step 2 of Solution 1 would have worked equally
231
+ # well:
232
+ #
233
+ # rio('adir').norecurse('.svn').files('*.rb',is_ruby_exe) > ruby_progs
234
+ #
235
+ # Furthermore if our problem were changed slightly and instead of having our results
236
+ # ending up in an array, we wished to iterate through them, we could use:
237
+ #
238
+ # rio('adir').norecurse('.svn').files('*.rb',is_ruby_exe) { |ruby_prog_rio| ... }
239
+ #
240
+ # Note the similarities. In fact, solution 1 could have been written:
241
+ #
242
+ # rio('adir').norecurse('.svn').files('*.rb',is_ruby_exe).to_a
243
+ # or
244
+ # rio('adir').norecurse('.svn').files('*.rb',is_ruby_exe)[]
245
+ #
246
+ # Passing the arguments for +files+ to the subscript operator is syntactic sugar.
247
+ # The subscript operator does not really take any arguments of its own. It always
248
+ # passes them to the most recently called of the grande selection methods (or the
249
+ # default selection method, if none have been called). So,
250
+ #
251
+ # rio('adir').files['*.rb']
252
+ # is a shortcut for
253
+ # rio('adir').files('*.rb').to_a
254
+ #
255
+ # rio('adir')['*.rb']
256
+ # is a shortcut for
257
+ # rio('adir').entries('*.rb').to_a
258
+ #
259
+ # rio('afile').lines[0..10]
260
+ # is a shortcut for
261
+ # rio('afile').lines(0..10).to_a
262
+ #
263
+ # And so on.
264
+ #
265
+ #
266
+ #
267
+ def files(*args,&block) target.files(*args,&block); self end
268
+
269
+ # Grande File Exclude Method
270
+ #
271
+ # If no args are provided selects anything but files.
272
+ # ario.skipfiles do |el|
273
+ # el.file? #=> false
274
+ # end
275
+ # If args are provided, sets the rio to select files as with Rio#files, but the arguments are
276
+ # used to determine which files will *not* be processed
277
+ #
278
+ # If a block is given behaves like <tt>ario.skipfiles(*args).each(&block)</tt>
279
+ #
280
+ # See Rio#files
281
+ #
282
+ # rio('adir').skipfiles { |ent| ... } # iterate through everything except files
283
+ # rio('adir').skipfiles('*~') { |frio| ... } # iterate through files, skipping those ending with a tilde
284
+ #
285
+ #
286
+ def skipfiles(*args,&block) target.skipfiles(*args,&block); self end
287
+
288
+
289
+ # Returns +true+ if the rio is in +all+ (recursive) mode. See Rio#all
290
+ #
291
+ # adir = rio('adir').all.dirs
292
+ # adir.all? # true
293
+ # adir.each do |subdir|
294
+ # subdir.all? # true
295
+ # end
296
+ #
297
+ # rio('adir').all? # false
298
+ #
299
+ def all?() target.all?() end
300
+
301
+
302
+ # Grande Directory Recursion Method
303
+ #
304
+ # Sets the Rio to all mode (recursive)
305
+ #
306
+ # When called with a block, behaves as if all.each(&block) had been called
307
+ #
308
+ # +all+ causes subsequent calls to +files+ or +dirs+ to be applied recursively
309
+ # to subdirectories
310
+ #
311
+ # rio('adir').all.files('*.[ch]').each { |file| ... } # process all c language source files in adir
312
+ # # and all subdirectories of adir
313
+ # rio('adir').all.files(/\.[ch]$/) { |file| ... } # same as above
314
+ # rio('adir').files("*.[ch]").all { |file| ... } # once again
315
+ # rio('adir').all.files["*.[ch]"] # same, but return an array instead of iterating
316
+ #
317
+ def all(arg=true,&block) target.all(arg,&block); self end
318
+
319
+
320
+ # Grande Directory Recursion Selection Method
321
+ #
322
+ # Sets the Rio to recurse into directories like Rio#all. If no args are provided behaves like Rio#all.
323
+ # If args are provided, they are processed like Rio#dirs, to select which subdirectories should
324
+ # be recursed into. Rio#recurse always implies Rio#all.
325
+ #
326
+ # +args+ may be one or more of:
327
+ # Regexp:: recurse into matching subdirectories
328
+ # glob:: recurse into matching subdirectories
329
+ # Proc:: called for each directory. The directory is recursed into unless the proc returns false
330
+ # Symbol:: sent to each directory. Each directory is recursed into unless the symbol returns false
331
+ #
332
+ # If a block is given, behaves like <tt>ario.recurse(*args).each(&block)</tt>
333
+ #
334
+ # See also Rio#norecurse, Rio#all, Rio#dirs
335
+ #
336
+ # rio('adir').recurse('test*') { |drio| ... } # process all entries and all entries in subdirectories
337
+ # # starting with 'test' -- recursively
338
+ #
339
+ def recurse(*args,&block) target.recurse(*args,&block); self end
340
+
341
+
342
+ # Grande Directory Recursion Exclude Method
343
+ #
344
+ # Sets the Rio to recurse into directories like Rio#all. If no args are provided, no
345
+ # directories will be recursed into. If args are provided, behaves like Rio#recurse, except
346
+ # that matching directories will *not* be recursed into
347
+ #
348
+ # rio('adir').norecurse('.svn') { |drio| ... } # recurse, skipping subversion directories
349
+ #
350
+ def norecurse(*args,&block) target.norecurse(*args,&block); self end
351
+
352
+
353
+ end
354
+ end
355
+
@@ -42,12 +42,21 @@ module RIO
42
42
  #
43
43
  # If called with a block behaves as if lines(*args).each(&block) had been called
44
44
  #
45
+ # +lines+ returns the Rio which called it. This might seem counter-intuitive at first.
46
+ # One might reasonably assume that
47
+ # rio('adir').lines(0..10)
48
+ # would return lines. It does not. It configures the rio to return lines and returns
49
+ # the Rio. This enables chaining for further configuration so constructs like
50
+ # rio('afile').lines(0..10).skiplines(/::/)
51
+ # are possible.
52
+ #
45
53
  # If args are provided they may be one or more of the following:
46
54
  # Regexp:: any matching record will be processed
47
55
  # Range:: specifies a range of records (zero-based) to be included
48
56
  # Integer:: interpreted as a one element range of lines to be processed
49
57
  # Proc:: a proc which will be called for each record, records are included unless nil or false is returned
50
58
  # Symbol:: a symbol which will _sent_ to each record, records are included unless nil or false is returned
59
+ # Array:: an array of other selectors. records are selected unless any of the matches fail.
51
60
  #
52
61
  # rio('f.txt').lines(/^\s*#/) { |line| ... } # iterate over comment-only lines
53
62
  # rio('f.txt').lines(/^\s*#/).each { |line| ... } # same as above
@@ -94,16 +103,12 @@ module RIO
94
103
  # and extensions such as Rio#csv.
95
104
  #
96
105
  # If args are provided they may be one or more of the following:
97
- # [Regexp]
98
- # any matching record will be iterated over by Rio#each or returned by Rio#getrec
99
- # [Integer]
100
- # specifies a record-number (zero-based) to be iterated over by Rio#each or returned by Rio#getrec
101
- # [Range]
102
- # specifies a range of records (zero-based) to included in the iteration
103
- # [Proc]
104
- # a proc which will be called for each record, records are included unless nil or false is returned
105
- # [Symbol]
106
- # a symbol which will _sent_ to each record, records are included unless nil or false is returned
106
+ # Regexp:: any matching record will be iterated over by Rio#each or returned by Rio#getrec
107
+ # Integer:: specifies a record-number (zero-based) to be iterated over by Rio#each or returned by Rio#getrec
108
+ # Range:: specifies a range of records (zero-based) to included in the iteration
109
+ # Proc:: a proc which will be called for each record, records are included unless nil or false is returned
110
+ # Symbol:: a symbol which will _sent_ to each record, records are included unless nil or false is returned
111
+ # Array:: an array of any of above. All must match for a line to be included
107
112
  #
108
113
  # Note in the following examples that since +lines+ is the default <tt>ario.records(*args)</tt>
109
114
  # is effectively the same as <tt>ario.lines(*args)</tt>.
@@ -111,23 +116,24 @@ module RIO
111
116
  # rio('afile').records(0) { |line| ... } # iterate over the first line of 'afile'
112
117
  # rio('afile').records(0,5..7)) { |line| ... } # iterate over lines 0,5,6 and 7
113
118
  # rio('afile').records(/Zippy/) { |line| ... } # iterate over all lines containing 'Zippy'
114
- # rio('afile').lines(0,/^\s*#/) { |line| ... } # iterate over the first line and comment lines
115
- # rio('afile').records(0,/^\s*#/) { |line| ... } # same thing
116
- # rio('afile').lines(proc { |rec,rnum,rio| rnum == 0 || rec =~ /^\s*#/ }) { |line| ... } # same thing
117
- # rio('afile').chomp.lines(proc { |rec,rnum,rio| rec.size > 0 }) { |line| ... } # non-empty lines
118
- # # return array containing line 0, all comment lines and any line containing the filename of the Rio
119
- # rio('afile').lines[0,/^\s*#/,proc { |rec,rnum,ario| rec =~ /#{ario.filename}/ }]
120
119
  #
120
+ #
121
+ # rio('f.csv').puts!(["h0,h1","f0,f1"]) # Create f.csv
122
+ #
123
+ # rio('f.csv').csv.records[] #==>[["h0", "h1"], ["f0", "f1"]]
124
+ # rio('f.csv').csv.lines[] #==>["h0,h1\n", "f0,f1\n"]
125
+ # rio('f.csv').csv.records[0] #==>[["h0", "h1"]]
121
126
  #
122
127
  def records(*args,&block) target.records(*args,&block); self end
123
128
 
124
129
  # Specifies records which should *not* be iterated through by Rio#each or returned by Rio#getrec
125
130
  #
126
- # If called with a block behaves as if norecords(*args).each(&block) had been called
131
+ # If called with a block behaves as if <tt>skiprecords(*args).each(&block)</tt>
132
+ # had been called
127
133
  #
128
134
  # Returns the Rio
129
135
  #
130
- # See also Rio#records, Rio#nolines, Rio#lines
136
+ # See also Rio#records, Rio#skiplines, Rio#lines
131
137
  #
132
138
  # If no args are provided, no records are rejected. What constitutes a record is affected by Rio#lines,Rio#bytes,
133
139
  # and extensions such as Rio#csv.
@@ -138,22 +144,23 @@ module RIO
138
144
  # Range:: specifies a range of records (zero-based) to be excluded
139
145
  # Proc:: a proc which will be called for each record, records are excluded unless nil or false is returned
140
146
  # Symbol:: a symbol which will _sent_ to each record, records are excluded unless nil or false is returned
147
+ # Array:: an array of any of the above, all of which must match for the array to match.
141
148
  #
142
149
  # Note in the following examples that since +lines+ is the default record
143
- # type <tt>ario.norecords(*args)</tt> is effectively
144
- # the same as <tt>ario.nolines(*args)</tt>.
150
+ # type <tt>ario.skiprecords(*args)</tt> is effectively
151
+ # the same as <tt>ario.skiplines(*args)</tt>.
145
152
  #
146
- # rio('afile').norecords(0) { |line| ... } # iterate over all but the first line of 'afile'
147
- # rio('afile').norecords(0,5..7)) { |line| ... } # don't iterate over lines 0,5,6 and 7
148
- # rio('afile').norecords(/Zippy/) { |line| ... } # skip all lines containing 'Zippy'
149
- # rio('afile').chomp.nolines(:empty?) { |line| ... } # skip empty lines
153
+ # rio('afile').skiprecords(0) { |line| ... } # iterate over all but the first line of 'afile'
154
+ # rio('afile').skiprecords(0,5..7)) { |line| ... } # don't iterate over lines 0,5,6 and 7
155
+ # rio('afile').skiprecords(/Zippy/) { |line| ... } # skip all lines containing 'Zippy'
156
+ # rio('afile').chomp.skiplines(:empty?) { |line| ... } # skip empty lines
150
157
  #
151
- def norecords(*args,&block) target.norecords(*args,&block); self end
158
+ def skiprecords(*args,&block) target.skiprecords(*args,&block); self end
152
159
 
153
160
  # Sets the Rio to read lines and specifies lines which should *not* be iterated through by Rio#each or
154
161
  # returned by Rio#getrec
155
162
  #
156
- # If called with a block behaves as if <tt>nolines(*args).each(&block)</tt> had been called
163
+ # If called with a block behaves as if <tt>skiplines(*args).each(&block)</tt> had been called
157
164
  #
158
165
  # Returns the Rio
159
166
  #
@@ -162,32 +169,33 @@ module RIO
162
169
  # If no args are provided, no lines are rejected.
163
170
  #
164
171
  # If args are provided they may be one or more of the following:
165
- # [Regexp] any matching line will not be processed
166
- # [Integer] specifies a line-number (zero-based) to be skipped
167
- # [Range] specifies a range of lines (zero-based) to be excluded
168
- # [Proc] a proc which will be called for each line, lines are excluded unless nil or false is returned
169
- # [Symbol] a symbol which will _sent_ to each line, lines are excluded unless nil or false is returned
172
+ # Regexp:: any matching line will not be processed
173
+ # Integer:: specifies a line-number (zero-based) to be skipped
174
+ # Range:: specifies a range of lines (zero-based) to be excluded
175
+ # Proc:: a proc which will be called for each line, lines are excluded unless nil or false is returned
176
+ # Symbol:: a symbol which will _sent_ to each line, lines are excluded unless nil or false is returned
177
+ # Array:: an array of any of above. All must match for a line to be included
170
178
  #
171
- # rio('afile').nolines(0) { |line| ... } # iterate over all but the first line of 'afile'
172
- # rio('afile').nolines(0,5..7)) { |line| ... } # don't iterate over lines 0,5,6 and 7
173
- # rio('afile').nolines(/Zippy/) { |line| ... } # skip all lines containing 'Zippy'
174
- # rio('afile').chomp.nolines(:empty?) { |line| ... } # skip empty lines
179
+ # rio('afile').skiplines(0) { |line| ... } # iterate over all but the first line of 'afile'
180
+ # rio('afile').skiplines(0,5..7)) { |line| ... } # don't iterate over lines 0,5,6 and 7
181
+ # rio('afile').skiplines(/Zippy/) { |line| ... } # skip all lines containing 'Zippy'
182
+ # rio('afile').chomp.skiplines(:empty?) { |line| ... } # skip empty lines
175
183
  #
176
- def nolines(*args,&block) target.nolines(*args,&block); self end
184
+ def skiplines(*args,&block) target.skiplines(*args,&block); self end
177
185
 
178
186
 
179
187
 
180
188
  # Sets the Rio to read rows and specifies rows which should be iterated through
181
- # by Rio#each or returned by Rio#getrec
189
+ # by Rio#each or returned by Rio#getrec.
182
190
  # Rio#rows is intended for use by extensions, where the concept of a row is reasonable.
183
- # In the absensence of an extension behaves like Rio#records
191
+ # In the absensence of an extension behaves like Rio#records.
184
192
  def rows(*args,&block) target.rows(*args,&block); self end
185
193
 
186
194
  # Sets the Rio to read rows and specifies lines which should *not* be iterated
187
195
  # through by Rio#each or returned by Rio#getrec
188
- # Rio#norows is intended for use by extensions, where the concept of a row is
189
- # reasonable. In the absensence of an extension behaves like Rio#norecords
190
- def norows(*args,&block) target.norows(*args,&block); self end
196
+ # Rio#skiprows is intended for use by extensions, where the concept of a row is
197
+ # reasonable. In the absence of an extension behaves like Rio#skiprecords
198
+ def skiprows(*args,&block) target.skiprows(*args,&block); self end
191
199
 
192
200
  # Sets the implicit output mode to 'a'.
193
201
  #
@@ -383,7 +391,7 @@ module RIO
383
391
  # dest.close # must be explicitly closed
384
392
  #
385
393
  # dest = rio('destfile')
386
- # dest.print(rio('srcfile').slurp)
394
+ # dest.print(rio('srcfile').contents)
387
395
  # dest.closed? #=> false (Rio#print is not a copy operator)
388
396
  # dest.close
389
397
  #
@@ -520,6 +528,25 @@ module RIO
520
528
  def chomp(arg=true,&block) target.chomp(arg,&block); self end
521
529
 
522
530
 
531
+ # Queries the Rio's strip-mode.
532
+ # See #strip.
533
+ #
534
+ def strip?() target.strip?() end
535
+
536
+
537
+ # Sets the Rio to strip lines and returns the Rio
538
+ #
539
+ # When called with a block, behaves as if strip.each(&block) had been called
540
+ #
541
+ # +strip+ causes lines returned by each, to_a, readlines, readline, gets, each_line etc.
542
+ # to be stripped with String#strip before iterated over or assigned
543
+ #
544
+ # ans = rio(?-).print("A Prompt> ").strip.gets # prompt the user
545
+ #
546
+ # See also #chomp
547
+ def strip(arg=true,&block) target.strip(arg,&block); self end
548
+
549
+
523
550
  # Sets the Rio to gzip mode.
524
551
  # ario.gzip #=> ario
525
552
  # If applied to a Rio that is being read from Reads
@@ -562,52 +589,6 @@ module RIO
562
589
  #def outputmode?() target.outputmode?() end
563
590
 
564
591
 
565
- # Sets the 'sync-mode' of the underlying IO using IO#sync=
566
- # ario.sync(boolean=true,&block) => ario
567
- # Sets the Rio so that its 'sync mode' will be set to +true+ or +false+ when opened, or set
568
- # it immediatly if already open. When sync mode is
569
- # true, all output is immediately flushed to the underlying operating
570
- # system and is not buffered internally. Returns the rio. See
571
- # also Rio#fsync, Rio#nosync, Rio#sync?.
572
- #
573
- # If a block is given behaves like <tt>ario.sync(arg).each(&block)</tt>
574
- #
575
- # f = rio("testfile").sync.puts("Hello World")
576
- # f.sync? # => true
577
- #
578
- def sync(arg=true,&block) target.sync(arg,&block); self end
579
-
580
- # Similar to IO#sync= false
581
- # ario.nosync(&block) => ario
582
- # Sets the Rio so that its 'sync mode' will be set to +false+ when opened, or set
583
- # it immediatly if already open. When sync mode is
584
- # true, all output is immediately flushed to the underlying operating
585
- # system and is not buffered internally. Returns the rio. See
586
- # also Rio#fsync, Rio#sync, Rio#sync?.
587
- #
588
- # If a block is given behaves like <tt>ario.nosync.each(&block)</tt>
589
- #
590
- # f = rio("testfile").sync.puts("Hello World")
591
- # f.sync? # => true
592
- # f.nosync
593
- # f.sync? # => false
594
- #
595
- def nosync(arg=false,&block) target.nosync(arg,&block); self end
596
-
597
- # Query the current 'sync mode' with IO#sync
598
- # ario.sync? => true or false
599
- # Returns the current ``sync mode'' of _ario_. When sync mode is true,
600
- # all output is immediately flushed to the underlying operating
601
- # system and is not buffered by Ruby internally. See also +Rio#fsync+,
602
- # Rio#sync, Rio#nosync
603
- #
604
- # f = rio("testfile")
605
- # f.sync? #=> false
606
- #
607
- def sync?() target.sync?() end
608
-
609
-
610
-
611
592
 
612
593
  end
613
594
  end