The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Dear glob

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Brian Ford

Posts: 153
Nickname: brixen
Registered: Dec, 2005

Brian Ford is Rails developer with PLANET ARGON.
Dear glob Posted: Sep 17, 2007 12:26 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Brian Ford.
Original Post: Dear glob
Feed Title: def euler(x); cos(x) + i*sin(x); end
Feed URL: http://feeds.feedburner.com/defeulerxcosxisinxend
Feed Description: euler(PI) # => -1
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Brian Ford
Latest Posts From def euler(x); cos(x) + i*sin(x); end

Advertisement

At some point, you likely needed to grab some files and do something with them. You probably had a vague recollection about Dir[] from reading the Pickaxe book. To refresh your memory, you crack it open and fire up irb. Ah, easy…


  irb(main):001:0> Dir['spec/**/*_spec.rb'].each do |file|
  irb(main):002:1* puts file
  irb(main):003:1> end

There’s no denying that Ruby makes this task dead simple. So simple, in fact, that you probably don’t think twice about how that nifty Dir[] method does its work. That is, unless you’re trying to implement it.

During the Rubinius sprint, I realized that having this in Rubinius would enable me to make our continuous integration spec runner much better. Now, I know that there’s a glob function in C that provides behavior similar to what you get in the shell using * and ? to match file names. There’s also a function fnmatch that wraps up some of that magic. No problem. We’ve got this nifty foreign-function interface (FFI) that Evan has graciously provided. Evan recommended I take that route first. Yep, took all of 10 minutes to hook everything up.

Of course, it wouldn’t be that interesting were this the end of the story. It’s not. Our fnmatch specs were mostly passing, but when I looked into the failing ones, I discovered something that I’d probably tried to shield my psyche from. Ruby implements its own fnmatch and glob functions. And when I say ‘implements’, it doesn’t really give you any idea of the pain and suffering involved. Do take a peek:

It doesn’t take but a minute to see that Ola Bini’s java code is extraordinarily more readable than the MRI source. But both are daunting to say the least. So, I’ve decided to take a different route.


  def self.fnmatch(pattern, path, flags=0)
    pattern = StringValue(pattern).dup
    path = StringValue(path).dup
    escape = (flags & FNM_NOESCAPE) == 0
    pathname = (flags & FNM_PATHNAME) != 0
    nocase = (flags & FNM_CASEFOLD) != 0

    pattern.gsub!('.', '\.')
    subs = { /\*{1,2}/ => '(.*)', /\?/ => '(.)', /\{/ => '\{', /\}/ => '\}' }
    subs.each { |p,s| pattern.gsub!(p, s) }
    if escape
      pattern.gsub!(/\\([*?\[\]])/, '\1')
      pattern.gsub!(/\\([^*?\[\]])/, '\1')
    else
      pattern.gsub!(/(\\)([^*?\[\]])/, '\1\1\2')
    end

    re = Regexp.new("^#{pattern}$", nocase ? Regexp::IGNORECASE : 0)
    m = re.match path
    if m
      return false unless m[0].size == path.size
      m.captures.each { |c| return false if c.include?('/') and pathname }
      return true
    else
      return false
    end
  end

This code is only passing 80% of our existing specs for File.fnmatch?, so the jury is still out. And I’m sure someone can make this much better. The lesson for me is that 1) Ruby’s implementation is typically not accessible (I already knew that), and 2) writing Ruby code is a good way to handle tough problems.

But then, you already knew that. ;)

Read: Dear glob

Topic: Come tipp some links with us Previous Topic   Next Topic Topic: More Protest - win32-api

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use