rio 0.4.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (641) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +4 -0
  3. data/{COPYING → LICENSE} +3 -0
  4. data/README +20 -27
  5. data/Rakefile +48 -277
  6. data/lib/rio.rb +63 -24
  7. data/lib/rio/.document +5 -0
  8. data/lib/rio/abstract_method.rb +3 -14
  9. data/lib/rio/alturi.rb +507 -0
  10. data/lib/rio/alturi/algorithm.rb +313 -0
  11. data/lib/rio/alturi/cached_fields.rb +68 -0
  12. data/lib/rio/alturi/escape.rb +82 -0
  13. data/lib/rio/alturi/parse.rb +75 -0
  14. data/lib/rio/alturi/path_parts.rb +81 -0
  15. data/lib/rio/alturi/regex.rb +76 -0
  16. data/lib/rio/alturi/uri_parts.rb +512 -0
  17. data/lib/rio/argv.rb +3 -14
  18. data/lib/rio/arraynge.rb +146 -0
  19. data/lib/rio/arycopy.rb +3 -14
  20. data/lib/rio/assert.rb +87 -15
  21. data/lib/rio/base.rb +7 -30
  22. data/lib/rio/callstr.rb +3 -14
  23. data/lib/rio/const.rb +3 -14
  24. data/lib/rio/construct.rb +4 -15
  25. data/lib/rio/constructor.rb +4 -19
  26. data/lib/rio/context.rb +17 -14
  27. data/lib/rio/context/autoclose.rb +3 -14
  28. data/lib/rio/context/binmode.rb +63 -0
  29. data/lib/rio/context/copying.rb +3 -14
  30. data/lib/rio/context/cxx.rb +3 -14
  31. data/lib/rio/context/dir.rb +5 -15
  32. data/lib/rio/context/encoding.rb +84 -0
  33. data/lib/rio/context/gzip.rb +3 -14
  34. data/lib/rio/context/methods.rb +8 -17
  35. data/lib/rio/context/skip.rb +3 -14
  36. data/lib/rio/context/stream.rb +3 -14
  37. data/lib/rio/cp.rb +5 -20
  38. data/lib/rio/cxuri.rb +67 -0
  39. data/lib/rio/dbg/trace_states.rb +18 -0
  40. data/lib/rio/def.rb +3 -14
  41. data/lib/rio/dir.rb +9 -18
  42. data/lib/rio/doc.rb +3 -14
  43. data/lib/rio/doc/EXAMPLES.rb +256 -269
  44. data/lib/rio/doc/HOWTO.rb +685 -707
  45. data/lib/rio/doc/INDEX.rb +261 -282
  46. data/lib/rio/doc/INTRO.rb +1029 -1040
  47. data/lib/rio/doc/OPTIONAL.rb +77 -103
  48. data/lib/rio/doc/SYNOPSIS.rb +122 -143
  49. data/lib/rio/entrysel.rb +3 -14
  50. data/lib/rio/exception.rb +4 -14
  51. data/lib/rio/exception/copy.rb +3 -14
  52. data/lib/rio/exception/notimplemented.rb +3 -14
  53. data/lib/rio/exception/notsupported.rb +3 -14
  54. data/lib/rio/exception/open.rb +3 -14
  55. data/lib/rio/exception/state.rb +3 -14
  56. data/lib/rio/ext.rb +14 -17
  57. data/lib/rio/ext/csv.rb +25 -304
  58. data/lib/rio/ext/csv/csv-legacy.rb +344 -0
  59. data/lib/rio/ext/csv/csv.rb +359 -0
  60. data/lib/rio/ext/csv/filter.rb +209 -0
  61. data/lib/rio/ext/if.rb +3 -14
  62. data/lib/rio/ext/mp3info.rb +3 -14
  63. data/lib/rio/ext/splitlines.rb +3 -14
  64. data/lib/rio/ext/yaml.rb +3 -14
  65. data/lib/rio/ext/yaml/doc.rb +3 -14
  66. data/lib/rio/ext/yaml/tie.rb +3 -14
  67. data/lib/rio/ext/zipfile.rb +3 -14
  68. data/lib/rio/ext/zipfile/fs.rb +3 -14
  69. data/lib/rio/ext/zipfile/rl.rb +3 -14
  70. data/lib/rio/ext/zipfile/rootdir.rb +3 -14
  71. data/lib/rio/ext/zipfile/state.rb +3 -14
  72. data/lib/rio/ext/zipfile/wrap.rb +3 -14
  73. data/lib/rio/factory.rb +96 -213
  74. data/lib/rio/fibpipe.rb +373 -0
  75. data/lib/rio/file.rb +8 -17
  76. data/lib/rio/filter.rb +4 -15
  77. data/lib/rio/filter/closeoneof.rb +3 -14
  78. data/lib/rio/filter/gzip.rb +18 -27
  79. data/lib/rio/fs.rb +172 -0
  80. data/lib/rio/fs/base.rb +3 -14
  81. data/lib/rio/fs/impl.rb +3 -14
  82. data/lib/rio/fs/native.rb +3 -14
  83. data/lib/rio/fs/stream.rb +3 -14
  84. data/lib/rio/fs/url.rb +3 -14
  85. data/lib/rio/ftp/conncache.rb +16 -18
  86. data/lib/rio/ftp/dir.rb +4 -15
  87. data/lib/rio/ftp/fs.rb +62 -42
  88. data/lib/rio/fwd.rb +15 -0
  89. data/lib/rio/grande.rb +4 -15
  90. data/lib/rio/handle.rb +3 -45
  91. data/lib/rio/if.rb +15 -20
  92. data/lib/rio/if/basic.rb +3 -36
  93. data/lib/rio/if/csv.rb +7 -20
  94. data/lib/rio/if/dir.rb +9 -21
  95. data/lib/rio/if/file.rb +6 -19
  96. data/lib/rio/if/fileordir.rb +18 -29
  97. data/lib/rio/if/grande.rb +109 -120
  98. data/lib/rio/if/grande_entry.rb +5 -18
  99. data/lib/rio/if/grande_stream.rb +29 -42
  100. data/lib/rio/if/internal.rb +15 -16
  101. data/lib/rio/if/path.rb +35 -47
  102. data/lib/rio/if/rubyio.rb +35 -47
  103. data/lib/rio/if/string.rb +3 -16
  104. data/lib/rio/if/temp.rb +3 -16
  105. data/lib/rio/if/test.rb +8 -20
  106. data/lib/rio/if/yaml.rb +16 -29
  107. data/lib/rio/ioh.rb +35 -34
  108. data/lib/rio/iomode.rb +3 -14
  109. data/lib/rio/ios/fail.rb +3 -14
  110. data/lib/rio/ios/generic.rb +3 -14
  111. data/lib/rio/ios/mode.rb +3 -14
  112. data/lib/rio/ios/null.rb +3 -14
  113. data/lib/rio/iowrap.rb +3 -14
  114. data/lib/rio/kernel.rb +4 -17
  115. data/lib/rio/local.rb +3 -14
  116. data/lib/rio/match.rb +3 -14
  117. data/lib/rio/matchrecord.rb +8 -17
  118. data/lib/rio/no_warn.rb +3 -14
  119. data/lib/rio/nullio.rb +3 -14
  120. data/lib/rio/open3.rb +3 -16
  121. data/lib/rio/ops.rb +33 -0
  122. data/lib/rio/ops/construct.rb +3 -14
  123. data/lib/rio/ops/create.rb +11 -25
  124. data/lib/rio/ops/dir.rb +17 -24
  125. data/lib/rio/ops/either.rb +28 -31
  126. data/lib/rio/ops/file.rb +29 -26
  127. data/lib/rio/ops/path.rb +65 -34
  128. data/lib/rio/ops/stream.rb +13 -15
  129. data/lib/rio/ops/stream/input.rb +59 -28
  130. data/lib/rio/ops/stream/output.rb +4 -14
  131. data/lib/rio/ops/stream/read.rb +4 -15
  132. data/lib/rio/ops/stream/write.rb +3 -14
  133. data/lib/rio/ops/symlink.rb +6 -15
  134. data/lib/rio/path.rb +10 -17
  135. data/lib/rio/path/reset.rb +3 -14
  136. data/lib/rio/piper.rb +3 -27
  137. data/lib/rio/piper/cp.rb +50 -27
  138. data/lib/rio/prompt.rb +3 -14
  139. data/lib/rio/rectype.rb +8 -16
  140. data/lib/rio/rl/base.rb +12 -25
  141. data/lib/rio/rl/builder.rb +25 -24
  142. data/lib/rio/rl/chmap.rb +3 -16
  143. data/lib/rio/rl/fs2url.rb +5 -16
  144. data/lib/rio/rl/ioi.rb +3 -14
  145. data/lib/rio/rl/path.rb +14 -25
  146. data/lib/rio/rl/pathmethods.rb +3 -14
  147. data/lib/rio/rl/uri.rb +18 -35
  148. data/lib/rio/rl/withpath.rb +36 -53
  149. data/lib/rio/rrl/base.rb +75 -0
  150. data/lib/rio/rrl/builder.rb +122 -0
  151. data/lib/rio/rrl/chmap.rb +53 -0
  152. data/lib/rio/rrl/ioi.rb +78 -0
  153. data/lib/rio/rrl/path.rb +117 -0
  154. data/lib/rio/rrl/withpath.rb +269 -0
  155. data/lib/rio/scheme/aryio.rb +3 -14
  156. data/lib/rio/scheme/cmdio.rb +73 -42
  157. data/lib/rio/scheme/cmdpipe.rb +122 -59
  158. data/lib/rio/scheme/fd.rb +19 -33
  159. data/lib/rio/scheme/ftp.rb +34 -40
  160. data/lib/rio/scheme/http.rb +13 -22
  161. data/lib/rio/scheme/null.rb +6 -17
  162. data/lib/rio/scheme/path.rb +60 -71
  163. data/lib/rio/scheme/stderr.rb +9 -21
  164. data/lib/rio/scheme/stdio.rb +14 -26
  165. data/lib/rio/scheme/strio.rb +37 -38
  166. data/lib/rio/scheme/sysio.rb +20 -32
  167. data/lib/rio/scheme/tcp.rb +3 -14
  168. data/lib/rio/scheme/temp.rb +103 -92
  169. data/lib/rio/state.rb +85 -67
  170. data/lib/rio/state/data.rb +55 -0
  171. data/lib/rio/state/error.rb +7 -27
  172. data/lib/rio/stream.rb +46 -19
  173. data/lib/rio/stream/base.rb +14 -14
  174. data/lib/rio/stream/duplex.rb +64 -26
  175. data/lib/rio/stream/open.rb +9 -19
  176. data/lib/rio/symantics.rb +3 -14
  177. data/lib/rio/tempdir.rb +8 -17
  178. data/lib/rio/to_rio.rb +3 -16
  179. data/lib/rio/to_rio/all.rb +3 -14
  180. data/lib/rio/to_rio/array.rb +3 -14
  181. data/lib/rio/to_rio/io.rb +3 -14
  182. data/lib/rio/to_rio/object.rb +3 -14
  183. data/lib/rio/to_rio/string.rb +3 -14
  184. data/lib/rio/uri/file.rb +98 -153
  185. data/lib/rio/uriref.rb +144 -0
  186. data/lib/rio/util.rb +3 -14
  187. data/lib/rio/version.rb +4 -15
  188. data/misc/clean-heading-comments.rb +39 -0
  189. data/misc/fixdoclinks.rb +36 -0
  190. data/misc/update-copyright.rb +17 -0
  191. data/rio.gemspec +31 -0
  192. data/test/alturi/tc/create.rb +24 -0
  193. data/test/alturi/tc/empty.rb +13 -0
  194. data/test/alturi/tc/encoding.rb +73 -0
  195. data/test/alturi/tc/file_test.rb +335 -0
  196. data/test/alturi/tc/ftp_alturi.rb +147 -0
  197. data/test/alturi/tc/generic_test.rb +335 -0
  198. data/test/alturi/tc/http_test.rb +359 -0
  199. data/test/alturi/tc/path_parts_test.rb +215 -0
  200. data/test/alturi/tc/rfc_test.rb +83 -0
  201. data/test/alturi/tc/uri_parts_authority.rb +129 -0
  202. data/test/alturi/tc/uri_parts_test.rb +473 -0
  203. data/test/alturi/tc/uri_parts_userinfo.rb +140 -0
  204. data/test/alturi/tests.rb +27 -0
  205. data/test/base_test.rb +18 -0
  206. data/test/bin/demo_chdir.rb +60 -0
  207. data/test/bin/elipsis.rb +11 -0
  208. data/test/env.sh +4 -0
  209. data/test/ftp/initftpfiles.rb +1 -0
  210. data/test/ftp/tc/anon_copy_data.rb +31 -0
  211. data/test/ftp/tc/anon_misc.rb +109 -0
  212. data/test/ftp/tc/anon_read.rb +99 -0
  213. data/test/ftp/tc/anon_special.rb +37 -0
  214. data/test/ftp/tc/anon_write.rb +68 -0
  215. data/test/ftp/tc/copy.rb +35 -0
  216. data/test/ftp/tc/empty.rb +16 -0
  217. data/test/ftp/tc/ftp2ftp.rb +42 -0
  218. data/test/ftp/tc/ftp_fs.rb +333 -0
  219. data/test/ftp/testdef.rb +7 -2
  220. data/test/ftp/tests.rb +24 -0
  221. data/test/gem_runtests.rb +1 -1
  222. data/test/http/copy-from-http.rb +0 -1
  223. data/test/http/def.rb +20 -0
  224. data/test/http/tc/copy_from_http.rb +128 -0
  225. data/test/http/tc/empty.rb +14 -0
  226. data/test/http/tc/uri_meta.rb +52 -0
  227. data/test/http/tests.rb +19 -0
  228. data/test/lib/assertions.rb +7 -0
  229. data/test/lib/run_tests.rb +26 -0
  230. data/test/lib/temp_server.rb +7 -4
  231. data/test/methods/test_suite.rb +108 -0
  232. data/test/platform.rb +5 -0
  233. data/test/qpdir.rb +2 -0
  234. data/test/rio/scheme.rb +49 -0
  235. data/test/rio/tc/pathparts.rb +61 -0
  236. data/test/riotest/test_suite.rb +33 -0
  237. data/test/riotest/unit_test.rb +118 -0
  238. data/test/riotest/util.rb +23 -0
  239. data/test/runalltests.rb +1 -1
  240. data/test/runftptests.rb +2 -7
  241. data/test/runhttp.rb +4 -2
  242. data/test/runhttptests.rb +6 -5
  243. data/test/runtests.rb +66 -37
  244. data/test/srv/www/htdocs/riotest/dir/index.html +11 -0
  245. data/test/srv/www/htdocs/riotest/hw.html +8 -0
  246. data/test/srv/www/htdocs/riotest/lines.txt.gz +0 -0
  247. data/test/tc/abs2.rb +358 -0
  248. data/test/tc/all.rb +17 -10
  249. data/test/tc/base2.rb +8 -7
  250. data/test/tc/clearsel.rb +3 -2
  251. data/test/tc/closeoneof.rb +14 -15
  252. data/test/tc/cmdio.rb +193 -0
  253. data/test/tc/cmdpipe.rb +258 -63
  254. data/test/tc/copy.rb +3 -2
  255. data/test/tc/copyarray.rb +0 -4
  256. data/test/tc/copydest.rb +2 -3
  257. data/test/tc/copydir.rb +5 -1
  258. data/test/tc/copydir2.rb +68 -0
  259. data/test/tc/create.rb +4 -9
  260. data/test/tc/csv.rb +38 -119
  261. data/test/tc/csv2.rb +38 -57
  262. data/test/tc/csv_columns.rb +210 -8
  263. data/test/tc/csv_gzip.rb +78 -0
  264. data/test/tc/csv_headers.rb +134 -0
  265. data/test/tc/csvutil.rb +53 -16
  266. data/test/tc/dir.rb +3 -4
  267. data/test/tc/dir_iter.rb +3 -1
  268. data/test/tc/dirent.rb +8 -7
  269. data/test/tc/each.rb +62 -47
  270. data/test/tc/each_break.rb +67 -25
  271. data/test/tc/edf.rb +3 -2
  272. data/test/tc/empty.rb +6 -4
  273. data/test/tc/encoding.rb +30 -0
  274. data/test/tc/entary.rb +6 -5
  275. data/test/tc/eq.rb +2 -2
  276. data/test/tc/expand_path.rb +14 -14
  277. data/test/tc/ext.rb +7 -7
  278. data/test/tc/fileno.rb +3 -2
  279. data/test/tc/files_select.rb +1 -1
  280. data/test/tc/getrec.rb +2 -3
  281. data/test/tc/gzip.rb +5 -3
  282. data/test/tc/likeio.rb +5 -5
  283. data/test/tc/lineno.rb +1 -1
  284. data/test/tc/lines.rb +4 -4
  285. data/test/tc/misc.rb +29 -171
  286. data/test/tc/nolines.rb +4 -2
  287. data/test/tc/noqae.rb +12 -10
  288. data/test/tc/overload.rb +1 -2
  289. data/test/tc/pa.rb +25 -24
  290. data/test/tc/path_parts.rb +54 -20
  291. data/test/tc/paths.rb +3 -2
  292. data/test/tc/piper.rb +32 -31
  293. data/test/tc/programs_util.rb +9 -9
  294. data/test/tc/qae.rb +9 -8
  295. data/test/tc/qae_riovar.rb +9 -8
  296. data/test/tc/records.rb +3 -2
  297. data/test/tc/rename.rb +4 -4
  298. data/test/tc/riorl.rb +19 -19
  299. data/test/tc/rlparts.ans.yml +1161 -0
  300. data/test/tc/splitlines.rb +1 -1
  301. data/test/tc/splitpath.rb +9 -8
  302. data/test/tc/strio.rb +73 -0
  303. data/test/tc/symlink.rb +3 -2
  304. data/test/tc/symlink0.rb +4 -3
  305. data/test/tc/symlink1.rb +4 -3
  306. data/test/tc/temp.rb +40 -26
  307. data/test/tc/tempdir.rb +12 -12
  308. data/test/tc/testcase.rb +45 -31
  309. data/test/tc/tonl.rb +0 -1
  310. data/test/tc/truncate.rb +111 -13
  311. data/test/tc/yaml.rb +1 -1
  312. data/test/test_suite.rb +31 -0
  313. data/test/tests.rb +35 -0
  314. data/test/tsuite.rb +19 -0
  315. data/test/uriref/tc/basic.rb +171 -0
  316. data/test/uriref/tc/build.rb +30 -0
  317. data/test/uriref/tc/empty.rb +13 -0
  318. data/test/uriref/tc/route.rb +72 -0
  319. data/test/uriref/tests.rb +16 -0
  320. metadata +356 -424
  321. data/ChangeLog +0 -3122
  322. data/VERSION +0 -1
  323. data/build_doc.rb +0 -94
  324. data/doc/ANNOUNCE +0 -157
  325. data/doc/RELEASE_NOTES +0 -308
  326. data/doc/RIOIS +0 -215
  327. data/doc/generators/template/html/rio.css +0 -428
  328. data/doc/generators/template/html/rio.rb +0 -523
  329. data/doc/generators/template/html/ugly.rb +0 -132
  330. data/doc/pkg_def.rb +0 -60
  331. data/doc/rdoc/classes/Kernel.html +0 -133
  332. data/doc/rdoc/classes/Kernel.src/M000234.html +0 -18
  333. data/doc/rdoc/classes/RIO.html +0 -625
  334. data/doc/rdoc/classes/RIO.src/M000001.html +0 -18
  335. data/doc/rdoc/classes/RIO.src/M000002.html +0 -18
  336. data/doc/rdoc/classes/RIO.src/M000003.html +0 -18
  337. data/doc/rdoc/classes/RIO/Doc.html +0 -149
  338. data/doc/rdoc/classes/RIO/Doc/EXAMPLES.html +0 -432
  339. data/doc/rdoc/classes/RIO/Doc/HOWTO.html +0 -1084
  340. data/doc/rdoc/classes/RIO/Doc/INDEX.html +0 -368
  341. data/doc/rdoc/classes/RIO/Doc/INTRO.html +0 -1529
  342. data/doc/rdoc/classes/RIO/Doc/OPTIONAL.html +0 -221
  343. data/doc/rdoc/classes/RIO/Doc/SYNOPSIS.html +0 -336
  344. data/doc/rdoc/classes/RIO/IF.html +0 -165
  345. data/doc/rdoc/classes/RIO/IF/CSV.html +0 -203
  346. data/doc/rdoc/classes/RIO/IF/CSV.src/M000129.html +0 -19
  347. data/doc/rdoc/classes/RIO/IF/CSV.src/M000130.html +0 -16
  348. data/doc/rdoc/classes/RIO/IF/CSV.src/M000131.html +0 -16
  349. data/doc/rdoc/classes/RIO/IF/Dir.html +0 -343
  350. data/doc/rdoc/classes/RIO/IF/Dir.src/M000045.html +0 -16
  351. data/doc/rdoc/classes/RIO/IF/Dir.src/M000046.html +0 -16
  352. data/doc/rdoc/classes/RIO/IF/Dir.src/M000047.html +0 -16
  353. data/doc/rdoc/classes/RIO/IF/Dir.src/M000048.html +0 -16
  354. data/doc/rdoc/classes/RIO/IF/Dir.src/M000049.html +0 -16
  355. data/doc/rdoc/classes/RIO/IF/Dir.src/M000050.html +0 -16
  356. data/doc/rdoc/classes/RIO/IF/Dir.src/M000051.html +0 -16
  357. data/doc/rdoc/classes/RIO/IF/File.html +0 -223
  358. data/doc/rdoc/classes/RIO/IF/File.src/M000216.html +0 -16
  359. data/doc/rdoc/classes/RIO/IF/File.src/M000217.html +0 -16
  360. data/doc/rdoc/classes/RIO/IF/File.src/M000218.html +0 -16
  361. data/doc/rdoc/classes/RIO/IF/File.src/M000219.html +0 -16
  362. data/doc/rdoc/classes/RIO/IF/FileOrDir.html +0 -572
  363. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000117.html +0 -16
  364. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000118.html +0 -16
  365. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000119.html +0 -16
  366. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000120.html +0 -16
  367. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000121.html +0 -16
  368. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000122.html +0 -16
  369. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000123.html +0 -16
  370. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000124.html +0 -16
  371. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000125.html +0 -16
  372. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000126.html +0 -16
  373. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000127.html +0 -16
  374. data/doc/rdoc/classes/RIO/IF/FileOrDir.src/M000128.html +0 -16
  375. data/doc/rdoc/classes/RIO/IF/Grande.html +0 -1376
  376. data/doc/rdoc/classes/RIO/IF/Grande.src/M000052.html +0 -16
  377. data/doc/rdoc/classes/RIO/IF/Grande.src/M000053.html +0 -16
  378. data/doc/rdoc/classes/RIO/IF/Grande.src/M000054.html +0 -16
  379. data/doc/rdoc/classes/RIO/IF/Grande.src/M000055.html +0 -16
  380. data/doc/rdoc/classes/RIO/IF/Grande.src/M000056.html +0 -16
  381. data/doc/rdoc/classes/RIO/IF/Grande.src/M000057.html +0 -16
  382. data/doc/rdoc/classes/RIO/IF/Grande.src/M000058.html +0 -21
  383. data/doc/rdoc/classes/RIO/IF/Grande.src/M000059.html +0 -16
  384. data/doc/rdoc/classes/RIO/IF/Grande.src/M000060.html +0 -16
  385. data/doc/rdoc/classes/RIO/IF/Grande.src/M000061.html +0 -16
  386. data/doc/rdoc/classes/RIO/IF/Grande.src/M000062.html +0 -16
  387. data/doc/rdoc/classes/RIO/IF/Grande.src/M000063.html +0 -16
  388. data/doc/rdoc/classes/RIO/IF/Grande.src/M000064.html +0 -16
  389. data/doc/rdoc/classes/RIO/IF/Grande.src/M000065.html +0 -21
  390. data/doc/rdoc/classes/RIO/IF/Grande.src/M000066.html +0 -16
  391. data/doc/rdoc/classes/RIO/IF/Grande.src/M000067.html +0 -16
  392. data/doc/rdoc/classes/RIO/IF/Grande.src/M000068.html +0 -16
  393. data/doc/rdoc/classes/RIO/IF/Grande.src/M000069.html +0 -16
  394. data/doc/rdoc/classes/RIO/IF/Grande.src/M000070.html +0 -16
  395. data/doc/rdoc/classes/RIO/IF/GrandeEntry.html +0 -810
  396. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000107.html +0 -16
  397. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000108.html +0 -16
  398. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000109.html +0 -16
  399. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000110.html +0 -16
  400. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000111.html +0 -16
  401. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000112.html +0 -16
  402. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000113.html +0 -16
  403. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000114.html +0 -16
  404. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000115.html +0 -16
  405. data/doc/rdoc/classes/RIO/IF/GrandeEntry.src/M000116.html +0 -16
  406. data/doc/rdoc/classes/RIO/IF/GrandeStream.html +0 -1513
  407. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000071.html +0 -16
  408. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000072.html +0 -16
  409. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000073.html +0 -16
  410. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000074.html +0 -16
  411. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000075.html +0 -16
  412. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000076.html +0 -16
  413. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000077.html +0 -16
  414. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000078.html +0 -16
  415. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000079.html +0 -16
  416. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000080.html +0 -16
  417. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000081.html +0 -16
  418. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000082.html +0 -16
  419. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000083.html +0 -16
  420. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000084.html +0 -16
  421. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000085.html +0 -16
  422. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000086.html +0 -16
  423. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000087.html +0 -19
  424. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000088.html +0 -16
  425. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000089.html +0 -16
  426. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000090.html +0 -16
  427. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000091.html +0 -16
  428. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000092.html +0 -16
  429. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000093.html +0 -16
  430. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000094.html +0 -16
  431. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000095.html +0 -16
  432. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000096.html +0 -16
  433. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000097.html +0 -16
  434. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000098.html +0 -16
  435. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000099.html +0 -16
  436. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000100.html +0 -16
  437. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000101.html +0 -16
  438. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000102.html +0 -16
  439. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000103.html +0 -16
  440. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000104.html +0 -16
  441. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000105.html +0 -16
  442. data/doc/rdoc/classes/RIO/IF/GrandeStream.src/M000106.html +0 -16
  443. data/doc/rdoc/classes/RIO/IF/Path.html +0 -999
  444. data/doc/rdoc/classes/RIO/IF/Path.src/M000132.html +0 -16
  445. data/doc/rdoc/classes/RIO/IF/Path.src/M000133.html +0 -16
  446. data/doc/rdoc/classes/RIO/IF/Path.src/M000134.html +0 -16
  447. data/doc/rdoc/classes/RIO/IF/Path.src/M000135.html +0 -16
  448. data/doc/rdoc/classes/RIO/IF/Path.src/M000136.html +0 -16
  449. data/doc/rdoc/classes/RIO/IF/Path.src/M000137.html +0 -16
  450. data/doc/rdoc/classes/RIO/IF/Path.src/M000138.html +0 -16
  451. data/doc/rdoc/classes/RIO/IF/Path.src/M000139.html +0 -16
  452. data/doc/rdoc/classes/RIO/IF/Path.src/M000140.html +0 -16
  453. data/doc/rdoc/classes/RIO/IF/Path.src/M000141.html +0 -16
  454. data/doc/rdoc/classes/RIO/IF/Path.src/M000142.html +0 -16
  455. data/doc/rdoc/classes/RIO/IF/Path.src/M000143.html +0 -16
  456. data/doc/rdoc/classes/RIO/IF/Path.src/M000144.html +0 -16
  457. data/doc/rdoc/classes/RIO/IF/Path.src/M000145.html +0 -16
  458. data/doc/rdoc/classes/RIO/IF/Path.src/M000146.html +0 -16
  459. data/doc/rdoc/classes/RIO/IF/Path.src/M000147.html +0 -16
  460. data/doc/rdoc/classes/RIO/IF/Path.src/M000148.html +0 -16
  461. data/doc/rdoc/classes/RIO/IF/Path.src/M000149.html +0 -16
  462. data/doc/rdoc/classes/RIO/IF/Path.src/M000150.html +0 -16
  463. data/doc/rdoc/classes/RIO/IF/Path.src/M000151.html +0 -16
  464. data/doc/rdoc/classes/RIO/IF/Path.src/M000152.html +0 -16
  465. data/doc/rdoc/classes/RIO/IF/Path.src/M000153.html +0 -16
  466. data/doc/rdoc/classes/RIO/IF/Path.src/M000154.html +0 -18
  467. data/doc/rdoc/classes/RIO/IF/Path.src/M000155.html +0 -16
  468. data/doc/rdoc/classes/RIO/IF/Path.src/M000156.html +0 -16
  469. data/doc/rdoc/classes/RIO/IF/Path.src/M000157.html +0 -16
  470. data/doc/rdoc/classes/RIO/IF/Path.src/M000158.html +0 -16
  471. data/doc/rdoc/classes/RIO/IF/Path.src/M000159.html +0 -16
  472. data/doc/rdoc/classes/RIO/IF/Path.src/M000160.html +0 -16
  473. data/doc/rdoc/classes/RIO/IF/Path.src/M000161.html +0 -16
  474. data/doc/rdoc/classes/RIO/IF/Path.src/M000162.html +0 -16
  475. data/doc/rdoc/classes/RIO/IF/Path.src/M000163.html +0 -16
  476. data/doc/rdoc/classes/RIO/IF/RubyIO.html +0 -1416
  477. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000004.html +0 -16
  478. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000005.html +0 -16
  479. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000006.html +0 -16
  480. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000007.html +0 -16
  481. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000008.html +0 -16
  482. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000009.html +0 -16
  483. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000010.html +0 -16
  484. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000011.html +0 -16
  485. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000012.html +0 -16
  486. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000013.html +0 -16
  487. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000014.html +0 -16
  488. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000015.html +0 -16
  489. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000016.html +0 -16
  490. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000017.html +0 -16
  491. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000018.html +0 -16
  492. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000019.html +0 -16
  493. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000020.html +0 -16
  494. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000021.html +0 -16
  495. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000022.html +0 -16
  496. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000023.html +0 -16
  497. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000024.html +0 -16
  498. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000025.html +0 -16
  499. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000026.html +0 -16
  500. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000027.html +0 -16
  501. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000028.html +0 -16
  502. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000029.html +0 -16
  503. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000030.html +0 -16
  504. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000031.html +0 -16
  505. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000032.html +0 -16
  506. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000033.html +0 -16
  507. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000034.html +0 -16
  508. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000035.html +0 -16
  509. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000036.html +0 -16
  510. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000037.html +0 -16
  511. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000038.html +0 -16
  512. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000039.html +0 -16
  513. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000040.html +0 -16
  514. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000041.html +0 -16
  515. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000042.html +0 -16
  516. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000043.html +0 -16
  517. data/doc/rdoc/classes/RIO/IF/RubyIO.src/M000044.html +0 -16
  518. data/doc/rdoc/classes/RIO/IF/String.html +0 -203
  519. data/doc/rdoc/classes/RIO/IF/String.src/M000213.html +0 -16
  520. data/doc/rdoc/classes/RIO/IF/String.src/M000214.html +0 -16
  521. data/doc/rdoc/classes/RIO/IF/String.src/M000215.html +0 -16
  522. data/doc/rdoc/classes/RIO/IF/Test.html +0 -990
  523. data/doc/rdoc/classes/RIO/IF/Test.src/M000177.html +0 -16
  524. data/doc/rdoc/classes/RIO/IF/Test.src/M000178.html +0 -16
  525. data/doc/rdoc/classes/RIO/IF/Test.src/M000179.html +0 -16
  526. data/doc/rdoc/classes/RIO/IF/Test.src/M000180.html +0 -16
  527. data/doc/rdoc/classes/RIO/IF/Test.src/M000181.html +0 -16
  528. data/doc/rdoc/classes/RIO/IF/Test.src/M000182.html +0 -16
  529. data/doc/rdoc/classes/RIO/IF/Test.src/M000183.html +0 -16
  530. data/doc/rdoc/classes/RIO/IF/Test.src/M000184.html +0 -16
  531. data/doc/rdoc/classes/RIO/IF/Test.src/M000185.html +0 -16
  532. data/doc/rdoc/classes/RIO/IF/Test.src/M000186.html +0 -16
  533. data/doc/rdoc/classes/RIO/IF/Test.src/M000187.html +0 -16
  534. data/doc/rdoc/classes/RIO/IF/Test.src/M000188.html +0 -16
  535. data/doc/rdoc/classes/RIO/IF/Test.src/M000189.html +0 -16
  536. data/doc/rdoc/classes/RIO/IF/Test.src/M000190.html +0 -16
  537. data/doc/rdoc/classes/RIO/IF/Test.src/M000191.html +0 -16
  538. data/doc/rdoc/classes/RIO/IF/Test.src/M000192.html +0 -16
  539. data/doc/rdoc/classes/RIO/IF/Test.src/M000193.html +0 -16
  540. data/doc/rdoc/classes/RIO/IF/Test.src/M000194.html +0 -16
  541. data/doc/rdoc/classes/RIO/IF/Test.src/M000195.html +0 -16
  542. data/doc/rdoc/classes/RIO/IF/Test.src/M000196.html +0 -16
  543. data/doc/rdoc/classes/RIO/IF/Test.src/M000197.html +0 -16
  544. data/doc/rdoc/classes/RIO/IF/Test.src/M000198.html +0 -16
  545. data/doc/rdoc/classes/RIO/IF/Test.src/M000199.html +0 -16
  546. data/doc/rdoc/classes/RIO/IF/Test.src/M000200.html +0 -16
  547. data/doc/rdoc/classes/RIO/IF/Test.src/M000201.html +0 -16
  548. data/doc/rdoc/classes/RIO/IF/Test.src/M000202.html +0 -16
  549. data/doc/rdoc/classes/RIO/IF/Test.src/M000203.html +0 -16
  550. data/doc/rdoc/classes/RIO/IF/Test.src/M000204.html +0 -16
  551. data/doc/rdoc/classes/RIO/IF/Test.src/M000205.html +0 -16
  552. data/doc/rdoc/classes/RIO/IF/Test.src/M000206.html +0 -16
  553. data/doc/rdoc/classes/RIO/IF/Test.src/M000207.html +0 -16
  554. data/doc/rdoc/classes/RIO/IF/Test.src/M000208.html +0 -16
  555. data/doc/rdoc/classes/RIO/IF/Test.src/M000209.html +0 -16
  556. data/doc/rdoc/classes/RIO/IF/Test.src/M000210.html +0 -16
  557. data/doc/rdoc/classes/RIO/IF/Test.src/M000211.html +0 -16
  558. data/doc/rdoc/classes/RIO/IF/Test.src/M000212.html +0 -16
  559. data/doc/rdoc/classes/RIO/IF/YAML.html +0 -517
  560. data/doc/rdoc/classes/RIO/IF/YAML.src/M000164.html +0 -19
  561. data/doc/rdoc/classes/RIO/IF/YAML.src/M000165.html +0 -16
  562. data/doc/rdoc/classes/RIO/IF/YAML.src/M000166.html +0 -16
  563. data/doc/rdoc/classes/RIO/IF/YAML.src/M000167.html +0 -16
  564. data/doc/rdoc/classes/RIO/IF/YAML.src/M000168.html +0 -16
  565. data/doc/rdoc/classes/RIO/IF/YAML.src/M000169.html +0 -16
  566. data/doc/rdoc/classes/RIO/IF/YAML.src/M000170.html +0 -16
  567. data/doc/rdoc/classes/RIO/IF/YAML.src/M000171.html +0 -16
  568. data/doc/rdoc/classes/RIO/IF/YAML.src/M000172.html +0 -16
  569. data/doc/rdoc/classes/RIO/IF/YAML.src/M000173.html +0 -16
  570. data/doc/rdoc/classes/RIO/IF/YAML.src/M000174.html +0 -16
  571. data/doc/rdoc/classes/RIO/IF/YAML.src/M000175.html +0 -16
  572. data/doc/rdoc/classes/RIO/IF/YAML.src/M000176.html +0 -16
  573. data/doc/rdoc/classes/RIO/Rio.html +0 -508
  574. data/doc/rdoc/classes/RIO/Rio.src/M000220.html +0 -18
  575. data/doc/rdoc/classes/RIO/Rio.src/M000221.html +0 -20
  576. data/doc/rdoc/classes/RIO/Rio.src/M000222.html +0 -27
  577. data/doc/rdoc/classes/RIO/Rio.src/M000223.html +0 -16
  578. data/doc/rdoc/classes/RIO/Rio.src/M000225.html +0 -19
  579. data/doc/rdoc/classes/RIO/Rio.src/M000226.html +0 -20
  580. data/doc/rdoc/classes/RIO/Rio.src/M000227.html +0 -16
  581. data/doc/rdoc/classes/RIO/Rio.src/M000228.html +0 -16
  582. data/doc/rdoc/classes/RIO/Rio.src/M000229.html +0 -16
  583. data/doc/rdoc/classes/RIO/Rio.src/M000230.html +0 -16
  584. data/doc/rdoc/classes/RIO/Rio.src/M000231.html +0 -16
  585. data/doc/rdoc/classes/RIO/Rio.src/M000232.html +0 -16
  586. data/doc/rdoc/classes/RIO/Rio.src/M000233.html +0 -16
  587. data/doc/rdoc/created.rid +0 -1
  588. data/doc/rdoc/files/README.html +0 -232
  589. data/doc/rdoc/files/lib/rio/constructor_rb.html +0 -141
  590. data/doc/rdoc/files/lib/rio/doc/EXAMPLES_rb.html +0 -134
  591. data/doc/rdoc/files/lib/rio/doc/HOWTO_rb.html +0 -134
  592. data/doc/rdoc/files/lib/rio/doc/INDEX_rb.html +0 -134
  593. data/doc/rdoc/files/lib/rio/doc/INTRO_rb.html +0 -134
  594. data/doc/rdoc/files/lib/rio/doc/OPTIONAL_rb.html +0 -134
  595. data/doc/rdoc/files/lib/rio/doc/SYNOPSIS_rb.html +0 -134
  596. data/doc/rdoc/files/lib/rio/if/basic_rb.html +0 -134
  597. data/doc/rdoc/files/lib/rio/if/csv_rb.html +0 -134
  598. data/doc/rdoc/files/lib/rio/if/dir_rb.html +0 -134
  599. data/doc/rdoc/files/lib/rio/if/file_rb.html +0 -134
  600. data/doc/rdoc/files/lib/rio/if/fileordir_rb.html +0 -134
  601. data/doc/rdoc/files/lib/rio/if/grande_entry_rb.html +0 -134
  602. data/doc/rdoc/files/lib/rio/if/grande_rb.html +0 -141
  603. data/doc/rdoc/files/lib/rio/if/grande_stream_rb.html +0 -134
  604. data/doc/rdoc/files/lib/rio/if/internal_rb.html +0 -134
  605. data/doc/rdoc/files/lib/rio/if/path_rb.html +0 -134
  606. data/doc/rdoc/files/lib/rio/if/rubyio_rb.html +0 -134
  607. data/doc/rdoc/files/lib/rio/if/string_rb.html +0 -134
  608. data/doc/rdoc/files/lib/rio/if/temp_rb.html +0 -134
  609. data/doc/rdoc/files/lib/rio/if/test_rb.html +0 -134
  610. data/doc/rdoc/files/lib/rio/if/yaml_rb.html +0 -134
  611. data/doc/rdoc/files/lib/rio/kernel_rb.html +0 -142
  612. data/doc/rdoc/files/lib/rio_rb.html +0 -153
  613. data/doc/rdoc/fr_class_index.html +0 -49
  614. data/doc/rdoc/fr_file_index.html +0 -51
  615. data/doc/rdoc/fr_method_index.html +0 -260
  616. data/doc/rdoc/index.html +0 -30
  617. data/doc/rdoc/rdoc-style.css +0 -428
  618. data/doc/rfc1738.txt +0 -1403
  619. data/doc/rfc959.txt +0 -3933
  620. data/ex/catcsv.rb +0 -64
  621. data/ex/colx.rb +0 -8
  622. data/ex/findinruby +0 -15
  623. data/ex/findruby +0 -14
  624. data/ex/passwd_report.rb +0 -8
  625. data/ex/prompt.rb +0 -25
  626. data/ex/rgb.txt.gz +0 -0
  627. data/ex/riocat +0 -42
  628. data/ex/riogunzip +0 -31
  629. data/ex/riogzip +0 -24
  630. data/ex/rioprompt.rb +0 -10
  631. data/ex/targz2zip +0 -17
  632. data/ex/tonl +0 -10
  633. data/setup.rb +0 -1360
  634. data/test/ftp/all.rb +0 -9
  635. data/test/ftp/anon_copy_data.rb +0 -36
  636. data/test/ftp/anon_misc.rb +0 -124
  637. data/test/ftp/anon_read.rb +0 -105
  638. data/test/ftp/anon_special.rb +0 -68
  639. data/test/ftp/anon_write.rb +0 -70
  640. data/test/ftp/ftp2ftp.rb +0 -51
  641. data/test/tc/abs.rb +0 -355
@@ -1,6 +1,6 @@
1
1
  #--
2
- # ===============================================================================
3
- # Copyright (c) 2005,2006,2007,2008 Christopher Kleckner
2
+ # ===========================================================================
3
+ # Copyright (c) 2005-2012 Christopher Kleckner
4
4
  # All rights reserved
5
5
  #
6
6
  # This file is part of the Rio library for ruby.
@@ -18,1050 +18,1039 @@
18
18
  # You should have received a copy of the GNU General Public License
19
19
  # along with Rio; if not, write to the Free Software
20
20
  # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # ===============================================================================
21
+ # ===========================================================================
22
22
  #++
23
23
  #
24
- # To create the documentation for Rio run the command
25
- # ruby build_doc.rb
26
- # from the distribution directory.
27
- #
28
- # Suggested Reading
29
- # * RIO::Doc::SYNOPSIS
30
- # * RIO::Doc::INTRO
31
- # * RIO::Doc::HOWTO
32
- # * RIO::Doc::EXAMPLES
33
- # * RIO::Rio
34
- #
35
-
36
-
37
24
  module RIO
38
25
  module Doc
39
- =begin rdoc
40
-
41
- = Rio - Ruby I/O Facilitator
42
-
43
- Rio is a facade for most of the standard ruby classes that deal with I/O;
44
- providing a simple, intuitive, succinct interface to the functionality
45
- provided by IO, File, Dir, Pathname, FileUtils, Tempfile, StringIO, OpenURI
46
- and others. Rio also provides an application level interface which allows many
47
- common I/O idioms to be expressed succinctly.
48
-
49
-
50
- Rio functionality can be broadly broken into three categories
51
- * path manipulation
52
- * file system access
53
- * stream manipulation
54
-
55
- Which methods are available to a given Rio, depends on the underlying
56
- object.
57
-
58
- A Rio generally does not need to be opened or have its mode specified.
59
- Most of Rio's methods simply configure it. When an actual IO
60
- operation is specified, Rio determines how to open it based on the
61
- object it is opening, the operation it is performing, and the options
62
- specified.
63
-
64
- Rio configuration methods return the Rio for easy chaining and regard
65
- the presence of a block as an implied +each+.
66
-
67
- == Using a Rio
68
-
69
- Using a Rio can be described as having 3 steps:
70
- * Creating a Rio
71
- * Configuring a Rio
72
- * Rio I/O
73
-
74
- === Creating a Rio
75
-
76
- Rio extends Kernel with one function +rio+, its constructor. This
77
- function is overloaded to create any type of Rio. +rio+ looks at the
78
- class and sometimes the value of its first argument to create an
79
- internal representation of the resource specified, additional
80
- arguments are used as needed by the resource type. The rio constructor
81
- does not initiate any io, it does not check for a resources existance
82
- or type. It neither knows nor cares what can be done with this Rio.
83
- Using methods like <tt>respond_to?</tt> are meaningless at best and usually
84
- misleading.
85
-
86
- For purposes of discussion, we divide Rios into two catagories, those
87
- that have a path and those that don't.
88
-
89
- ==== Creating a Rio that has a path
90
-
91
- To create a Rio that has a path the arguments to +rio+ may be:
92
-
93
- * a string representing the entire path. The separator used for Rios
94
- is as specified in RFC1738 ('/').
95
-
96
- rio('adir/afile')
97
-
98
- * a string representing a fully qualified +file+ URI as per RFC1738
99
-
100
- rio('file:///atopleveldir/adir/afile')
101
-
102
- * a +URI+ object representing a +file+ or generic +URI+
103
-
104
- rio(URI('adir/afile'))
105
-
106
- * the components of a path as separate arguments
107
-
108
- rio('adir','afile')
109
-
110
- * the components of a path as an array
111
-
112
- rio(%w/adir afile/)
113
-
114
- * another Rio
115
-
116
- another_rio = rio('adir/afile')
117
- rio(another_rio)
118
-
119
- * any object whose +to_s+ method returns one of the above
120
-
121
- rio(Pathname.new('apath'))
122
-
123
- * any combination of the above either as separate arguments or as
124
- elements of an array,
125
-
126
- another_rio = rio('dir1/dir2')
127
- auri = URI('dir4/dir5)
128
- rio(another_rio,'dir3',auri,'dir6/dir7')
129
-
130
- ===== Creating a Rio that refers to a web page
131
-
132
- To create a Rio that refers to a web page the arguments to +rio+ may
133
- be:
134
-
135
- * a string representing a fully qualified +http+ URI
136
-
137
- rio('http://ruby-doc.org/index.html')
138
-
139
- * a +URI+ object representing a +http+ +URI+
140
-
141
- rio(URI('http://ruby-doc.org/index.html'))
142
-
143
- * either of the above with additional path elements
144
-
145
- rio('http://www.ruby-doc.org/','core','classes/Object.html')
146
-
147
-
148
- ===== Creating a Rio that refers to a file or directory on a FTP server
149
-
150
- To create a Rio that refers to a file on a FTP server the arguments to
151
- +rio+ may be:
152
-
153
- * a string representing a fully qualified +ftp+ URI
154
-
155
- rio('ftp://user:password@ftp.example.com/afile.tar.gz')
156
-
157
- * a +URI+ object representing a +ftp+ +URI+
158
-
159
- rio(URI('ftp://ftp.example.com/afile.tar.gz'))
160
-
161
- * either of the above with additional path elements
162
-
163
- rio('ftp://ftp.gnu.org/pub/gnu','emacs','windows','README')
164
-
165
- ==== Creating Rios that do not have a path
166
-
167
- To create a Rio without a path, the first argument to +rio+ is usually
168
- a single character.
169
-
170
- ===== Creating a Rio that refers to a clone of your programs stdin or stdout.
171
-
172
- <tt>rio(?-)</tt> (mnemonic: '-' is used by some Unix programs to
173
- specify stdin or stdout in place of a file)
174
-
175
- Just as a Rio that refers to a file, does not know whether that file
176
- will be opened for reading or writing until an io operation is
177
- specified, a <tt>stdio:</tt> Rio does not know whether it will connect
178
- to stdin or stdout until an I/O operation is specified.
179
-
180
- ===== Creating a Rio that refers to a clone of your programs stderr.
181
-
182
- <tt>rio(?=)</tt> (mnemonic: '-' refers to fileno 1, so '=' refers to
183
- fileno 2)
184
-
185
- ===== Creating a Rio that refers to an arbitrary IO object.
186
-
187
- an_io = ::File.new('afile')
188
- rio(an_io)
189
-
190
- ===== Creating a Rio that refers to a file descriptor
191
-
192
- <tt>rio(?#,fd)</tt> (mnemonic: a file descriptor is a number '#' )
193
-
194
- an_io = ::File.new('afile')
195
- rio(an_io)
196
-
197
- ===== Creating a Rio that refers to a StringIO object
198
-
199
- <tt>rio(?")</tt> (mnemonic: '"' surrounds strings)
200
- * create a Rio that refers to its own string
201
- rio(?")
202
- * create a Rio that refers to a string of your choosing
203
- astring = ""
204
- rio(?",astring)
205
-
206
- ===== Creating a Rio that refers to a Temporary object
207
-
208
- <tt>rio(??)</tt> (mnemonic: '?' you don't know its name)
209
-
210
- To create a temporary object that will become a file
211
- or a directory, depending on how you use it:
212
- rio(??)
213
- rio(??,basename='rio',tmpdir=Dir::tmpdir)
214
-
215
- To force it to become a directory:
216
- rio(??).mkdir
217
- or
218
- rio(??).chdir
219
-
220
-
221
-
222
- ===== Creating a Rio that refers to an arbitrary TCPSocket
223
-
224
- rio('tcp:',hostname,port)
225
- or
226
- rio('tcp://hostname:port')
227
-
228
- ===== Creating a Rio that runs an external program and connects to its stdin and stdout
229
-
230
- <tt>rio(?-,cmd)</tt> (mnemonic: '-' is used by some Unix programs to
231
- specify stdin or stdout in place of a file)
232
-
233
- or
234
-
235
- <tt>rio(?`,cmd)</tt> (mnemonic: '`' (backtick) runs an external
236
- program in ruby)
237
-
238
- This is Rio's interface to IO#popen
239
-
240
- === Path Manipulation
241
-
242
- Rio's path manipulation methods are for the most part simply forwarded
243
- to the File or URI classes with the return values converted to a Rio.
244
-
245
- ==== Creating a Rio from a Rio's component parts.
246
-
247
- The Rio methods for creating a Rio from a Rio's component parts are
248
- IF::Path#dirname, IF::Path#filename, IF::Path#basename, and IF::Path#extname. The
249
- behavior of IF::Path#basename depends on the setting of the +ext+
250
- configuration variable and is different from its counterpart in the
251
- File class. The default value of the +ext+ configuration variable is
252
- the string returned File#extname. The +ext+ configuration variable can
253
- be changed using IF::Path#ext and IF::Path#noext and can be queried using
254
- IF::Path#ext?. This value is used by calls to IF::Path#basename.
255
-
256
- IF::Path#filename returns the last component of a path, and is basically
257
- the same as +basename+ without consideration of an extension.
258
-
259
- rio('afile.txt').basename #=> rio('afile')
260
- rio('afile.txt').filename #=> rio('afile.txt')
261
-
262
- ario = rio('afile.tar.gz')
263
- ario.basename #=> rio('afile.tar')
264
- ario.ext? #=> ".gz"
265
- ario.ext('.tar.gz').basename #=> rio('afile')
266
- ario.ext? #=> ".tar.gz"
267
-
268
- ==== Changing a path's component parts.
269
-
270
- Rio also provides methods for changing the component parts of its
271
- path. They are IF::Path#dirname=, IF::Path#filename=, IF::Path#basename=, and
272
- IF::Path#extname=. These methods replace the part extracted as described
273
- above with their argument.
274
-
275
- ario = rio('dirA/dirB/afile.rb')
276
- ario.dirname = 'dirC' # rio('dirC/afile.rb')
277
- ario.basename = 'bfile' # rio('dirC/bfile.rb')
278
- ario.extname = '.txt' # rio('dirC/bfile.txt')
279
- ario.filename = 'cfile.rb' # rio('dirC/cfile.rb')
280
-
281
- Rio also has a +rename+ mode which causes each of these to rename the
282
- actual file system object as well as changing the Rio. This is
283
- discussed in the section on Renaming and Moving.
284
-
285
- ==== Splitting a Rio
286
-
287
- IF::Grande#split (or IF::Path#splitpath) returns an array of Rios, one
288
- for each path element. (Note that this behavior differs from File#split.)
289
-
290
- rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
291
-
292
- The array returned is extended with a +to_rio+ method, which will put
293
- the parts back together again.
294
-
295
- ary = rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
296
- ary.to_rio #=> rio('a/b/c')
297
-
298
- ==== Creating a Rio by specifying the individual parts of its path
299
-
300
- The first way to create a Rio by specifying its parts is to use the
301
- Rio constructor Rio#rio. Since a Rio is among the arguments the
302
- constructor will take, the constructor can be used.
303
-
304
- ario = rio('adir')
305
- rio(ario,'b') #=> rio('adir/b')
306
-
307
- IF::Path#join and IF::Path#/ do the same thing, but the operator version
308
- <tt>/</tt> can take only one argument.
309
-
310
- a = rio('a')
311
- b = rio('b')
312
- c = a.join(b) #=> rio('a/b')
313
- c = a/b #=> rio('a/b')
314
-
315
- The arguments to IF::Path#join and IF::Path#/ do not need to be Rios, of course
316
- ario = rio('adir')
317
- ario/'afile.rb' #=> rio('adir/afile.rb')
318
- ario.join('b','c','d') #=> rio('adir/b/c/d')
319
- ario/'b'/'c'/'d' #=> rio('adir/b/c/d')
320
- ario /= 'e' #=> rio('adir/b/c/d/e')
321
-
322
- ==== Manipulating a Rio path by treating it as a string.
323
-
324
- The Rio methods which treat a Rio as a string are IF::String#sub, IF::String#gsub
325
- and IF::String#+. These methods create a new Rio using the string created by
326
- forwarding the method to the String returned by Rio#to_s.
327
-
328
- ario = rio('dirA/dirB/afile') + '-1.1.1' # rio('dirA/dirB/afile-1.1.1')
329
- brio = ario.sub(/^dirA/, 'dirC') # rio('dirC/dirB/afile-1.1.1')
330
-
331
-
332
- ==== Creating a Rio based on its relationship to another
333
-
334
- IF::Path#abs creates a new rio whose path is the absolute path of a Rio.
335
- If called with an argument, it uses it as the base path, otherwise
336
- it uses an internal base path (usually the current working directory
337
- when it was created).
338
-
339
- rio('/tmp').chdir do
340
- rio('a').abs #=> rio('/tmp/a')
341
- rio('a').abs('/usr') #=> rio('/usr/a')
342
- end
343
-
344
- IF::Path#rel creates a new rio with a path relative to a Rio.
345
-
346
- rio('/tmp').chdir do
347
- rio('/tmp/a').rel #=> rio('a')
348
- end
349
- rio('/tmp/b').rel('/tmp') #=> rio('b')
350
-
351
- IF::Path#route_to and IF::Path#route_from creates a new rio with a path
352
- representing the route to get to/from a Rio. They are based on the
353
- methods of the same names in the ::URI class
354
-
355
- === Configuring a Rio
356
-
357
- The second step in using a rio is configuring it. Note that many times
358
- no configuration is necessary and that this is not a comprehensive
359
- list of all of Rio's configuration methods.
360
-
361
- Rio's configuration mehods fall into three categories.
362
-
363
- * I/O manipulators
364
-
365
- An I/O manipulator alters the behavior of a Rio's underlying IO
366
- object. These affect the behaviour of I/O methods which are
367
- forwarded directly to the underlying object as well as the grande
368
- I/O methods.
369
-
370
- * Grande configuration methods
371
-
372
- The grande configuration methods affect the behaviour of Rio's
373
- grande I/O methods
374
-
375
- * Grande selection methods
376
-
377
- The grande selection methods select what data is returned by Rio's
378
- grande I/O methods
379
-
380
- All of Rio's configuration and selection methods can be passed a
381
- block, which will cause the Rio to behave as if IF::Grande#each had been called
382
- with the block after the method.
383
-
384
- ==== IO manipulators
385
-
386
- * +gzip+ a file on output, and ungzip it on input
387
-
388
- rio('afile.gz').gzip
389
-
390
- This causes the rio to read through a Zlib::GzipReader and to write
391
- Zlib::GzipWriter.
392
-
393
- * +chomp+ lines as they are read
394
-
395
- rio('afile').chomp
396
-
397
- This causes a Rio to call String#chomp on the the String returned by
398
- all line oriented read operations.
399
-
400
- ==== Grande configuration methods
401
-
402
- * +all+, +recurse+, +norecurse+
403
-
404
- rio('adir').all
405
- rio('adir').norecurse('CVS')
406
-
407
- These methods instruct the Rio to also include entries in
408
- subdirectories when iterating through directories and control which
409
- subdirectories are included or excluded.
410
-
411
- * +bytes+
412
-
413
- rio('afile').bytes(1024)
414
-
415
- This causes a Rio to read the specified number of bytes at a time as
416
- a file is iterated through.
417
-
418
- ==== Grande selection methods
419
-
420
- * +lines+, +skiplines+
421
-
422
- rio('afile').lines(0..9)
423
- rio('afile').skiplines(/^\s*#/)
424
-
425
- Strictly speaking these are both configuration and selection
426
- methods. They configure the Rio to iterate through an input stream
427
- as lines. The arguments select which lines are actually returned.
428
- Lines are included (+lines+) or excluded (+skiplines+) if they match
429
- *any* of the arguments as follows.
430
-
431
- If the argument is a:
432
- +RegExp+:: the line is matched against it
433
- +Range+:: the lineno is matched against it
434
- +Integer+:: the lineno is matched against it as if it were a one element range
435
- +Symbol+:: the symbol is +sent+ to the string; the line is included unless it returns false
436
- +Proc+:: the proc is called with the line as an argument; the line is included unless it returns false
437
- +Array+:: an array containing any of the above, all of which must match for the line to be included
438
-
439
- * +entries+, +files+, +dirs+, +skipentries+, +skipfiles+, +skipdirs+
440
-
441
- rio('adir').files('*.txt')
442
- rio('adir').skipfiles(/^\./)
443
-
444
- These methods select which entries will be returned when iterating
445
- through directories. Entries are included (+entries+,+files+,+dirs+)
446
- or excluded(+skipentries+,+skipfiles+,+skipdirs+) if they match *any* of
447
- the arguments as follows.
448
-
449
- If the argument is a:
450
- +String+:: the arg is treated as a glob; the filname is matched against it
451
- +RegExp+:: the filname is matched against it
452
- +Symbol+:: the symbol is +sent+ to the entry (a Rio); the entry is included unless it returns false
453
- +Proc+:: the proc is called with the entry (a Rio) as an argument; the entry is included unless it returns false
454
- +Array+:: an array containing any of the above, all of which must match for the line to be included
455
-
456
- * +records+, +rows+, +skiprecords+, +skiprows+
457
-
458
- rio('afile').bytes(1024).records(0...10)
459
-
460
- These select items from an input stream just as +lines+, but without
461
- specifying lines as the input record type. They can be used to
462
- select different record types in extension modules. The only such
463
- module at this writing is the CSV extension. In that case +records+
464
- causes each line of a CSV file to be parsed into an array while
465
- +lines+ causes each line of the file to be returned normally.
466
-
467
- === Rio I/O
468
-
469
- As stated above the the three steps to using a Rio are:
470
- * Creating a Rio
471
- * Configuring a Rio
472
- * Doing I/O
473
-
474
- This section describes that final step.
475
-
476
- After creating and configuring a Rio, the file-system has not been
477
- accessed, no socket has been opened, not so much as a test for a files
478
- existance has been done. When an I/O method is called on a Rio, the
479
- sequence of events required to complete that operation on the
480
- underlying object takes place. Rio takes care of creating the
481
- appropriate object (eg IO,Dir), opening the object with the appropriate
482
- mode, performing the operation, closing the object if required, and
483
- returning the results of the operation.
484
-
485
- Rio's I/O operations can be divide into two catagories:
486
- * Proxy operations
487
- * Grande operations
488
-
489
- ==== Proxy operations
490
-
491
- These are calls which are forwarded to the underlying object (eg
492
- IO,Dir,Net::FTP), after appropriately creating and configuring that
493
- object. The result produced by the method is returned, and the object
494
- is closed.
495
-
496
- In some cases the result is modified before being returned, as when a
497
- Rio is configured with IF::GrandeStream#chomp.
498
-
499
- In all cases, if the result returned by the underlying object, could
500
- itself be used for further I/O operations it is returned as a Rio. For
501
- example: where File#dirname returns a string, IF::Path#dirname returns a
502
- Rio; where Dir#read returns a string representing a directory entry,
503
- IF::FileOrDir#read returns a Rio.
504
-
505
- With some noteable exceptions, most of the operations available if one
506
- were using the underlying Ruby I/O class are available to the Rio and
507
- will behave identically.
508
-
509
- For things that exist on a file system:
510
-
511
- * All the methods in FileTest are available as Rio instance
512
- methods. For example
513
-
514
- FileTest.file?('afile')
515
-
516
- becomes
517
-
518
- rio('afile').file?
519
-
520
- * All the instance methods of +File+ except +path+ are available to a
521
- rio without change
522
-
523
- * Most of the class methods of +File+ are available.
524
-
525
- * For those that take a filename as their only argument the calls
526
- are mapped to Rio instance methods as described above for
527
- FileTest.
528
-
529
- * +dirname+, and +readlink+ return Rios instead of strings
530
-
531
- * Rio has its own IF::Path#basename, IF::Path#join and IF::FileOrDir#symlink, which
532
- provide similar functionality.
533
-
534
- * The class methods which take multiple filenames
535
- (+chmod+,+chown+,+lchmod+,+lchown+) are available as Rio instance
536
- methods. For example
537
-
538
- File.chmod(0666,'afile')
539
- becomes
540
- rio('afile').chmod(06660)
541
-
542
- For I/O Streams
543
-
544
- Most of the instance methods of IO are available, and most do the same
545
- thing, with some interface changes. <b>The big exception to this is
546
- the '<<' operator.</b> This is one of Rio's grande operators. While
547
- the symantics one would use to write to an IO object would actually
548
- accomplish the same thing with a Rio, It is a very different
549
- operator. Read the section on grande operators. The other differences
550
- between IO instance methods and the Rio equivelence can be summarized
551
- as follows.
552
-
553
- * The simple instance methods (eg +fcntl+, <tt>eof?</tt>,
554
- <tt>tty?</tt> etc.) are forwarded and the result returned as is
555
-
556
- * Anywhere IO returns an IO, Rio returns a Rio
557
-
558
- * +close+ and its cousins return the Rio.
559
-
560
- * +each_byte+ and +each_line+ are forwarded as is.
561
-
562
- * All methods which read (read*,get*,each*) will cause the file to
563
- closed when the end of file is reached. This behavior is
564
- configurable, but the default is to close on eof
565
-
566
- * The methods which write (put*,print*) are forwarded as is; put* and
567
- print* return the Rio; write returns the value returned by IO#write;
568
- as mentioned above '<<' is a grande operator in Rio.
569
-
570
- For directories:
571
-
572
- * all the instance methods of Dir are available except +each+ which is
573
- a grande method.
574
-
575
- * the class methods +mkdir+, +delete+, +rmdir+ are provided as
576
- instance methods.
577
-
578
- * +chdir+ is provided as an instance method. IF::Dir#chdir returns a Rio
579
- and passes a Rio to a block if one is provided.
580
-
581
- * +glob+ is provided as an instance method, but returns an array of
582
- Rios
583
-
584
- * +foreach+ is not supported
585
-
586
- * +each+ and <tt>[]</tt> have similar functionality provided by Rio
587
-
588
-
589
- For other Rios, instance methods are generally forwarded where
590
- appropriate. For example
591
-
592
- * Rios that refer to StringIO objects forward 'string' and 'string='
593
-
594
- * Rios that refer to http URIs support all the Meta methods provided
595
- by open-uri
596
-
597
-
598
- ==== Grande operators
599
-
600
- The primary grande operator is IF::Grande#each. +each+ is used to iterate
601
- through Rios. When applied to a file it iterates through records in
602
- the file. When applied to a directory it iterates through the entries
603
- in the directory. Its behavior is modified by configuring the Rio
604
- prior to calling it using the configuration methods discussed
605
- above. Since iterating through things is ubiquitous in ruby, it is
606
- implied by the presence of a block after any of the grande
607
- configuration methods and many times does not need to be call
608
- explicitly. For example:
609
-
610
- # iterate through chomped ruby comment lines
611
- rio('afile.rb').chomp.lines(/^\s*#/) { |line| ... }
612
-
613
- # iterate through all .rb files in 'adir' and its subdirectories
614
- rio('adir').all.files('*.rb') { |f| ... }
615
-
616
- Because a Rio is an Enumerable, it supports +to_a+, which is the basis
617
- for the grande subscript operator. IF::Grande#[] with no arguments simply
618
- calls to_a. With arguments it behaves as if those arguments had been
619
- passed to the most recently called of the grande selection methods
620
- listed above, and then calls to_a. For example to get the first ten
621
- lines of a file into an array with lines chomped
622
-
623
- rio('afile').chomp.lines(0...10).to_a
624
-
625
- can be written as
626
-
627
- rio('afile.gz').chomp.lines[0...10]
628
-
629
- or, to create an array of all the .c files in a directory, one could
630
- write
631
-
632
- rio('adir').files['*.c']
633
-
634
- The other grande operators are its copy operators. They are:
635
-
636
- * <tt><</tt> (copy-from)
637
-
638
- * <tt><<</tt> (append-from)
639
-
640
- * <tt>></tt> (copy-to)
641
-
642
- * <tt>>></tt> (append-to)
643
-
644
- The only difference between the 'copy' and 'append' versions is how
645
- they deal with an unopened resource. In the former the open it with
646
- mode 'w' and in the latter, mode 'a'. Beyond that, their behavior can
647
- be summarized as:
648
-
649
- source.each do |entry|
650
- destination << entry
651
- end
652
-
653
- Since they are based on the +each+ operator, all of the selection and
654
- configuration options are available. And the right-hand-side argument
655
- of the operators are not restricted to Rios -- Strings and Arrays are
656
- also supported.
657
-
658
- For example:
659
-
660
- rio('afile') > astring # copy a file into a string
661
-
662
- rio('afile').chomp > anarray # copy the chomped lines of afile into an array
663
-
664
- rio('afile.gz').gzip.lines(0...100) > rio('bfile') # copy 100 lines from a gzipped file into another file
665
-
666
- rio(?-) < rio('http://rubydoc.org/') # copy a web page to stdout
667
-
668
- rio('bdir') < rio('adir') # copy an entire directory structure
669
-
670
- rio('adir').dirs.files('README') > rio('bdir') # same thing, but only README files
671
-
672
- rio(?-,'ps -a').skiplines(0,/ps$/) > anarray # copy the output of th ps command into an array, skippying
673
- # the header line and the ps command entry
674
-
675
- === Renaming and Moving
676
-
677
- Rio provides two methods for directly renaming objects on the
678
- filesystem: IF::FileOrDir#rename and IF::FileOrDir#rename!.
679
- Both of these use File#rename.
680
- The difference between them is the returned Rio.
681
- IF::FileOrDir#rename leaves the path of the Rio unchanged,
682
- while IF::FileOrDir#rename! changes the path of the Rio to refer
683
- to the renamed path.
684
-
685
- ario = rio('a')
686
- ario.rename('b') # file 'a' has been renamed to 'b' but 'ario' => rio('a')
687
- ario.rename!('b') # file 'a' has been renamed to 'b' and 'ario' => rio('b')
688
-
689
- Rio also has a +rename+ mode, which causes the path manipulation
690
- methods IF::Path#dirname=, IF::Path#filename=, IF::Path#basename= and
691
- IF::Path#extname= to rename an object on the filesystem when they are
692
- used to change a Rio's path. A Rio is put in +rename+ mode by calling
693
- IF::FileOrDir#rename with no arguments.
694
-
695
- rio('adir/afile.txt').rename.filename = 'bfile.rb' # adir/afile.txt => adir/bfile.rb
696
- rio('adir/afile.txt').rename.basename = 'bfile' # adir/afile.txt => adir/bfile.txt
697
- rio('adir/afile.txt').rename.extname = '.rb' # adir/afile.txt => adir/afile.rb
698
- rio('adir/afile.txt').rename.dirname = 'b/c' # adir/afile.txt => b/c/afile.txt
699
-
700
- When +rename+ mode is set for a directory Rio, it is automatically set
701
- in the Rios created when iterating through that directory.
702
-
703
- rio('adir').rename.files('*.htm') do |frio|
704
- frio.extname = '.html' #=> changes the rio and renames the file
705
- end
706
-
707
- === Deleting
708
-
709
- The Rio methods for deleting filesystem objects are IF::File#rm, IF::Dir#rmdir,
710
- IF::Dir#rmtree, IF::Grande#delete, and IF::Grande#delete!. +rm+, +rmdir+ and +rmtree+
711
- are passed the like named methods in the FileUtils module. IF::Grande#delete
712
- calls +rmdir+ for directories and +rm+ for anything else, while
713
- IF::Grande#delete! calls IF::Dir#rmtree for directories.
714
-
715
- * To delete something only if it is not a directory use IF::File#rm
716
- * To delete an empty directory use IF::Dir#rmdir
717
- * To delete an entire directory tree use IF::Dir#rmtree
718
- * To delete anything except a populated directory use IF::Grande#delete
719
- * To delete anything use IF::Grande#delete!
720
-
721
- It is not an error to call any of the deleting methods on something
722
- that does not exist. Rio provides IF::Test#exist? and IF::Test#symlink? to check
723
- if something exists (<tt>exist?</tt> returns false for symlinks to
724
- non-existant object even though the symlink itself exists). The
725
- deleting methods' purpose is to make things not exist, so calling one
726
- of them on something that already does not exist is considered a
727
- success.
728
-
729
- To create a clean copy of a directory whether or not anything with
730
- that name exists one might do this
731
-
732
- rio('adir').delete!.mkpath.chdir do
733
- # do something in adir
734
- end
735
-
736
- ---
737
-
738
- == Miscellany
739
-
740
-
741
- ==== Using Symbolic Links
742
-
743
- To create a symbolic link (symlink) to the file-system entry refered
744
- to by a Rio, use IF::FileOrDir#symlink. IF::FileOrDir#symlink differs from File#symlink
745
- in that it calculates the path from the symlink location to the Rio's
746
- position.
747
-
748
- File#symlink('adir/afile','adir/alink')
749
-
750
- creates a symlink in the directory 'adir' named 'alink' which
751
- references 'adir/afile'. From the perspective of 'alink', 'adir/afile'
752
- does not exist. While:
753
-
754
- rio('adir/afile').symlink('adir/alink')
755
-
756
- creates a symlink in the directory 'adir' named 'alink' which
757
- references 'afile'. This is the route to 'adir/afile' from the
758
- perspective of 'adir/alink'.
759
-
760
- Note that the return value from +symlink+ is the calling Rio and not a
761
- Rio refering to the symlink. This is done for consistency with the
762
- rest of Rio.
763
-
764
- IF::Test#symlink? can be used to test if a file-system object is a
765
- symlink. A Rio is extended with IF::FileOrDir#readlink, and
766
- IF::Test#lstat only if IF::Test#symlink? returns true. So for
767
- non-symlinks, these will raise a NoMethodError. These are both passed
768
- to their counterparts in File. IF::FileOrDir#readlink returns a Rio
769
- refering to the result of File#readlink.
770
-
771
-
772
- ==== Using A Rio as an IO (or File or Dir)
773
-
774
- Rio supports so much of IO's interface that one might be tempted to
775
- pass it to a method that expects an IO. While Rio is not and is not
776
- intended to be a stand in for IO, this can work. It requires
777
- knowledge of every IO method that will be called, under any
778
- circumstances.
779
-
780
- Even in cases where Rio supports the required IO interface, A Rio
781
- feature that seems to cause the most incompatibility, is its automatic
782
- closing of files. To turn off all of Rio's automatic closing use
783
- IF::GrandeStream#noautoclose.
784
-
785
- For example:
786
- require 'yaml'
787
- yrio = rio('ran.yaml').delete!.noautoclose
788
- YAML.dump( ['badger', 'elephant', 'tiger'], yrio )
789
- obj = YAML::load( yrio ) #=> ["badger", "tiger", "elephant"]
790
-
791
-
792
- ==== Automatically Closing Files
793
-
794
- Rio closes files automatically in three instances.
795
-
796
- When reading from an IO it is closed when the end of file is
797
- reached. While this is a reasonable thing to do in many cases,
798
- sometimes this is not desired. To turn Rio's automatic closing on end
799
- of file use IF::GrandeStream#nocloseoneof (it can be turned back on via
800
- IF::GrandeStream#closeoneof)
801
-
802
- ario = rio('afile').nocloseoneof
803
- lines = ario[]
804
- ario.closed? #=> false
805
-
806
- Closing on end-of-file is necessary for many of Rio's one-liners, but
807
- has an implication that may be surprising at first. A Rio starts life
808
- as a path, not much more than a string. When one of its read methods
809
- is called it becomes an input stream. When the stream is closed, it
810
- becomes a path again. This means that when reading from a Rio, the
811
- end-of-file condition is seen only once before it becomes a path
812
- again, and will be reopened if another read operation is attempted.
813
-
814
- Another time a Rio will be closed atomatically is when writing to it
815
- with one of the copy operators (<tt><, <<, >, >></tt>). This behavior
816
- can be turned off with IF::GrandeStream#nocloseoncopy.
817
-
818
- To turn off both of thes types of automatic closing use
819
- IF::GrandeStream#noautoclose.
820
-
821
- The third instance when Rio will close a file automatically is when a
822
- file opened for one type of access receives a method which that access
823
- mode does not support. So, the code
824
- rio('afile').puts("Hello World").gets
825
- will open the file for write access when the +puts+
826
- method is received. When +gets+ is called the file is closed and
827
- reopened with read access.
828
-
829
- ==== Explicitly Closing Files
830
-
831
- Rio can not determine when the client is finished writing to it, as it
832
- does using +eof+ on read. It is the author's understanding that Ruby
833
- does not support a mechanism to have code run when there are no more
834
- references to it -- that finalizers are not necessarily run immediatly
835
- upon an object's reference count reaching 0. If this understanding is
836
- incorrect, some of Rio's extranious ways of closing a file may be
837
- rethought.
838
-
839
- That being said, Rio support several ways to explicitly close a
840
- file. IF::RubyIO#close will close any open Rio.
841
- The output methods
842
- IF::RubyIO#puts!, IF::RubyIO#putc!, IF::RubyIO#printf!, IF::RubyIO#print!, and IF::RubyIO#write!
843
- behave as if their
844
- counterparts without the exclamation point had been called and then
845
- call IF::RubyIO#close or IF::RubyIO#close_write if the underlying IO object is
846
- opened for duplex access.
847
-
848
-
849
- ==== Open mode selection
850
-
851
- A Rio is typically not explicitly opened. It opens a file
852
- automatically when an input or output methed is called. For output
853
- methods Rio opens a file with mode 'w', and otherwise opens a file
854
- with mode 'r'. This behavior can be modified using the tersely named
855
- methods IF::GrandeStream#a, IF::GrandeStream#a!, IF::GrandeStream#r, IF::GrandeStream#r!, IF::GrandeStream#w, and IF::GrandeStream#w!, which cause
856
- the Rio to use modes 'a','a+','r','r+','w',and 'w+' respectively.
857
26
 
858
- One way to append a string to a file and close it in one line is
859
-
860
- rio('afile').a.puts!("Hello World")
861
-
862
- Run a cmd that must be opened for read and write
863
-
864
- ans = rio(?-,'cat').w!.puts!("Hello Kitty").readline
865
-
866
- The automatic selection of mode can be bypassed entirely using
867
- IF::RubyIO#mode and IF::FileOrDir#open.
868
-
869
- If a mode is specified using +mode+, the file will still be opened
870
- automatically, but the mode specified in the +mode+ method will be
871
- used regardless of whether it makes sense.
872
-
873
- A Rio can also be opened explicitly using IF::FileOrDir#open. +open+ takes one
874
- parameter, a mode. This also will override all of Rio's automatic
875
- mode selection.
876
-
877
-
878
- ==== CSV mode
879
-
880
- Rio uses the CSV class from the Ruby standard library to provide
881
- support for reading and writing comma-separated-value files. Normally
882
- using <tt>(skip)records</tt> is identical to <tt>(skip)lines</tt> because
883
- while +records+ only selects and does not specify the record-type,
884
- +lines+ is the default.
885
-
886
- rio('afile').records(1..2)
887
-
888
- effectively means
889
-
890
- rio('afile').lines.records(1..2)
891
-
892
- The CSV extension distingishes between items selected using
893
- IF::GrandeStream#records and those selected using IF::GrandeStream#lines. Rio returns records
894
- parsed into Arrays by the CSV library when +records+ is used, and
895
- returns Strings as normal when +lines+ is used. +records+ is the
896
- default.
897
-
898
- rio('f.csv').puts!(["h0,h1","f0,f1"])
899
-
900
- rio('f.csv').csv.records[] #==>[["h0", "h1"], ["f0", "f1"]]
901
- rio('f.csv').csv[] #==> same thing
902
- rio('f.csv').csv.lines[] #==>["h0,h1\n", "f0,f1\n"]
903
- rio('f.csv').csv.records[0] #==>[["h0", "h1"]]
904
- rio('f.csv').csv[0] #==> same thing
905
- rio('f.csv').csv.lines[0] #==>["h0,h1\n"]
906
- rio('f.csv').csv.skiprecords[0] #==>[["f0", "f1"]]
907
- rio('f.csv').csv.skiplines[0] #==>["f0,f1\n"]
908
-
909
- This distinction, of course, applies equally when using the copy
910
- operators and +each+
911
-
912
- rio('f.csv').csv[0] > rio('out').csv # out contains "f0,f1\n"
913
-
914
- rio('f.csv').csv { |array_of_fields| ... }
915
-
916
- Notice that +csv+ mode is called on both the input and output
917
- Rios. The +csv+ on the 'out' Rio causes it to treat an array written
918
- to it as an array of records which is converted into CSV format before
919
- writing. Without the +csv+, the output would be written as if
920
- Array#to_s on [["f0","f1"]] had been called
921
-
922
- rio('f.csv').csv[0] > rio('out') # out contains "f0f1"
923
-
924
- The String representing a record that is returned when using +lines+
925
- is extended with a +to_a+ method which will parse it into an array of
926
- fields. Likewise the Array returned when a record is returned using
927
- +records+ is extended with a modified +to_s+ which treats it as an
928
- array CSV fields, rather than just an array of strings.
929
-
930
- array_of_lines = rio('f.csv').csv.lines[1] #==>["f0,f1\n"]
931
- array_of_records = rio('f.csv').csv.records[1] #==>[["f0", "f1"]]
932
-
933
- array_of_lines[0].to_a #==>["f0", "f1"]
934
- array_of_records[0].to_s #==>"f0,f1"
935
-
936
- IF::CSV#csv takes two optional parameters, which are passed on to the CSV
937
- library. They are the +field_separator+ and the +record_separator+.
938
-
939
- rio('semisep').puts!(["h0;h1","f0;f1"])
940
-
941
- rio('semisep').csv(';').to_a #==>[["h0", "h1"], ["f0", "f1"]]
942
-
943
- These are specified independently on the source and destination when
944
- using the copy operators.
945
-
946
- rio('semisep').csv(';') > rio('colonsep').csv(':')
947
- rio('colonsep').contents #==>"h0:h1\nf0:f1\n"
948
-
949
- Rio provides two methods for selecting fields from CSV records in a
950
- manner similar to that provided for selecting lines -- IF::CSV#columns and
951
- IF::CSV#skipcolumns.
952
-
953
- rio('f.csv').puts!(["h0,h1,h2,h3","f0,f1,f2,f3"])
954
-
955
- rio('f.csv').csv.columns(0).to_a #==>[["h0"], ["f0"]]
956
- rio('f.csv').csv.skipcolumns(0).to_a #==>[["h1", "h2", "h3"], ["f1", "f2", "f3"]]
957
- rio('f.csv').csv.columns(1..2).to_a #==>[["h1", "h2"], ["f1", "f2"]]
958
- rio('f.csv').csv.skipcolumns(1..2).to_a #==>[["h0", "h3"], ["f0", "f3"]]
959
-
960
- IF::CSV#columns can, of course be used with the +each+ and the copy
961
- operators:
962
-
963
- rio('f.csv').csv.columns(0..1) > rio('out').csv
964
- rio('out').contents #==>"h0,h1\nf0,f1\n"
965
-
966
-
967
- ==== YAML mode
968
-
969
- Rio uses the YAML class from the Ruby standard library to provide
970
- support for reading and writing YAML files. Normally
971
- using <tt>(skip)records</tt> is identical to <tt>(skip)lines</tt> because
972
- while +records+ only selects and does not specify the record-type,
973
- +lines+ is the default.
974
-
975
- The YAML extension distingishes between items selected using
976
- IF::GrandeStream#records, IF::GrandeStream#rows and IF::GrandeStream#lines. Rio returns objects
977
- loaded via YAML#load when +records+ is used; returns the YAML text
978
- as a String when +rows+ is used; and
979
- returns lines as Strings as normal when +lines+ is used.
980
- +records+ is the default. In yaml-mode, <tt>(skip)records</tt> can be called
981
- as <tt>(skip)objects</tt> and <tt>(skip)rows</tt> can be called as
982
- <tt>(skip)documents</tt>
983
-
984
- To read a single YAML document, Rio provides #getobj and #load
985
- For example, consider the following partial 'database.yml' from
986
- the rails distribution:
987
-
988
- development:
989
- adapter: mysql
990
- database: rails_development
991
-
992
- test:
993
- adapter: mysql
994
- database: rails_test
995
-
996
-
997
- To get the object represented in the yaml file:
998
-
999
- rio('database.yml').yaml.load
1000
- ==>{"development"=>{"adapter"=>"mysql", "database"=>"rails_development"},
1001
- "test"=>{"adapter"=>"mysql", "database"=>"rails_test"}}
1002
-
1003
- Or one could read parts of the file like so:
1004
-
1005
- rio('database.yml').yaml.getobj['development']['database']
1006
- ==>"rails_development"
1007
-
1008
- Single objects can be written using #putobj and #putobj!
1009
- which is aliased to #dump
1010
-
1011
- anobject = {
1012
- 'production' => {
1013
- 'adapter' => 'mysql',
1014
- 'database' => 'rails_production',
1015
- }
1016
- }
1017
- rio('afile.yaml').yaml.dump(anobject)
1018
-
1019
-
1020
- IF::Grande#> (copy-to) and IF::Grande#>> (append-to) will fill an array with with all selected
1021
- YAML documents in the Rio. For non-arrays, the yaml text is copied. (This may change
1022
- if a useful reasonable alternative can be found)
1023
-
1024
- rio('afile.yaml').yaml > anarray # load all YAML documents from 'afile.yaml'
1025
-
1026
- Single objects can be written using IF::GrandeStream#putrec (aliased to IF::YAML#putobj and IF::YAML#dump)
1027
-
1028
- rio('afile.yaml').yaml.putobj(anobject)
1029
-
1030
- Single objects can be loaded using IF::GrandeStream#getrec (aliase to IF::YAML#getobj and IF::YAML#load)
1031
-
1032
- anobject = rio('afile.yaml').yaml.getobj
1033
-
1034
- A Rio in yaml-mode is just like any other Rio. And all the things you
1035
- can do with any Rio come for free. They can be iterated over using
1036
- IF::Grande#each and read into an array using IF::Grande#[] just like
1037
- any other Rio. All the selection criteria are identical also.
1038
-
1039
- Get the first three objects into an array:
1040
-
1041
- array_of_objects = rio('afile.yaml').yaml[0..2]
1042
-
1043
- Iterate over only YAML documents that are a kind_of ::Hash use:
1044
-
1045
- rio('afile.yaml').yaml(::Hash) {|ahash| ...}
1046
-
1047
- This takes advantage of the fact that the default for matching records is <tt>===</tt>
1048
-
1049
- Selecting records using a Proc can be used as normal:
1050
-
1051
- anarray = rio('afile.yaml').yaml(proc{|anobject| ...}).to_a
1052
-
1053
-
1054
-
1055
- ---
1056
-
1057
-
1058
- See also:
1059
- * RIO::Doc::SYNOPSIS
1060
- * RIO::Doc::HOWTO
1061
- * RIO::Doc::EXAMPLES
1062
- * RIO::Rio
27
+ #
28
+ # = Rio - Ruby I/O Facilitator
29
+ #
30
+ # fa-cil-i-tate: To make easy or easier.
31
+ #
32
+ # Rio is a facade for most of the standard ruby classes that deal with I/O;
33
+ # providing a simple, intuitive, succinct interface to the functionality
34
+ # provided by IO, File, Dir, Pathname, FileUtils, Tempfile, StringIO, OpenURI
35
+ # and others. Rio also provides an application level interface which allows many
36
+ # common I/O idioms to be expressed succinctly.
37
+ #
38
+ #
39
+ # Rio functionality can be broadly broken into three categories
40
+ # * path manipulation
41
+ # * file system access
42
+ # * stream manipulation
43
+ #
44
+ # Which methods are available to a given Rio, depends on the underlying
45
+ # object.
46
+ #
47
+ # A Rio generally does not need to be opened or have its mode specified.
48
+ # Most of Rio's methods simply configure it. When an actual IO
49
+ # operation is specified, Rio determines how to open it based on the
50
+ # object it is opening, the operation it is performing, and the options
51
+ # specified.
52
+ #
53
+ # Rio configuration methods return the Rio for easy chaining and regard
54
+ # the presence of a block as an implied +each+.
55
+ #
56
+ # == Using a Rio
57
+ #
58
+ # Using a Rio can be described as having 3 steps:
59
+ # * Creating a Rio
60
+ # * Configuring a Rio
61
+ # * Rio I/O
62
+ #
63
+ # === Creating a Rio
64
+ #
65
+ # Rio extends Kernel with one function +rio+, its constructor. This
66
+ # function is overloaded to create any type of Rio. +rio+ looks at the
67
+ # class and sometimes the value of its first argument to create an
68
+ # internal representation of the resource specified, additional
69
+ # arguments are used as needed by the resource type. The rio constructor
70
+ # does not initiate any io, it does not check for a resources existance
71
+ # or type. It neither knows nor cares what can be done with this Rio.
72
+ # Using methods like <tt>respond_to?</tt> are meaningless at best and usually
73
+ # misleading.
74
+ #
75
+ # For purposes of discussion, we divide Rios into two catagories, those
76
+ # that have a path and those that don't.
77
+ #
78
+ # ==== Creating a Rio that has a path
79
+ #
80
+ # To create a Rio that has a path the arguments to +rio+ may be:
81
+ #
82
+ # * a string representing the entire path. The separator used for Rios
83
+ # is as specified in RFC1738 ('/').
84
+ #
85
+ # rio('adir/afile')
86
+ #
87
+ # * a string representing a fully qualified +file+ URI as per RFC1738
88
+ #
89
+ # rio('file:///atopleveldir/adir/afile')
90
+ #
91
+ # * a +URI+ object representing a +file+ or generic +URI+
92
+ #
93
+ # rio(URI('adir/afile'))
94
+ #
95
+ # * the components of a path as separate arguments
96
+ #
97
+ # rio('adir','afile')
98
+ #
99
+ # * the components of a path as an array
100
+ #
101
+ # rio(%w/adir afile/)
102
+ #
103
+ # * another Rio
104
+ #
105
+ # another_rio = rio('adir/afile')
106
+ # rio(another_rio)
107
+ #
108
+ # * any object whose +to_s+ method returns one of the above
109
+ #
110
+ # rio(Pathname.new('apath'))
111
+ #
112
+ # * any combination of the above either as separate arguments or as
113
+ # elements of an array,
114
+ #
115
+ # another_rio = rio('dir1/dir2')
116
+ # auri = URI('dir4/dir5)
117
+ # rio(another_rio,'dir3',auri,'dir6/dir7')
118
+ #
119
+ # ===== Creating a Rio that refers to a web page
120
+ #
121
+ # To create a Rio that refers to a web page the arguments to +rio+ may
122
+ # be:
123
+ #
124
+ # * a string representing a fully qualified +http+ URI
125
+ #
126
+ # rio('http://ruby-doc.org/index.html')
127
+ #
128
+ # * a +URI+ object representing a +http+ +URI+
129
+ #
130
+ # rio(URI('http://ruby-doc.org/index.html'))
131
+ #
132
+ # * either of the above with additional path elements
133
+ #
134
+ # rio('http://www.ruby-doc.org/','core','classes/Object.html')
135
+ #
136
+ #
137
+ # ===== Creating a Rio that refers to a file or directory on a FTP server
138
+ #
139
+ # To create a Rio that refers to a file on a FTP server the arguments to
140
+ # +rio+ may be:
141
+ #
142
+ # * a string representing a fully qualified +ftp+ URI
143
+ #
144
+ # rio('ftp://user:password@ftp.example.com/afile.tar.gz')
145
+ #
146
+ # * a +URI+ object representing a +ftp+ +URI+
147
+ #
148
+ # rio(URI('ftp://ftp.example.com/afile.tar.gz'))
149
+ #
150
+ # * either of the above with additional path elements
151
+ #
152
+ # rio('ftp://ftp.gnu.org/pub/gnu','emacs','windows','README')
153
+ #
154
+ # ==== Creating Rios that do not have a path
155
+ #
156
+ # To create a Rio without a path, the first argument to +rio+ is usually
157
+ # a single character.
158
+ #
159
+ # ===== Creating a Rio that refers to a clone of your programs stdin or stdout.
160
+ #
161
+ # <tt>rio(?-)</tt> (mnemonic: '-' is used by some Unix programs to
162
+ # specify stdin or stdout in place of a file)
163
+ #
164
+ # Just as a Rio that refers to a file, does not know whether that file
165
+ # will be opened for reading or writing until an io operation is
166
+ # specified, a <tt>stdio:</tt> Rio does not know whether it will connect
167
+ # to stdin or stdout until an I/O operation is specified.
168
+ #
169
+ # ===== Creating a Rio that refers to a clone of your programs stderr.
170
+ #
171
+ # <tt>rio(?=)</tt> (mnemonic: '-' refers to fileno 1, so '=' refers to
172
+ # fileno 2)
173
+ #
174
+ # ===== Creating a Rio that refers to an arbitrary IO object.
175
+ #
176
+ # an_io = ::File.new('afile')
177
+ # rio(an_io)
178
+ #
179
+ # ===== Creating a Rio that refers to a file descriptor
180
+ #
181
+ # <tt>rio(?#,fd)</tt> (mnemonic: a file descriptor is a number '#' )
182
+ #
183
+ # an_io = ::File.new('afile')
184
+ # rio(an_io)
185
+ #
186
+ # ===== Creating a Rio that refers to a StringIO object
187
+ #
188
+ # <tt>rio(?")</tt> (mnemonic: '"' surrounds strings)
189
+ # * create a Rio that refers to its own string
190
+ # rio(?")
191
+ # * create a Rio that refers to a string of your choosing
192
+ # astring = ""
193
+ # rio(?",astring)
194
+ #
195
+ # ===== Creating a Rio that refers to a Temporary object
196
+ #
197
+ # <tt>rio(??)</tt> (mnemonic: '?' you don't know its name)
198
+ #
199
+ # To create a temporary object that will become a file
200
+ # or a directory, depending on how you use it:
201
+ # rio(??)
202
+ # rio(??,basename='rio',tmpdir=Dir::tmpdir)
203
+ #
204
+ # To force it to become a directory:
205
+ # rio(??).mkdir
206
+ # or
207
+ # rio(??).chdir
208
+ #
209
+ #
210
+ #
211
+ # ===== Creating a Rio that refers to an arbitrary TCPSocket
212
+ #
213
+ # rio('tcp:',hostname,port)
214
+ # or
215
+ # rio('tcp://hostname:port')
216
+ #
217
+ # ===== Creating a Rio that runs an external program and connects to its stdin and stdout
218
+ #
219
+ # <tt>rio(?-,cmd)</tt> (mnemonic: '-' is used by some Unix programs to
220
+ # specify stdin or stdout in place of a file)
221
+ #
222
+ # or
223
+ #
224
+ # <tt>rio(?`,cmd)</tt> (mnemonic: '`' (backtick) runs an external
225
+ # program in ruby)
226
+ #
227
+ # This is Rio's interface to IO#popen
228
+ #
229
+ # === Path Manipulation
230
+ #
231
+ # Rio's path manipulation methods are for the most part simply forwarded
232
+ # to the File or URI classes with the return values converted to a Rio.
233
+ #
234
+ # ==== Creating a Rio from a Rio's component parts.
235
+ #
236
+ # The Rio methods for creating a Rio from a Rio's component parts are
237
+ # {#dirname}[rdoc-ref:IF::Path#dirname], {#filename}[rdoc-ref:IF::Path#filename], {#basename}[rdoc-ref:IF::Path#basename], and {#extname}[rdoc-ref:IF::Path#extname]. The
238
+ # behavior of {#basename}[rdoc-ref:IF::Path#basename] depends on the setting of the +ext+
239
+ # configuration variable and is different from its counterpart in the
240
+ # File class. The default value of the +ext+ configuration variable is
241
+ # the string returned File#extname. The +ext+ configuration variable can
242
+ # be changed using {#ext}[rdoc-ref:IF::Path#ext] and {#noext}[rdoc-ref:IF::Path#noext] and can be queried using
243
+ # {#ext?}[rdoc-ref:IF::Path#ext?]. This value is used by calls to {#basename}[rdoc-ref:IF::Path#basename].
244
+ #
245
+ # {#filename}[rdoc-ref:IF::Path#filename] returns the last component of a path, and is basically
246
+ # the same as +basename+ without consideration of an extension.
247
+ #
248
+ # rio('afile.txt').basename #=> rio('afile')
249
+ # rio('afile.txt').filename #=> rio('afile.txt')
250
+ #
251
+ # ario = rio('afile.tar.gz')
252
+ # ario.basename #=> rio('afile.tar')
253
+ # ario.ext? #=> ".gz"
254
+ # ario.ext('.tar.gz').basename #=> rio('afile')
255
+ # ario.ext? #=> ".tar.gz"
256
+ #
257
+ # ==== Changing a path's component parts.
258
+ #
259
+ # Rio also provides methods for changing the component parts of its
260
+ # path. They are {#dirname=}[rdoc-ref:IF::Path#dirname=], {#filename=}[rdoc-ref:IF::Path#filename=], {#basename=}[rdoc-ref:IF::Path#basename=], and
261
+ # {#extname=}[rdoc-ref:IF::Path#extname=]. These methods replace the part extracted as described
262
+ # above with their argument.
263
+ #
264
+ # ario = rio('dirA/dirB/afile.rb')
265
+ # ario.dirname = 'dirC' # rio('dirC/afile.rb')
266
+ # ario.basename = 'bfile' # rio('dirC/bfile.rb')
267
+ # ario.extname = '.txt' # rio('dirC/bfile.txt')
268
+ # ario.filename = 'cfile.rb' # rio('dirC/cfile.rb')
269
+ #
270
+ # Rio also has a +rename+ mode which causes each of these to rename the
271
+ # actual file system object as well as changing the Rio. This is
272
+ # discussed in the section on Renaming and Moving.
273
+ #
274
+ # ==== Splitting a Rio
275
+ #
276
+ # {#split}[rdoc-ref:IF::Grande#split] (or {#splitpath}[rdoc-ref:IF::Path#splitpath]) returns an array of Rios, one
277
+ # for each path element. (Note that this behavior differs from File#split.)
278
+ #
279
+ # rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
280
+ #
281
+ # The array returned is extended with a +to_rio+ method, which will put
282
+ # the parts back together again.
283
+ #
284
+ # ary = rio('a/b/c').split #=> [rio('a'),rio('b'),rio('c')]
285
+ # ary.to_rio #=> rio('a/b/c')
286
+ #
287
+ # ==== Creating a Rio by specifying the individual parts of its path
288
+ #
289
+ # The first way to create a Rio by specifying its parts is to use the
290
+ # Rio constructor Rio#rio. Since a Rio is among the arguments the
291
+ # constructor will take, the constructor can be used.
292
+ #
293
+ # ario = rio('adir')
294
+ # rio(ario,'b') #=> rio('adir/b')
295
+ #
296
+ # {#join}[rdoc-ref:IF::Path#join] and {#/}[rdoc-ref:IF::Path#/] do the same thing, but the operator version
297
+ # <tt>/</tt> can take only one argument.
298
+ #
299
+ # a = rio('a')
300
+ # b = rio('b')
301
+ # c = a.join(b) #=> rio('a/b')
302
+ # c = a/b #=> rio('a/b')
303
+ #
304
+ # The arguments to {#join}[rdoc-ref:IF::Path#join] and {#/}[rdoc-ref:IF::Path#/] do not need to be Rios, of course
305
+ # ario = rio('adir')
306
+ # ario/'afile.rb' #=> rio('adir/afile.rb')
307
+ # ario.join('b','c','d') #=> rio('adir/b/c/d')
308
+ # ario/'b'/'c'/'d' #=> rio('adir/b/c/d')
309
+ # ario /= 'e' #=> rio('adir/b/c/d/e')
310
+ #
311
+ # ==== Manipulating a Rio path by treating it as a string.
312
+ #
313
+ # The Rio methods which treat a Rio as a string are {#sub}[rdoc-ref:IF::String#sub], {#gsub}[rdoc-ref:IF::String#gsub]
314
+ # and {#+}[rdoc-ref:IF::String#+]. These methods create a new Rio using the string created by
315
+ # forwarding the method to the String returned by Rio#to_s.
316
+ #
317
+ # ario = rio('dirA/dirB/afile') + '-1.1.1' # rio('dirA/dirB/afile-1.1.1')
318
+ # brio = ario.sub(/^dirA/, 'dirC') # rio('dirC/dirB/afile-1.1.1')
319
+ #
320
+ #
321
+ # ==== Creating a Rio based on its relationship to another
322
+ #
323
+ # {#abs}[rdoc-ref:IF::Path#abs] creates a new rio whose path is the absolute path of a Rio.
324
+ # If called with an argument, it uses it as the base path, otherwise
325
+ # it uses an internal base path (usually the current working directory
326
+ # when it was created).
327
+ #
328
+ # rio('/tmp').chdir do
329
+ # rio('a').abs #=> rio('/tmp/a')
330
+ # rio('a').abs('/usr') #=> rio('/usr/a')
331
+ # end
332
+ #
333
+ # {#rel}[rdoc-ref:IF::Path#rel] creates a new rio with a path relative to a Rio.
334
+ #
335
+ # rio('/tmp').chdir do
336
+ # rio('/tmp/a').rel #=> rio('a')
337
+ # end
338
+ # rio('/tmp/b').rel('/tmp') #=> rio('b')
339
+ #
340
+ # {#route}[rdoc-ref:IF::Path#route]_to and {#route}[rdoc-ref:IF::Path#route]_from creates a new rio with a path
341
+ # representing the route to get to/from a Rio. They are based on the
342
+ # methods of the same names in the ::URI class
343
+ #
344
+ # === Configuring a Rio
345
+ #
346
+ # The second step in using a rio is configuring it. Note that many times
347
+ # no configuration is necessary and that this is not a comprehensive
348
+ # list of all of Rio's configuration methods.
349
+ #
350
+ # Rio's configuration mehods fall into three categories.
351
+ #
352
+ # * I/O manipulators
353
+ #
354
+ # An I/O manipulator alters the behavior of a Rio's underlying IO
355
+ # object. These affect the behaviour of I/O methods which are
356
+ # forwarded directly to the underlying object as well as the grande
357
+ # I/O methods.
358
+ #
359
+ # * Grande configuration methods
360
+ #
361
+ # The grande configuration methods affect the behaviour of Rio's
362
+ # grande I/O methods
363
+ #
364
+ # * Grande selection methods
365
+ #
366
+ # The grande selection methods select what data is returned by Rio's
367
+ # grande I/O methods
368
+ #
369
+ # All of Rio's configuration and selection methods can be passed a
370
+ # block, which will cause the Rio to behave as if {#each}[rdoc-ref:IF::Grande#each] had been called
371
+ # with the block after the method.
372
+ #
373
+ # ==== IO manipulators
374
+ #
375
+ # * +gzip+ a file on output, and ungzip it on input
376
+ #
377
+ # rio('afile.gz').gzip
378
+ #
379
+ # This causes the rio to read through a Zlib::GzipReader and to write
380
+ # Zlib::GzipWriter.
381
+ #
382
+ # * +chomp+ lines as they are read
383
+ #
384
+ # rio('afile').chomp
385
+ #
386
+ # This causes a Rio to call String#chomp on the the String returned by
387
+ # all line oriented read operations.
388
+ #
389
+ # ==== Grande configuration methods
390
+ #
391
+ # * +all+, +recurse+, +norecurse+
392
+ #
393
+ # rio('adir').all
394
+ # rio('adir').norecurse('CVS')
395
+ #
396
+ # These methods instruct the Rio to also include entries in
397
+ # subdirectories when iterating through directories and control which
398
+ # subdirectories are included or excluded.
399
+ #
400
+ # * +bytes+
401
+ #
402
+ # rio('afile').bytes(1024)
403
+ #
404
+ # This causes a Rio to read the specified number of bytes at a time as
405
+ # a file is iterated through.
406
+ #
407
+ # ==== Grande selection methods
408
+ #
409
+ # * +lines+, +skiplines+
410
+ #
411
+ # rio('afile').lines(0..9)
412
+ # rio('afile').skiplines(/^\s*#/)
413
+ #
414
+ # Strictly speaking these are both configuration and selection
415
+ # methods. They configure the Rio to iterate through an input stream
416
+ # as lines. The arguments select which lines are actually returned.
417
+ # Lines are included (+lines+) or excluded (+skiplines+) if they match
418
+ # *any* of the arguments as follows.
419
+ #
420
+ # If the argument is a:
421
+ # +RegExp+:: the line is matched against it
422
+ # +Range+:: the lineno is matched against it
423
+ # +Integer+:: the lineno is matched against it as if it were a one element range
424
+ # +Symbol+:: the symbol is +sent+ to the string; the line is included unless it returns false
425
+ # +Proc+:: the proc is called with the line as an argument; the line is included unless it returns false
426
+ # +Array+:: an array containing any of the above, all of which must match for the line to be included
427
+ #
428
+ # * +entries+, +files+, +dirs+, +skipentries+, +skipfiles+, +skipdirs+
429
+ #
430
+ # rio('adir').files('*.txt')
431
+ # rio('adir').skipfiles(/^\./)
432
+ #
433
+ # These methods select which entries will be returned when iterating
434
+ # through directories. Entries are included (+entries+,+files+,+dirs+)
435
+ # or excluded(+skipentries+,+skipfiles+,+skipdirs+) if they match *any* of
436
+ # the arguments as follows.
437
+ #
438
+ # If the argument is a:
439
+ # +String+:: the arg is treated as a glob; the filname is matched against it
440
+ # +RegExp+:: the filname is matched against it
441
+ # +Symbol+:: the symbol is +sent+ to the entry (a Rio); the entry is included unless it returns false
442
+ # +Proc+:: the proc is called with the entry (a Rio) as an argument; the entry is included unless it returns false
443
+ # +Array+:: an array containing any of the above, all of which must match for the line to be included
444
+ #
445
+ # * +records+, +rows+, +skiprecords+, +skiprows+
446
+ #
447
+ # rio('afile').bytes(1024).records(0...10)
448
+ #
449
+ # These select items from an input stream just as +lines+, but without
450
+ # specifying lines as the input record type. They can be used to
451
+ # select different record types in extension modules. The only such
452
+ # module at this writing is the CSV extension. In that case +records+
453
+ # causes each line of a CSV file to be parsed into an array while
454
+ # +lines+ causes each line of the file to be returned normally.
455
+ #
456
+ # === Rio I/O
457
+ #
458
+ # As stated above the the three steps to using a Rio are:
459
+ # * Creating a Rio
460
+ # * Configuring a Rio
461
+ # * Doing I/O
462
+ #
463
+ # This section describes that final step.
464
+ #
465
+ # After creating and configuring a Rio, the file-system has not been
466
+ # accessed, no socket has been opened, not so much as a test for a files
467
+ # existance has been done. When an I/O method is called on a Rio, the
468
+ # sequence of events required to complete that operation on the
469
+ # underlying object takes place. Rio takes care of creating the
470
+ # appropriate object (eg IO,Dir), opening the object with the appropriate
471
+ # mode, performing the operation, closing the object if required, and
472
+ # returning the results of the operation.
473
+ #
474
+ # Rio's I/O operations can be divide into two catagories:
475
+ # * Proxy operations
476
+ # * Grande operations
477
+ #
478
+ # ==== Proxy operations
479
+ #
480
+ # These are calls which are forwarded to the underlying object (eg
481
+ # IO,Dir,Net::FTP), after appropriately creating and configuring that
482
+ # object. The result produced by the method is returned, and the object
483
+ # is closed.
484
+ #
485
+ # In some cases the result is modified before being returned, as when a
486
+ # Rio is configured with {#chomp}[rdoc-ref:IF::GrandeStream#chomp].
487
+ #
488
+ # In all cases, if the result returned by the underlying object, could
489
+ # itself be used for further I/O operations it is returned as a Rio. For
490
+ # example: where File#dirname returns a string, {#dirname}[rdoc-ref:IF::Path#dirname] returns a
491
+ # Rio; where Dir#read returns a string representing a directory entry,
492
+ # {#read}[rdoc-ref:IF::FileOrDir#read] returns a Rio.
493
+ #
494
+ # With some noteable exceptions, most of the operations available if one
495
+ # were using the underlying Ruby I/O class are available to the Rio and
496
+ # will behave identically.
497
+ #
498
+ # For things that exist on a file system:
499
+ #
500
+ # * All the methods in FileTest are available as Rio instance
501
+ # methods. For example
502
+ #
503
+ # FileTest.file?('afile')
504
+ #
505
+ # becomes
506
+ #
507
+ # rio('afile').file?
508
+ #
509
+ # * All the instance methods of +File+ except +path+ are available to a
510
+ # rio without change
511
+ #
512
+ # * Most of the class methods of +File+ are available.
513
+ #
514
+ # * For those that take a filename as their only argument the calls
515
+ # are mapped to Rio instance methods as described above for
516
+ # FileTest.
517
+ #
518
+ # * +dirname+, and +readlink+ return Rios instead of strings
519
+ #
520
+ # * Rio has its own {#basename}[rdoc-ref:IF::Path#basename], {#join}[rdoc-ref:IF::Path#join] and {#symlink}[rdoc-ref:IF::FileOrDir#symlink], which
521
+ # provide similar functionality.
522
+ #
523
+ # * The class methods which take multiple filenames
524
+ # (+chmod+,+chown+,+lchmod+,+lchown+) are available as Rio instance
525
+ # methods. For example
526
+ #
527
+ # File.chmod(0666,'afile')
528
+ # becomes
529
+ # rio('afile').chmod(06660)
530
+ #
531
+ # For I/O Streams
532
+ #
533
+ # Most of the instance methods of IO are available, and most do the same
534
+ # thing, with some interface changes. <b>The big exception to this is
535
+ # the '<<' operator.</b> This is one of Rio's grande operators. While
536
+ # the symantics one would use to write to an IO object would actually
537
+ # accomplish the same thing with a Rio, It is a very different
538
+ # operator. Read the section on grande operators. The other differences
539
+ # between IO instance methods and the Rio equivelence can be summarized
540
+ # as follows.
541
+ #
542
+ # * The simple instance methods (eg +fcntl+, <tt>eof?</tt>,
543
+ # <tt>tty?</tt> etc.) are forwarded and the result returned as is
544
+ #
545
+ # * Anywhere IO returns an IO, Rio returns a Rio
546
+ #
547
+ # * +close+ and its cousins return the Rio.
548
+ #
549
+ # * +each_byte+ and +each_line+ are forwarded as is.
550
+ #
551
+ # * All methods which read (read*,get*,each*) will cause the file to
552
+ # closed when the end of file is reached. This behavior is
553
+ # configurable, but the default is to close on eof
554
+ #
555
+ # * The methods which write (put*,print*) are forwarded as is; put* and
556
+ # print* return the Rio; write returns the value returned by IO#write;
557
+ # as mentioned above '<<' is a grande operator in Rio.
558
+ #
559
+ # For directories:
560
+ #
561
+ # * all the instance methods of Dir are available except +each+ which is
562
+ # a grande method.
563
+ #
564
+ # * the class methods +mkdir+, +delete+, +rmdir+ are provided as
565
+ # instance methods.
566
+ #
567
+ # * +chdir+ is provided as an instance method. {#chdir}[rdoc-ref:IF::Dir#chdir] returns a Rio
568
+ # and passes a Rio to a block if one is provided.
569
+ #
570
+ # * +glob+ is provided as an instance method, but returns an array of
571
+ # Rios
572
+ #
573
+ # * +foreach+ is not supported
574
+ #
575
+ # * +each+ and <tt>[]</tt> have similar functionality provided by Rio
576
+ #
577
+ #
578
+ # For other Rios, instance methods are generally forwarded where
579
+ # appropriate. For example
580
+ #
581
+ # * Rios that refer to StringIO objects forward 'string' and 'string='
582
+ #
583
+ # * Rios that refer to http URIs support all the Meta methods provided
584
+ # by open-uri
585
+ #
586
+ #
587
+ # ==== Grande operators
588
+ #
589
+ # The primary grande operator is {#each}[rdoc-ref:IF::Grande#each]. +each+ is used to iterate
590
+ # through Rios. When applied to a file it iterates through records in
591
+ # the file. When applied to a directory it iterates through the entries
592
+ # in the directory. Its behavior is modified by configuring the Rio
593
+ # prior to calling it using the configuration methods discussed
594
+ # above. Since iterating through things is ubiquitous in ruby, it is
595
+ # implied by the presence of a block after any of the grande
596
+ # configuration methods and many times does not need to be call
597
+ # explicitly. For example:
598
+ #
599
+ # # iterate through chomped ruby comment lines
600
+ # rio('afile.rb').chomp.lines(/^\s*#/) { |line| ... }
601
+ #
602
+ # # iterate through all .rb files in 'adir' and its subdirectories
603
+ # rio('adir').all.files('*.rb') { |f| ... }
604
+ #
605
+ # Because a Rio is an Enumerable, it supports +to_a+, which is the basis
606
+ # for the grande subscript operator. {#[]}[rdoc-ref:IF::Grande#[]] with no arguments simply
607
+ # calls to_a. With arguments it behaves as if those arguments had been
608
+ # passed to the most recently called of the grande selection methods
609
+ # listed above, and then calls to_a. For example to get the first ten
610
+ # lines of a file into an array with lines chomped
611
+ #
612
+ # rio('afile').chomp.lines(0...10).to_a
613
+ #
614
+ # can be written as
615
+ #
616
+ # rio('afile.gz').chomp.lines[0...10]
617
+ #
618
+ # or, to create an array of all the .c files in a directory, one could
619
+ # write
620
+ #
621
+ # rio('adir').files['*.c']
622
+ #
623
+ # The other grande operators are its copy operators. They are:
624
+ #
625
+ # * <tt><</tt> (copy-from)
626
+ #
627
+ # * <tt><<</tt> (append-from)
628
+ #
629
+ # * <tt>></tt> (copy-to)
630
+ #
631
+ # * <tt>>></tt> (append-to)
632
+ #
633
+ # The only difference between the 'copy' and 'append' versions is how
634
+ # they deal with an unopened resource. In the former the open it with
635
+ # mode 'w' and in the latter, mode 'a'. Beyond that, their behavior can
636
+ # be summarized as:
637
+ #
638
+ # source.each do |entry|
639
+ # destination << entry
640
+ # end
641
+ #
642
+ # Since they are based on the +each+ operator, all of the selection and
643
+ # configuration options are available. And the right-hand-side argument
644
+ # of the operators are not restricted to Rios -- Strings and Arrays are
645
+ # also supported.
646
+ #
647
+ # For example:
648
+ #
649
+ # rio('afile') > astring # copy a file into a string
650
+ #
651
+ # rio('afile').chomp > anarray # copy the chomped lines of afile into an array
652
+ #
653
+ # rio('afile.gz').gzip.lines(0...100) > rio('bfile') # copy 100 lines from a gzipped file into another file
654
+ #
655
+ # rio(?-) < rio('http://rubydoc.org/') # copy a web page to stdout
656
+ #
657
+ # rio('bdir') < rio('adir') # copy an entire directory structure
658
+ #
659
+ # rio('adir').dirs.files('README') > rio('bdir') # same thing, but only README files
660
+ #
661
+ # rio(?-,'ps -a').skiplines(0,/ps$/) > anarray # copy the output of th ps command into an array, skippying
662
+ # # the header line and the ps command entry
663
+ #
664
+ # === Renaming and Moving
665
+ #
666
+ # Rio provides two methods for directly renaming objects on the
667
+ # filesystem: {#rename}[rdoc-ref:IF::FileOrDir#rename] and {#rename!}[rdoc-ref:IF::FileOrDir#rename!].
668
+ # Both of these use File#rename.
669
+ # The difference between them is the returned Rio.
670
+ # {#rename}[rdoc-ref:IF::FileOrDir#rename] leaves the path of the Rio unchanged,
671
+ # while {#rename!}[rdoc-ref:IF::FileOrDir#rename!] changes the path of the Rio to refer
672
+ # to the renamed path.
673
+ #
674
+ # ario = rio('a')
675
+ # ario.rename('b') # file 'a' has been renamed to 'b' but 'ario' => rio('a')
676
+ # ario.rename!('b') # file 'a' has been renamed to 'b' and 'ario' => rio('b')
677
+ #
678
+ # Rio also has a +rename+ mode, which causes the path manipulation
679
+ # methods {#dirname=}[rdoc-ref:IF::Path#dirname=], {#filename=}[rdoc-ref:IF::Path#filename=], {#basename=}[rdoc-ref:IF::Path#basename=] and
680
+ # {#extname=}[rdoc-ref:IF::Path#extname=] to rename an object on the filesystem when they are
681
+ # used to change a Rio's path. A Rio is put in +rename+ mode by calling
682
+ # {#rename}[rdoc-ref:IF::FileOrDir#rename] with no arguments.
683
+ #
684
+ # rio('adir/afile.txt').rename.filename = 'bfile.rb' # adir/afile.txt => adir/bfile.rb
685
+ # rio('adir/afile.txt').rename.basename = 'bfile' # adir/afile.txt => adir/bfile.txt
686
+ # rio('adir/afile.txt').rename.extname = '.rb' # adir/afile.txt => adir/afile.rb
687
+ # rio('adir/afile.txt').rename.dirname = 'b/c' # adir/afile.txt => b/c/afile.txt
688
+ #
689
+ # When +rename+ mode is set for a directory Rio, it is automatically set
690
+ # in the Rios created when iterating through that directory.
691
+ #
692
+ # rio('adir').rename.files('*.htm') do |frio|
693
+ # frio.extname = '.html' #=> changes the rio and renames the file
694
+ # end
695
+ #
696
+ # === Deleting
697
+ #
698
+ # The Rio methods for deleting filesystem objects are {#rm}[rdoc-ref:IF::File#rm], {#rmdir}[rdoc-ref:IF::Dir#rmdir],
699
+ # {#rmtree}[rdoc-ref:IF::Dir#rmtree], {#delete}[rdoc-ref:IF::Grande#delete], and {#delete!}[rdoc-ref:IF::Grande#delete!]. +rm+, +rmdir+ and +rmtree+
700
+ # are passed the like named methods in the FileUtils module. {#delete}[rdoc-ref:IF::Grande#delete]
701
+ # calls +rmdir+ for directories and +rm+ for anything else, while
702
+ # {#delete!}[rdoc-ref:IF::Grande#delete!] calls {#rmtree}[rdoc-ref:IF::Dir#rmtree] for directories.
703
+ #
704
+ # * To delete something only if it is not a directory use {#rm}[rdoc-ref:IF::File#rm]
705
+ # * To delete an empty directory use {#rmdir}[rdoc-ref:IF::Dir#rmdir]
706
+ # * To delete an entire directory tree use {#rmtree}[rdoc-ref:IF::Dir#rmtree]
707
+ # * To delete anything except a populated directory use {#delete}[rdoc-ref:IF::Grande#delete]
708
+ # * To delete anything use {#delete!}[rdoc-ref:IF::Grande#delete!]
709
+ #
710
+ # It is not an error to call any of the deleting methods on something
711
+ # that does not exist. Rio provides {#exist?}[rdoc-ref:IF::Test#exist?] and {#symlink?}[rdoc-ref:IF::Test#symlink?] to check
712
+ # if something exists (<tt>exist?</tt> returns false for symlinks to
713
+ # non-existant object even though the symlink itself exists). The
714
+ # deleting methods' purpose is to make things not exist, so calling one
715
+ # of them on something that already does not exist is considered a
716
+ # success.
717
+ #
718
+ # To create a clean copy of a directory whether or not anything with
719
+ # that name exists one might do this
720
+ #
721
+ # rio('adir').delete!.mkpath.chdir do
722
+ # # do something in adir
723
+ # end
724
+ #
725
+ # ---
726
+ #
727
+ # == Miscellany
728
+ #
729
+ #
730
+ # ==== Using Symbolic Links
731
+ #
732
+ # To create a symbolic link (symlink) to the file-system entry refered
733
+ # to by a Rio, use {#symlink}[rdoc-ref:IF::FileOrDir#symlink]. {#symlink}[rdoc-ref:IF::FileOrDir#symlink] differs from File#symlink
734
+ # in that it calculates the path from the symlink location to the Rio's
735
+ # position.
736
+ #
737
+ # File#symlink('adir/afile','adir/alink')
738
+ #
739
+ # creates a symlink in the directory 'adir' named 'alink' which
740
+ # references 'adir/afile'. From the perspective of 'alink', 'adir/afile'
741
+ # does not exist. While:
742
+ #
743
+ # rio('adir/afile').symlink('adir/alink')
744
+ #
745
+ # creates a symlink in the directory 'adir' named 'alink' which
746
+ # references 'afile'. This is the route to 'adir/afile' from the
747
+ # perspective of 'adir/alink'.
748
+ #
749
+ # Note that the return value from +symlink+ is the calling Rio and not a
750
+ # Rio refering to the symlink. This is done for consistency with the
751
+ # rest of Rio.
752
+ #
753
+ # {#symlink?}[rdoc-ref:IF::Test#symlink?] can be used to test if a file-system object is a
754
+ # symlink. A Rio is extended with {#readlink}[rdoc-ref:IF::FileOrDir#readlink], and
755
+ # {#lstat}[rdoc-ref:IF::Test#lstat] only if {#symlink?}[rdoc-ref:IF::Test#symlink?] returns true. So for
756
+ # non-symlinks, these will raise a NoMethodError. These are both passed
757
+ # to their counterparts in File. {#readlink}[rdoc-ref:IF::FileOrDir#readlink] returns a Rio
758
+ # refering to the result of File#readlink.
759
+ #
760
+ #
761
+ # ==== Using A Rio as an IO (or File or Dir)
762
+ #
763
+ # Rio supports so much of IO's interface that one might be tempted to
764
+ # pass it to a method that expects an IO. While Rio is not and is not
765
+ # intended to be a stand in for IO, this can work. It requires
766
+ # knowledge of every IO method that will be called, under any
767
+ # circumstances.
768
+ #
769
+ # Even in cases where Rio supports the required IO interface, A Rio
770
+ # feature that seems to cause the most incompatibility, is its automatic
771
+ # closing of files. To turn off all of Rio's automatic closing use
772
+ # {#noautoclose}[rdoc-ref:IF::GrandeStream#noautoclose].
773
+ #
774
+ # For example:
775
+ # require 'yaml'
776
+ # yrio = rio('ran.yaml').delete!.noautoclose
777
+ # YAML.dump( ['badger', 'elephant', 'tiger'], yrio )
778
+ # obj = YAML::load( yrio ) #=> ["badger", "tiger", "elephant"]
779
+ #
780
+ #
781
+ # ==== Automatically Closing Files
782
+ #
783
+ # Rio closes files automatically in three instances.
784
+ #
785
+ # When reading from an IO it is closed when the end of file is
786
+ # reached. While this is a reasonable thing to do in many cases,
787
+ # sometimes this is not desired. To turn Rio's automatic closing on end
788
+ # of file use {#nocloseoneof}[rdoc-ref:IF::GrandeStream#nocloseoneof] (it can be turned back on via
789
+ # {#closeoneof}[rdoc-ref:IF::GrandeStream#closeoneof])
790
+ #
791
+ # ario = rio('afile').nocloseoneof
792
+ # lines = ario[]
793
+ # ario.closed? #=> false
794
+ #
795
+ # Closing on end-of-file is necessary for many of Rio's one-liners, but
796
+ # has an implication that may be surprising at first. A Rio starts life
797
+ # as a path, not much more than a string. When one of its read methods
798
+ # is called it becomes an input stream. When the stream is closed, it
799
+ # becomes a path again. This means that when reading from a Rio, the
800
+ # end-of-file condition is seen only once before it becomes a path
801
+ # again, and will be reopened if another read operation is attempted.
802
+ #
803
+ # Another time a Rio will be closed atomatically is when writing to it
804
+ # with one of the copy operators (<tt><, <<, >, >></tt>). This behavior
805
+ # can be turned off with {#nocloseoncopy}[rdoc-ref:IF::GrandeStream#nocloseoncopy].
806
+ #
807
+ # To turn off both of thes types of automatic closing use
808
+ # {#noautoclose}[rdoc-ref:IF::GrandeStream#noautoclose].
809
+ #
810
+ # The third instance when Rio will close a file automatically is when a
811
+ # file opened for one type of access receives a method which that access
812
+ # mode does not support. So, the code
813
+ # rio('afile').puts("Hello World").gets
814
+ # will open the file for write access when the +puts+
815
+ # method is received. When +gets+ is called the file is closed and
816
+ # reopened with read access.
817
+ #
818
+ # ==== Explicitly Closing Files
819
+ #
820
+ # Rio can not determine when the client is finished writing to it, as it
821
+ # does using +eof+ on read. It is the author's understanding that Ruby
822
+ # does not support a mechanism to have code run when there are no more
823
+ # references to it -- that finalizers are not necessarily run immediatly
824
+ # upon an object's reference count reaching 0. If this understanding is
825
+ # incorrect, some of Rio's extranious ways of closing a file may be
826
+ # rethought.
827
+ #
828
+ # That being said, Rio support several ways to explicitly close a
829
+ # file. {#close}[rdoc-ref:IF::RubyIO#close] will close any open Rio.
830
+ # The output methods
831
+ # {#puts!}[rdoc-ref:IF::RubyIO#puts!], {#putc!}[rdoc-ref:IF::RubyIO#putc!], {#printf!}[rdoc-ref:IF::RubyIO#printf!], {#print!}[rdoc-ref:IF::RubyIO#print!], and {#write!}[rdoc-ref:IF::RubyIO#write!]
832
+ # behave as if their
833
+ # counterparts without the exclamation point had been called and then
834
+ # call {#close}[rdoc-ref:IF::RubyIO#close] or {#close}[rdoc-ref:IF::RubyIO#close]_write if the underlying IO object is
835
+ # opened for duplex access.
836
+ #
837
+ #
838
+ # ==== Open mode selection
839
+ #
840
+ # A Rio is typically not explicitly opened. It opens a file
841
+ # automatically when an input or output methed is called. For output
842
+ # methods Rio opens a file with mode 'w', and otherwise opens a file
843
+ # with mode 'r'. This behavior can be modified using the tersely named
844
+ # methods {#a}[rdoc-ref:IF::GrandeStream#a], {#a!}[rdoc-ref:IF::GrandeStream#a!], {#r}[rdoc-ref:IF::GrandeStream#r], {#r!}[rdoc-ref:IF::GrandeStream#r!], {#w}[rdoc-ref:IF::GrandeStream#w], and {#w!}[rdoc-ref:IF::GrandeStream#w!], which cause
845
+ # the Rio to use modes 'a','a+','r','r+','w',and 'w+' respectively.
846
+ #
847
+ # One way to append a string to a file and close it in one line is
848
+ #
849
+ # rio('afile').a.puts!("Hello World")
850
+ #
851
+ # Run a cmd that must be opened for read and write
852
+ #
853
+ # ans = rio(?-,'cat').w!.puts!("Hello Kitty").readline
854
+ #
855
+ # The automatic selection of mode can be bypassed entirely using
856
+ # {#mode}[rdoc-ref:IF::RubyIO#mode] and {#open}[rdoc-ref:IF::FileOrDir#open].
857
+ #
858
+ # If a mode is specified using +mode+, the file will still be opened
859
+ # automatically, but the mode specified in the +mode+ method will be
860
+ # used regardless of whether it makes sense.
861
+ #
862
+ # A Rio can also be opened explicitly using {#open}[rdoc-ref:IF::FileOrDir#open]. +open+ takes one
863
+ # parameter, a mode. This also will override all of Rio's automatic
864
+ # mode selection.
865
+ #
866
+ #
867
+ # ==== CSV mode
868
+ #
869
+ # Rio uses the CSV class from the Ruby standard library to provide
870
+ # support for reading and writing comma-separated-value files. Normally
871
+ # using <tt>(skip)records</tt> is identical to <tt>(skip)lines</tt> because
872
+ # while +records+ only selects and does not specify the record-type,
873
+ # +lines+ is the default.
874
+ #
875
+ # rio('afile').records(1..2)
876
+ #
877
+ # effectively means
878
+ #
879
+ # rio('afile').lines.records(1..2)
880
+ #
881
+ # The CSV extension distingishes between items selected using
882
+ # {#records}[rdoc-ref:IF::GrandeStream#records] and those selected using {#lines}[rdoc-ref:IF::GrandeStream#lines]. Rio returns records
883
+ # parsed into Arrays by the CSV library when +records+ is used, and
884
+ # returns Strings as normal when +lines+ is used. +records+ is the
885
+ # default.
886
+ #
887
+ # rio('f.csv').puts!(["h0,h1","f0,f1"])
888
+ #
889
+ # rio('f.csv').csv.records[] #==>[["h0", "h1"], ["f0", "f1"]]
890
+ # rio('f.csv').csv[] #==> same thing
891
+ # rio('f.csv').csv.lines[] #==>["h0,h1\n", "f0,f1\n"]
892
+ # rio('f.csv').csv.records[0] #==>[["h0", "h1"]]
893
+ # rio('f.csv').csv[0] #==> same thing
894
+ # rio('f.csv').csv.lines[0] #==>["h0,h1\n"]
895
+ # rio('f.csv').csv.skiprecords[0] #==>[["f0", "f1"]]
896
+ # rio('f.csv').csv.skiplines[0] #==>["f0,f1\n"]
897
+ #
898
+ # This distinction, of course, applies equally when using the copy
899
+ # operators and +each+
900
+ #
901
+ # rio('f.csv').csv[0] > rio('out').csv # out contains "f0,f1\n"
902
+ #
903
+ # rio('f.csv').csv { |array_of_fields| ... }
904
+ #
905
+ # Notice that +csv+ mode is called on both the input and output
906
+ # Rios. The +csv+ on the 'out' Rio causes it to treat an array written
907
+ # to it as an array of records which is converted into CSV format before
908
+ # writing. Without the +csv+, the output would be written as if
909
+ # Array#to_s on [["f0","f1"]] had been called
910
+ #
911
+ # rio('f.csv').csv[0] > rio('out') # out contains "f0f1"
912
+ #
913
+ # The String representing a record that is returned when using +lines+
914
+ # is extended with a +to_a+ method which will parse it into an array of
915
+ # fields. Likewise the Array returned when a record is returned using
916
+ # +records+ is extended with a modified +to_s+ which treats it as an
917
+ # array CSV fields, rather than just an array of strings.
918
+ #
919
+ # array_of_lines = rio('f.csv').csv.lines[1] #==>["f0,f1\n"]
920
+ # array_of_records = rio('f.csv').csv.records[1] #==>[["f0", "f1"]]
921
+ #
922
+ # array_of_lines[0].to_a #==>["f0", "f1"]
923
+ # array_of_records[0].to_s #==>"f0,f1"
924
+ #
925
+ # {#csv}[rdoc-ref:IF::CSV#csv] takes two optional parameters, which are passed on to the CSV
926
+ # library. They are the +field_separator+ and the +record_separator+.
927
+ #
928
+ # rio('semisep').puts!(["h0;h1","f0;f1"])
929
+ #
930
+ # rio('semisep').csv(';').to_a #==>[["h0", "h1"], ["f0", "f1"]]
931
+ #
932
+ # These are specified independently on the source and destination when
933
+ # using the copy operators.
934
+ #
935
+ # rio('semisep').csv(';') > rio('colonsep').csv(':')
936
+ # rio('colonsep').contents #==>"h0:h1\nf0:f1\n"
937
+ #
938
+ # Rio provides two methods for selecting fields from CSV records in a
939
+ # manner similar to that provided for selecting lines -- {#columns}[rdoc-ref:IF::CSV#columns] and
940
+ # {#skipcolumns}[rdoc-ref:IF::CSV#skipcolumns].
941
+ #
942
+ # rio('f.csv').puts!(["h0,h1,h2,h3","f0,f1,f2,f3"])
943
+ #
944
+ # rio('f.csv').csv.columns(0).to_a #==>[["h0"], ["f0"]]
945
+ # rio('f.csv').csv.skipcolumns(0).to_a #==>[["h1", "h2", "h3"], ["f1", "f2", "f3"]]
946
+ # rio('f.csv').csv.columns(1..2).to_a #==>[["h1", "h2"], ["f1", "f2"]]
947
+ # rio('f.csv').csv.skipcolumns(1..2).to_a #==>[["h0", "h3"], ["f0", "f3"]]
948
+ #
949
+ # {#columns}[rdoc-ref:IF::CSV#columns] can, of course be used with the +each+ and the copy
950
+ # operators:
951
+ #
952
+ # rio('f.csv').csv.columns(0..1) > rio('out').csv
953
+ # rio('out').contents #==>"h0,h1\nf0,f1\n"
954
+ #
955
+ #
956
+ # ==== YAML mode
957
+ #
958
+ # Rio uses the YAML class from the Ruby standard library to provide
959
+ # support for reading and writing YAML files. Normally
960
+ # using <tt>(skip)records</tt> is identical to <tt>(skip)lines</tt> because
961
+ # while +records+ only selects and does not specify the record-type,
962
+ # +lines+ is the default.
963
+ #
964
+ # The YAML extension distingishes between items selected using
965
+ # {#records}[rdoc-ref:IF::GrandeStream#records], {#rows}[rdoc-ref:IF::GrandeStream#rows] and {#lines}[rdoc-ref:IF::GrandeStream#lines]. Rio returns objects
966
+ # loaded via YAML#load when +records+ is used; returns the YAML text
967
+ # as a String when +rows+ is used; and
968
+ # returns lines as Strings as normal when +lines+ is used.
969
+ # +records+ is the default. In yaml-mode, <tt>(skip)records</tt> can be called
970
+ # as <tt>(skip)objects</tt> and <tt>(skip)rows</tt> can be called as
971
+ # <tt>(skip)documents</tt>
972
+ #
973
+ # To read a single YAML document, Rio provides #getobj and #load
974
+ # For example, consider the following partial 'database.yml' from
975
+ # the rails distribution:
976
+ #
977
+ # development:
978
+ # adapter: mysql
979
+ # database: rails_development
980
+ #
981
+ # test:
982
+ # adapter: mysql
983
+ # database: rails_test
984
+ #
985
+ #
986
+ # To get the object represented in the yaml file:
987
+ #
988
+ # rio('database.yml').yaml.load
989
+ # ==>{"development"=>{"adapter"=>"mysql", "database"=>"rails_development"},
990
+ # "test"=>{"adapter"=>"mysql", "database"=>"rails_test"}}
991
+ #
992
+ # Or one could read parts of the file like so:
993
+ #
994
+ # rio('database.yml').yaml.getobj['development']['database']
995
+ # ==>"rails_development"
996
+ #
997
+ # Single objects can be written using #putobj and #putobj!
998
+ # which is aliased to #dump
999
+ #
1000
+ # anobject = {
1001
+ # 'production' => {
1002
+ # 'adapter' => 'mysql',
1003
+ # 'database' => 'rails_production',
1004
+ # }
1005
+ # }
1006
+ # rio('afile.yaml').yaml.dump(anobject)
1007
+ #
1008
+ #
1009
+ # {#>}[rdoc-ref:IF::Grande#>] (copy-to) and {#>>}[rdoc-ref:IF::Grande#>>] (append-to) will fill an array with with all selected
1010
+ # YAML documents in the Rio. For non-arrays, the yaml text is copied. (This may change
1011
+ # if a useful reasonable alternative can be found)
1012
+ #
1013
+ # rio('afile.yaml').yaml > anarray # load all YAML documents from 'afile.yaml'
1014
+ #
1015
+ # Single objects can be written using {#putrec}[rdoc-ref:IF::GrandeStream#putrec] (aliased to {#putobj}[rdoc-ref:IF::YAML#putobj] and {#dump}[rdoc-ref:IF::YAML#dump])
1016
+ #
1017
+ # rio('afile.yaml').yaml.putobj(anobject)
1018
+ #
1019
+ # Single objects can be loaded using {#getrec}[rdoc-ref:IF::GrandeStream#getrec] (aliase to {#getobj}[rdoc-ref:IF::YAML#getobj] and {#load}[rdoc-ref:IF::YAML#load])
1020
+ #
1021
+ # anobject = rio('afile.yaml').yaml.getobj
1022
+ #
1023
+ # A Rio in yaml-mode is just like any other Rio. And all the things you
1024
+ # can do with any Rio come for free. They can be iterated over using
1025
+ # {#each}[rdoc-ref:IF::Grande#each] and read into an array using {#[]}[rdoc-ref:IF::Grande#[]] just like
1026
+ # any other Rio. All the selection criteria are identical also.
1027
+ #
1028
+ # Get the first three objects into an array:
1029
+ #
1030
+ # array_of_objects = rio('afile.yaml').yaml[0..2]
1031
+ #
1032
+ # Iterate over only YAML documents that are a kind_of ::Hash use:
1033
+ #
1034
+ # rio('afile.yaml').yaml(::Hash) {|ahash| ...}
1035
+ #
1036
+ # This takes advantage of the fact that the default for matching records is <tt>===</tt>
1037
+ #
1038
+ # Selecting records using a Proc can be used as normal:
1039
+ #
1040
+ # anarray = rio('afile.yaml').yaml(proc{|anobject| ...}).to_a
1041
+ #
1042
+ #
1043
+ #
1044
+ # ---
1045
+ #
1046
+ #
1047
+ # See also:
1048
+ # * RIO::Doc::SYNOPSIS
1049
+ # * RIO::Doc::HOWTO
1050
+ # * RIO::Doc::EXAMPLES
1051
+ # * RIO::Rio
1052
+ #
1063
1053
 
1064
- =end
1065
1054
  module INTRO
1066
1055
  end
1067
1056
  end