wishdev-rio 0.4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +341 -0
- data/README +81 -0
- data/Rakefile +281 -0
- data/build_doc.rb +94 -0
- data/doc/ANNOUNCE +159 -0
- data/doc/RELEASE_NOTES +308 -0
- data/doc/RIOIS +215 -0
- data/doc/generators/template/html/rio.css +428 -0
- data/doc/generators/template/html/rio.rb +523 -0
- data/doc/generators/template/html/ugly.rb +132 -0
- data/doc/pkg_def.rb +60 -0
- data/doc/rfc1738.txt +1403 -0
- data/doc/rfc959.txt +3933 -0
- data/ex/catcsv.rb +64 -0
- data/ex/colx.rb +8 -0
- data/ex/findinruby +15 -0
- data/ex/findruby +14 -0
- data/ex/passwd_report.rb +8 -0
- data/ex/prompt.rb +25 -0
- data/ex/rgb.txt.gz +0 -0
- data/ex/riocat +42 -0
- data/ex/riogunzip +31 -0
- data/ex/riogzip +24 -0
- data/ex/rioprompt.rb +10 -0
- data/ex/targz2zip +17 -0
- data/ex/tonl +10 -0
- data/lib/rio/abstract_method.rb +56 -0
- data/lib/rio/argv.rb +56 -0
- data/lib/rio/arycopy.rb +43 -0
- data/lib/rio/assert.rb +114 -0
- data/lib/rio/base.rb +56 -0
- data/lib/rio/callstr.rb +46 -0
- data/lib/rio/const.rb +51 -0
- data/lib/rio/construct.rb +50 -0
- data/lib/rio/constructor.rb +258 -0
- data/lib/rio/context/autoclose.rb +72 -0
- data/lib/rio/context/copying.rb +55 -0
- data/lib/rio/context/cxx.rb +66 -0
- data/lib/rio/context/dir.rb +120 -0
- data/lib/rio/context/gzip.rb +50 -0
- data/lib/rio/context/methods.rb +182 -0
- data/lib/rio/context/skip.rb +66 -0
- data/lib/rio/context/stream.rb +229 -0
- data/lib/rio/context.rb +117 -0
- data/lib/rio/cp.rb +370 -0
- data/lib/rio/def.rb +53 -0
- data/lib/rio/dir.rb +144 -0
- data/lib/rio/doc/EXAMPLES.rb +299 -0
- data/lib/rio/doc/HOWTO.rb +737 -0
- data/lib/rio/doc/INDEX.rb +311 -0
- data/lib/rio/doc/INTRO.rb +1068 -0
- data/lib/rio/doc/OPTIONAL.rb +130 -0
- data/lib/rio/doc/SYNOPSIS.rb +183 -0
- data/lib/rio/doc.rb +45 -0
- data/lib/rio/entrysel.rb +246 -0
- data/lib/rio/exception/copy.rb +97 -0
- data/lib/rio/exception/notimplemented.rb +57 -0
- data/lib/rio/exception/notsupported.rb +46 -0
- data/lib/rio/exception/open.rb +61 -0
- data/lib/rio/exception/state.rb +73 -0
- data/lib/rio/exception.rb +41 -0
- data/lib/rio/ext/csv.rb +351 -0
- data/lib/rio/ext/if.rb +45 -0
- data/lib/rio/ext/mp3info.rb +80 -0
- data/lib/rio/ext/splitlines.rb +253 -0
- data/lib/rio/ext/yaml/doc.rb +133 -0
- data/lib/rio/ext/yaml/tie.rb +149 -0
- data/lib/rio/ext/yaml.rb +164 -0
- data/lib/rio/ext/zipfile/fs.rb +116 -0
- data/lib/rio/ext/zipfile/rl.rb +251 -0
- data/lib/rio/ext/zipfile/rootdir.rb +117 -0
- data/lib/rio/ext/zipfile/state.rb +161 -0
- data/lib/rio/ext/zipfile/wrap.rb +204 -0
- data/lib/rio/ext/zipfile.rb +110 -0
- data/lib/rio/ext.rb +138 -0
- data/lib/rio/factory.rb +436 -0
- data/lib/rio/file.rb +118 -0
- data/lib/rio/filter/closeoneof.rb +103 -0
- data/lib/rio/filter/gzip.rb +70 -0
- data/lib/rio/filter.rb +94 -0
- data/lib/rio/fs/base.rb +41 -0
- data/lib/rio/fs/impl.rb +122 -0
- data/lib/rio/fs/native.rb +75 -0
- data/lib/rio/fs/stream.rb +61 -0
- data/lib/rio/fs/url.rb +63 -0
- data/lib/rio/ftp/conncache.rb +101 -0
- data/lib/rio/ftp/dir.rb +94 -0
- data/lib/rio/ftp/fs.rb +180 -0
- data/lib/rio/ftp/ftpfile.rb +20 -0
- data/lib/rio/grande.rb +97 -0
- data/lib/rio/handle.rb +100 -0
- data/lib/rio/if/basic.rb +64 -0
- data/lib/rio/if/csv.rb +76 -0
- data/lib/rio/if/dir.rb +157 -0
- data/lib/rio/if/file.rb +89 -0
- data/lib/rio/if/fileordir.rb +268 -0
- data/lib/rio/if/grande.rb +729 -0
- data/lib/rio/if/grande_entry.rb +379 -0
- data/lib/rio/if/grande_stream.rb +693 -0
- data/lib/rio/if/internal.rb +125 -0
- data/lib/rio/if/path.rb +462 -0
- data/lib/rio/if/rubyio.rb +681 -0
- data/lib/rio/if/string.rb +83 -0
- data/lib/rio/if/temp.rb +45 -0
- data/lib/rio/if/test.rb +282 -0
- data/lib/rio/if/yaml.rb +206 -0
- data/lib/rio/if.rb +64 -0
- data/lib/rio/ioh.rb +162 -0
- data/lib/rio/iomode.rb +109 -0
- data/lib/rio/ios/fail.rb +106 -0
- data/lib/rio/ios/generic.rb +119 -0
- data/lib/rio/ios/mode.rb +60 -0
- data/lib/rio/ios/null.rb +119 -0
- data/lib/rio/iowrap.rb +128 -0
- data/lib/rio/kernel.rb +54 -0
- data/lib/rio/local.rb +62 -0
- data/lib/rio/match.rb +53 -0
- data/lib/rio/matchrecord.rb +283 -0
- data/lib/rio/no_warn.rb +49 -0
- data/lib/rio/nullio.rb +159 -0
- data/lib/rio/open3.rb +68 -0
- data/lib/rio/ops/construct.rb +61 -0
- data/lib/rio/ops/create.rb +77 -0
- data/lib/rio/ops/dir.rb +346 -0
- data/lib/rio/ops/either.rb +134 -0
- data/lib/rio/ops/file.rb +102 -0
- data/lib/rio/ops/path.rb +296 -0
- data/lib/rio/ops/stream/input.rb +267 -0
- data/lib/rio/ops/stream/output.rb +100 -0
- data/lib/rio/ops/stream/read.rb +86 -0
- data/lib/rio/ops/stream/write.rb +57 -0
- data/lib/rio/ops/stream.rb +87 -0
- data/lib/rio/ops/symlink.rb +80 -0
- data/lib/rio/path/reset.rb +69 -0
- data/lib/rio/path.rb +129 -0
- data/lib/rio/piper/cp.rb +80 -0
- data/lib/rio/piper.rb +122 -0
- data/lib/rio/prompt.rb +66 -0
- data/lib/rio/rectype.rb +88 -0
- data/lib/rio/rl/base.rb +118 -0
- data/lib/rio/rl/builder.rb +117 -0
- data/lib/rio/rl/chmap.rb +66 -0
- data/lib/rio/rl/fs2url.rb +82 -0
- data/lib/rio/rl/ioi.rb +78 -0
- data/lib/rio/rl/path.rb +110 -0
- data/lib/rio/rl/pathmethods.rb +116 -0
- data/lib/rio/rl/uri.rb +200 -0
- data/lib/rio/rl/withpath.rb +296 -0
- data/lib/rio/scheme/aryio.rb +88 -0
- data/lib/rio/scheme/cmdio.rb +80 -0
- data/lib/rio/scheme/cmdpipe.rb +118 -0
- data/lib/rio/scheme/fd.rb +65 -0
- data/lib/rio/scheme/ftp.rb +141 -0
- data/lib/rio/scheme/http.rb +78 -0
- data/lib/rio/scheme/null.rb +55 -0
- data/lib/rio/scheme/path.rb +98 -0
- data/lib/rio/scheme/stderr.rb +55 -0
- data/lib/rio/scheme/stdio.rb +71 -0
- data/lib/rio/scheme/strio.rb +87 -0
- data/lib/rio/scheme/sysio.rb +63 -0
- data/lib/rio/scheme/tcp.rb +75 -0
- data/lib/rio/scheme/temp.rb +200 -0
- data/lib/rio/state/error.rb +72 -0
- data/lib/rio/state.rb +242 -0
- data/lib/rio/stream/base.rb +54 -0
- data/lib/rio/stream/duplex.rb +79 -0
- data/lib/rio/stream/open.rb +202 -0
- data/lib/rio/stream.rb +181 -0
- data/lib/rio/symantics.rb +45 -0
- data/lib/rio/tempdir.rb +132 -0
- data/lib/rio/to_rio/all.rb +39 -0
- data/lib/rio/to_rio/array.rb +39 -0
- data/lib/rio/to_rio/io.rb +40 -0
- data/lib/rio/to_rio/object.rb +42 -0
- data/lib/rio/to_rio/string.rb +40 -0
- data/lib/rio/to_rio.rb +67 -0
- data/lib/rio/uri/file.rb +198 -0
- data/lib/rio/util.rb +48 -0
- data/lib/rio/version.rb +51 -0
- data/lib/rio.rb +162 -0
- data/setup.rb +1360 -0
- data/test/bin/count_lines.rb +11 -0
- data/test/bin/find_lines.rb +13 -0
- data/test/bin/list_dir.rb +14 -0
- data/test/ftp/all.rb +9 -0
- data/test/ftp/anon_copy_data.rb +36 -0
- data/test/ftp/anon_misc.rb +124 -0
- data/test/ftp/anon_read.rb +105 -0
- data/test/ftp/anon_special.rb +68 -0
- data/test/ftp/anon_write.rb +70 -0
- data/test/ftp/ftp2ftp.rb +51 -0
- data/test/ftp/initftpfiles.rb +14 -0
- data/test/ftp/testdef.rb +55 -0
- data/test/gem_runtests.rb +15 -0
- data/test/http/all.rb +4 -0
- data/test/http/copy-from-http.rb +141 -0
- data/test/http/uri-meta.rb +72 -0
- data/test/lib/temp_server.rb +46 -0
- data/test/runalltests.rb +17 -0
- data/test/runftptests.rb +14 -0
- data/test/runhttp.rb +11 -0
- data/test/runhttptests.rb +14 -0
- data/test/runtests.rb +52 -0
- data/test/tc/abs.rb +355 -0
- data/test/tc/all.rb +80 -0
- data/test/tc/base.rb +31 -0
- data/test/tc/base2.rb +87 -0
- data/test/tc/cd1.rb +113 -0
- data/test/tc/clearsel.rb +68 -0
- data/test/tc/clone.rb +208 -0
- data/test/tc/closeoncopy.rb +102 -0
- data/test/tc/closeoneof.rb +194 -0
- data/test/tc/cmdpipe.rb +149 -0
- data/test/tc/copy-dir-samevar.rb +91 -0
- data/test/tc/copy-from.rb +129 -0
- data/test/tc/copy-to.rb +91 -0
- data/test/tc/copy.rb +74 -0
- data/test/tc/copyarray.rb +188 -0
- data/test/tc/copydest.rb +50 -0
- data/test/tc/copydir.rb +166 -0
- data/test/tc/copydirlines.rb +121 -0
- data/test/tc/copylines.rb +46 -0
- data/test/tc/copynonex.rb +118 -0
- data/test/tc/copysymlink.rb +39 -0
- data/test/tc/create.rb +114 -0
- data/test/tc/csv.rb +226 -0
- data/test/tc/csv2.rb +138 -0
- data/test/tc/csv_columns.rb +37 -0
- data/test/tc/csvutil.rb +56 -0
- data/test/tc/dir.rb +76 -0
- data/test/tc/dir_iter.rb +383 -0
- data/test/tc/dirautoclose.rb +67 -0
- data/test/tc/dirent.rb +178 -0
- data/test/tc/dirss.rb +81 -0
- data/test/tc/each.rb +111 -0
- data/test/tc/each_break.rb +243 -0
- data/test/tc/edf.rb +81 -0
- data/test/tc/empty.rb +51 -0
- data/test/tc/emptyriodir.rb +129 -0
- data/test/tc/entary.rb +227 -0
- data/test/tc/entsel.rb +110 -0
- data/test/tc/eq.rb +101 -0
- data/test/tc/expand_path.rb +69 -0
- data/test/tc/ext.rb +136 -0
- data/test/tc/fileno.rb +94 -0
- data/test/tc/files_select.rb +92 -0
- data/test/tc/get.rb +152 -0
- data/test/tc/getrec.rb +137 -0
- data/test/tc/gzip.rb +109 -0
- data/test/tc/io_each_byte.rb +60 -0
- data/test/tc/io_read.rb +80 -0
- data/test/tc/iometh.rb +149 -0
- data/test/tc/likeio.rb +116 -0
- data/test/tc/line_record_row.rb +51 -0
- data/test/tc/lineno.rb +196 -0
- data/test/tc/lines.rb +66 -0
- data/test/tc/misc.rb +432 -0
- data/test/tc/nolines.rb +204 -0
- data/test/tc/noqae.rb +879 -0
- data/test/tc/null.rb +45 -0
- data/test/tc/once.rb +6 -0
- data/test/tc/overload.rb +140 -0
- data/test/tc/pa.rb +158 -0
- data/test/tc/path_parts.rb +175 -0
- data/test/tc/pathop.rb +60 -0
- data/test/tc/paths.rb +145 -0
- data/test/tc/pid.rb +31 -0
- data/test/tc/piper.rb +143 -0
- data/test/tc/programs_util.rb +24 -0
- data/test/tc/qae.rb +493 -0
- data/test/tc/qae_riovar.rb +499 -0
- data/test/tc/readline.rb +30 -0
- data/test/tc/records.rb +68 -0
- data/test/tc/rename.rb +233 -0
- data/test/tc/rename_assign.rb +45 -0
- data/test/tc/riorl.rb +181 -0
- data/test/tc/route.rb +51 -0
- data/test/tc/selnosel.rb +33 -0
- data/test/tc/skip.rb +89 -0
- data/test/tc/skiplines.rb +71 -0
- data/test/tc/split.rb +28 -0
- data/test/tc/splitlines.rb +65 -0
- data/test/tc/splitpath.rb +83 -0
- data/test/tc/sub.rb +46 -0
- data/test/tc/symlink.rb +176 -0
- data/test/tc/symlink0.rb +348 -0
- data/test/tc/symlink1.rb +114 -0
- data/test/tc/synopsis.rb +75 -0
- data/test/tc/temp.rb +152 -0
- data/test/tc/tempdir.rb +60 -0
- data/test/tc/tempfile.rb +66 -0
- data/test/tc/testcase.rb +170 -0
- data/test/tc/tonl.rb +37 -0
- data/test/tc/truncate.rb +39 -0
- data/test/tc/yaml.rb +275 -0
- metadata +387 -0
@@ -0,0 +1,311 @@
|
|
1
|
+
#--
|
2
|
+
# ===============================================================================
|
3
|
+
# Copyright (c) 2005,2006,2007 Christopher Kleckner
|
4
|
+
# All rights reserved
|
5
|
+
#
|
6
|
+
# This file is part of the Rio library for ruby.
|
7
|
+
#
|
8
|
+
# Rio is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation; either version 2 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Rio is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Rio; if not, write to the Free Software
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
21
|
+
# ===============================================================================
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
# To create the documentation for Rio run the command
|
25
|
+
# 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
|
+
module RIO
|
38
|
+
module Doc
|
39
|
+
=begin rdoc
|
40
|
+
|
41
|
+
= Rio - Index
|
42
|
+
|
43
|
+
Constructors:
|
44
|
+
RIO#rio
|
45
|
+
RIO#cwd
|
46
|
+
RIO#root
|
47
|
+
|
48
|
+
Directories:
|
49
|
+
RIO::IF::Dir#chdir
|
50
|
+
RIO::IF::Dir#find
|
51
|
+
RIO::IF::Dir#glob
|
52
|
+
RIO::IF::Dir#mkdir
|
53
|
+
RIO::IF::Dir#mkpath
|
54
|
+
RIO::IF::Dir#rmdir
|
55
|
+
RIO::IF::Dir#rmtree
|
56
|
+
|
57
|
+
Files:
|
58
|
+
RIO::IF::File#clear
|
59
|
+
RIO::IF::File#rm
|
60
|
+
RIO::IF::File#touch
|
61
|
+
RIO::IF::File#truncate
|
62
|
+
|
63
|
+
Files or Directories:
|
64
|
+
RIO::IF::FileOrDir#open
|
65
|
+
RIO::IF::FileOrDir#pos
|
66
|
+
RIO::IF::FileOrDir#pos=
|
67
|
+
RIO::IF::FileOrDir#read
|
68
|
+
RIO::IF::FileOrDir#readlink
|
69
|
+
RIO::IF::FileOrDir#rename
|
70
|
+
RIO::IF::FileOrDir#rename!
|
71
|
+
RIO::IF::FileOrDir#reopen
|
72
|
+
RIO::IF::FileOrDir#rewind
|
73
|
+
RIO::IF::FileOrDir#seek
|
74
|
+
RIO::IF::FileOrDir#symlink
|
75
|
+
RIO::IF::FileOrDir#tell
|
76
|
+
|
77
|
+
Path:
|
78
|
+
RIO::IF::Path#/
|
79
|
+
RIO::IF::Path#abs
|
80
|
+
RIO::IF::Path#base
|
81
|
+
RIO::IF::Path#basename
|
82
|
+
RIO::IF::Path#basename=
|
83
|
+
RIO::IF::Path#cleanpath
|
84
|
+
RIO::IF::Path#dirname
|
85
|
+
RIO::IF::Path#dirname=
|
86
|
+
RIO::IF::Path#expand_path
|
87
|
+
RIO::IF::Path#ext
|
88
|
+
RIO::IF::Path#ext?
|
89
|
+
RIO::IF::Path#extname
|
90
|
+
RIO::IF::Path#extname=
|
91
|
+
RIO::IF::Path#filename
|
92
|
+
RIO::IF::Path#filename=
|
93
|
+
RIO::IF::Path#fspath
|
94
|
+
RIO::IF::Path#host
|
95
|
+
RIO::IF::Path#join
|
96
|
+
RIO::IF::Path#join!
|
97
|
+
RIO::IF::Path#merge
|
98
|
+
RIO::IF::Path#noext
|
99
|
+
RIO::IF::Path#opaque
|
100
|
+
RIO::IF::Path#path
|
101
|
+
RIO::IF::Path#realpath
|
102
|
+
RIO::IF::Path#rel
|
103
|
+
RIO::IF::Path#route_from
|
104
|
+
RIO::IF::Path#route_to
|
105
|
+
RIO::IF::Path#scheme
|
106
|
+
RIO::IF::Path#splitpath
|
107
|
+
RIO::IF::Path#to_uri
|
108
|
+
RIO::IF::Path#to_url
|
109
|
+
RIO::IF::Path#urlpath
|
110
|
+
|
111
|
+
String:
|
112
|
+
RIO::IF::String#+
|
113
|
+
RIO::IF::String#gsub
|
114
|
+
RIO::IF::String#sub
|
115
|
+
|
116
|
+
Grande:
|
117
|
+
RIO::IF::Grande#[]
|
118
|
+
RIO::IF::Grande#<
|
119
|
+
RIO::IF::Grande#<<
|
120
|
+
RIO::IF::Grande#>
|
121
|
+
RIO::IF::Grande#>>
|
122
|
+
RIO::IF::Grande#|
|
123
|
+
RIO::IF::Grande#append_from
|
124
|
+
RIO::IF::Grande#append_to
|
125
|
+
RIO::IF::Grande#copy_from
|
126
|
+
RIO::IF::Grande#copy_to
|
127
|
+
RIO::IF::Grande#delete
|
128
|
+
RIO::IF::Grande#delete!
|
129
|
+
RIO::IF::Grande#each
|
130
|
+
RIO::IF::Grande#empty?
|
131
|
+
RIO::IF::Grande#get
|
132
|
+
RIO::IF::Grande#skip
|
133
|
+
RIO::IF::Grande#split
|
134
|
+
RIO::IF::Grande#to_a
|
135
|
+
|
136
|
+
Grande Directory:
|
137
|
+
RIO::IF::GrandeEntry#all
|
138
|
+
RIO::IF::GrandeEntry#all?
|
139
|
+
RIO::IF::GrandeEntry#dirs
|
140
|
+
RIO::IF::GrandeEntry#entries
|
141
|
+
RIO::IF::GrandeEntry#files
|
142
|
+
RIO::IF::GrandeEntry#norecurse
|
143
|
+
RIO::IF::GrandeEntry#recurse
|
144
|
+
RIO::IF::GrandeEntry#skipdirs
|
145
|
+
RIO::IF::GrandeEntry#skipentries
|
146
|
+
RIO::IF::GrandeEntry#skipfiles
|
147
|
+
|
148
|
+
Grande Stream:
|
149
|
+
RIO::IF::GrandeStream#+@
|
150
|
+
RIO::IF::GrandeStream#a
|
151
|
+
RIO::IF::GrandeStream#a!
|
152
|
+
RIO::IF::GrandeStream#bytes
|
153
|
+
RIO::IF::GrandeStream#chomp
|
154
|
+
RIO::IF::GrandeStream#chomp?
|
155
|
+
RIO::IF::GrandeStream#closeoncopy
|
156
|
+
RIO::IF::GrandeStream#closeoncopy?
|
157
|
+
RIO::IF::GrandeStream#closeoneof
|
158
|
+
RIO::IF::GrandeStream#closeoneof?
|
159
|
+
RIO::IF::GrandeStream#contents
|
160
|
+
RIO::IF::GrandeStream#getline
|
161
|
+
RIO::IF::GrandeStream#getrec
|
162
|
+
RIO::IF::GrandeStream#getrow
|
163
|
+
RIO::IF::GrandeStream#gzip
|
164
|
+
RIO::IF::GrandeStream#gzip?
|
165
|
+
RIO::IF::GrandeStream#line
|
166
|
+
RIO::IF::GrandeStream#lines
|
167
|
+
RIO::IF::GrandeStream#noautoclose
|
168
|
+
RIO::IF::GrandeStream#nocloseoncopy
|
169
|
+
RIO::IF::GrandeStream#nocloseoneof
|
170
|
+
RIO::IF::GrandeStream#putrec
|
171
|
+
RIO::IF::GrandeStream#r
|
172
|
+
RIO::IF::GrandeStream#r!
|
173
|
+
RIO::IF::GrandeStream#record
|
174
|
+
RIO::IF::GrandeStream#records
|
175
|
+
RIO::IF::GrandeStream#row
|
176
|
+
RIO::IF::GrandeStream#rows
|
177
|
+
RIO::IF::GrandeStream#skiplines
|
178
|
+
RIO::IF::GrandeStream#skiprecords
|
179
|
+
RIO::IF::GrandeStream#skiprows
|
180
|
+
RIO::IF::GrandeStream#splitlines
|
181
|
+
RIO::IF::GrandeStream#strip
|
182
|
+
RIO::IF::GrandeStream#strip?
|
183
|
+
RIO::IF::GrandeStream#w
|
184
|
+
RIO::IF::GrandeStream#w!
|
185
|
+
|
186
|
+
Ruby I/O:
|
187
|
+
RIO::IF::RubyIO#binmode
|
188
|
+
RIO::IF::RubyIO#close
|
189
|
+
RIO::IF::RubyIO#close_write
|
190
|
+
RIO::IF::RubyIO#each_byte
|
191
|
+
RIO::IF::RubyIO#each_line
|
192
|
+
RIO::IF::RubyIO#eof?
|
193
|
+
RIO::IF::RubyIO#fcntl
|
194
|
+
RIO::IF::RubyIO#fileno
|
195
|
+
RIO::IF::RubyIO#flush
|
196
|
+
RIO::IF::RubyIO#fsync
|
197
|
+
RIO::IF::RubyIO#getc
|
198
|
+
RIO::IF::RubyIO#gets
|
199
|
+
RIO::IF::RubyIO#ioctl
|
200
|
+
RIO::IF::RubyIO#ioh
|
201
|
+
RIO::IF::RubyIO#ios
|
202
|
+
RIO::IF::RubyIO#lineno
|
203
|
+
RIO::IF::RubyIO#lineno=
|
204
|
+
RIO::IF::RubyIO#mode
|
205
|
+
RIO::IF::RubyIO#mode?
|
206
|
+
RIO::IF::RubyIO#nosync
|
207
|
+
RIO::IF::RubyIO#pid
|
208
|
+
RIO::IF::RubyIO#print
|
209
|
+
RIO::IF::RubyIO#print!
|
210
|
+
RIO::IF::RubyIO#printf
|
211
|
+
RIO::IF::RubyIO#printf!
|
212
|
+
RIO::IF::RubyIO#putc
|
213
|
+
RIO::IF::RubyIO#putc!
|
214
|
+
RIO::IF::RubyIO#puts
|
215
|
+
RIO::IF::RubyIO#puts!
|
216
|
+
RIO::IF::RubyIO#readline
|
217
|
+
RIO::IF::RubyIO#readlines
|
218
|
+
RIO::IF::RubyIO#readpartial
|
219
|
+
RIO::IF::RubyIO#recno
|
220
|
+
RIO::IF::RubyIO#sync
|
221
|
+
RIO::IF::RubyIO#sync?
|
222
|
+
RIO::IF::RubyIO#to_i
|
223
|
+
RIO::IF::RubyIO#to_io
|
224
|
+
RIO::IF::RubyIO#tty?
|
225
|
+
RIO::IF::RubyIO#ungetc
|
226
|
+
RIO::IF::RubyIO#write
|
227
|
+
RIO::IF::RubyIO#write!
|
228
|
+
|
229
|
+
Test:
|
230
|
+
RIO::IF::Test#abs?
|
231
|
+
RIO::IF::Test#absolute?
|
232
|
+
RIO::IF::Test#atime
|
233
|
+
RIO::IF::Test#blockdev?
|
234
|
+
RIO::IF::Test#chardev?
|
235
|
+
RIO::IF::Test#closed?
|
236
|
+
RIO::IF::Test#ctime
|
237
|
+
RIO::IF::Test#dir?
|
238
|
+
RIO::IF::Test#directory?
|
239
|
+
RIO::IF::Test#executable_real?
|
240
|
+
RIO::IF::Test#executable?
|
241
|
+
RIO::IF::Test#exist?
|
242
|
+
RIO::IF::Test#file?
|
243
|
+
RIO::IF::Test#fnmatch?
|
244
|
+
RIO::IF::Test#ftype
|
245
|
+
RIO::IF::Test#grpowned?
|
246
|
+
RIO::IF::Test#lstat
|
247
|
+
RIO::IF::Test#mountpoint?
|
248
|
+
RIO::IF::Test#mtime
|
249
|
+
RIO::IF::Test#open?
|
250
|
+
RIO::IF::Test#owned?
|
251
|
+
RIO::IF::Test#pipe?
|
252
|
+
RIO::IF::Test#readable_real?
|
253
|
+
RIO::IF::Test#readable?
|
254
|
+
RIO::IF::Test#root?
|
255
|
+
RIO::IF::Test#setgid?
|
256
|
+
RIO::IF::Test#setuid?
|
257
|
+
RIO::IF::Test#size
|
258
|
+
RIO::IF::Test#size?
|
259
|
+
RIO::IF::Test#socket?
|
260
|
+
RIO::IF::Test#stat
|
261
|
+
RIO::IF::Test#sticky?
|
262
|
+
RIO::IF::Test#symlink?
|
263
|
+
RIO::IF::Test#writable_real?
|
264
|
+
RIO::IF::Test#writable?
|
265
|
+
RIO::IF::Test#zero?
|
266
|
+
|
267
|
+
|
268
|
+
Basic:
|
269
|
+
RIO::Rio#==
|
270
|
+
RIO::Rio#===
|
271
|
+
RIO::Rio#=~
|
272
|
+
RIO::Rio#dup
|
273
|
+
RIO::Rio#eql?
|
274
|
+
RIO::Rio#hash
|
275
|
+
RIO::Rio#initialize_copy
|
276
|
+
RIO::Rio#inspect
|
277
|
+
RIO::Rio#length
|
278
|
+
RIO::Rio#new
|
279
|
+
RIO::Rio#rio
|
280
|
+
RIO::Rio#string
|
281
|
+
RIO::Rio#to_s
|
282
|
+
RIO::Rio#to_str
|
283
|
+
|
284
|
+
CSV:
|
285
|
+
RIO::IF::CSV#columns
|
286
|
+
RIO::IF::CSV#csv
|
287
|
+
RIO::IF::CSV#skipcolumns
|
288
|
+
|
289
|
+
YAML:
|
290
|
+
RIO::IF::YAML#document
|
291
|
+
RIO::IF::YAML#documents
|
292
|
+
RIO::IF::YAML#dump
|
293
|
+
RIO::IF::YAML#getobj
|
294
|
+
RIO::IF::YAML#load
|
295
|
+
RIO::IF::YAML#object
|
296
|
+
RIO::IF::YAML#objects
|
297
|
+
RIO::IF::YAML#putobj
|
298
|
+
RIO::IF::YAML#putobj!
|
299
|
+
RIO::IF::YAML#skipdocuments
|
300
|
+
RIO::IF::YAML#skipobjects
|
301
|
+
RIO::IF::YAML#yaml
|
302
|
+
RIO::IF::YAML#yaml?
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
=end
|
307
|
+
module INDEX
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
@@ -0,0 +1,1068 @@
|
|
1
|
+
#--
|
2
|
+
# ===============================================================================
|
3
|
+
# Copyright (c) 2005,2006,2007 Christopher Kleckner
|
4
|
+
# All rights reserved
|
5
|
+
#
|
6
|
+
# This file is part of the Rio library for ruby.
|
7
|
+
#
|
8
|
+
# Rio is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation; either version 2 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Rio is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Rio; if not, write to the Free Software
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
21
|
+
# ===============================================================================
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
# To create the documentation for Rio run the command
|
25
|
+
# 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
|
+
module RIO
|
38
|
+
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
|
+
|
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
|
1063
|
+
|
1064
|
+
=end
|
1065
|
+
module INTRO
|
1066
|
+
end
|
1067
|
+
end
|
1068
|
+
end
|