Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[ANN] Rio 0.3.3

0 views
Skip to first unread message

rio4ruby

unread,
Aug 19, 2005, 8:19:03 PM8/19/05
to
For your perusal -- Rio 0.3.3

== Overview

Rio is a Ruby I/O convenience class wrapping much of the functionality
of IO, File and Dir. Rio also uses Pathname, FileUtils, Tempfile,
StringIO, OpenURI, Zlib, and CSV to provide similar functionality using
a simple consistent interface. In addition to forwarding the interfaces
provided by IO, File, and Dir to an appropriate object, Rio provides
a "grande" interface that allows many common application-level I/O and
file-system tasks to be expressed succinctly.

== New for version 0.3.3
* Expanded support and documentation for CSV files
Examples:
* Copy, changing the separator to a semicolon
rio('comma.csv').csv > rio('semicolon.csv').csv(';')
* Iterate through a file with each line parsed into an array
rio('afile.csv').csv { |array_of_fields| ...}
* Create an array of arrays of selected fields
array_of_arrays = rio('afile.csv').csv.columns(1..3,7).to_a
* 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")

Project:: http://rubyforge.org/projects/rio/
Documentation:: http://rio.rubyforge.org/
Bugs:: http://rubyforge.org/tracker/?group_id=821

Sascha Ebach

unread,
Aug 19, 2005, 9:16:57 PM8/19/05
to
rio4ruby wrote:
> For your perusal -- Rio 0.3.3
>
> == Overview
>
> Rio is a Ruby I/O convenience class wrapping much of the functionality
> of IO, File and Dir. Rio also uses Pathname, FileUtils, Tempfile,
> StringIO, OpenURI, Zlib, and CSV to provide similar functionality using
> a simple consistent interface. In addition to forwarding the interfaces
> provided by IO, File, and Dir to an appropriate object, Rio provides
> a "grande" interface that allows many common application-level I/O and
> file-system tasks to be expressed succinctly.
>
> == New for version 0.3.3
> * Expanded support and documentation for CSV files
> Examples:
> * Copy, changing the separator to a semicolon
> rio('comma.csv').csv > rio('semicolon.csv').csv(';')
> * Iterate through a file with each line parsed into an array
> rio('afile.csv').csv { |array_of_fields| ...}
> * Create an array of arrays of selected fields
> array_of_arrays = rio('afile.csv').csv.columns(1..3,7).to_a
> * 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")

This is great. Thanks for this incredibly useful lib.

Sascha Ebach


Ezra Zygmuntowicz

unread,
Aug 20, 2005, 12:30:18 AM8/20/05
to

This is a _very_ nice library. Great docs too. I will use this heavily.
Thanks for the work-

-Ezra Zygmuntowicz
WebMaster
Yakima Herald-Republic Newspaper
ez...@yakima-herald.com
509-577-7732

Jim Freeze

unread,
Aug 20, 2005, 12:49:47 AM8/20/05
to
Hi

On 8/19/05, Ezra Zygmuntowicz <ez...@yakima-herald.com> wrote:
> > >
> > This is great. Thanks for this incredibly useful lib.
> >
> > Sascha Ebach
> >
>
> This is a _very_ nice library. Great docs too. I will use this heavily.
> Thanks for the work-

Yes, very nice. When rio copies directories, how does it handle
soft links? Do they stay as links?


--
Jim Freeze


rio4ruby

unread,
Aug 23, 2005, 9:28:36 PM8/23/05
to
I thought I had addressed this issue. It currently copies the
referenced file instead of the symlink. This is a bug.
-Thanks

gsin...@gmail.com

unread,
Aug 24, 2005, 4:13:17 AM8/24/05
to
Suggestions (inspired by the documentation):

* Iterate over only the dot files in a directory: rio('adir').dotfiles
{ ... }

* Iterate over the .rb files in a directory and its subdirectories:
rio('adir').find('*.rb') { ... }

* Iterate over the files in a directory and its subdirectories,
skipping '.svn' and 'CVS' directories: rio('adir').skip('.svn',
'CVS')

Very creative library!

Cheers,
Gavin

rio4ruby

unread,
Aug 25, 2005, 5:15:34 PM8/25/05
to
gsin...@gmail.com wrote:

>
> * Iterate over only the dot files in a directory: rio('adir').dotfiles
> { ... }

Currently selection is controlled using files(), dirs() and entries().
Would I also need to add a dotdirs and a dotentries method? Is
the need to select dot files sufficiantly general? I will give
this some thought.


> * Iterate over the .rb files in a directory and its subdirectories:
> rio('adir').find('*.rb') { ... }

rio('adir').all.files('*.rb') { ... } does precisely this.

Currently recursion is configured using all(), recurse() and
norecurse().
The arguments to recurse()/norecurse() select/reject the directories to
recurse into. Passing no arguments to recurse means recurse into all
directories -- all() is a synonym for this.

Having recursion configured independently of selection adds
flexibility.

# Create an array of rdoc directories in a ruby installation
rio('/lib/ruby').all.dirs['rdoc']
# Same thing but skip those that are part of
rio('/lib/ruby').norecurse('rio*').dirs['rdoc']

>
> * Iterate over the files in a directory and its subdirectories,
> skipping '.svn' and 'CVS' directories: rio('adir').skip('.svn',
> 'CVS')

Currently rejection is controlled using nofiles(), nodirs() and
noentries(). I have never been fond of these names. skipfiles() etc.
seems like a much better choice. Thanks for the suggestion!


> Very creative library!
Thanks!

I am not really satisfied with the whole
[no]files/[no]dirs/[no]entries/[no]recurse scheme.
Suggestions are most welcome in this area.

Dave Burt

unread,
Aug 26, 2005, 8:43:32 AM8/26/05
to
Some suggestions for Rio. I think what you've done is awesome.

* Rename Rio#copy to Rio#copy_to

* Add aliases:
* append_to >>
* copy_from <
* append_from <<
* - rel

* Rename multi-word methods:
* closeoncopy ? close_on_copy
* closeoneof? ? close_on_eof?
* ...

* Change + and =~ to use to_str instead of to_s.

* Add the following Pathname functionality:
* mountpoint?
* root?
* realpath
* cleanpath
* each_filename (iterates over path components: "a/b/c" -> "a", "b", "c")
* children

* If Rio provided a superset of IO's functionality, you could use Rio
objects in place of IO objects, duck-type style. Same with File, Dir and
Pathname. I think you're only a few methods off (sys*, *=...)
slurp and contents... maybe too many synonyms for read? Don't add to_string
(it means the wrong thing).

* What is the dir method? (It crashes a lot)

* dup needs fixing. I think it should perform a deep copy (i.e. copy
underlying IOs and other objects).

* Instead of the no* methods, you could add a wrapper ("except" or "skip"...
or both) which could be passed into methods like so:
io(foo).recurse(except(".svn")) {||...}.

module Except; end;
def except(*args)
args.map! {|obj| obj.dup.extend Except };
if args.size > 1 then args else args[0] end
end
Then in recurse, lines, etc., you can negate the result of testing against
those objects by XORing the test, like this: re.kind_of?(Except) ^
re.match(line).

* Add an top-level shortcut for rio(?-, *)
module Kernel
def cmdio(*args, &block)
rio(?-, *args, &block)
end
end

* Add pipes. The following should be possible:
io(foo) | io(bar) | io(baz)

Maybe a new container class?

module RIO
class Rio
def |(other)
Pipe.new(self, other)
end
end
# A pipe is a set of two Rio objects which share data internally.
# Input given to the pipe is given to +left+, and any output requested
# comes from +right+.
# +copy+ copies output from +left+ to +right+'s input.
class Pipe < Rio
def initialize(write, read, *others)
@write= write
@read= others.empty? ? read: Pipe.new(read, others.first)
# connect left's output to right's input... Rio state?
IO.pipe/IO.popen?
# the Rio object needs to do write operations on @write, and
read ops on @read.
end
# assuming old #copy is renamed copy_to
def copy
@left > @right
end
attr_accessor :write, :read
end
end

Cheers,
Dave


rio4ruby

unread,
Aug 26, 2005, 2:19:01 PM8/26/05
to
Thanks for the feedback!

Dave Burt wrote:
> * Rename Rio#copy to Rio#copy_to
>
> * Add aliases:
> * append_to >>
> * copy_from <
> * append_from <<

I have considered this for a while. Good idea.

> * - rel
Please provide usage examples

>
> * Rename multi-word methods:
> * closeoncopy ? close_on_copy
> * closeoneof? ? close_on_eof?
> * ...
>
> * Change + and =~ to use to_str instead of to_s.

This is a bug. Thanks

>
> * Add the following Pathname functionality:
> * mountpoint?
> * root?
> * realpath
> * cleanpath

absolutely.

> * each_filename (iterates over path components: "a/b/c" -> "a", "b", "c")

rio('a/b/c').filenames.each ?

> * children
Another way to get the contents of a directory into an array? Is this
the a non-grande version of []? a straight mapping of
Pathname#children ? an alias for Rio#to_a ?
I have no strong opinion either way.

>
> * If Rio provided a superset of IO's functionality, you could use Rio
> objects in place of IO objects, duck-type style. Same with File, Dir and
> Pathname.

The section "Using A Rio as an IO (or File or Dir)" in Rio::Doc::INTRO
discusses this, with an illustration using a Rio with yaml.

> slurp and contents... maybe too many synonyms

YES! Only one will survive the cut (or perhaps neither, if someone
comes up with something better). Opinions are welcome.

> Don't add to_string
> (it means the wrong thing).

yep.

>
> * What is the dir method? (It crashes a lot)

The dir method is a recent addition having to do with tempdirs.
Ignore it - it is going away.

>
> * dup needs fixing. I think it should perform a deep copy (i.e. copy
> underlying IOs and other objects).

Right now clone does that, while dup only copies the path.
Did I get these backwards? What is the Ruby way?

>
> * Instead of the no* methods, you could add a wrapper ("except" or "skip"...
> or both) which could be passed into methods like so:
> io(foo).recurse(except(".svn")) {||...}.

Very interesting.

>
> * Add an top-level shortcut for rio(?-, *)

I have been trying to avoid too much Kernel clutter, but am not sure
how much is too much. Your guidance is appreciated.

> * Add pipes. The following should be possible:
> io(foo) | io(bar) | io(baz)

I have wanted to do this for a while, but had not delved into it.
Very nice. Rio says "mucho gracias".

Cheers,
-Christopher

Dave Burt

unread,
Aug 26, 2005, 10:36:03 PM8/26/05
to
>> * - rel
> Please provide usage examples

io = rio("/absolute/path/to/foo") - rio("/absolute/path/") #=>
rio("to/foo")

Also, I there is a bug in io1.rel(io2) when io1 is absolute and io2 is
relative.

>> * each_filename (iterates over path components: "a/b/c" -> "a", "b",
>> "c")
> rio('a/b/c').filenames.each ?

That seems to fit the Rio way of doing things better. I assume that would
imply you can give a block straight to #filenames and it will pass it to
#each.

>> * children
> Another way to get the contents of a directory into an array? Is this
> the a non-grande version of []? a straight mapping of
> Pathname#children ? an alias for Rio#to_a ?
> I have no strong opinion either way.

I'm not sure why I put that on this list; it fits best with the next point.

>> * If Rio provided a superset of IO's functionality, you could use Rio
>> objects in place of IO objects, duck-type style. Same with File, Dir and
>> Pathname.
> The section "Using A Rio as an IO (or File or Dir)" in Rio::Doc::INTRO
> discusses this, with an illustration using a Rio with yaml.

I still think it would be fairly easy to have Rio able to replace IO, Dir,
File, Pathname in _all_ situations. Maybe this extra clutter would be best
placed in a mixin.

>> slurp and contents... maybe too many synonyms
> YES! Only one will survive the cut (or perhaps neither, if someone
> comes up with something better). Opinions are welcome.

contents works for me. What should it do for directories, though? Fail, or
return entries.join("\n")?

>> * dup needs fixing. I think it should perform a deep copy (i.e. copy
>> underlying IOs and other objects).
> Right now clone does that, while dup only copies the path.
> Did I get these backwards? What is the Ruby way?

dup doesn't work for rio(?-, "foo"); it gets turned into rio("foo")

I think clone should basically return an exact copy of the Rio objects,
which I think implies the underlying IO should be the same object; read one,
there should be nothing left to read from the other.

>> * Instead of the no* methods, you could add a wrapper ("except" or
>> "skip"...
>> or both) which could be passed into methods like so:
>> io(foo).recurse(except(".svn")) {||...}.
> Very interesting.

I'm not 100% happy with the implementation of this idea (I like the
wrapper). Alternatives to adding and testing for a mixin include inserting
an instance variable (which is uglier), or adding a method returning true to
the mixin, and the same method returning nil in Object (the definition is
more verbose and pollutes Object).

>> * Add an top-level shortcut for rio(?-, *)
> I have been trying to avoid too much Kernel clutter, but am not sure
> how much is too much. Your guidance is appreciated.

Yes, I realise you've been careful there, and it's important to be. I
retract that request. I was going to ask for rio("cmdio:foo") and friends
rio("stdin:") etc., but I tried it and it works... just needs to be
documented in INTRO.

(By the way, the line under "Creating a Rio that refers to a file
descriptor" in that document should read "an_io = ::IO.new(fd)")

It would also be nice to have a more reader-friendly way to create Rios of
these different types. You could accept a Symbol as the first argument:
rio(:fd, 2)
rio(:string, my_string)
rio(:stdin)
rio(:stdio)
rio(:cmdio, "sort")

Then there's the missing .new. Add:
Rio = RIO::Rio

And I don't think a set of methods like Rio.new_stdio, Rio.new_cmdio, would
go astray.

>> * Add pipes. The following should be possible:
>> io(foo) | io(bar) | io(baz)
> I have wanted to do this for a while, but had not delved into it.
> Very nice. Rio says "mucho gracias".

I will say "mucho gracias" to Rio when "|" happens - it is very very cool,
and will make irb a very handy general-purpose shell!

I must add, there are two things about Rio that make it appeal to me. The
first and foremost is a unified interface to IOs (File and Dir in
particular). The second is brevity in handle creation and useful operations.
I'm thinking of hacking irb to turn ./foo into rio("./foo"); I'll let you
know if that happens.

Cheers,
Dave


rio4ruby

unread,
Aug 28, 2005, 7:21:12 PM8/28/05
to
Dave Burt wrote:
> I was going to ask for rio("cmdio:foo") and friends
> rio("stdin:") etc., but I tried it and it works... just needs to be
> documented in INTRO.
>
> ...

>
> It would also be nice to have a more reader-friendly way to create Rios of
> these different types. You could accept a Symbol as the first argument:
> rio(:fd, 2)
> rio(:string, my_string)
> rio(:stdin)
> rio(:stdio)
> rio(:cmdio, "sort")
>
You're a damn genius, aren't you :)

The reason 'stdin:', 'stdout:", etc. are not documented, is that
they are not currently part of the published interface. I also
noticed that if you move the colon to the begining and removed
the quotes, you have a symbol. I have not decided whether to have
the string form, the symbol form or both be part of the
documented interface.

The string form is not actually an alternative syntax.
It is core to Rio.
rio(?-)
is immediatly converted to
rio('stdio:')

Internally all resources are converted to a URL-like syntax,
a IORL if you like. The fully qualified IORL for stderr is
rio:stderr:
Rio, of course, assumes the 'rio:' part, if missing.

You may have noticed also, that if you drop the 'r', you have
io:stderr:
A readable, language neutral, way of addressing I/O within a
program. Similar to localhost in a URL, io:stdin: always refers
to stdin of the current process.

My ideas in this area are not fully hashed out -- hence the
lack of documentation.

Cheers,
-Christopher

rio4ruby

unread,
Aug 28, 2005, 7:54:25 PM8/28/05
to
Dave Burt wrote:
> * Rename Rio#copy to Rio#copy_to

> * Add aliases:
> * append_to >>
> * copy_from <
> * append_from <<

This change has been checked into CVS, and will be in the next release.

> * Change + and =~ to use to_str instead of to_s.

This change has been checked into CVS, and will be in the next release.


> * Add the following Pathname functionality:
> * mountpoint?
> * root?
> * realpath
> * cleanpath

These will be included, but I have not finished evalutating their
integration into Rio.

> * Instead of the no* methods, you could add a wrapper ("except" or "skip"...
> or both) which could be passed into methods like so:
> io(foo).recurse(except(".svn")) {||...}.

When I was pondering a scheme for selection and rejection of files,
lines, etc. I decided from the start, that one thing I would
absolutely avoid is the introduction of a sub-language. I have seen
too many libraries do this only to become unusable to the casual
user. Rio's grande selection methods accept a Proc to deal with the
most general case and they accept every possible parameter type I
could dream up to handle most common cases. In my opinion, as readable
as 'except' is, it falls into the category of a sub-language.

> Also, I there is a bug in io1.rel(io2) when io1 is absolute and io2 is
> relative.

I will look into this. Thanks. A specific example would be helpful.

>
> >> * each_filename (iterates over path components: "a/b/c" -> "a", "b",
> >> "c")
> > rio('a/b/c').filenames.each ?
>
> That seems to fit the Rio way of doing things better. I assume that would
> imply you can give a block straight to #filenames and it will pass it to
> #each.
>

Rio#split returns an array of filenames, as described. This is not the
same as what you propose. Were #filenames a Rio configuration method,
it would take a block directly. This seems like a solid proposal. I
need to give this a little more thought, but at this point I am
inclined to dump #split in favor of #filenames.

> >> * If Rio provided a superset of IO's functionality, you could use Rio
> >> objects in place of IO objects, duck-type style. Same with File, Dir and
> >> Pathname.
> > The section "Using A Rio as an IO (or File or Dir)" in Rio::Doc::INTRO
> > discusses this, with an illustration using a Rio with yaml.
>
> I still think it would be fairly easy to have Rio able to replace IO, Dir,
> File, Pathname in _all_ situations. Maybe this extra clutter would be best
> placed in a mixin.
>

Ignoring the *big* problem with #<<, as described in RIO::Doc::INTRO,
Rio is close enough that it would be a shame not to allow a Rio to be
used anywhere an IO is. You have won me over on this one. Ditto File
and Dir

Off the top of my head, what would you think of an emulation mode
rio(...).likeio
or somesuch?
Describe how you see a mixin working.

Pathname is another matter. IO, File and Dir are integral parts of
Ruby. Pathname is not. I am not convinced that providing emulation
of legacy libraries such as Pathname should be a priority.

> * Add pipes. The following should be possible:
> io(foo) | io(bar) | io(baz)

I still love this idea. After revisiting it, I remembered why I had
put it aside before. Its behaviour is obvious in some cases ie. where
'foo' is a file, and 'bar' is a cmdio and 'baz' is a file, or if they
are all cmdios. It becomes murky to me what the behaviour should be
if, for instance, they are all files.

To generalize, for duplex streams, piping is clear, but for non-duplex
streams, what exactly does piping mean?

One possibility that comes to mind is making it simply a copy-to in
those cases. That would make possible the following:

# tee the output of 'acmd' to a file and to stdout.
rio(?-,'acmd') | rio('output_file') | rio(?-)

Another possibility, is to simply raise an error unless one of the
participants is a duplex-stream.

Another possibility, is that I don't understand what you are proposing.

This is too elegant to not be included in Rio. I need help defining
what its behaviour should be.

Cheers,
-Christopher

Dave Burt

unread,
Aug 29, 2005, 4:10:28 AM8/29/05
to
"rio4ruby" <rio4...@rubyforge.org> wrote in message
news:1125271272.4...@g47g2000cwa.googlegroups.com...

Dave Burt

unread,
Aug 29, 2005, 4:18:09 AM8/29/05
to
(Sorry about the blank post prior to this)

Christopher wrote:
> The reason 'stdin:', 'stdout:", etc. are not documented, is that
> they are not currently part of the published interface. I also
> noticed that if you move the colon to the begining and removed
> the quotes, you have a symbol. I have not decided whether to have
> the string form, the symbol form or both be part of the
> documented interface.

I like both, and would like to have the option to use either. I prefer the
symbol, but having the string be a key part of the concept of a Rio object,
like a URL protocol, and showing up as such in #inspect, isn't a bad idea. I
don't like the character/Fixnum; the brevity is good, but a single-character
prefix in the string itself is shorter... maybe makes Rio less flexible,
though - rio("!sort") for a cmdio?

Cheers,
Dave


Dave Burt

unread,
Aug 29, 2005, 4:40:06 AM8/29/05
to
Christopher wrote:
> When I was pondering a scheme for selection and rejection of files,
> lines, etc. I decided from the start, that one thing I would
> absolutely avoid is the introduction of a sub-language. I have seen
> too many libraries do this only to become unusable to the casual
> user. Rio's grande selection methods accept a Proc to deal with the
> most general case and they accept every possible parameter type I
> could dream up to handle most common cases. In my opinion, as readable
> as 'except' is, it falls into the category of a sub-language.
>
>> Also, I there is a bug in io1.rel(io2) when io1 is absolute and io2 is
>> relative.
> I will look into this. Thanks. A specific example would be helpful.

irb(main):002:0> rio('/usr/bin/ruby').rel('foo/bar')
=> #<Rio:0x1620220:"path:../../usr/bin/ruby" (Path::Reset)>

I'm not sure what the correct answer is; probably an exception would be
appropriate. Otherwise, if the parameter is relative, you might want to
evaluate it as an absolute path from the working directory.

> Ignoring the *big* problem with #<<, as described in RIO::Doc::INTRO,
> Rio is close enough that it would be a shame not to allow a Rio to be
> used anywhere an IO is. You have won me over on this one. Ditto File
> and Dir
>
> Off the top of my head, what would you think of an emulation mode
> rio(...).likeio
> or somesuch?
> Describe how you see a mixin working.

I was thinking of a mixin that mainly adds aliases and wrappers to
functionality that's already in Rio. It might override #<< to be
IO-compatible (probably retaining the Rio semantics for rio << rio). You
could mix it in like this:
r = rio(foo)
r.extend(Rio::IO)
some_method_which_wants_an_io(r)

You could add a #to_io method:
class Rio # I'm not sure if this is the right class to put it in - what is
Base?
def to_io
clone.extend(Rio::IO)
end
end

I'm not sure what the ethics of having a to_x method that only returns a
duck-X, but if it does fully quack right, I don't mind.

> Pathname is another matter. IO, File and Dir are integral parts of
> Ruby. Pathname is not. I am not convinced that providing emulation
> of legacy libraries such as Pathname should be a priority.

Fair enough. I don't get Pathname 100%, either (in particular, why is
Pathname#chdir deprecated?)

>> * Add pipes. The following should be possible:
>> io(foo) | io(bar) | io(baz)
>
> I still love this idea. After revisiting it, I remembered why I had
> put it aside before. Its behaviour is obvious in some cases ie. where
> 'foo' is a file, and 'bar' is a cmdio and 'baz' is a file, or if they
> are all cmdios. It becomes murky to me what the behaviour should be
> if, for instance, they are all files.
>
> To generalize, for duplex streams, piping is clear, but for non-duplex
> streams, what exactly does piping mean?
>
> One possibility that comes to mind is making it simply a copy-to in
> those cases. That would make possible the following:
>
> # tee the output of 'acmd' to a file and to stdout.
> rio(?-,'acmd') | rio('output_file') | rio(?-)
>
> Another possibility, is to simply raise an error unless one of the
> participants is a duplex-stream.

Initially I preferred the error, but the tee makes sense, even if it's a
little less than obvious. An input-only stream is still going to produce an
error, isn't it?

> Another possibility, is that I don't understand what you are proposing.
>
> This is too elegant to not be included in Rio. I need help defining
> what its behaviour should be.

If you like it, and you understand *nix shell process-chaining pipes, then
you understand.

Cheers,
Dave


rio4ruby

unread,
Sep 6, 2005, 8:26:57 PM9/6/05
to
Dave Burt wrote:
>>> Also, I there is a bug in io1.rel(io2) when io1 is absolute and io2 is
>>> relative.
>> I will look into this. Thanks. A specific example would be helpful.

> irb(main):002:0> rio('/usr/bin/ruby').rel('foo/bar')
> => #<Rio:0x1620220:"path:../../usr/bin/ruby" (Path::Reset)>

> I'm not sure what the correct answer is; probably an exception would be
> appropriate. Otherwise, if the parameter is relative, you might want to
> evaluate it as an absolute path from the working directory.

Your example seems wrong, but is actually correct. If you ran
the code in the directory /baz.

Rio does, in fact, do exactly what you suggest -- it converts the
relative path foo/bar to /baz/foo/bar. Non-existant paths are assumed
to be files, and so the path to /usr/bin/ruby relative to the
directory /baz/foo is ../../usr/bin/ruby.

I do not necessarily defend this behaviour, but it is consistant with
the Ruby standard library class URI. Rio#rel uses URI#route_from to
calculate relative paths, and that is what the URI class does:

irb(main):004:0*
URI('http://localhost/usr/bin/ruby').route_from('http://localhost/baz/foo/bar')
=> #<URI::Generic:0x813057c URL:../../usr/bin/ruby>

Rio had been checking to see if foo/bar is a directory, and
if so produce ../../../usr/bin/ruby. Somewhere along the
way that got lost. This is a bug.

Non-existant paths can be forced to be treated as directories by ending

them with a slash.

irb(main):007:0> rio('/usr/bin/ruby').rel('foo/bar/')
=> #<Rio:0x829db3c:"path:../../../usr/bin/ruby" (Path::Reset)>

Again this is done, because this is what URI does.

irb(main):005:0>
URI('http://localhost/usr/bin/ruby').route_from('http://localhost/baz/foo/bar/')
=> #<URI::Generic:0x812dfa8 URL:../../../usr/bin/ruby>

I am open to suggestions in this area.

Cheers,
-Christopher

rio4ruby

unread,
Sep 6, 2005, 8:31:21 PM9/6/05
to

Dave Burt wrote:
> I like both, and would like to have the option to use either.

You now have both -- and more. You now can create pathless Rios in
the following ways (using strio as an example)
str = "Hello World\n"

rio(?",str)
rio(:strio,str)
rio("strio:",str)
rio.strio(str)
RIO.strio(str)
RIO::Rio.strio(str)
RIO::Rio.new(char_or_symbol_or_string_as above,str)
RIO::rio(char_or_symbol_or_string_as above,str)
RIO::Rio.rio(char_or_symbol_or_string_as above,str)

I most likely will drop some of these in the next release, based on the

feedback I get.

> I prefer the
> symbol, but having the string be a key part of the concept of a Rio object,
> like a URL protocol, and showing up as such in #inspect, isn't a bad idea.

In each of the following the part in quotes after the second colon
is the IORL.

irb(main):005:0> rio(?=)
=> #<Rio:0x81334f8:"stderr:" (Stream::Open)>
irb(main):006:0> rio(?#,2)
=> #<Rio:0x81299d0:"fd:2" (Stream::Open)>
irb(main):007:0> rio($stderr)
=> #<Rio:0x812346c:"sysio:0x08076f1c" (Stream::Open)>
irb(main):008:0> rio('foo/bar')
=> #<Rio:0x811d898:"path:foo/bar" (Path::Reset)>
irb(main):009:0> rio('/tmp')
=> #<Rio:0x8126088:"file:///tmp" (Path::Reset)>
irb(main):010:0> rio('http://localhost/')
=> #<Rio:0x81234c0:"http://localhost/" (HTTP::Stream::Open)>
irb(main):011:0> rio(??,'zippy','/tmp')
=> #<Rio:0x82a5fa0:"temp:/tmp/zippy" (Temp::Reset)>

> I don't like the character/Fixnum; the brevity is good, but a single-character
> prefix in the string itself is shorter... maybe makes Rio less flexible,
> though - rio("!sort") for a cmdio?

Originally I was using single character strings like rio('-') for
stdio:,
as the super brief version -- which is longer than rio(?-).
At the time I felt that the single character was cleaner (is that
stdio,
or a file named '-').

The embedded character works in some places, and certainly has
precedant,
but what do you propose for strio, stdio and the others?

I would like to have this issue decided by the next release.

0 new messages