Monday, July 30, 2007
Why Rio?
The first time I saw Ruby I was in awe of her beauty -- and she was so smart! It was as if she could read my mind. I would write:
3.times { print "Hello Ruby" }
and she would print "Hello Ruby" 3 times.
She really understood me.
I had dated her older cousin Perl for several years. While Perl was resourceful, she was not much to look at. And while she tried so hard to understand things like objects, it always seemed like she was faking it. She pretended to understand them only because she knew that was what I wanted. She never really got it.
Being so enamored of Ruby I wanted to take her out in public. I was stunned to find that when I tried to have her do common tasks, like dealing with files, directories and streams, she was as clumsy as her cousin. Sometimes she acted like an object and other times she made me treat her like a function. Her I/O interface was spread across File, Dir, IO, and Pathname. Sometimes available through instance methods and other times using class methods. In many ways she reminded me of her grandfather, C. I was getting confused.
I thought the problem must be with me and decided to seek more documentation. The only thing I could find was Why's Poignant Guide... now I was really confused.
I decided I must find a way to help Ruby be as beautiful when dealing with the public as she was with me in private; to make her Input/Output operations so simple that they would be an afterthought; so that I and others could concentrate on the problem we were trying to solve rather than mundane things like I/O. I also decided to document my work well -- with lots of examples.
I remembered a pretty dress I saw Perl wear once called IO::All. Using that as a starting point, I tried to design a gown that, when adorning Ruby's natural beauty, would make common I/O operations as simple and painless as they should be.
Saturday, July 7, 2007
Rio 0.4.1 Released
- Includes fix for bug involving file system paths with special characters.
- Other minor fixes.
Rio - Ruby I/O Facilitator
fa-cil-i-tate: To make easy or easier.
Overview
Rio is a facade for most of the standard ruby classes that deal with I/O; providing a simple, intuitive, succinct interface to the functionality provided by IO, File, Dir, Pathname, FileUtils, Tempfile, StringIO, OpenURI and others. Rio also provides an application level interface which allows many common I/O idioms to be expressed succinctly.
SYNOPSIS
For the following assume:
astring = ""
anarray = []
Iterate over the .rb files in a directory.
rio('adir').files('*.rb') { |entrio| ... }
Return an array of the .rb files in a directory.
anarray = rio('adir').files['*.rb']
Copy the .rb files in a directory.to another directory.
rio('adir').files('*.rb') > rio('another_directory')
Iterate over the .rb files in a directory and its subdirectories.
rio('adir').all.files('*.rb') { |entrio| ... }
Return an array of the .rb files in a directory and its
subdirectories.
anarray = rio('adir').all.files['*.rb']
Copy or append a file to a string
rio('afile') > astring # copy
rio('afile') >> astring # append
Copy or append a string to a file
rio('afile') <>
Copy or append the lines of a file to an array
rio('afile') > anarray
rio('afile') >> anarray
Copy or append a file to another file
rio('afile') > rio('another_file')
rio('afile') >> rio('another_file')
Copy a file to a directory
rio('adir') <<>
Copy a directory to another directory
rio('adir') >> rio('another_directory')
Copy a web-page to a file
rio('http://rubydoc.org/') > rio('afile')
Read a web-page into a string
astring = rio('http://rubydoc.org/').read
Ways to get the chomped lines of a file into an array
anarray = rio('afile').chomp[] # subscript operator
rio('afile').chomp > anarray # copy-to operator
anarray = rio('afile').chomp.to_a # to_a
anarray = rio('afile').chomp.readlines # IO#readlines
Iterate over selected lines of a file
rio('adir').lines(0..3) { |aline| ... } # a range of lines
rio('adir').lines(/re/) { |aline| ... } # by regular expression
rio('adir').lines(0..3,/re/) { |aline| ... } # or both
Return selected lines of a file as an array
rio('adir').lines[0..3] # a range of lines
rio('adir').lines[/re/] # by regular expression
rio('adir').lines[0..3,/re/] # or both
Iterate over selected chomped lines of a file
rio('adir').chomp.lines(0..3) { |aline| ... } # a range of lines
rio('adir').chomp.lines(/re/) { |aline| ... } # by regular expression
Return selected chomped lines of a file as an array
rio('adir').chomp[0..3] # a range of lines
rio('adir').chomp[/re/] # by regular expression
Copy a gzipped file un-gzipping it
rio('afile.gz').gzip > rio('afile')
Copy a plain file, gzipping it
rio('afile.gz').gzip <>
Copy a file from a ftp server into a local file un-gzipping it
rio('ftp://host/afile.gz').gzip > rio('afile')
Return an array of .rb files excluding symlinks to .rb files
rio('adir').files('*.rb').skip[:symlink?]
Put the first 10 chomped lines of a gzipped file into an array
anarray = rio('afile.gz').chomp.gzip[0...10]
Copy lines 0 and 3 thru 5 of a gzipped file on an ftp server to stdout
rio('ftp://host/afile.gz').gzip.lines(0,3..5) > ?-
Return an array of files in a directory and its subdirectories,
without descending into .svn directories.
rio('adir').norecurse(/^\.svn$/).files[]
Iterate over the non-empty, non-comment chomped lines of a file
rio('afile').chomp.skip(:empty?,/^\s*#/) { |line| ... }
Copy the output of th ps command into an array, skipping the header
line and the ps command entry
rio(?-,'ps -a').skiplines(0,/ps$/) > anarray
Prompt for input and return what was typed
ans = rio(?-).print("Type Something: ").chomp.gets
Change the extension of all .htm files in a directory and its
subdirectories to .html
rio('adir').rename.all.files('*.htm') do |htmfile|
htmfile.extname = '.html'
end
Copy a CSV file, changing the separator to a semicolon
rio('comma.csv').csv > rio('semicolon.csv').csv(';')
Iterate through a CSVfile with each line parsed into an array
rio('afile.csv').csv { |array_of_fields| ...}
Create a tab separated file of accounts in a UNIX passwd file,
listing only the username, uid, and realname fields
rio('/etc/passwd').csv(':').columns(0,2,4) > rio('rpt').csv("\t")
Pipe multiple commands
rio('afile') | rio(?-,'acmd') | 'another_cmd' | ?-
Contact
Project:: http://rubyforge.org/projects/rio/
Documentation:: http://rio.rubyforge.org/
Bugs:: http://rubyforge.org/tracker/?group_id=821
All rights reserved
Rio is released under the GNU General Public License
(http://www.gnu.org/licenses/gpl.html).