From noreply at rubyforge.org Wed Jul 18 21:29:56 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Wed, 18 Jul 2007 21:29:56 -0400 (EDT)
Subject: [Facets] [ facets-Patches-12397 ] FileUtils.which/whereis: Add .cmd
to other extensions (.bat, .exe)
Message-ID: <20070719012956.87AE05240F0A@rubyforge.org>
Patches item #12397, was opened at 2007-07-18 18:29
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3171&aid=12397&group_id=804
Category: None
Group: None
Status: Open
Resolution: None
Priority: 3
Submitted By: Tyler Rick (tylerrick)
Assigned to: Nobody (None)
Summary: FileUtils.which/whereis: Add .cmd to other extensions (.bat, .exe)
Initial Comment:
In both of these files:
/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/fileutils/which.rb
/usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/fileutils/whereis.rb
I believe that .cmd should be added as a valid win32 executable extension, like so:
if defined?(Win32Exts)
Win32Exts ||= %w{.exe .com .bat .cmd}
else
Win32Exts = %w{.exe .com .bat .cmd}
end
I only discovered this .cmd extension today, but apparently that's how RubyGems works on windows: it creates a .cmd wrapper for all executables specified in a gems gemspec when you install the gem.
Examples:
>dir c:\ruby\bin\rails.*
Volume in drive C has no label.
Volume Serial Number is 4C33-932F
Directory of c:\ruby\bin
2007-07-17 11:12 352 rails
2007-07-17 11:12 30 rails.cmd
2 File(s) 382 bytes
0 Dir(s) 1,827,725,312 bytes free
rails.cmd is what gets executed when you type rails from the command line. (And then rails.cmd immediately calls 'ruby rails %*')
But FileUtils.which returns nil!:
>irb
irb> require 'facets/core/fileutils/whereis'
=> true
irb> require 'facets/core/fileutils/which'
=> true
irb> FileUtils.which('rails')
=> nil
irb> FileUtils.whereis('rails')
=> nil
Another example:
> irb
irb> require 'facets/core/fileutils/which'
irb> require 'facets/core/fileutils/whereis'
irb> ENV['PATH']
=> "C:\ruby\lib\ruby\gems\1.8\gems\subwrap-0.3.3\bin;c:\ruby\bin;C:\Program Files\Subversion\bin"
# This should return
# "C:\ruby\lib\ruby\gems\1.8\gems\subwrap-0.3.3\bin\svn.cmd"
# since that directory is listed first in ENV['PATH'], but instead
# it only lists the svn.exe file
irb> FileUtils.which('svn')
=> "C:\Program Files\Subversion\bin\svn.exe"
# Currently, the only way to find a .cmd file is to explicitly include .cmd in the string you pass to FileUtils.which
irb> FileUtils.which('svn.cmd')
=> "C:\ruby\lib\ruby\gems\1.8\gems\subwrap-0.3.3\bin\svn.cmd"
Thanks,
Tyler :-)
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3171&aid=12397&group_id=804
From noreply at rubyforge.org Wed Jul 25 01:26:00 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Wed, 25 Jul 2007 01:26:00 -0400 (EDT)
Subject: [Facets] [ facets-Feature Requests-12559 ] Improved snapshot.rb
Message-ID: <20070725052600.75B425240F02@rubyforge.org>
Feature Requests item #12559, was opened at 2007-07-24 22:25
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3172&aid=12559&group_id=804
Category: None
Group: Next Release (example)
Status: Open
Priority: 3
Submitted By: Nasir Khan (rnakhan)
Assigned to: Nobody (None)
Summary: Improved snapshot.rb
Initial Comment:
Consider adding optional fields argument to both take_snapshot() and restore_snapshot() to selectively take snapshot of selected fields as against all fields which is the default.
Patch provided below over 1.8.54 : methods changes take_snapshot and restore_snapshot.
# = snapshot.rb
#
# == Copyright (c) 2004 Michael Neumann
#
# Ruby License
#
# This module is free software. You may use, modify, and/or redistribute this
# software under the same terms as Ruby.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.
#
# == Author(s)
#
# * Michael Neumann
#
# == Developer Notes
#
# TODO Perhaps extend to offer multiple depths.
#
# TODO Should key consitancy be enforced? Currently
# Struct's will have symobl keys while other classes
# will have string keys in the form of "@name".
#
# TODO Add other core classes.
#
# TODO Convert to Kernel#to_data ?
# Author:: Michael Neumann
# Copyright:: Copyright (c) 2004 Michael Neumann
# License:: Ruby License
# = Snapshot
#
# A lightweight single-depth object state capture.
# The #take_snapshot method reads the object's state,
# which is generally it's collection of instance variables,
# and returns them in a hash. The state can be restored
# with #apply_snapshot.
#
# == Usage
#
# Customer = Struct.new("Customer", :name, :address, :zip)
# joe = Customer.new( "Joe Pitare", "1115 Lila Ln.", 47634 )
#
# # simple transactions
# joe_snap = joe.take_snapshot
# begin
# do_something_with( joe )
# rescue
# joe.apply_snapshot( joe_snap )
# end
#
# joe_snap[:name] => "Joe Pitare"
# joe_snap[:address] => "1115 Lila Ln."
# joe_snap[:zip] => 47634
#
# == Details
#
# Class Snapshot simply represents a collection of objects from
# which snapshots were taken via their methods #take_snapshot.
# It provides methods to add an object to a snapshot
# (Snapshot#add) as well as to restore all objects
# of the snapshot to their state stored in the snapshot (method
# Snapshot#restore).
#
# In Wee, this class is used to backtracking the state of
# components (or decorations/presenters). Components that want
# an undo-facility to be implemented (triggered for example by
# a browsers back-button), have to overwrite the
# Wee::Component#backtrack_state method.
class Snapshot
def initialize
@objects = Hash.new
end
def add(object)
oid = object.object_id
@objects[oid] = [object, object.take_snapshot] unless @objects.include?(oid)
end
def restore
@objects.each_value { |object, value| object.restore_snapshot(value) }
end
end
# Simplist form of a snapshot.
#
#module SnapshotMixin
# def take_snapshot() dup end
# def restore_snapshot(snap) replace(snap) end
#end
# Implements a value holder. In Wee this is useful for
# backtracking the reference assigned to an instance variable
# (not the object itself!). An example where this is used is the
# @__decoration attribute of class Wee::Component.
class Snapshot::ValueHolder
attr_accessor :value
def initialize(value=nil)
@value = value
end
def take_snapshot
@value
end
def restore_snapshot(value)
@value = value
end
end
#--
# Extend some base classes of Ruby (Object, Array, String, Hash,
# Struct) for the two methods #take_snapshot and
# #restore_snapshot, required by Snapshot.
#++
class Object
def take_snapshot(fields=nil)
snap = Hash.new
fields = instance_variables unless fields
fields.each do |iv|
snap[iv] = instance_variable_get(iv)
end
snap
end
def restore_snapshot(snap, fields=nil)
fields = instance_variables unless fields
fields.each do |iv|
instance_variable_set(iv, snap[iv])
end
end
end
class Array
def take_snapshot() dup end
def restore_snapshot(snap) replace(snap) end
end
class String
def take_snapshot() dup end
def restore_snapshot(snap) replace(snap) end
end
class Hash
def take_snapshot() dup end
def restore_snapshot(snap) replace(snap) end
end
class Struct
def take_snapshot
snap = Hash.new
each_pair {|k,v| snap[k] = v}
snap
end
def restore_snapshot(snap)
snap.each_pair {|k,v| send(k.to_s + "=", v)}
end
end
# _____ _
# |_ _|__ ___| |_
# | |/ _ \/ __| __|
# | | __/\__ \ |_
# |_|\___||___/\__|
#
=begin testing
require 'test/unit'
class TC_Snapshot < Test::Unit::TestCase
def setup
customer = Struct.new("Customer", :name, :address, :zip)
joe = customer.new( "Joe Pitare", "1115 Lila Ln.", 47634 )
@joe_snap = joe.take_snapshot
end
def test_storage
assert_equal( "Joe Pitare", @joe_snap[:name] )
assert_equal( "1115 Lila Ln.", @joe_snap[:address] )
assert_equal( 47634, @joe_snap[:zip] )
end
end
=end
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3172&aid=12559&group_id=804
From noreply at rubyforge.org Thu Jul 26 05:22:40 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Thu, 26 Jul 2007 05:22:40 -0400 (EDT)
Subject: [Facets] [ facets-Bugs-10372 ] String#index_all breaks when passed
a String for a search term
Message-ID: <20070726092241.3A15B5240A26@rubyforge.org>
Bugs item #10372, was opened at 2007-04-25 18:34
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=10372&group_id=804
Category: None
Group: None
>Status: Closed
>Resolution: Accepted
Priority: 3
Submitted By: Tyler Rick (tylerrick)
Assigned to: Nobody (None)
Summary: String#index_all breaks when passed a String for a search term
Initial Comment:
The existing test shows that it works for Regexp as input:
def test_index_all_with_regexp
assert_equal( [0,4,8], "a123a567a9".index_all(/a/) )
end
but doesn't take into account the other 2 classes of search terms that a user might want to pass in (at least if you're trying to offer behavior analogous to that of String#index, http://corelib.rubyonrails.org/classes/String.html#M001505, which I hope you are)...
I've added a new test case for strings:
def test_index_all_with_string
assert_equal( [0,4,8], "a123a567a9".index_all('a') )
end
... which fails unless the implementation is changed.
NoMethodError: undefined method `length' for nil:NilClass
Changing this line:
i += (reuse ? 1 : $~.length )
to this seems to have fixed the problem:
i += (reuse ? $~.length : 1 )
I really don't understand the reuse flag (could you add some comments explaining how it works and (to the docs) why I'd ever want to use that flag (performance boost??), but it looked like you just had the order mixed up on that one line :)
Would suggest a test such as this be added that actually exercises that behavior:
def test_index_all_with_regexp_reuse
assert_equal( [0,4,8], "a123a567a9".index_all(/a/, true) )
end
I tried to see what was going on by adding this line:
puts "Incrementing by #{ (reuse ? $~.length : 1 ) }"
but it printed "1" for all of 3 tests, indicating that the reuse flag didn't make one iota of difference...
Question: Should it only use $~ if s is a Regexp? (Should it *automatically* use it if $~ is a Regexp?)
$~ appears to not even be set if s is a string; only if it's a Regexp, so we probably shouldn't let people shoot their foot off by calling index_all('a', true)...
Haven't even looked at the Fixnum===s case.
class String
# Like index but returns an array of all index locations.
# The reuse flag allows the trailing portion of a match to be
# reused for subsquent matches.
#
# "abcabcabc".index_all('a') #=> [0,3,6]
#
def index_all(s, reuse=false)
ia = []; i = 0
while (i = self.index(s,i))
ia << i
i += (reuse ? $~.length : 1 )
end
ia
end
end
By the way, thanks for this method. I was just about to create my own String#nth_index(s, 2) method, but then saw this and decided I could just use index_all(s)[2] instead...
----------------------------------------------------------------------
Comment By: Trans Onoma (transami)
Date: 2007-07-26 04:20
Message:
Thanks for the bug report. I added
s = Regexp.new(Regexp.escape(s)) unless Regexp===s
To take into account the string case.
As for the reuse flag. Turns out the real problem wasn't the order but '$~.size'. The fix is:
i += (reuse ? 1 : $~[0].size)
The reuse flag increments the search offset by one, without it the search index is incremented by the size of the last match. The difference is:
"bbb".index_all('bb') => [0]
"bbb".index_all('bb',true) => [0,1]
Should be all good now for next release (Facets 2.0).
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=10372&group_id=804
From noreply at rubyforge.org Thu Jul 26 05:41:50 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Thu, 26 Jul 2007 05:41:50 -0400 (EDT)
Subject: [Facets] [ facets-Bugs-9466 ] String margin error
Message-ID: <20070726094150.53C415240A3D@rubyforge.org>
Bugs item #9466, was opened at 2007-03-22 07:50
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=9466&group_id=804
Category: None
Group: None
>Status: Closed
>Resolution: Accepted
Priority: 3
Submitted By: Trans Onoma (transami)
Assigned to: Nobody (None)
Summary: String margin error
Initial Comment:
I have been getting errors from Facets when I use the margin facility:
brains hgs 52 %> ./class_generator.rb
/usr/local/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/string/margin.rb:16:in `margin': undefined method `[]' for nil:NilClass (NoMethodError)
from ./class_generator.rb:353:in `process_arg'
from ./class_generator.rb:309:in `each_pair'
from ./class_generator.rb:309:in `process_arg'
from ./class_generator.rb:191:in `initialize'
from ./class_generator.rb:132:in `open'
from ./class_generator.rb:132:in `initialize'
from ./class_generator.rb:2079:in `new'
from ./class_generator.rb:2079
brains hgs 53 %> cat -n /usr/local/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/string/margin.rb | body 10 20
10 # }.margin
11 #
12 #--
13 # This may still need a bit of tweaking.
14 #++
15 def margin(n=0)
16 d = /\A.*\n\s*(.)/.match( self )[1]
17 d = /\A\s*(.)/.match( self)[1] unless d
18 return '' unless d
19 if n == 0
20 gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, '')
brains hgs 54 %>
It seems to me that match is only ever used if it will fail (it is
a test). Line 17 expects possible failure of line 16 ("unless d").
When match fails, it returns nil.
----------------------------------------------------------- Regexp#match
rxp.match(str) => matchdata or nil
------------------------------------------------------------------------
Returns a +MatchData+ object describing the match, or +nil+ if
there was no match. This is equivalent to retrieving the value of
the special variable +$~+ following a normal match.
/(.)(.)(.)/.match("abc")[2] #=> "b"
Nil does not have the [] method, so arguably the example in the docs
is buggy as well. I suggest the following change in the patch
below.
However, I have a problem. Running setup will attempt a full install.
Running
setup.rb config
setup.rb setup
setup.rb test
tells me that it has run 0 tests, with 0 failures and 0 errors.
How do I get tests to run to be sure that this change doesn't
break things before I install?
--Hugh
--- facets-1.8.54/lib/facets/core/string/margin.rb.orig 2007-02-20 15:39:38.000000000 +0000
+++ facets-1.8.54/lib/facets/core/string/margin.rb 2007-03-22 11:37:53.927850000 +0000
@@ -13,8 +13,8 @@
# This may still need a bit of tweaking.
#++
def margin(n=0)
- d = /\A.*\n\s*(.)/.match( self )[1]
- d = /\A\s*(.)/.match( self)[1] unless d
+ d = ((/\A.*\n\s*(.)/.match( self )) ||
+ (/\A\s*(.)/.match( self)))[1]
return '' unless d
if n == 0
gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, '')
----------------------------------------------------------------------
>Comment By: Trans Onoma (transami)
Date: 2007-07-26 04:41
Message:
Thanks for the report. I made your changes and tested. It looks good. It would be good to have a test case for what was creating this error, though. Do you have a simple example?
As for testing. The basic way it to remark the test block, putting a # in front of =being and =end like so:
#=begin test
...
#=end
Then just run the script. It has no other dependencies so no worries about the load_path. I actually use a tool that does this automatically for me. 'gem install 'exacto' and then:
$ exrb margin.rb
Also, I have a script that extracts all embedded tests and adds them to test/. (I haven't released that yet though.) I should have shipped those tests with the package. I'll fix that for the next release.
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=9466&group_id=804
From noreply at rubyforge.org Thu Jul 26 09:21:00 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Thu, 26 Jul 2007 09:21:00 -0400 (EDT)
Subject: [Facets] [ facets-Bugs-9988 ] Singular function fails many tests
Message-ID: <20070726132100.DB3DC5240BAF@rubyforge.org>
Bugs item #9988, was opened at 2007-04-09 08:19
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=9988&group_id=804
Category: None
Group: None
Status: Open
>Resolution: Postponed
Priority: 3
Submitted By: Nobody (None)
Assigned to: Nobody (None)
Summary: Singular function fails many tests
Initial Comment:
I ran some additional tests on the Singular function and it failed 10 out of the following 68 tests:
tests["Americans"] = "American"
tests["analyses"] = "analysis"
tests["bays"] = "bay"
tests["bureaus"] = "bureau"
tests["businesses"] = "business"
tests["cacti"] = "cactus"
tests["cactuses"] = "cactus"
tests["calves"] = "calf"
tests["carpets"] = "carpet"
tests["chiefs"] = "chief"
tests["choruses"] = "chorus"
tests["churches"] = "church"
tests["companies"] = "company"
tests["courses"] = "course"
tests["cows"] = "cow"
tests["crashes"] = "crash"
tests["criteria"] = "criterion"
tests["discos"] = "disco"
tests["doors"] = "door"
tests["factories"] = "factory"
tests["farms"] = "farm"
tests["farmers"] = "farmer"
tests["faxes"] = "fax"
tests["firemen"] = "fireman"
tests["fish"] = "fish"
tests["flowers"] = "flower"
tests["forks"] = "fork"
tests["foxes"] = "fox"
tests["friends"] = "friend"
tests["garages"] = "garage"
tests["gardens"] = "garden"
tests["geese"] = "goose"
tests["grown-ups"] = "grown-up"
tests["heroes"] = "hero"
tests["highways"] = "highway"
tests["horses"] = "horse"
tests["hovercraft"] = "hovercraft"
tests["indexes"] = "index"
tests["indices"] = "index"
tests["kisses"] = "kiss"
tests["lives"] = "life"
tests["lights"] = "light"
tests["loaves"] = "loaf"
tests["memos"] = "memo"
tests["mountains"] = "mountain"
tests["mice"] = "mouse"
tests["ovens"] = "oven"
tests["parties"] = "party"
tests["pens"] = "pen"
tests["pennies"] = "penny"
tests["potatoes"] = "potato"
tests["prizes"] = "prize"
tests["proofs"] = "proof"
tests["scarves"] = "scarf"
tests["series"] = "series"
tests["staples"] = "staple"
tests["statuses"] = "status"
tests["stores"] = "store"
tests["Swiss"] = "Swiss"
tests["tables"] = "table"
tests["take-offs"] = "take-off"
tests["teachers"] = "teacher"
tests["theses"] = "thesis"
tests["thieves"] = "thief"
tests["tomatoes"] = "tomato"
tests["torpedoes"] = "torpedo"
tests["videos"] = "video"
tests["watches"] = "watch"
----------------------------------------------------------------------
>Comment By: Trans Onoma (transami)
Date: 2007-07-26 08:21
Message:
Nice work! Thanks, for catching these. We'll work on this soon.
But BIG NEWS here too. inflect.rb is one of libraries being spun-off from Facets. It will now be found in the English project. (http://english.rubyforge.org). The intent is that we can better develop a solid, strong english grammer and general "writ-processing" library by having it separate.
I'll keep the community posted when this get's it's first release. If anyone is interested in becoming a main developer on that project, please let me know. --trans
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=9988&group_id=804
From noreply at rubyforge.org Thu Jul 26 09:37:02 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Thu, 26 Jul 2007 09:37:02 -0400 (EDT)
Subject: [Facets] [ facets-Bugs-11544 ] FileUtils.compress('zip', 'filepath',
'filepath.zip') got error when filepath.zip doedn't exist
Message-ID: <20070726133702.E95735240BF2@rubyforge.org>
Bugs item #11544, was opened at 2007-06-13 04:37
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=11544&group_id=804
Category: None
Group: None
Status: Open
Resolution: None
Priority: 3
Submitted By: Bin Dong (dongbin)
Assigned to: Nobody (None)
Summary: FileUtils.compress('zip', 'filepath', 'filepath.zip') got error when filepath.zip doedn't exist
Initial Comment:
Found the reason: in the compress.rb
cmd = "zip -cf #{to_file} #{folder}"
should be replace with
cmd = "zip #{to_file} #{folder}"
The "-c" option of zip is different with tar.
----------------------------------------------------------------------
>Comment By: Trans Onoma (transami)
Date: 2007-07-26 08:37
Message:
Thanks. compress.rb is still a work in progress. For Facets 2.0 I renamed it ZipUtils. (I know it's not _all_ about Zip, but hey tissue paper isn't all Kleenex either ;)
I'm actually not sure what that line should be. I'm thinking:
cmd = "zip -ru #{to_file} #{folder}"
recursive with updates. Look right?
On the TODO list is to use Ruby's own zlib to create the Zip files (should be possible). Anyone want to take a crack at it?
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3169&aid=11544&group_id=804
From noreply at rubyforge.org Mon Jul 30 11:02:14 2007
From: noreply at rubyforge.org (noreply at rubyforge.org)
Date: Mon, 30 Jul 2007 11:02:14 -0400 (EDT)
Subject: [Facets] [ facets-Feature Requests-12691 ] Enumerable.dupes -
return items that occur >1
Message-ID: <20070730150216.5CA145240AA4@rubyforge.org>
Feature Requests item #12691, was opened at 2007-07-30 11:02
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3172&aid=12691&group_id=804
Category: None
Group: None
Status: Open
Priority: 3
Submitted By: Dan Bernier (danbernier)
Assigned to: Nobody (None)
Summary: Enumerable.dupes - return items that occur >1
Initial Comment:
It'd be great if an Enumerable could return an Array of its duplicates. I've come across this need several times, and think it'd be a great addition to facets.
There are three pretty good implementations at:
http://snippets.dzone.com/posts/show/4148
http://snippets.dzone.com/posts/show/3838
Usage example (borrowed from the links above):
arr = %w{foo bar baz bar baz qux foo zub}
puts arr.dupes.inspect # => ["baz", "foo", "bar"]
arr = [1,3,5,5,6,7,9,10,14,18,22,22,4,4,4,3,6]
puts arr.dupes #=> [5, 22, 6, 3, 4]
----------------------------------------------------------------------
You can respond by visiting:
http://rubyforge.org/tracker/?func=detail&atid=3172&aid=12691&group_id=804
From transfire at gmail.com Mon Jul 30 14:24:34 2007
From: transfire at gmail.com (TRANS)
Date: Mon, 30 Jul 2007 11:24:34 -0700
Subject: [Facets] [ facets-Feature Requests-12691 ] Enumerable.dupes -
return items that occur >1
In-Reply-To: <20070730150216.5CA145240AA4@rubyforge.org>
References: <20070730150216.5CA145240AA4@rubyforge.org>
Message-ID: <4b6f054f0707301124o6bcd95f7t2f569b159509dc6b@mail.gmail.com>
On 7/30/07, noreply at rubyforge.org wrote:
> Initial Comment:
> It'd be great if an Enumerable could return an Array of its duplicates. I've come across this need several times, and think it'd be a great addition to facets.
>
> There are three pretty good implementations at:
> http://snippets.dzone.com/posts/show/4148
> http://snippets.dzone.com/posts/show/3838
>
> Usage example (borrowed from the links above):
> arr = %w{foo bar baz bar baz qux foo zub}
> puts arr.dupes.inspect # => ["baz", "foo", "bar"]
>
> arr = [1,3,5,5,6,7,9,10,14,18,22,22,4,4,4,3,6]
> puts arr.dupes #=> [5, 22, 6, 3, 4]
Hmm... I suppose I could add Enumerable#duplicates. There's already
#nonuniq, but maybe that name isn't obvious. Also there if #collisions
which does nearly same thing, but is less efficient b/c it can also
take a block.
T.
From transfire at gmail.com Tue Jul 31 16:39:58 2007
From: transfire at gmail.com (Trans)
Date: Tue, 31 Jul 2007 20:39:58 -0000
Subject: [Facets] Facets SVN
Message-ID: <1185914398.541104.99240@r34g2000hsd.googlegroups.com>
Hi--
I just imported Facets into the Rubyforge subversion repository. You
should be able to get an anonymous checkout of the latest with:
svn checkout svn://rubyforge.org/var/svn/facets/trunk facets/
Facets 2.0 is coming along nicely --still some things I'd like to get
cleaned up, but a release (beta?) is Real Soon Now(tm).
Btw, if you are interested in becoming a honest to goodness ruby spit-
shining Facets developer, let me know.
T.