Fools Filing

Ya know, it always seems like I’m jump’n all around with these file/
dir related classes/modules/methods.

We have:

  • File
  • Dir
  • FileTest
  • FileUtils
  • Pathname

Not to mention the String we often use to store the filename. It seems
so hap hazard and the code is more often than not looking distinctly
non-OOP. While using pathname helps, it doesn’t seem to quite cut it,
and I end falling back to File or Dir here and there.

So I came upon and particular case that got me thinking what the
fundamental problem might be. I had extended Pathname with #glob
basically like so:

def glob(pattern, opts=0)
Dir.glob(self + pattern, opts).collect{ |f| Pathname.new(f) }
end

Works great. But then I went to do:

somepathname.mkdir(‘foo’)

And it bombed. Why? Because it doesn’t expect a path argument, but
rather it wants to make the directory indicated by the pathname object
itself. So the two method don’t mesh well. You might think that my
glob definition is the one out of sync, but if you define glob to act
on the pathname itself, eg. Pathname.new(’*’).glob, code starts to get
ugly again. Compare:

(Pathname.new(‘foo’) + ‘’).glob
Pathname.new(‘foo’).glob(’
’)

My immediate thought was then, what about Dir, does it support #glob?
That was immediately followed by, “hey, I never ever use Dir.new”.
That was key. I looked it up:

Instance Methods:
close, each, path, pos, pos=, read, rewind, seek, tell

That’s it. I don’t even fully understand what all those do. It’s
treating a Dir as an IO object?

And there’s the problem, what we need are “lazy” File and Dir classes
that delegate to the IO ones, that allow us to do everything we need,
rather than fussing with all these others.

I think I’ll throw this together. Anyone else interested?

T.

On Tue, 2008-08-19 at 15:19 +0900, Trans wrote:

I think I’ll throw this together. Anyone else interested?

http://rio.rubyforge.org

Is this kind of what you have in mind?

Trans wrote:

My immediate thought was then, what about Dir, does it support #glob?
That was immediately followed by, “hey, I never ever use Dir.new”.
That was key. I looked it up:

Instance Methods:
close, each, path, pos, pos=, read, rewind, seek, tell

That’s it. I don’t even fully understand what all those do. It’s
treating a Dir as an IO object?

This is wrapping the diropen function from C. Calling opendir returns a
DIR* (which is similar to a FILE*). Individual directory entities can
be read one at a time with readdir and the rest just modify the position
indicator.

Reading them all with glob may not always be appropriate. On very large
directories (thousands of files), that would be pretty slow and use a
good chunk of RAM.

And there’s the problem, what we need are “lazy” File and Dir classes
that delegate to the IO ones, that allow us to do everything we need,
rather than fussing with all these others.

I think I’ll throw this together. Anyone else interested?

T.

Can you give a mockup of what you’re talking about?

On Tue, Aug 19, 2008 at 2:35 AM, Michael T. Richter
[email protected] wrote:

On Tue, 2008-08-19 at 15:19 +0900, Trans wrote:

I think I’ll throw this together. Anyone else interested?

http://rio.rubyforge.org

+1


Avdi

Home: http://avdi.org
Developer Blog: Avdi Grimm, Code Cleric
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com

On Aug 19, 2:35 am, “Michael T. Richter” [email protected] wrote:

On Tue, 2008-08-19 at 15:19 +0900, Trans wrote:

I think I’ll throw this together. Anyone else interested?

http://rio.rubyforge.org

Is this kind of what you have in mind?

Where’s that lib been hiding?

Pretty nice stuff and well documented (in a very interesting way too
btw, using rdoc on =begin comments in modules). However, it’s not
quite what I had in mind. This is more like a special DSL --a very
good and useful one, but I’m thinking more along the lines of
emulating how we actually interact with the file system in a command
shell.

T.

On Aug 19, 2:45 am, Michael M. [email protected] wrote:

This is wrapping the diropen function from C. Calling opendir returns a
DIR* (which is similar to a FILE*). Individual directory entities can
be read one at a time with readdir and the rest just modify the position
indicator.

Reading them all with glob may not always be appropriate. On very large
directories (thousands of files), that would be pretty slow and use a
good chunk of RAM.

I see. That’s good to know actually. These are some cases were I could
use this to optimize my code.

And there’s the problem, what we need are “lazy” File and Dir classes
that delegate to the IO ones, that allow us to do everything we need,
rather than fussing with all these others.

I think I’ll throw this together. Anyone else interested?

Can you give a mockup of what you’re talking about?

I’ve been working on it today. I post it up tomorrow.

T.

On Aug 20, 7:29 am, “Michael T. Richter” [email protected] wrote:

Then I will await your library with worms on my tongue. I mean
baited^Wbated breath.

Well, worms or no, I put out a first draft of the project today. The
gem should seed in about an hour.

$ sudo gem install folio

The website has quick and dirty README that is not 100% in sync with
the API yet, but it give the overall idea nonetheless:

http://folio.rubyforge.org

Note that this is very very very much an alpha release. The api will
change. But the overall design structure is in place, so you can see
how it basically works.

I have a few issues to workout:

  • What methods to provide to return a list of file names, versus
    file objects, versus an enumerator of file objects.
  • Whether dryrun, verbose, etc. modes should propagate from the
    “prompt” object into the file objects.
  • Is there a better name for Prompt? (Cursor maybe?)
  • Best name for file object classes: File instead of Document?
    Folder instead of Directory?

T.