Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Path-Class CPAN distribution.

Maintainer(s)' notes

I prefer that bugs & patches are filed on GitHub rather than on RT: https://github.com/kenahoo/Path-Class/issues. Thanks.

Report information
The Basics
Id: 12759
Status: resolved
Priority: 0/
Queue: Path-Class

People
Owner: Nobody in particular
Requestors: smylers [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 0.10
Fixed in: (no value)



Subject: chomp-ing slurp-ed input
In a recent Perl Module Authors thread there was discussion of how this could be better expressed: my @mp3s = grep { -f } @ARGV, ($m3u?(map{chomp;$_}`cat "$m3u"`):()); I came up with this example of using Path::Class: push @ARGV, (file $m3u)->slurp if $m3u; chomp @ARGV; my @mp3s = grep { -f } @ARGV; That's still a little awkward. The awkwardness is Perl's built-in chomp function not returning the chomped text, so can't be chained (at least not without using a map block, as in the one-liner above). I considered: Perhaps Path::Class::File should steal IO::All's chomp method? (Or perhaps that would start to bloat what is currently a very clean and elegant suite of modules -- and if we keep doing things like that we'd just end up turning Path::Class into IO::All, thereby proving that Ingy was right in the first place.) But I've since come up with a real-world situation where I wanted this: I'm trying to get the current CVS repository directory from a working copy; that involves constructing a path from the contents of CVS/Root and CVS/Repository: my $cvs_dir = dir map { my $f = (file 'CVS', $_)->slurp; chomp $f; $f } qw<Root Repository>; Ug! I don't like that. This seems much cleaner: my $cvs_dir = dir map { (file 'CVS', $_)->slurp(1) } qw<Root Repository>; Attached is a patch that makes that work, with tests and docs. Having a true value flag that chomping is desired is a little obfuscatory, but I don't think it's too bad, and I didn't like any of the other interfaces I tried: * $file->chomp->slurp, as per IO::All, doesn't make as much sense here as there because IO::All has a number of file-reading methods that are all affected by chomp. In Path::Class::File slurp is the only such method, so we've effectively made chomp->slurp the only circumstance in which it is meaningful to call the chomp method. (Also I kept wanting to write it as $file->slurp->chomp instead.) * That led me on to thinking that since the chomp method is only of use when slurping, why not make it slurp as well, and rename the method so you have something like $file->chomp_and_slurp. But that seemed quite long for a method name, and having lots of similarly named methods just doing slightly different things always grated on me in PHP. * So really it's just an option on the slurp method. That suggested $file->slurp(chomped => 1), or perhaps $file->slurp(chomp => 1). I don't really object to that in general (though the Perl 6 version of $file->slurp(:chomped) is much nicer), but there aren't lots of Path::Class methods with named arguments at the moment that this has to fit in with, and it isn't immediately apparent that there'll be more options needed on slurp. * Which made me decide that I find $file->slurp(1) to be the nicest. If it turns out that slurp does need further options in the future then it isn't too much hassle to switch to having named options then and just keep (1) as a special case for backwards compatibility. Obviously it's your call, and I don't much mind having a different interface! For reference, here's the original thread: http://groups.google.co.uk/groups?threadm=slrnd6uabh.ohq.Smylers@stripey.com Cheers. Smylers
diff -ur -r Path-Class-0.10/lib/Path/Class/File.pm Path-Class-dev/lib/Path/Class/File.pm --- Path-Class-0.10/lib/Path/Class/File.pm Wed Apr 6 23:05:08 2005 +++ Path-Class-dev/lib/Path/Class/File.pm Wed May 11 17:22:45 2005 @@ -62,10 +62,11 @@ sub openw { $_[0]->open('w') or die "Can't write $_[0]: $!" } sub slurp { - my $self = shift; + my ($self, $chomp) = @_; my $fh = $self->open() or die "Can't open $self: $!"; - local $/ unless wantarray; - return <$fh>; + my @content = do { local $/ unless wantarray; <$fh> }; + chomp @content if $chomp; + return wantarray ? @content : $content[0]; } 1; @@ -243,7 +244,10 @@ In a scalar context, returns the contents of C<$file> in a string. In a list context, returns the lines of C<$file> (according to how C<$/> is set) as a list. If the file can't be read, this method will throw -an exception. +an exception. The output will be C<chomp>ed if you pass a true value to +C<slurp()>: + + my @staff = $file->slurp(1); =item $st = $file->stat() diff -ur -r Path-Class-0.10/t/03-filesystem.t Path-Class-dev/t/03-filesystem.t --- Path-Class-0.10/t/03-filesystem.t Wed Apr 6 23:05:08 2005 +++ Path-Class-dev/t/03-filesystem.t Wed May 11 17:23:31 2005 @@ -3,7 +3,7 @@ use Test; use Path::Class; -plan tests => 42; +plan tests => 46; ok 1; my $file = file('t', 'testfile'); @@ -104,10 +104,18 @@ my $content = $file->slurp; ok $content, "Line1\nLine2\n"; + $content = $file->slurp(1); + ok $content, "Line1\nLine2"; + my @content = $file->slurp; ok @content, 2; ok $content[0], "Line1\n"; ok $content[1], "Line2\n"; + + @content = $file->slurp(1); + ok @content, 2; + ok $content[0], "Line1"; + ok $content[1], "Line2"; unlink $file; ok -e $file, undef;
I think in the next version of Path::Class, there may be more named options - for example, the cleanup() method might take a thorough=>1 parameter that says whether to resolve foo/../bar (requiring a check on the filesystem to see whether foo/ is a symlink). Thus I'm inclined to add the chomp=>1 version. -Ken
I just checked this in, you can now chomp while you slurp. -Ken