rio 0.3.8 → 0.3.9

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 (223) hide show
  1. data/README +18 -12
  2. data/Rakefile +57 -87
  3. data/build_doc.rb +19 -17
  4. data/doc/ANNOUNCE +3 -32
  5. data/doc/RELEASE_NOTES +4 -5
  6. data/doc/RIOIS +215 -0
  7. data/doc/generators/template/html/rio.css +428 -0
  8. data/doc/generators/template/html/rio.rb +18 -389
  9. data/doc/generators/template/html/ugly.rb +130 -0
  10. data/doc/pkg_def.rb +66 -0
  11. data/ex/catcsv.rb +64 -0
  12. data/ex/colx.rb +8 -0
  13. data/ex/findinruby +15 -0
  14. data/ex/findruby +14 -0
  15. data/ex/passwd_report.rb +8 -0
  16. data/ex/prompt.rb +25 -0
  17. data/ex/rgb.txt.gz +0 -0
  18. data/ex/riocat +42 -0
  19. data/ex/riogunzip +31 -0
  20. data/ex/riogzip +24 -0
  21. data/ex/rioprompt.rb +10 -0
  22. data/ex/targz2zip +17 -0
  23. data/ex/tonl +10 -0
  24. data/lib/rio.rb +16 -10
  25. data/lib/rio/abstract_method.rb +3 -4
  26. data/lib/rio/argv.rb +3 -4
  27. data/lib/rio/arycopy.rb +3 -4
  28. data/lib/rio/assert.rb +3 -4
  29. data/lib/rio/base.rb +3 -4
  30. data/lib/rio/callstr.rb +3 -4
  31. data/lib/rio/const.rb +3 -4
  32. data/lib/rio/construct.rb +3 -4
  33. data/lib/rio/constructor.rb +12 -8
  34. data/lib/rio/context.rb +15 -30
  35. data/lib/rio/context/autoclose.rb +3 -4
  36. data/lib/rio/context/copying.rb +3 -4
  37. data/lib/rio/context/cxx.rb +3 -4
  38. data/lib/rio/context/dir.rb +3 -4
  39. data/lib/rio/context/gzip.rb +3 -4
  40. data/lib/rio/context/methods.rb +16 -5
  41. data/lib/rio/context/skip.rb +3 -4
  42. data/lib/rio/context/stream.rb +42 -5
  43. data/lib/rio/cp.rb +7 -7
  44. data/lib/rio/def.rb +3 -4
  45. data/lib/rio/dir.rb +3 -4
  46. data/lib/rio/doc.rb +4 -5
  47. data/lib/rio/doc/EXAMPLES.rb +299 -0
  48. data/lib/rio/doc/HOWTO.rb +3 -4
  49. data/lib/rio/doc/INTRO.rb +86 -105
  50. data/lib/rio/doc/OPTIONAL.rb +4 -5
  51. data/lib/rio/doc/SYNOPSIS.rb +7 -6
  52. data/lib/rio/entrysel.rb +21 -23
  53. data/lib/rio/exception.rb +3 -4
  54. data/lib/rio/exception/copy.rb +3 -4
  55. data/lib/rio/exception/notimplemented.rb +57 -0
  56. data/lib/rio/exception/notsupported.rb +3 -4
  57. data/lib/rio/exception/open.rb +3 -4
  58. data/lib/rio/exception/state.rb +3 -4
  59. data/lib/rio/ext.rb +47 -13
  60. data/lib/rio/ext/csv.rb +4 -5
  61. data/lib/rio/ext/if.rb +45 -0
  62. data/lib/rio/ext/mp3info.rb +80 -0
  63. data/lib/rio/ext/splitlines.rb +253 -0
  64. data/lib/rio/ext/yaml.rb +9 -5
  65. data/lib/rio/ext/yaml/doc.rb +133 -0
  66. data/lib/rio/ext/yaml/tie.rb +149 -0
  67. data/lib/rio/ext/zipfile.rb +23 -4
  68. data/lib/rio/ext/zipfile/fs.rb +116 -0
  69. data/lib/rio/ext/zipfile/rl.rb +251 -0
  70. data/lib/rio/ext/zipfile/rootdir.rb +117 -0
  71. data/lib/rio/ext/zipfile/state.rb +161 -0
  72. data/lib/rio/ext/zipfile/wrap.rb +204 -0
  73. data/lib/rio/factory.rb +235 -27
  74. data/lib/rio/file.rb +4 -4
  75. data/lib/rio/filter.rb +3 -4
  76. data/lib/rio/filter/closeoneof.rb +3 -4
  77. data/lib/rio/filter/gzip.rb +9 -4
  78. data/lib/rio/fs/base.rb +3 -4
  79. data/lib/rio/fs/impl.rb +4 -5
  80. data/lib/rio/fs/native.rb +3 -4
  81. data/lib/rio/fs/stream.rb +3 -4
  82. data/lib/rio/fs/url.rb +3 -4
  83. data/lib/rio/ftp/conncache.rb +19 -5
  84. data/lib/rio/ftp/dir.rb +3 -4
  85. data/lib/rio/ftp/fs.rb +30 -24
  86. data/lib/rio/grande.rb +27 -7
  87. data/lib/rio/handle.rb +3 -4
  88. data/lib/rio/if.rb +19 -15
  89. data/lib/rio/if/basic.rb +7 -7
  90. data/lib/rio/if/csv.rb +5 -6
  91. data/lib/rio/if/dir.rb +120 -114
  92. data/lib/rio/if/file.rb +52 -44
  93. data/lib/rio/if/fileordir.rb +217 -211
  94. data/lib/rio/if/grande.rb +674 -644
  95. data/lib/rio/if/grande_entry.rb +321 -313
  96. data/lib/rio/if/grande_stream.rb +653 -553
  97. data/lib/rio/if/internal.rb +3 -4
  98. data/lib/rio/if/path.rb +425 -426
  99. data/lib/rio/if/rubyio.rb +681 -0
  100. data/lib/rio/if/string.rb +42 -5
  101. data/lib/rio/if/temp.rb +3 -4
  102. data/lib/rio/if/test.rb +245 -238
  103. data/lib/rio/if/yaml.rb +15 -41
  104. data/lib/rio/ioh.rb +7 -5
  105. data/lib/rio/iomode.rb +19 -7
  106. data/lib/rio/ios/fail.rb +4 -5
  107. data/lib/rio/ios/generic.rb +4 -5
  108. data/lib/rio/ios/mode.rb +4 -5
  109. data/lib/rio/ios/null.rb +6 -7
  110. data/lib/rio/iowrap.rb +3 -4
  111. data/lib/rio/kernel.rb +3 -5
  112. data/lib/rio/local.rb +3 -4
  113. data/lib/rio/match.rb +3 -4
  114. data/lib/rio/matchrecord.rb +3 -4
  115. data/lib/rio/no_warn.rb +3 -4
  116. data/lib/rio/nullio.rb +3 -4
  117. data/lib/rio/open3.rb +4 -5
  118. data/lib/rio/ops/construct.rb +3 -4
  119. data/lib/rio/ops/create.rb +11 -6
  120. data/lib/rio/ops/dir.rb +19 -8
  121. data/lib/rio/ops/either.rb +6 -5
  122. data/lib/rio/ops/file.rb +3 -4
  123. data/lib/rio/ops/path.rb +14 -35
  124. data/lib/rio/ops/stream.rb +3 -4
  125. data/lib/rio/ops/stream/input.rb +4 -7
  126. data/lib/rio/ops/stream/output.rb +3 -4
  127. data/lib/rio/ops/stream/read.rb +6 -5
  128. data/lib/rio/ops/stream/write.rb +3 -4
  129. data/lib/rio/ops/symlink.rb +3 -4
  130. data/lib/rio/path.rb +22 -18
  131. data/lib/rio/path/reset.rb +4 -5
  132. data/lib/rio/piper.rb +3 -4
  133. data/lib/rio/piper/cp.rb +3 -4
  134. data/lib/rio/prompt.rb +10 -5
  135. data/lib/rio/rectype.rb +5 -5
  136. data/lib/rio/rl/base.rb +17 -71
  137. data/lib/rio/rl/builder.rb +14 -38
  138. data/lib/rio/rl/chmap.rb +66 -0
  139. data/lib/rio/rl/fs2url.rb +82 -0
  140. data/lib/rio/rl/ioi.rb +4 -4
  141. data/lib/rio/rl/path.rb +44 -122
  142. data/lib/rio/rl/pathmethods.rb +19 -8
  143. data/lib/rio/rl/uri.rb +137 -60
  144. data/lib/rio/rl/withpath.rb +295 -0
  145. data/lib/rio/scheme/aryio.rb +3 -4
  146. data/lib/rio/scheme/cmdio.rb +3 -4
  147. data/lib/rio/scheme/cmdpipe.rb +4 -4
  148. data/lib/rio/scheme/fd.rb +3 -4
  149. data/lib/rio/scheme/ftp.rb +7 -7
  150. data/lib/rio/scheme/http.rb +4 -5
  151. data/lib/rio/scheme/null.rb +3 -4
  152. data/lib/rio/scheme/path.rb +3 -4
  153. data/lib/rio/scheme/stderr.rb +3 -4
  154. data/lib/rio/scheme/stdio.rb +3 -4
  155. data/lib/rio/scheme/strio.rb +3 -4
  156. data/lib/rio/scheme/sysio.rb +3 -4
  157. data/lib/rio/scheme/tcp.rb +3 -4
  158. data/lib/rio/scheme/temp.rb +6 -6
  159. data/lib/rio/state.rb +18 -46
  160. data/lib/rio/state/error.rb +3 -4
  161. data/lib/rio/stream.rb +4 -4
  162. data/lib/rio/stream/base.rb +3 -4
  163. data/lib/rio/stream/duplex.rb +3 -4
  164. data/lib/rio/stream/open.rb +3 -8
  165. data/lib/rio/symantics.rb +3 -4
  166. data/lib/rio/tempdir.rb +2 -2
  167. data/lib/rio/to_rio.rb +3 -4
  168. data/lib/rio/to_rio/all.rb +3 -4
  169. data/lib/rio/to_rio/array.rb +4 -5
  170. data/lib/rio/to_rio/io.rb +4 -5
  171. data/lib/rio/to_rio/object.rb +4 -5
  172. data/lib/rio/to_rio/string.rb +4 -5
  173. data/lib/rio/uri/file.rb +41 -5
  174. data/lib/rio/util.rb +3 -4
  175. data/lib/rio/version.rb +4 -5
  176. data/setup.rb +368 -339
  177. data/test/bin/list_dir.rb +1 -1
  178. data/test/ftp/anon_misc.rb +13 -1
  179. data/test/ftp/anon_special.rb +6 -6
  180. data/test/ftp/anon_write.rb +10 -3
  181. data/test/ftp/ftp2ftp.rb +2 -2
  182. data/test/ftp/testdef.rb +9 -6
  183. data/test/http/all.rb +3 -0
  184. data/test/http/copy-from-http.rb +140 -0
  185. data/test/lib/temp_server.rb +44 -0
  186. data/test/runalltests.rb +3 -1
  187. data/test/runhttp.rb +12 -0
  188. data/test/runhttptests.rb +1 -1
  189. data/test/runtests.rb +41 -3
  190. data/test/tc/abs.rb +9 -5
  191. data/test/tc/all.rb +9 -4
  192. data/test/tc/base.rb +1 -1
  193. data/test/tc/base2.rb +87 -0
  194. data/test/tc/{methods.rb → clone.rb} +72 -50
  195. data/test/tc/closeoncopy.rb +13 -2
  196. data/test/tc/copy-dir-samevar.rb +91 -0
  197. data/test/tc/dir_iter.rb +0 -1
  198. data/test/tc/empty.rb +6 -2
  199. data/test/tc/expand_path.rb +36 -54
  200. data/test/tc/ext.rb +42 -18
  201. data/test/tc/gzip.rb +30 -3
  202. data/test/tc/likeio.rb +5 -1
  203. data/test/tc/line_record_row.rb +51 -0
  204. data/test/tc/noqae.rb +71 -70
  205. data/test/tc/path_parts.rb +175 -0
  206. data/test/tc/programs_util.rb +3 -3
  207. data/test/tc/rename.rb +4 -5
  208. data/test/tc/riorl.rb +9 -7
  209. data/test/tc/skip.rb +35 -6
  210. data/test/tc/skiplines.rb +34 -5
  211. data/test/tc/split.rb +8 -50
  212. data/test/tc/splitlines.rb +65 -0
  213. data/test/tc/splitpath.rb +83 -0
  214. data/test/tc/testcase.rb +1 -1
  215. data/test/tc/truncate.rb +39 -0
  216. data/test/tc/yaml.rb +9 -8
  217. metadata +261 -207
  218. data/ChangeLog +0 -1418
  219. data/VERSION +0 -1
  220. data/lib/rio/doc/MISC.rb +0 -259
  221. data/lib/rio/if/stream.rb +0 -680
  222. data/lib/rio/impl/path.rb +0 -87
  223. data/test/tc/copy-from-http.rb +0 -89
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # ===============================================================================
3
- # Copyright (c) 2005, 2006 Christopher Kleckner
3
+ # Copyright (c) 2005,2006,2007 Christopher Kleckner
4
4
  # All rights reserved
5
5
  #
6
6
  # This file is part of the Rio library for ruby.
@@ -23,662 +23,692 @@
23
23
  #
24
24
  # To create the documentation for Rio run the command
25
25
  # ruby build_doc.rb
26
- # from the distribution directory. Then point your browser at the 'doc/rdoc' directory.
26
+ # from the distribution directory.
27
27
  #
28
28
  # Suggested Reading
29
29
  # * RIO::Doc::SYNOPSIS
30
30
  # * RIO::Doc::INTRO
31
31
  # * RIO::Doc::HOWTO
32
+ # * RIO::Doc::EXAMPLES
32
33
  # * RIO::Rio
33
34
  #
34
- # <b>Rio is pre-alpha software.
35
- # The documented interface and behavior is subject to change without notice.</b>
36
35
 
37
36
  require 'rio/no_warn'
38
37
  module RIO
39
- class Rio
40
- # module IF
41
- # module Grande
42
- # Returns the contents of the rio as an array.
43
- # Rio#to_a is implemented in terms of Rio#each so the the following are roughly equivelent
44
- #
45
- # ary = ario.to_a
46
- #
47
- # ary = []
48
- # ario.each do |rec|
49
- # ary << ary
50
- # end
51
- #
52
- # What constitutes an array element is determined by Rio#lines, Rio#bytes, or
53
- # by an extension such as Rio#csv. Rio#lines is the default.
54
- #
55
- # rio('afile.txt').to_a # returns an array of the lines in afile.txt
56
- #
57
- # rio('afile.txt').lines(1...3).to_a # an array containing lines 1 and 2 of afile.txt
58
- #
59
- # rio('afile.dat').bytes(50).to_a # an array containing the contents of afile.dat broken
60
- # # up into 50 byte chunks
61
- #
62
- # See also Rio#[] (subscript operator)
63
- #
64
- # def to_a() target.to_a() end
65
-
66
- # Grande subscript operator.
67
- #
68
- # For files this returns all or part of a file as an array.
69
- #
70
- # For directories this returns all or some of the entries in a directory
71
- #
72
- # === Files
73
- #
74
- # This combines the record selection offered by Rio#records with
75
- # the conversion to an array provided by Rio#to_a. The following two are equivelant:
76
- # * ario[*args]
77
- # * ario.records(*args).to_a
78
- #
79
- # What constitutes an array element is determined by Rio#lines, Rio#bytes,
80
- # or by an extension such as Rio#csv. Rio#lines is the default.
81
- #
82
- # Arguments may consist of zero or more integers, ranges, regular expressions, symbols,
83
- # procs, and arrays
84
- # An empty argument list selects all records
85
- #
86
- # Records are selected as follows.
87
- # range:: specifies a range of records to be selected (zero based)
88
- # regexp:: matching records will be selected.
89
- # integer:: treated like a one element range
90
- # symbol:: the symbol is sent to each record. Record is selected
91
- # unless false is returned
92
- # proc:: the proc is called with the record as an argument.
93
- # Record is selected unless false is returned
94
- # array:: the array may contain any of the other selector types. Record is selected
95
- # unless any of the selectors returns false. (a logical and)
96
- #
97
- # A record matching *any* of the selectors will be included in the array. (acts like an _or_)
98
- #
99
- # Because this is implemented in terms of the Rio#each,
100
- # When only record ranges are used to select records,
101
- # iteration will stop when the recno exceeds the maximum of any range. That is to say
102
- #
103
- # This reads one record from a file and returns it
104
- # rio('bigfile.mp3').bytes(1024)[0]
105
- # While this reads *all* records from a file and returns the first one
106
- # rio('bigfile.mp3').bytes(1024).to_a[0]
107
- #
108
- # === Directories
109
- #
110
- # This combines the entry selection offered by Rio#entries with
111
- # the conversion to an array provided by Rio#to_a. The following two are equivelant:
112
- # * ario[*args]
113
- # * ario.entries(*args).to_a
114
- #
115
- # Arguments may consist of strings (treated as globs) or regular expressions.
116
- # An empty argument list selects all entries
117
- # See ::Dir#glob and ::File::fnmatch? for more in information on _globs_. Be warned that using the '**' glob
118
- # recurses into directories independently of Rio#all and using both is unsupported.
119
- #
120
- # ario = rio('adir')
121
- # ario[] # returns an array containg all entries in _adir_
122
- # ario[/^zippy/] # all entries starting with 'zippy'
123
- # ario['zippy*'] # same thing
124
- #
125
- # As with Rio#each:
126
- # * Files and directories are returned as Rios
127
- # * The types of entries is also affected by Rio#files and Rio#dirs.
128
- # rio('adir').files['*.txt'] # array of all _.txt_ files
129
- # rio('adir').dirs(/^\./) # array of all dot directories
130
- # * Recursion is enabled using Rio#all
131
- # rio('adir').all.files['*.[ch]'] # array of c source files in _adir_ and its subdirecories
132
- # rio('adir').all.dirs[/^\.svn/] # array of subversion directories in _adir_ and subdirectories
133
- # * Rio#files and Rio#dirs act independetly of each other. Specifying both will cause both to be returned.
134
- # The argument list to Rio#[] will be applied to the closest.
135
- # rio('adir').files('*.rb').dirs['ruby*'] # array of _.rb_ files and
136
- # # directories starting with 'ruby'
137
- # rio('adir').dirs('ruby*').files['*.rb'] # same thing
138
- #
139
- # === Lines
140
- # This section applies similarly to Rio#lines, Rio#bytes, Rio#records, and Rio#rows
141
- #
142
- # Using Rio#lines and related methods with a Rio referencing a directory
143
- # imples Rio#files and will cause an array of the lines or bytes in the files to be returned. As above,
144
- # the arguments to the subscript operator will be applied to the closest.
145
- # rio('adir').lines[] # array of all lines in the files in 'adir'
146
- # rio('adir').files.lines[] # same thing
147
- # rio('adir').lines(0..9).files['*.txt'] # array of the first ten lines of all .txt files
148
- # rio('adir').files('*.txt').lines[0..9] # same thing
149
- # rio('adir').all.files('*.rb').lines[/^\s*require/] # array of 'require' lines in .rb files in
150
- # # 'adir and its subdirectories
151
- #
152
- # Note the difference between the following similar usages
153
- # it1 = rio('adir').files('*.rb') # returns a Rio, prepared for selecting ruby files
154
- # it2 = rio('adir').files['*.rb'] # returns an array of the ruby files
155
- #
156
- # The second example above could have been written
157
- # it2 = it1.to_a
158
- #
159
- # Examples:
160
- #
161
- # rio('afile.txt').lines[1..2] # array containing the 2nd and 3rd line
162
- #
163
- # rio('afile.txt')[1,3..5] # array containing lines 1,3,4 and 5
164
- #
165
- # rio('afile.txt')[/Zippy/] # array of all lines containing 'Zippy'
166
- #
167
- # rio('afile.txt')[1,3..5,/Zippy/] # array with lines 1,3,4 and 5 and all lines containing 'Zippy'
168
- #
169
- # rio('afile.dat').bytes(50)[] # array containing the contents of afile.dat broken up into 50 byte chunks
170
- #
171
- # rio('afile.dat').bytes(50)[0,2] # array containing the first and third such chunk
172
- #
173
- # rio('afile.dat').bytes(50).records[0,2] # same thing
174
- #
175
- # rio('afile.dat').bytes(50).records(0,2).to_a # once again
176
- #
177
- # rio('afile.csv').csv[0..9] # array of the first 10 records of afile.csv parsed by the ::CSV module
178
- #
179
- # rio('afile.csv').csv.records[0..9] # same thing
180
- #
181
- # rio('afile.csv').csv(';').records[0..9] # same thing using semi-colon as the value separator
182
- #
183
- # rio('afile.csv').csv.records[0,/Zippy/] # record 0 and all records containing 'Zippy'
184
- # # the regexp is matched against the line before parsing by ::CSV
185
- #
186
- # rio('adir')[] # array of entries in 'adir'
187
- #
188
- # rio('adir')['*.txt'] # array of all .txt entries
189
- #
190
- # rio('adir').all['*.txt'] # array of all .txt entries in 'adir and its subdirectories
191
- #
192
- # rio('adir').files['*.txt'] # array of all .txt files
193
- #
194
- # rio('adir').dirs['CSV'] # array of all CSV directories
195
- # rio('adir').skipdirs['CSV'] # array of all non-CSV directories
196
- #
197
- def [](*selectors) target[*selectors] end
198
-
199
-
200
-
201
- # Iterate through a rio. Executes the block for each item selected for the Rio.
202
- # See Rio#lines, Rio#records, Rio#bytes, Rio#files, Rio#dirs, Rio#[]
203
- # and Rio#to_a for more information
204
- # on how records are selected and what kind of record is passed to the block.
205
- #
206
- # Rio#each is the fundemental method for all the Rio grande operators.
207
- # Rio#to_a and the Rio copy operators Rio#< Rio#<< Rio#>> Rio#> are all implemented
208
- # in terms of Rio#each.
209
- #
210
- # While Rio#each is fundamental to a Rio, it rarely needs
211
- # actually be called because all the grande configuration methods will also take a block
212
- # and call Rio#each if one is given.
213
- # So the existance of a block after many methods is taken as an implied
214
- # Rio#each
215
- #
216
- # For Rios that refer to files, the item passed to the block is a String containing
217
- # the line or block as selected by Rio#lines, or Rio#bytes. +lines+ is the default.
218
- # rio('afile').lines.each { |line| ...}
219
- #
220
- # The block passed to +each+ will also accept an optional second parameter which will contain
221
- # the result of the matching function. What this variable contains depends on the argument
222
- # to +lines+ that resulted in the match as follows:
223
- #
224
- # Regexp:: The MatchData that resulted from the match.
225
- # Range:: The record number of the matching record.
226
- # Fixnum:: The record number of the matching record.
227
- # Proc:: The value returned by the proc.
228
- # Symbol:: The value resulting from sending the symbol to the String.
229
- #
230
- # If no selection arguments were used, this variable will simply contain +true+.
231
- #
232
- # rio(??).puts(%w[0:zero 1:one]).rewind.lines(/(\d+):([a-z]+)/) do |line,match|
233
- # puts("#{match[1]} is spelled '#{match[2]}'")
234
- # end
235
- #
236
- # Produces:
237
- # 0 is spelled 'zero'
238
- # 1 is spelled 'one'
239
- #
240
- #
241
- # For Rios that refer to directories, the item passed to the block is a Rio refering to
242
- # the directory entry.
243
- #
244
- # rio('adir').files.each do |file|
245
- # file.kind_of?(RIO::Rio) # true
246
- # end
247
- #
248
- # In addition, the Rio passed to the block inherits certain attributes from the directory Rio.
249
- #
250
- # rio('adir').files.chomp.each do |file| # chomp is ignored for directories,
251
- # file.each do |line| # chomp attribute is inherited by the file rio
252
- # # .. line is chomped
253
- # end
254
- # end
255
- #
256
- # Rio#each returns the Rio which called it.
257
- #
258
- # Here are a few illustrative examples
259
- #
260
- # * Processing lines in a file
261
- #
262
- # rio('f.txt').each { |line| ... } # execute block for every line in the file
263
- # rio('f.txt').lines.each { |line| ... } # same thing
264
- # rio('f.txt').lines { |line| ... } # same thing
265
- #
266
- # rio('f.txt').chomp.each { |line| ... } # same as above with lines chomped
267
- # rio('f.txt').chomp { |line| ... } # ditto
268
- # rio('f.txt').lines.chomp { |line| ... } # ditto
269
- # rio('f.txt').chomp.lines { |line| ... } # ditto
270
- #
271
- # rio('f.txt.gz').gzip.each { |line| ... } # execute block for every line in a gzipped file
272
- # rio('f.txt.gz').gzip { |line| ... } # same thing
273
- # rio('f.txt.gz').lines.gzip { |line| ... } # same thing
274
- #
275
- # rio('f.txt.gz').gzip.chomp { |line| ... } # chomp lines from a gzipped file
276
- # rio('f.txt.gz').gzip.chomp.each { |line| ... } # ditto
277
- # rio('f.txt.gz').chomp.lines.gzip { |line| ... } # ditto
278
- #
279
- # rio('f.txt').lines(0..9) { |line| ... } # execute block for the first 10 lines in the file
280
- # rio('f.txt').lines(0..9).each { |line| ... } # same thing
281
- #
282
- # rio('f.txt').lines(/^\s*#/) { |line| ... } # execute block for comment-only lines
283
- # rio('f.txt').lines(/^\s*#/).each { |line| ... } # same thing
284
- #
285
- # rio('f.txt').lines(0,/Rio/) { |line| ... } # execute block for the first line and
286
- # # all lines containing 'Rio'
287
- #
288
- # rio('f.txt.gz').gzip.chomp.lines(0..1) { |line| ... } # first 2 lines chomped from a gzip file
289
- #
290
- # * Processing a file a block at a time
291
- #
292
- # rio('f.dat').bytes(10).each { |data| ... } # process the file 10 bytes at a time
293
- # rio('f.dat').bytes(10) { |data| ... } # same thing
294
- # rio('f.dat').bytes(10).records(2,4) { |data| ... } # only 3rd and 5th ten-byte data-block
295
- # rio('f.dat.gz').gzip.records(2,4).bytes(10) { |data| ... } # same from a gzipped file
296
- #
297
- # * Iterating over directories
298
- # rio('adir').each { |ent| ... } # execute the block for each entry in the directory 'adir'
299
- # rio('adir').files.each { |file| ...} # only files
300
- # rio('adir').files { |file| ...} # ditto
301
- # rio('adir').all.files { |file| ...} # files, recurse into subdirectories
302
- # rio('adir').dirs { |dir| ...} # only directories
303
- # rio('adir').files('*.rb') { |file| ...} # only .rb files using a glob
304
- # rio('adir').files(/\.rb$/) { |file| ...} # only .rb files using a regular expression
305
- # rio('adir').all.files('*.rb') { |file| ...} # .rb files, recursing into subdirectories
306
- # rio('adir').dirs(/^\./) { |dir| ... } # only dot directories
307
- # rio('adir').dirs('/home/*') { |dir| ... } # home directories
308
- #
309
- # See RIO::Doc::HOWTO and RIO::Doc::SYNOPSIS for more examples, and RIO::Doc::INTRO for further explanation.
310
- #
311
- def each(*args,&block) target.each(*args,&block); self end
312
-
313
-
314
- # For a file Rio +delete+ calls FileUtils#rm.
315
- # For a directory Rio +delete+ calls FileUtils#rmdir
316
- # Returns the Rio. If the Rio does not exist, simply return the Rio.
317
- #
318
- # rio('afile,txt').delete # delete 'afile.txt'
319
- # rio('adir').delete # delete adir
320
- # rio('something').delete # delete something
321
- #
322
- def delete() target.delete(); self end
323
-
324
- # For a file Rio#delete! calls FileUtils#rm.
325
- # For a directory Rio#delete! calls FileUtils#rmtree
326
- # Returns the Rio. If the rio does not exist, simply return itself.
327
- #
328
- # rio('afile,txt').delete! # delete f.txt
329
- # rio('adir').delete! # delete adir
330
- #
331
- # # create a directory, after deleting anything that previously had its name
332
- # rio('adir/asubdir').delete!.mkpath
333
- #
334
- # ==== Deleting Summary
335
- # * To delete something only if it is not a directory use Rio#rm
336
- # * To delete an empty directory use Rio#rmdir
337
- # * To delete an entire directory tree use Rio#rmtree
338
- # * To delete anything except a populated directory use Rio#delete
339
- # * To delete anything use Rio#delete!
340
- #
341
- # In all cases, deleting something that does not exist is considered successful
342
- #
343
- def delete!() target.delete!(); self end
344
-
345
- # Grande Copy-To Operator
346
- #
347
- # The copy grande-operator copies a Rio to a another Rio or another ruby object. The behaviour
348
- # and the library used depend on the types of the of the source and destination. For
349
- # simple file or directory copying ::FileUtils#cp or ::FileUtils#cp_r will be used. If
350
- # any of the Rio grande methods are specified for the source or destination, the
351
- # source Rio will be iterated through copying records to the destintion as specified. Roughly
352
- # equivelant to
353
- # dst = rio('dst_file')
354
- # rio('src_file').each do |line|
355
- # dst.print(line)
356
- # end
357
- # dst.close
358
- #
359
- # The destination of the copy operators may be a:
360
- # IO:: Each record of the Rio is written to the IO using IO#print. The IO must be opened for writing.
361
- # Array:: Each record or entry of the Rio becomes an element of the array
362
- # String:: Puts the entire contents of the Rio into the string
363
- # Rio:: Depends on the destination. See below.
364
- #
365
- # Copy a file to a file
366
- # rio('src_file') > rio('dst_file')
367
- #
368
- # Copy a file to a directory
369
- # rio('src_file') > rio('dst_dir')
370
- #
371
- # Copy a directory to another directory
372
- # rio('src_dir') > rio('dst_dir')
373
- #
374
- # Make an ungizipped copy of a gzipped file
375
- # rio('src.txt.gz').gzip > rio('dst.txt')
376
- #
377
- # Copying to an array
378
- # rio('afile') > ary # each line of the file becomes and element of the ary
379
- # rio('afile').chomp > ary # same thing with lines chomped
380
- # rio('afile.gz').gzip.chomp > ary # same thing from a gzipped file
381
- #
382
- # rio('afile').lines(0..9) > ary # ary will contain only the first ten lines of the file
383
- # rio('afile').chomp.lines(0..9) > ary # same thing with lines chomped
384
- # rio('afile').gzip.chomp.lines(0..9) > ary # same thing from a gzipped file
385
- #
386
- # rio('afile').skiplines(0..9) > ary # ary will contain all but the first ten lines of the file
387
- #
388
- # rio('adir') > ary # ary will contain a Rio for each entry in the directory
389
- # rio('adir').files > ary # same, but only files
390
- # rio('adir').files('*.rb') >ary # same, but only .rb files
391
- #
392
- # Copying to a string
393
- # rio('afile') > astring # slurp the entire contents of the file into astring
394
- # astring = rio('afile').contents # same effect
395
- #
396
- # Copy the first line *and* every line containing the word Rio into a gzipped file
397
- # rio('src').lines(1,/Rio/) > rio('dst.gz').gzip
398
- #
399
- # Copy lines of a web page into an array with each line chomped
400
- # rio('http://ruby-doc.org/index.html').chomp > an_array
401
- #
402
- # Copy the first and 8th through 10th columns of the first ten rows of a gzipped csv
403
- # file on a web site into a local gzipped csv file that uses semi-colons as separators
404
- # rio('http://domain/file.csv.gz').columns(0,7..9).gzip.csv[0..9] > rio('localfile.csv.gz').csv(';').gzip
405
- #
406
- def >(destination)
407
- RIO::no_warn {
408
- target > destination;
409
- }
410
- self
411
- end
412
-
413
- # Alias for Rio#> (copy-to grande operator)
414
- def copy_to(destination) target.copy_to(destination); self end
415
-
416
-
417
- # Grande Pipe Operator
418
- #
419
- # The Rio pipe operator is actually an alternative syntax for calling the copy-to operator, designed to
420
- # allow several copy operation to be performed in one line of code, with behaviour that mimics
421
- # the pipe operator commonly available in shells.
422
- #
423
- # If +destination+ is a +cmdio+, a <tt>cmdpipe</tt> Rio is returned, and none of the commands are run.
424
- #
425
- # Otherwise the +cmdpipe+ Rio is run with the output of the pipe being copied to the destination.
426
- # In this case a Rio representing the +destination+ is returned.
427
- #
428
- # If destination is not a Rio it is passed to the Rio constructor as is done with the copy-to operator
429
- # except that if +destination+ is a String it is assumed to be a command instead of a path.
430
- #
431
- # rio('afile') | rio(?-,'grep i') | rio(?-) # returns rio(?-)
432
- # # equivelent to rio(?-, 'grep i') < rio('afile') > rio(?-)
433
- #
434
- # rio('infile') | rio(?-, 'acmd') | rio(?-, 'acmd2') | rio('outfile')
435
- # # same as
436
- # # acmd = rio(?-,'acmd')
437
- # # acmd2 = rio(?-,'acmd2')
438
- # # out = rio('outfile')
439
- # # acmd < rio('infile')
440
- # # acmd2 < acmd
441
- # # out < acmd2
442
- #
443
- # rio('afile') | 'acmd' | 'acmd2' | rio('outfile') # same thing
444
- #
445
- # acmdpipe = rio(?-,'acmd') | 'acmd2'
446
- # rio('afile') | acmdpipe | rio('outfile') # same thing
447
- #
448
- # acmdpipe1 = rio(?|,'acmd','acmd2')
449
- # rio('afile') | acmdpipe1 | rio('outfile') # same thing
450
- #
451
- # acmdpipe2 = rio('afile') | 'acmd' | 'acmd2'
452
- # acmdpipe2 | rio('outfile') # same thing
453
- #
454
- # The grande pipe operator can not be used to create a +cmdpipe+ Rio that includes a destination.
455
- # This must be done using a Rio constructor
456
- # cmd_with_output = rio(?|,'acmd',rio('outfile'))
457
- # rio('afile') | cmd_with_output # same as above
458
- #
459
- def |(destination) target | destination end
460
-
461
- # Grande Append-To Operator
462
- #
463
- # The append-to grande-operator is the same as Rio#> (copy-to) except that it opens the destination
464
- # for append.
465
- # The destination can be a kind of:
466
- # IO:: Each record of the Rio is written to the IO using IO#print. The IO must be opened for writing.
467
- # Array:: Each record or entry of the Rio is appended to the destination array
468
- # String:: Appends the entire contents of the Rio to destination
469
- # Rio:: Just like Rio#> (copy-to) except the unopened object are
470
- # opened for append. If the destination is already opened for writing or is a
471
- # directory, this is identical to Rio#> (copy-to)
472
- #
473
- # See Rio#> (copy-to)
474
- #
475
- # rio('afile') >> rio('anotherfile') # append the contents of 'afile' to 'anotherfile'
476
- # rio('afile') >> rio('adir') # copies 'afile' to the directory 'adir'
477
- # rio('adir') >> rio('anotherdir') # copy directory 'adir' recursively to 'anotherdir'
478
- # rio('adir') >> array # a Rio for each entry in the directory will be appended to ary
479
- def >>(destination) target >> destination; self end
480
-
481
-
482
- # Alias for Rio#>> (append-to grande operator)
483
- def append_to(destination) target.append_to(destination); self end
484
-
485
-
486
- # Grande Append-From Operator
487
- #
488
- # The append-from grande-operator copies a Rio from another Rio or another ruby object. This
489
- # behaves like Rio#< (copy-from) except unopened Rios are opened for append.
490
- #
491
- # The following summarizes how objects are copied:
492
- # IO:: IO#each is used to iterate through the source with each record appended to the Rio
493
- # Array:: Each element of the Array is appended individually to the Rio.
494
- # String:: The string is appended to the Rio using Rio#print
495
- # Rio:: The source Rio is appended using its Rio#>> (append-to) operator
496
- #
497
- # See Rio#< (copy-from)
498
- def <<(source) target << source; self end
38
+ module IF
39
+ module Grande
40
+
41
+ # Returns the contents of the rio as an array. (See ::Enumerable#to_a)
42
+ #
43
+ # IF::Grande#to_a is implemented in terms of #each so the the following are roughly equivelent
44
+ #
45
+ # ary = ario.to_a
46
+ #
47
+ # ary = []
48
+ # ario.each do |rec|
49
+ # ary << ary
50
+ # end
51
+ #
52
+ # What constitutes an array element is determined by IF::GrandeStream#lines,
53
+ # IF::GrandeStream#bytes, IF::GrandeStream#records, IF::GrandeStream#rows or
54
+ # by an extension such as IF::CSV#csv. IF::GrandeStream#lines is the default.
55
+ #
56
+ # rio('afile.txt').to_a # returns an array of the lines in afile.txt
57
+ #
58
+ # rio('afile.txt').lines(1...3).to_a # an array containing lines 1 and 2 of afile.txt
59
+ #
60
+ # rio('afile.dat').bytes(50).to_a # an array containing the contents of afile.dat broken
61
+ # # up into 50 byte chunks
62
+ #
63
+ # See also IF::Grande#[] (subscript operator)
64
+ #
65
+ def to_a() target.to_a() end
66
+
67
+ # Grande subscript operator.
68
+ #
69
+ # For files this returns all or part of a file as an array.
70
+ #
71
+ # For directories this returns all or some of the entries in a directory
72
+ #
73
+ # === Files
74
+ #
75
+ # This combines the record selection offered by IF::GrandeStream#records with
76
+ # the conversion to an array provided by IF::Grande#to_a. The following two are equivelant:
77
+ # ario[*args]
78
+ # ario.records(*args).to_a
79
+ #
80
+ # What constitutes an array element is determined by IF::GrandeStream#lines, IF::GrandeStream#bytes,
81
+ # or by an extension such as IF::CSV#csv. IF::GrandeStream#lines is the default.
82
+ #
83
+ # Arguments may consist of zero or more integers, ranges, regular expressions, symbols,
84
+ # procs, and arrays
85
+ # An empty argument list selects all records
86
+ #
87
+ # Records are selected as follows.
88
+ # range:: specifies a range of records to be selected (zero based)
89
+ # regexp:: matching records will be selected.
90
+ # integer:: treated like a one element range
91
+ # symbol:: the symbol is sent to each record. Record is selected
92
+ # unless false is returned
93
+ # proc:: the proc is called with the record as an argument.
94
+ # Record is selected unless false is returned
95
+ # array:: the array may contain any of the other selector types. Record is selected
96
+ # unless any of the selectors returns false. (a logical and)
97
+ #
98
+ # A record matching *any* of the selectors will be included in the array. (acts like an _or_)
99
+ #
100
+ # Because this is implemented in terms of the IF::Grande#each,
101
+ # When only record ranges are used to select records,
102
+ # iteration will stop when the recno exceeds the maximum of any range. That is to say
103
+ #
104
+ # This reads one record from a file and returns it
105
+ # rio('bigfile.mp3').bytes(1024)[0]
106
+ # While this reads *all* records from a file and returns the first one
107
+ # rio('bigfile.mp3').bytes(1024).to_a[0]
108
+ #
109
+ # === Directories
110
+ #
111
+ # This combines the entry selection offered by IF::GrandeEntry#entries with
112
+ # the conversion to an array provided by IF::Grande#to_a. The following two are equivelant:
113
+ # ario[*args]
114
+ # ario.entries(*args).to_a
115
+ #
116
+ # Arguments may consist of strings (treated as globs) or regular expressions.
117
+ # An empty argument list selects all entries
118
+ # See ::Dir#glob and ::File::fnmatch? for more in information on _globs_. Be warned that using the '**' glob
119
+ # recurses into directories independently of IF::GrandeEntry#all and using both is unsupported.
120
+ #
121
+ # ario = rio('adir')
122
+ # ario[] # returns an array containg all entries in _adir_
123
+ # ario[/^zippy/] # all entries starting with 'zippy'
124
+ # ario['zippy*'] # same thing
125
+ #
126
+ # As with IF::Grande#each:
127
+ # * Files and directories are returned as Rios
128
+ # * The types of entries is also affected by IF::GrandeEntry#files and IF::GrandeEntry#dirs.
129
+ # rio('adir').files['*.txt'] # array of all _.txt_ files
130
+ # rio('adir').dirs(/^\./) # array of all dot directories
131
+ # * Recursion is enabled using IF::GrandeEntry#all
132
+ # rio('adir').all.files['*.[ch]'] # array of c source files in _adir_ and its subdirecories
133
+ # rio('adir').all.dirs[/^\.svn/] # array of subversion directories in _adir_ and subdirectories
134
+ # * IF::GrandeEntry#files and IF::GrandeEntry#dirs act independetly of each other.
135
+ # Specifying both will cause both to be returned.
136
+ # The argument list to IF::Grande#[] will be applied to the closest.
137
+ # rio('adir').files('*.rb').dirs['ruby*'] # array of _.rb_ files and
138
+ # # directories starting with 'ruby'
139
+ # rio('adir').dirs('ruby*').files['*.rb'] # same thing
140
+ #
141
+ # === Lines
142
+ # This section applies similarly to IF::GrandeStream#lines, IF::GrandeStream#bytes,
143
+ # IF::GrandeStream#records, and IF::GrandeStream#rows
144
+ #
145
+ # Using IF::GrandeStream#lines and related methods with a Rio referencing a directory
146
+ # imples IF::GrandeEntry#files and will cause an array of the lines or bytes in the files to be returned. As above,
147
+ # the arguments to the subscript operator will be applied to the closest.
148
+ # rio('adir').lines[] # array of all lines in the files in 'adir'
149
+ # rio('adir').files.lines[] # same thing
150
+ # rio('adir').lines(0..9).files['*.txt'] # array of the first ten lines of all .txt files
151
+ # rio('adir').files('*.txt').lines[0..9] # same thing
152
+ # rio('adir').all.files('*.rb').lines[/^\s*require/] # array of 'require' lines in .rb files in
153
+ # # 'adir and its subdirectories
154
+ #
155
+ # Note the difference between the following similar usages
156
+ # it1 = rio('adir').files('*.rb') # returns a Rio, prepared for selecting ruby files
157
+ # it2 = rio('adir').files['*.rb'] # returns an array of the ruby files
158
+ #
159
+ # The second example above could have been written
160
+ # it2 = it1.to_a
161
+ #
162
+ # Examples:
163
+ #
164
+ # rio('afile.txt').lines[1..2] # array containing the 2nd and 3rd line
165
+ #
166
+ # rio('afile.txt')[1,3..5] # array containing lines 1,3,4 and 5
167
+ #
168
+ # rio('afile.txt')[/Zippy/] # array of all lines containing 'Zippy'
169
+ #
170
+ # rio('afile.txt')[1,3..5,/Zippy/] # array with lines 1,3,4 and 5 and all lines containing 'Zippy'
171
+ #
172
+ # rio('afile.dat').bytes(50)[] # array containing the contents of afile.dat broken up into 50 byte chunks
173
+ #
174
+ # rio('afile.dat').bytes(50)[0,2] # array containing the first and third such chunk
175
+ #
176
+ # rio('afile.dat').bytes(50).records[0,2] # same thing
177
+ #
178
+ # rio('afile.dat').bytes(50).records(0,2).to_a # once again
179
+ #
180
+ # rio('afile.csv').csv[0..9] # array of the first 10 records of afile.csv parsed by the ::CSV module
181
+ #
182
+ # rio('afile.csv').csv.records[0..9] # same thing
183
+ #
184
+ # rio('afile.csv').csv(';').records[0..9] # same thing using semi-colon as the value separator
185
+ #
186
+ # rio('afile.csv').csv.records[0,/Zippy/] # record 0 and all records containing 'Zippy'
187
+ # # the regexp is matched against the line before parsing by ::CSV
188
+ #
189
+ # rio('adir')[] # array of entries in 'adir'
190
+ #
191
+ # rio('adir')['*.txt'] # array of all .txt entries
192
+ #
193
+ # rio('adir').all['*.txt'] # array of all .txt entries in 'adir and its subdirectories
194
+ #
195
+ # rio('adir').files['*.txt'] # array of all .txt files
196
+ #
197
+ # rio('adir').dirs['CSV'] # array of all CSV directories
198
+ # rio('adir').skipdirs['CSV'] # array of all non-CSV directories
199
+ #
200
+ def [](*selectors) target[*selectors] end
201
+
202
+
203
+
204
+ # Iterate through a rio. Executes the block for each item selected for the Rio.
205
+ # See IF::GrandeStream#lines, IF::GrandeStream#records, IF::GrandeStream#bytes,
206
+ # IF::GrandeEntry#files, IF::GrandeEntry#dirs, IF::Grande#[]
207
+ # and IF::Grande#to_a for more information
208
+ # on how records are selected and what kind of record is passed to the block.
209
+ #
210
+ # IF::Grande#each is the fundemental method for all the Rio grande operators.
211
+ # IF::Grande#to_a and the Rio copy operators
212
+ # IF::Grande#<, IF::Grande#<<, IF::Grande#>>, and IF::Grande#>
213
+ # are all implemented in terms of IF::Grande#each.
214
+ #
215
+ # While IF::Grande#each is fundamental to a Rio, it rarely needs
216
+ # actually be called because all the grande configuration methods will also take a block
217
+ # and call IF::Grande#each if one is given.
218
+ # So the existance of a block after many methods is taken as an implied
219
+ # IF::Grande#each
220
+ #
221
+ # For Rios that refer to files, the item passed to the block is a String containing
222
+ # the line or block as selected by IF::GrandeStream#lines, or IF::GrandeStream#bytes. +lines+ is the default.
223
+ # rio('afile').lines.each { |line| ...}
224
+ #
225
+ # The block passed to +each+ will also accept an optional second parameter which will contain
226
+ # the result of the matching function. What this variable contains depends on the argument
227
+ # to +lines+ that resulted in the match as follows:
228
+ #
229
+ # Regexp:: The MatchData that resulted from the match.
230
+ # Range:: The record number of the matching record.
231
+ # Fixnum:: The record number of the matching record.
232
+ # Proc:: The value returned by the proc.
233
+ # Symbol:: The value resulting from sending the symbol to the String.
234
+ #
235
+ # If no selection arguments were used, this variable will simply contain +true+.
236
+ #
237
+ # rio(??).puts(%w[0:zero 1:one]).rewind.lines(/(\d+):([a-z]+)/) do |line,match|
238
+ # puts("#{match[1]} is spelled '#{match[2]}'")
239
+ # end
240
+ #
241
+ # Produces:
242
+ # 0 is spelled 'zero'
243
+ # 1 is spelled 'one'
244
+ #
245
+ #
246
+ # For Rios that refer to directories, the item passed to the block is a Rio refering to
247
+ # the directory entry.
248
+ #
249
+ # rio('adir').files.each do |file|
250
+ # file.kind_of?(RIO::Rio) # true
251
+ # end
252
+ #
253
+ # In addition, the Rio passed to the block inherits certain attributes from the directory Rio.
254
+ #
255
+ # rio('adir').files.chomp.each do |file| # chomp is ignored for directories,
256
+ # file.each do |line| # chomp attribute is inherited by the file rio
257
+ # # .. line is chomped
258
+ # end
259
+ # end
260
+ #
261
+ # IF::Grande#each returns the Rio which called it.
262
+ #
263
+ # Here are a few illustrative examples
264
+ #
265
+ # * Processing lines in a file
266
+ #
267
+ # rio('f.txt').each { |line| ... } # execute block for every line in the file
268
+ # rio('f.txt').lines.each { |line| ... } # same thing
269
+ # rio('f.txt').lines { |line| ... } # same thing
270
+ #
271
+ # rio('f.txt').chomp.each { |line| ... } # same as above with lines chomped
272
+ # rio('f.txt').chomp { |line| ... } # ditto
273
+ # rio('f.txt').lines.chomp { |line| ... } # ditto
274
+ # rio('f.txt').chomp.lines { |line| ... } # ditto
275
+ #
276
+ # rio('f.txt.gz').gzip.each { |line| ... } # execute block for every line in a gzipped file
277
+ # rio('f.txt.gz').gzip { |line| ... } # same thing
278
+ # rio('f.txt.gz').lines.gzip { |line| ... } # same thing
279
+ #
280
+ # rio('f.txt.gz').gzip.chomp { |line| ... } # chomp lines from a gzipped file
281
+ # rio('f.txt.gz').gzip.chomp.each { |line| ... } # ditto
282
+ # rio('f.txt.gz').chomp.lines.gzip { |line| ... } # ditto
283
+ #
284
+ # rio('f.txt').lines(0..9) { |line| ... } # execute block for the first 10 lines in the file
285
+ # rio('f.txt').lines(0..9).each { |line| ... } # same thing
286
+ #
287
+ # rio('f.txt').lines(/^\s*#/) { |line| ... } # execute block for comment-only lines
288
+ # rio('f.txt').lines(/^\s*#/).each { |line| ... } # same thing
289
+ #
290
+ # rio('f.txt').lines(0,/Rio/) { |line| ... } # execute block for the first line and
291
+ # # all lines containing 'Rio'
292
+ #
293
+ # rio('f.txt.gz').gzip.chomp.lines(0..1) { |line| ... } # first 2 lines chomped from a gzip file
294
+ #
295
+ # * Processing a file a block at a time
296
+ #
297
+ # rio('f.dat').bytes(10).each { |data| ... } # process the file 10 bytes at a time
298
+ # rio('f.dat').bytes(10) { |data| ... } # same thing
299
+ # rio('f.dat').bytes(10).records(2,4) { |data| ... } # only 3rd and 5th ten-byte data-block
300
+ # rio('f.dat.gz').gzip.records(2,4).bytes(10) { |data| ... } # same from a gzipped file
301
+ #
302
+ # * Iterating over directories
303
+ # rio('adir').each { |ent| ... } # execute the block for each entry in the directory 'adir'
304
+ # rio('adir').files.each { |file| ...} # only files
305
+ # rio('adir').files { |file| ...} # ditto
306
+ # rio('adir').all.files { |file| ...} # files, recurse into subdirectories
307
+ # rio('adir').dirs { |dir| ...} # only directories
308
+ # rio('adir').files('*.rb') { |file| ...} # only .rb files using a glob
309
+ # rio('adir').files(/\.rb$/) { |file| ...} # only .rb files using a regular expression
310
+ # rio('adir').all.files('*.rb') { |file| ...} # .rb files, recursing into subdirectories
311
+ # rio('adir').dirs(/^\./) { |dir| ... } # only dot directories
312
+ # rio('adir').dirs('/home/*') { |dir| ... } # home directories
313
+ #
314
+ # See RIO::Doc::HOWTO and RIO::Doc::SYNOPSIS for more examples, and RIO::Doc::INTRO for further explanation.
315
+ #
316
+ def each(*args,&block) target.each(*args,&block); self end
317
+
318
+
319
+ # For a file Rio +delete+ calls FileUtils#rm.
320
+ # For a directory Rio +delete+ calls FileUtils#rmdir
321
+ # Returns the Rio. If the Rio does not exist, simply return the Rio.
322
+ #
323
+ # rio('afile,txt').delete # delete 'afile.txt'
324
+ # rio('adir').delete # delete adir
325
+ # rio('something').delete # delete something
326
+ #
327
+ def delete() target.delete(); self end
328
+
329
+ # For a file IF::Grande#delete! calls FileUtils#rm.
330
+ # For a directory IF::Grande#delete! calls FileUtils#rmtree
331
+ # Returns the Rio. If the rio does not exist, simply return itself.
332
+ #
333
+ # rio('afile,txt').delete! # delete f.txt
334
+ # rio('adir').delete! # delete adir
335
+ #
336
+ # # create a directory, after deleting anything that previously had its name
337
+ # rio('adir/asubdir').delete!.mkpath
338
+ #
339
+ # ==== Deleting Summary
340
+ # * To delete something only if it is not a directory use IF::File#rm
341
+ # * To delete an empty directory use IF::Dir#rmdir
342
+ # * To delete an entire directory tree use IF::Dir#rmtree
343
+ # * To delete anything except a populated directory use IF::Grande#delete
344
+ # * To delete anything use IF::Grande#delete!
345
+ #
346
+ # In all cases, deleting something that does not exist is considered successful
347
+ #
348
+ def delete!() target.delete!(); self end
349
+
350
+ # Grande Copy-To Operator
351
+ #
352
+ # The copy grande-operator copies a Rio to a another Rio or another ruby object. The behaviour
353
+ # and the library used depend on the types of the of the source and destination. For
354
+ # simple file or directory copying ::FileUtils#cp or ::FileUtils#cp_r will be used. If
355
+ # any of the Rio grande methods are specified for the source or destination, the
356
+ # source Rio will be iterated through copying records to the destintion as specified. Roughly
357
+ # equivelant to
358
+ # dst = rio('dst_file')
359
+ # rio('src_file').each do |line|
360
+ # dst.print(line)
361
+ # end
362
+ # dst.close
363
+ #
364
+ # The destination of the copy operators may be a:
365
+ # IO:: Each record of the Rio is written to the IO using IO#print. The IO must be opened for writing.
366
+ # Array:: Each record or entry of the Rio becomes an element of the array
367
+ # String:: Puts the entire contents of the Rio into the string
368
+ # Rio:: Depends on the destination. See below.
369
+ #
370
+ # Copy a file to a file
371
+ # rio('src_file') > rio('dst_file')
372
+ #
373
+ # Copy a file to a directory
374
+ # rio('src_file') > rio('dst_dir')
375
+ #
376
+ # Copy a directory to another directory
377
+ # rio('src_dir') > rio('dst_dir')
378
+ #
379
+ # Make an ungizipped copy of a gzipped file
380
+ # rio('src.txt.gz').gzip > rio('dst.txt')
381
+ #
382
+ # Copying to an array
383
+ # rio('afile') > ary # each line of the file becomes and element of the ary
384
+ # rio('afile').chomp > ary # same thing with lines chomped
385
+ # rio('afile.gz').gzip.chomp > ary # same thing from a gzipped file
386
+ #
387
+ # rio('afile').lines(0..9) > ary # ary will contain only the first ten lines of the file
388
+ # rio('afile').chomp.lines(0..9) > ary # same thing with lines chomped
389
+ # rio('afile').gzip.chomp.lines(0..9) > ary # same thing from a gzipped file
390
+ #
391
+ # rio('afile').skiplines(0..9) > ary # ary will contain all but the first ten lines of the file
392
+ #
393
+ # rio('adir') > ary # ary will contain a Rio for each entry in the directory
394
+ # rio('adir').files > ary # same, but only files
395
+ # rio('adir').files('*.rb') >ary # same, but only .rb files
396
+ #
397
+ # Copying to a string
398
+ # rio('afile') > astring # slurp the entire contents of the file into astring
399
+ # astring = rio('afile').contents # same effect
400
+ #
401
+ # Copy the first line *and* every line containing the word Rio into a gzipped file
402
+ # rio('src').lines(1,/Rio/) > rio('dst.gz').gzip
403
+ #
404
+ # Copy lines of a web page into an array with each line chomped
405
+ # rio('http://ruby-doc.org/index.html').chomp > an_array
406
+ #
407
+ # Copy the first and 8th through 10th columns of the first ten rows of a gzipped csv
408
+ # file on a web site into a local gzipped csv file that uses semi-colons as separators
409
+ # rio('http://domain/file.csv.gz').columns(0,7..9).gzip.csv[0..9] > rio('localfile.csv.gz').csv(';').gzip
410
+ #
411
+ # See also IF::Grande#>>, IF::Grande#|
412
+ #
413
+ def >(destination)
414
+ RIO::no_warn {
415
+ target > destination;
416
+ }
417
+ self
418
+ end
419
+
420
+ # Alias for IF::Grande#> (copy-to grande operator)
421
+ def copy_to(destination) target.copy_to(destination); self end
422
+
423
+
424
+ # Grande Pipe Operator
425
+ #
426
+ # The Rio pipe operator is actually an alternative syntax for calling the copy-to operator, designed to
427
+ # allow several copy operation to be performed in one line of code, with behaviour that mimics
428
+ # the pipe operator commonly available in shells.
429
+ #
430
+ # If +destination+ is a +cmdio+, a <tt>cmdpipe</tt> Rio is returned, and none of the commands are run.
431
+ #
432
+ # Otherwise the +cmdpipe+ Rio is run with the output of the pipe being copied to the destination.
433
+ # In this case a Rio representing the +destination+ is returned.
434
+ #
435
+ # If destination is not a Rio it is passed to the Rio constructor as is done with the copy-to operator
436
+ # except that if +destination+ is a String it is assumed to be a command instead of a path.
437
+ #
438
+ # rio('afile') | rio(?-,'grep i') | rio(?-) # returns rio(?-)
439
+ # # equivelent to rio(?-, 'grep i') < rio('afile') > rio(?-)
440
+ #
441
+ # rio('infile') | rio(?-, 'acmd') | rio(?-, 'acmd2') | rio('outfile')
442
+ # # same as
443
+ # # acmd = rio(?-,'acmd')
444
+ # # acmd2 = rio(?-,'acmd2')
445
+ # # out = rio('outfile')
446
+ # # acmd < rio('infile')
447
+ # # acmd2 < acmd
448
+ # # out < acmd2
449
+ #
450
+ # rio('afile') | 'acmd' | 'acmd2' | rio('outfile') # same thing
451
+ #
452
+ # acmdpipe = rio(?-,'acmd') | 'acmd2'
453
+ # rio('afile') | acmdpipe | rio('outfile') # same thing
454
+ #
455
+ # acmdpipe1 = rio(?|,'acmd','acmd2')
456
+ # rio('afile') | acmdpipe1 | rio('outfile') # same thing
457
+ #
458
+ # acmdpipe2 = rio('afile') | 'acmd' | 'acmd2'
459
+ # acmdpipe2 | rio('outfile') # same thing
460
+ #
461
+ # The grande pipe operator can not be used to create a +cmdpipe+ Rio that includes a destination.
462
+ # This must be done using a Rio constructor
463
+ # cmd_with_output = rio(?|,'acmd',rio('outfile'))
464
+ # rio('afile') | cmd_with_output # same as above
465
+ #
466
+ def |(destination) target | destination end
467
+
468
+ # Grande Append-To Operator
469
+ #
470
+ # The append-to grande-operator is the same as IF::Grande#> (copy-to) except that it opens the destination
471
+ # for append.
472
+ # The destination can be a kind of:
473
+ # IO:: Each record of the Rio is written to the IO using IO#print. The IO must be opened for writing.
474
+ # Array:: Each record or entry of the Rio is appended to the destination array
475
+ # String:: Appends the entire contents of the Rio to destination
476
+ # Rio:: Just like IF::Grande#> (copy-to) except the unopened object are
477
+ # opened for append. If the destination is already opened for writing or is a
478
+ # directory, this is identical to IF::Grande#> (copy-to)
479
+ #
480
+ # See IF::Grande#> (copy-to)
481
+ #
482
+ # rio('afile') >> rio('anotherfile') # append the contents of 'afile' to 'anotherfile'
483
+ # rio('afile') >> rio('adir') # copies 'afile' to the directory 'adir'
484
+ # rio('adir') >> rio('anotherdir') # copy directory 'adir' recursively to 'anotherdir'
485
+ # rio('adir') >> array # a Rio for each entry in the directory will be appended to ary
486
+ def >>(destination) target >> destination; self end
487
+
488
+
489
+ # Alias for IF::Grande#>> (append-to grande operator)
490
+ def append_to(destination) target.append_to(destination); self end
491
+
492
+
493
+ # Grande Append-From Operator
494
+ #
495
+ # The append-from grande-operator copies a Rio from another Rio or another ruby object. This
496
+ # behaves like IF::Grande#< (copy-from) except unopened Rios are opened for append.
497
+ #
498
+ # The following summarizes how objects are copied:
499
+ # IO:: IO#each is used to iterate through the source with each record appended to the Rio
500
+ # Array:: Each element of the Array is appended individually to the Rio.
501
+ # String:: The string is appended to the Rio using IF::RubyIO#print
502
+ # Rio:: The source Rio is appended using its IF::Grande#>> (append-to) operator
503
+ #
504
+ # See IF::Grande#< (copy-from)
505
+ def <<(source) target << source; self end
506
+
507
+
508
+ # Alias for IF::Grande#<< (append-from grande operator)
509
+ def append_from(source) target.append_from(source); self end
510
+
511
+
512
+ # Grande Copy-From Operator
513
+ #
514
+ # The copy-from grande-operator copies a Rio from another Rio or another ruby object.
515
+ # Its operation is dependent on the the file system objects referenced, the rio
516
+ # options set, and the state of its source and destination. In the broadest of terms
517
+ # it could be described as doing the following:
518
+ # source.each do |entry|
519
+ # destination << entry
520
+ # end
521
+ # That is to say, it iterates through its argument, calling the copy-from operator
522
+ # again for each element. While it is not implemented like this, and the above code would
523
+ # not give the same results, This generalized description is convenient.
524
+ # For example the code:
525
+ # dst < src
526
+ # # is like
527
+ # src.each { |line| dst << line }
528
+ # for any of the following definitions of src and dst
529
+ # * copying files
530
+ # src = rio('afile')
531
+ # dst = rio('acopy')
532
+ # * copying parts of files
533
+ # src = rio('afile').lines(0..9)
534
+ # dst = rio('acopy')
535
+ # * copying directories
536
+ # src = rio('srcdir')
537
+ # dst = rio('dstdir')
538
+ # * copy directories selectively
539
+ # src = rio('srcdir').dirs(/^\./).files('*.tmp')
540
+ # dst = rio('dstdir')
541
+ # * copying to a file from an array
542
+ # src = ["line0\n","line1\n"]
543
+ # dst = rio('afile')
544
+ # * copying to a directory from an array
545
+ # array = [rio("file1"),rio("file2")]
546
+ # dst = rio('adir')
547
+ #
548
+ # Arrays are handled differently depending on whether the rio references a file or a directory.
549
+ # * If the destination is a file.
550
+ # dest = rio('afile')
551
+ # dest < array
552
+ # # is roughly equivelent to
553
+ # array.each do |el|
554
+ # case el
555
+ # when ::String then dest.print(el)
556
+ # when ::Rio then dest << el
557
+ # else dest << rio(el)
558
+ # end
559
+ # * If the destination is a directory
560
+ # dest = rio('adir')
561
+ # dest < array
562
+ # # is roughly equivelent to
563
+ # array.each do |el|
564
+ # case el
565
+ # when ::String then rio(el)
566
+ # when ::Rio then dest << el
567
+ # else dest << rio(el)
568
+ # end
569
+ #
570
+ # To improve run-time efficiency, Rio will choose from among several strategies when
571
+ # copying. For instance when no file or directory filtering is specified, FileUtils#cp_r is
572
+ # used to copy directories; and when no line filtering is specified, FileUtils#cp is used to copy
573
+ # files.
574
+ #
575
+ # rio('adir') < rio('anotherdir') # 'anotherdir' is copied to 'adir' using FileUtils#cp_r
576
+ # rio('adir') < rio('anotherdir').files('*.rb') # copy only .rb files
577
+ # rio('afile') < rio('anotherfile') # 'anotherfile' is copied to 'afile' using FileUtils#cp
578
+ # rio('afile') < ios # ios must be an IO object opened for reading
579
+ # rio('afile') < astring # basically the same as rio('afile').print(astring)
580
+ #
581
+ # anarray = [ astring, rio('anotherfile') ]
582
+ # rio('afile') < anarray # copies each element to 'afile' as if one had written
583
+ # ario = rio('afile')
584
+ # anarray.each do |el|
585
+ # ario << el
586
+ # end
587
+ # ario.close
588
+ # rio('skeldir') < rio('adir').dirs # copy only the directory structure
589
+ # rio('destdir') < rio('adir').dirs.files(/^\./) # copy the directory structure and all dot files
590
+ #
591
+ # See also IF::Grande#> (copy-to), IF::Grande#each, IF::Grande#[]
592
+ #
593
+ def <(source)
594
+ RIO::no_warn {
595
+ target < source
596
+ }
597
+ self
598
+ end
599
+
600
+ # Alias for IF::Grande#< (copy-from grande operator)
601
+ def copy_from(source) target.copy_from(source); self end
602
+
603
+
604
+ # Reads and returns the next record or entry from a Rio,
605
+ # honoring the grande selection methods.
606
+ #
607
+ # Returns nil on end of file.
608
+ #
609
+ # See also IF::GrandeStream#records, IF::GrandeStream#lines, IF::Grande#each, IF::Grande#[]
610
+ #
611
+ # ario = rio('afile').lines(10..12)
612
+ # line10 = ario.get
613
+ # line11 = ario.get
614
+ # line12 = ario.get
615
+ # a_nil = ario.get
616
+ #
617
+ # ario = rio('adir').entries('*.txt')
618
+ # ent1 = ario.get
619
+ # ent2 = ario.get
620
+ #
621
+ def get() target.get() end
622
+
623
+ # Grande Exclude method
624
+ #
625
+ # +skip+ can be used in two ways.
626
+ #
627
+ # If called with no arguments it reverses the polarity of the
628
+ # next non-skip grande selection method that is called. That is,
629
+ # it turns +lines+, +records+, +rows+, +files+, +dirs+ and +entries+
630
+ # into +skiplines+, +skiprecords+, +skiprows+, +skipfiles+,
631
+ # +skipdirs+, and +skipentries+, respectively.
632
+ #
633
+ # rio('afile').skip.lines(0..5) # same as rio('afile').skiplines(0..5)
634
+ # rio('adir').skip.files('*~') # same as rio('adir').skipfiles('*~')
635
+ #
636
+ # Note that it only affects the next selection method seen -- and may be
637
+ # used more than once. If no grande selection method is seen, +skip+ is
638
+ # ignored.
639
+ #
640
+ # When called with arguments it acts like IF::GrandeEntry#skipentries for directory
641
+ # Rios and like IF::GrandeStream#skiprecords for stream Rios.
642
+ #
643
+ # rio('afile').lines(/Rio/).skip[0..4] # lines containg 'Rio' excluding the
644
+ # # first five lines
645
+ #
646
+ # rio('adir').files('*.rb').skip[:symlink?] # .rb files, but not symlinks to
647
+ # # .rb files
648
+ #
649
+ # If a block is given, behaves as if <tt>skip(*args).each(&block)</tt> had been called.
650
+ #
651
+ # Returns the Rio.
652
+ #
653
+ # See IF::GrandeStream#skiplines, IF::GrandeStream#skiprecords, IF::GrandeStream#skiprows,
654
+ # IF::GrandeEntry#skipfiles, IF::GrandeEntry#skipdirs, and IF::GrandeEntry#skipentries.
655
+ #
656
+ def skip(*args,&block) target.skip(*args,&block); self end
657
+
658
+
659
+ # Returns true if the referenced file or directory is empty after honoring the grande
660
+ # selection methods.
661
+ #
662
+ # rio('f0').delete!.touch.empty? #=> true
663
+ # rio('f1').puts!("Not Empty\n").empty? #=> false
664
+ # rio('d0').delete!.mkdir.empty? #=> true
665
+ #
666
+ def empty?() target.empty? end
667
+
668
+ # IF::Grande#split has two distinct behaviors depending on
669
+ # whether or not it is called with an argument.
670
+ #
671
+ # ==== split-with-no-aruments:
672
+ #
673
+ # Returns an array of Rios, one for each path element.
674
+ # (Note that this behavior differs from File#split.)
675
+ #
676
+ # rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
677
+ #
678
+ # The array returned is extended with a +to_rio+ method,
679
+ # which will put the parts back together again.
680
+ #
681
+ # ary = rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
682
+ # ary.to_rio #=> rio('a/b/c')
683
+ #
684
+ # ary = rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
685
+ # ary[1] = rio('d')
686
+ # ary.to_rio #=> rio('a/d/c')
687
+ #
688
+ # See also IF::Path#join, IF::Path#/, IF::Path#splitpath
689
+ #
690
+ # ==== split-with-an-argument:
691
+ #
692
+ # This causes String#split(arg) to be called on every line
693
+ # before it is returned. An array of the split lines is
694
+ # returned when iterating
695
+ #
696
+ # rio('/etc/passwd').split(':').columns(0,2) { |ary|
697
+ # username,uid = ary
698
+ # }
699
+ #
700
+ # rio('/etc/passwd').split(':').columns(0,2).to_a #=> [[user1,uid1],[user2,uid2]]
701
+ #
702
+ #
703
+ def split(*args,&block) target.split(*args,&block) end
499
704
 
500
705
 
501
- # Alias for Rio#<< (append-from grande operator)
502
- def append_from(source) target.append_from(source); self end
503
-
504
-
505
- # Grande Copy-From Operator
506
- #
507
- # The copy-from grande-operator copies a Rio from another Rio or another ruby object.
508
- # Its operation is dependent on the the file system objects referenced, the rio
509
- # options set, and the state of its source and destination. In the broadest of terms
510
- # it could be described as doing the following:
511
- # source.each do |entry|
512
- # destination << entry
513
- # end
514
- # That is to say, it iterates through its argument, calling the copy-from operator
515
- # again for each element. While it is not implemented like this, and the above code would
516
- # not give the same results, This generalized description is convenient.
517
- # For example the code:
518
- # dst < src
519
- # # is like
520
- # src.each { |line| dst << line }
521
- # for any of the following definitions of src and dst
522
- # * copying files
523
- # src = rio('afile')
524
- # dst = rio('acopy')
525
- # * copying parts of files
526
- # src = rio('afile').lines(0..9)
527
- # dst = rio('acopy')
528
- # * copying directories
529
- # src = rio('srcdir')
530
- # dst = rio('dstdir')
531
- # * copy directories selectively
532
- # src = rio('srcdir').dirs(/^\./).files('*.tmp')
533
- # dst = rio('dstdir')
534
- # * copying to a file from an array
535
- # src = ["line0\n","line1\n"]
536
- # dst = rio('afile')
537
- # * copying to a directory from an array
538
- # array = [rio("file1"),rio("file2")]
539
- # dst = rio('adir')
540
- #
541
- # Arrays are handled differently depending on whether the rio references a file or a directory.
542
- # * If the destination is a file.
543
- # dest = rio('afile')
544
- # dest < array
545
- # # is roughly equivelent to
546
- # array.each do |el|
547
- # case el
548
- # when ::String then dest.print(el)
549
- # when ::Rio then dest << el
550
- # else dest << rio(el)
551
- # end
552
- # * If the destination is a directory
553
- # dest = rio('adir')
554
- # dest < array
555
- # # is roughly equivelent to
556
- # array.each do |el|
557
- # case el
558
- # when ::String then rio(el)
559
- # when ::Rio then dest << el
560
- # else dest << rio(el)
561
- # end
562
- #
563
- # To improve run-time efficiency, Rio will choose from among several strategies when
564
- # copying. For instance when no file or directory filtering is specified, FileUtils#cp_r is
565
- # used to copy directories; and when no line filtering is specified, FileUtils#cp is used to copy
566
- # files.
567
- #
568
- # rio('adir') < rio('anotherdir') # 'anotherdir' is copied to 'adir' using FileUtils#cp_r
569
- # rio('adir') < rio('anotherdir').files('*.rb') # copy only .rb files
570
- # rio('afile') < rio('anotherfile') # 'anotherfile' is copied to 'afile' using FileUtils#cp
571
- # rio('afile') < ios # ios must be an IO object opened for reading
572
- # rio('afile') < astring # basically the same as rio('afile').print(astring)
573
- #
574
- # anarray = [ astring, rio('anotherfile') ]
575
- # rio('afile') < anarray # copies each element to 'afile' as if one had written
576
- # ario = rio('afile')
577
- # anarray.each do |el|
578
- # ario << el
579
- # end
580
- # ario.close
581
- # rio('skeldir') < rio('adir').dirs # copy only the directory structure
582
- # rio('destdir') < rio('adir').dirs.files(/^\./) # copy the directory structure and all dot files
583
- #
584
- # See also Rio#> (copy-to), Rio#each, Rio#[]
585
- #
586
- def <(source)
587
- RIO::no_warn {
588
- target < source
589
- }
590
- self
591
706
  end
707
+ end
708
+ end
592
709
 
593
- # Alias for Rio#< (copy-from grande operator)
594
- def copy_from(source) target.copy_from(source); self end
595
-
596
-
597
- # Temporarily set the Rio to read records, and call #get
598
- #
599
- # See also Rio#records, Rio#lines, Rio#each, Rio#[]
600
- #
601
- def getrec() target.getrec() end
602
-
603
- # Temporarily set the Rio to read rows, and call #get
604
- #
605
- # See also Rio#rows, Rio#lines, Rio#each, Rio#[]
606
- #
607
- def getrow() target.getrow() end
608
-
609
- # Temporarily set the Rio to read lines, and call #get
610
- #
611
- # See also Rio#records, Rio#lines, Rio#each, Rio#[]
612
- #
613
- def getline() target.getline() end
614
-
615
- # Reads and returns the next record or entry from a Rio,
616
- # honoring the grande selection methods.
617
- #
618
- # Returns nil on end of file.
619
- #
620
- # See also Rio#records, Rio#lines, Rio#each, Rio#[]
621
- #
622
- # ario = rio('afile').lines(10..12)
623
- # line10 = ario.get
624
- # line11 = ario.get
625
- # line12 = ario.get
626
- # a_nil = ario.get
627
- #
628
- # ario = rio('adir').entries('*.txt')
629
- # ent1 = ario.get
630
- # ent2 = ario.get
631
- #
632
- def get() target.get() end
633
-
634
- # Writes a single record to a Rio
635
- def putrec(el) target.putrec(el) end
636
-
637
-
638
- # Grande Exclude method
639
- #
640
- # +skip+ can be used in two ways.
641
- #
642
- # If called with no arguments it reverses the polarity of the
643
- # next non-skip grande selection method that is called. That is,
644
- # it turns +lines+, +records+, +rows+, +files+, +dirs+ and +entries+
645
- # into +skiplines+, +skiprecords+, +skiprows+, +skipfiles+,
646
- # +skipdirs+, and +skipentries+, respectively.
647
- #
648
- # rio('afile').skip.lines(0..5) # same as rio('afile').skiplines(0..5)
649
- # rio('adir').skip.files('*~') # same as rio('adir').skipfiles('*~')
650
- #
651
- # Note that it only affects the next selection method seen -- and may be
652
- # used more than once. If no grande selection method is seen, +skip+ is
653
- # ignored.
654
- #
655
- # When called with arguments it acts like Rio#skipentries for directory
656
- # Rios and like Rio#skiprecords for stream Rios.
657
- #
658
- # rio('afile').lines(/Rio/).skip[0..4] # lines containg 'Rio' excluding the
659
- # # first five lines
660
- #
661
- # rio('adir').files('*.rb').skip[:symlink?] # .rb files, but not symlinks to
662
- # # .rb files
663
- #
664
- # If a block is given, behaves as if <tt>skip(*args).each(&block)</tt> had been called.
665
- #
666
- # Returns the Rio.
667
- #
668
- # See Rio#skiplines, Rio#skiprecords, Rio#skiprows, Rio#skipfiles,
669
- # Rio#skipdirs, and Rio#skipentries.
670
- #
671
- def skip(*args,&block) target.skip(*args,&block); self end
672
-
673
-
674
- # Returns true if the referenced file or directory is empty after honoring the grande
675
- # selection methods.
676
- #
677
- # rio('f0').delete!.touch.empty? #=> true
678
- # rio('f1').puts!("Not Empty\n").empty? #=> false
679
- # rio('d0').delete!.mkdir.empty? #=> true
680
- #
681
- def empty?() target.empty? end
682
-
710
+ module RIO
711
+ class Rio
712
+ #include RIO::IF::Grande
683
713
  end
684
714
  end