rio 0.4.2 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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