From 7d095077b3103b4d892f296e86f56bdbcf020a47 Mon Sep 17 00:00:00 2001 From: "William H. Gilmore" Date: Sat, 22 Jul 2023 13:45:43 -0500 Subject: [PATCH 1/3] added pattern support for lines --- lib/Path/Tiny.pm | 98 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 13 deletions(-) diff --git a/lib/Path/Tiny.pm b/lib/Path/Tiny.pm index fc8653e..0c8f2a6 100644 --- a/lib/Path/Tiny.pm +++ b/lib/Path/Tiny.pm @@ -5,7 +5,7 @@ use warnings; package Path::Tiny; # ABSTRACT: File path utility -our $VERSION = '0.145'; +our $VERSION = '0.145lbe'; # Dependencies use Config; @@ -239,6 +239,7 @@ sub path { (my $escaped = $tilde) =~ s/([\[\{\*\?\\])/\\$1/g; require File::Glob; my ($homedir) = File::Glob::bsd_glob($escaped); + no warnings 'once'; if (defined $homedir && ! $File::Glob::ERROR) { $homedir =~ tr[\\][/] if IS_WIN32(); $path =~ s{^\Q$tilde\E}{$homedir}; @@ -523,6 +524,48 @@ sub _replacment_path { return $temp; } +## start of copy from Path::Iterator::Rule +sub _regexify { + my ( $re, $add ) = @_; + $add ||= ''; + my $new = ref($re) eq 'Regexp' ? $re : Text::Glob::glob_to_regex($re); + return $new unless $add; + my ( $pattern, $flags ) = _split_re($new); + my $new_flags = $add ? _reflag( $flags, $add ) : ""; + return qr/$new_flags$pattern/; +} + +sub _split_re { + my $value = shift; + if ( $] ge 5.010 ) { + return re::regexp_pattern($value); + } + else { + $value =~ s/^\(\?\^?//; + $value =~ s/\)$//; + my ( $opt, $re ) = split( /:/, $value, 2 ); + $opt =~ s/\-\w+$//; + return ( $re, $opt ); + } +} + +sub _reflag { + my ( $orig, $add ) = @_; + $orig ||= ""; + + if ( $] >= 5.014 ) { + return "(?^$orig$add)"; + } + else { + my ( $pos, $neg ) = split /-/, $orig; + $pos ||= ""; + $neg ||= ""; + $neg =~ s/i//; + $neg = "-$neg" if length $neg; + return "(?$add$pos$neg)"; + } +} +## end of copy from Path::Iterator::Rule #--------------------------------------------------------------------------# # Public methods #--------------------------------------------------------------------------# @@ -1355,10 +1398,11 @@ sub iterator { @contents = path("/tmp/foo.txt")->lines_raw; @contents = path("/tmp/foo.txt")->lines_utf8; - @contents = path("/tmp/foo.txt")->lines( { chomp => 1, count => 4 } ); + @contents = path("/tmp/foo.txt")->lines( { chomp => 1, count => 4, + pattern => qr/foo/i } ); Returns a list of lines from a file. Optionally takes a hash-reference of -options. Valid options are C, C and C. +options. Valid options are C, C and C and C. If C is provided, it will be set on the handle prior to reading. @@ -1370,6 +1414,9 @@ exceeds the number of lines in the file, all lines will be returned. If C is set, any end-of-line character sequences (C, C, or C) will be removed from the lines returned. +If C is set to a C value, only lines the matching the given regular +expression. If C is provided, C will be applied to the lines returned. + Because the return is a list, C in scalar context will return the number of lines (and throw away the data). @@ -1385,13 +1432,13 @@ lines will be split. This is actually faster than relying on IO layers, though a bit memory intensive. If memory use is a concern, consider C and iterating directly on the handle. -Current API available since 0.065. +Current API available since 0.065 <= Will need to be updated if Pull Request is accepted - lbe. =cut sub lines { my $self = shift; - my $args = _get_args( shift, qw/binmode chomp count/ ); + my $args = _get_args( shift, qw/binmode chomp count pattern/ ); my $binmode = $args->{binmode}; $binmode = ( ( caller(0) )[10] || {} )->{'open<'} unless defined $binmode; my $fh = $self->filehandle( { locked => 1 }, "<", $binmode ); @@ -1413,12 +1460,20 @@ sub lines { # reorder results if full and wrapped somewhere in the middle splice( @result, 0, 0, splice( @result, $counter ) ) if @result == $mod && $counter % $mod; + if ( $args->{pattern} ) { + my $re = _regexify( $args->{pattern} ); + @result = grep { m/$re/} @result; + } return @result; } elsif ($chomp) { local $!; my @lines = map { s/(?:\x{0d}?\x{0a}|\x{0d})\z//; $_ } <$fh>; ## no critic $self->_throw('readline') if $!; + if ( $args->{pattern} ) { + my $re = _regexify( $args->{pattern} ); + @lines = grep { m/$re/ } @lines; + } return @lines; } else { @@ -1426,11 +1481,24 @@ sub lines { local $!; my @lines = <$fh>; $self->_throw('readline') if $!; + if ( $args->{pattern} ) { + my $re = _regexify( $args->{pattern} ); + @lines = grep { m/$re/ } @lines; + } return @lines; } else { local $!; - my $count =()= <$fh>; - $self->_throw('readline') if $!; + my $count; + if ( $args->{pattern} ) { + my @lines = <$fh>; + $self->_throw('readline') if $!; + my $re = _regexify( $args->{pattern} ); + $count = grep { m/$re/ } @lines; + } + else { + $count = () = <$fh>; + $self->_throw('readline') if $!; + } return $count; } } @@ -1438,9 +1506,11 @@ sub lines { sub lines_raw { my $self = shift; - my $args = _get_args( shift, qw/binmode chomp count/ ); + my $args = _get_args( shift, qw/binmode chomp count pattern/ ); if ( $args->{chomp} && !$args->{count} ) { - return split /\n/, slurp_raw($self); ## no critic + return $args->{pattern} + ? grep { _regexify( $args->{pattern} ) } split /\n/, slurp_raw($self) + : split /\n/, slurp_raw($self); ## no critic } else { $args->{binmode} = ":raw"; @@ -1452,14 +1522,16 @@ my $CRLF = qr/(?:\x{0d}?\x{0a}|\x{0d})/; sub lines_utf8 { my $self = shift; - my $args = _get_args( shift, qw/binmode chomp count/ ); + my $args = _get_args( shift, qw/binmode chomp count pattern/ ); if ( ( defined($HAS_UU) ? $HAS_UU : ( $HAS_UU = _check_UU() ) ) && $args->{chomp} && !$args->{count} ) { my $slurp = slurp_utf8($self); - $slurp =~ s/$CRLF\z//; # like chomp, but full CR?LF|CR - return split $CRLF, $slurp, -1; ## no critic + $slurp =~ s/$CRLF\z//; # like chomp, but full CR?LF|CR + return $args->{pattern} + ? grep { _regexify( $args->{pattern} ) } split $CRLF, $slurp - 1 + : split $CRLF, $slurp, -1; ## no critic } elsif ( defined($HAS_PU) ? $HAS_PU : ( $HAS_PU = _check_PU() ) ) { $args->{binmode} = ":raw:utf8_strict"; @@ -1610,7 +1682,7 @@ my %opens = ( ); while ( my ( $k, $v ) = each %opens ) { - no strict 'refs'; + no strict 'refs'; ## no critic (Strict) # must check for lexical IO mode hint *{$k} = sub { my ( $self, @args ) = @_; From 738fdbb0cb46c03472b6e7c3f5a601448577644c Mon Sep 17 00:00:00 2001 From: "William H. Gilmore" Date: Sat, 22 Jul 2023 13:46:10 -0500 Subject: [PATCH 2/3] added pattern tests for lines --- t/filesystem.t | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/t/filesystem.t b/t/filesystem.t index 3b20acd..ff57217 100644 --- a/t/filesystem.t +++ b/t/filesystem.t @@ -31,7 +31,7 @@ if ( -e "/dev/null" ) { } my ( $volume, $dirname, $basename ) = - map { s{\\}{/}; $_ } File::Spec->splitpath($file); + map { s{\\}{/}; $_ } File::Spec->splitpath($file); ## no critic is( $file->volume, $volume, "volume correct" ); is( $file->volume, $volume, "volume cached " ); # for coverage is( $file->dirname, $dirname, "dirname correct" ); @@ -202,6 +202,12 @@ my $tmpdir = Path::Tiny->tempdir; @content = $file->lines( { chomp => 1 } ); is_deeply \@content, [ "Line1", "Line2" ]; + @content = $file->lines( { pattern => qr/Line1/ } ); + is_deeply \@content, [ "Line1\n" ]; + + @content = $file->lines( { chomp => 1, pattern => qr/Line1/ } ); + is_deeply \@content, [ "Line1" ]; + ok( $file->remove, "removing file" ); ok !-e $file, "file is gone"; ok !$file->remove, "removing file again returns false"; From c1c2c1a1fbae7f1be3a1a3da75f9ede60b7ff389 Mon Sep 17 00:00:00 2001 From: "William H. Gilmore" Date: Sat, 22 Jul 2023 13:46:17 -0500 Subject: [PATCH 3/3] added pattern tests for lines --- t/input_output.t | 225 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/t/input_output.t b/t/input_output.t index 5c61bb7..87ea1d2 100644 --- a/t/input_output.t +++ b/t/input_output.t @@ -28,6 +28,18 @@ sub _utf8_no_end_of_newline_lines { return ( _utf8_lines(), "No end of newline" ); } +sub _re1 { + return ( qr/Line1/ ); +} + +sub _re2 { + return ( qr/Line2/ ); +} + +sub _re3 { + return ( qr/No end of newlin/ ); +} + subtest "spew -> slurp" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_lines), "spew" ); @@ -91,6 +103,15 @@ subtest "spew -> lines" => sub { is( scalar $file->lines, my $cnt =()= _lines, "lines (scalar)" ); }; +subtest "spew -> lines (pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_lines), "spew" ); + my $re1 = _re1; + is( join( '', $file->lines( { pattern => _re1 } ) ), + join( '', grep { m/$re1/ } _lines ), "lines" ); + is( scalar $file->lines, my $cnt = () = _lines, "lines (scalar)" ); +}; + subtest "spew -> lines (open hint)" => sub { plan skip_all => "Needs 5.10" unless $] >= 5.010; use open IO => ":utf8"; @@ -101,6 +122,17 @@ subtest "spew -> lines (open hint)" => sub { ok( utf8::is_utf8($got), "is UTF8" ); }; +subtest "spew -> lines (open hint pattern)" => sub { + plan skip_all => "Needs 5.10" unless $] >= 5.010; + use open IO => ":utf8"; + my $file = Path::Tiny->tempfile; + ok( $file->spew(_utf8_lines), "spew" ); + my $re1 = _re1; + my $got = join( '', $file->lines( { pattern => _re1 } ) ); + is( $got, join( '', grep { m/$re1/ } _utf8_lines ), "slurp" ); + ok( utf8::is_utf8($got), "is UTF8" ); +}; + subtest "spew -> lines (UTF-8)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_lines), "spew" ); @@ -110,12 +142,34 @@ subtest "spew -> lines (UTF-8)" => sub { is( scalar $file->lines, my $cnt =()= _utf8_lines, "lines (scalar)" ); }; +subtest "spew -> lines (UTF-8 pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_utf8(_utf8_lines), "spew" ); + my $re1 = _re1; + my $got = join( '', $file->lines_utf8( { pattern => _re1 } ) ); + is( $got, join( '', grep { m/$re1/ } _utf8_lines ), "slurp" ); + ok( utf8::is_utf8($got), "is UTF8" ); + is( + scalar $file->lines( { pattern => _re1 } ), + my $cnt = () = grep { m/$re1/ } _utf8_lines, + "lines (scalar)" + ); +}; + subtest "spew -> lines (raw)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_raw(_lines), "spew" ); is( join( '', $file->lines_raw ), join( '', _lines ), "lines" ); }; +subtest "spew -> lines (raw pattern)" => sub { + my $file = Path::Tiny->tempfile; + my $re1 = _re1; + ok( $file->spew_raw(_lines), "spew" ); + is( join( '', $file->lines_raw( { pattern => _re1 } ) ), + join( '', grep { m/$re1/ } _lines ), "lines" ); +}; + subtest "spew -> lines (count)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_lines), "spew" ); @@ -126,6 +180,17 @@ subtest "spew -> lines (count)" => sub { join( '', @exp[ 0 .. 1 ] ), "lines" ); }; +subtest "spew -> lines (count)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_lines), "spew" ); + my $re1 = _re1; + my @exp = _lines; + is( join( '', $file->lines( { count => 2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 1 ] ), "lines" ); + is( join( '', $file->lines( { count => -2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 1 ] ), "lines" ); +}; + subtest "spew -> lines (count, less than)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_lines), "spew" ); @@ -134,6 +199,18 @@ subtest "spew -> lines (count, less than)" => sub { is( join( '', $file->lines( { count => -1 } ) ), $exp[1], "lines" ); }; +subtest "spew -> lines (count, less than, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_lines), "spew" ); + my $re1 = _re1; + my $re2 = _re2; + my @exp = _lines; + is( join( '', $file->lines( { count => 1, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 1 ] ), "lines" ); + is( join( '', $file->lines( { count => -1, pattern => $re2 } ) ), + join( '', grep { m/$re2/ } @exp[ 0 .. 1 ] ), "lines" ); +}; + subtest "spew -> lines (count, more than)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_lines), "spew" ); @@ -142,6 +219,17 @@ subtest "spew -> lines (count, more than)" => sub { is( join( '|', $file->lines( { count => -3 } ) ), join( "|", @exp ), "lines" ); }; +subtest "spew -> lines (count, more than, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_lines), "spew" ); + my $re1 = _re1; + my @exp = _lines; + is( join( '|', $file->lines( { count => 3, pattern => $re1 } ) ), + join( "|", grep { m/$re1/ } @exp ), "lines" ); + is( join( '|', $file->lines( { count => -3, pattern => $re1 } ) ), + join( "|", grep { m/$re1/ } @exp ), "lines" ); +}; + subtest "spew -> lines (count, chomp)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_lines), "spew" ); @@ -152,6 +240,17 @@ subtest "spew -> lines (count, chomp)" => sub { join( '', @exp[ 0 .. 1 ] ), "lines" ); }; +subtest "spew -> lines (count, chomp, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_lines), "spew" ); + my $re1 = _re1; + my @exp = map { s/[\r\n]+//; $_ } _lines; + is( join( '', $file->lines( { chomp => 1, count => 2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 1 ] ), "lines" ); + is( join( '', $file->lines( { chomp => 1, count => -2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 1 ] ), "lines" ); +}; + subtest "spew -> lines (count, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_no_end_of_newline_lines), "spew" ); @@ -162,6 +261,18 @@ subtest "spew -> lines (count, no end of newline)" => sub { join( '', @exp[ 0 .. 2 ] ), "lines" ); }; +subtest "spew -> lines (count, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my $re3 = _re3; + my @exp = _no_end_of_newline_lines; + is( join( '', $file->lines( { count => 3, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 2 ] ), "lines" ); + is( join( '', $file->lines( { count => -3, pattern => $re3 } ) ), + join( '', grep { m/$re3/ } @exp[ 0 .. 2 ] ), "lines" ); +}; + subtest "spew -> lines (count, less than, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_no_end_of_newline_lines), "spew" ); @@ -170,6 +281,18 @@ subtest "spew -> lines (count, less than, no end of newline)" => sub { is( join( '', $file->lines( { count => -1 } ) ), $exp[2], "lines" ); }; +subtest "spew -> lines (count, less than, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my $re3 = _re3; + my @exp = _no_end_of_newline_lines; + is( join( '', $file->lines( { count => 1, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } ( $exp[0] ) ), "lines" ); + is( join( '', $file->lines( { count => -1, pattern => $re3 } ) ), + join( '', grep { m/$re3/ } ( $exp[2] ) ), "lines" ); +}; + subtest "spew -> lines (count, more than, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_no_end_of_newline_lines), "spew" ); @@ -178,6 +301,18 @@ subtest "spew -> lines (count, more than, no end of newline)" => sub { is( join( '|', $file->lines( { count => -4 } ) ), join( "|", @exp ), "lines" ); }; +subtest "spew -> lines (count, more than, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my $re3 = _re3; + my @exp = _no_end_of_newline_lines; + is( join( '|', $file->lines( { count => 4, pattern => $re1 } ) ), + join( "|", grep { m/$re1/ } @exp ), "lines" ); + is( join( '|', $file->lines( { count => -4, pattern => $re3 } ) ), + join( "|", grep { m/$re3/ } @exp ), "lines" ); +}; + subtest "spew -> lines (count, chomp, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew(_no_end_of_newline_lines), "spew" ); @@ -188,6 +323,18 @@ subtest "spew -> lines (count, chomp, no end of newline)" => sub { join( '', @exp[ 0 .. 2 ] ), "lines" ); }; +subtest "spew -> lines (count, chomp, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew(_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my $re3 = _re3; + my @exp = map { s/[\r\n]+//; $_ } _no_end_of_newline_lines; + is( join( '', $file->lines( { chomp => 1, count => 3, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 2 ] ), "lines" ); + is( join( '', $file->lines( { chomp => 1, count => -3, pattern => $re3 } ) ), + join( '', grep { m/$re3/ } @exp[ 0 .. 2 ] ), "lines" ); +}; + subtest "spew -> lines (count, UTF-8)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_lines), "spew" ); @@ -196,6 +343,17 @@ subtest "spew -> lines (count, UTF-8)" => sub { is( join( '', $file->lines_utf8( { count => -3 } ) ), join( '', @exp ), "lines" ); }; +subtest "spew -> lines (count, UTF-8)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_utf8(_utf8_lines), "spew" ); + my $re1 = _re1; + my @exp = _utf8_lines; + is( join( '', $file->lines_utf8( { count => 3, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); + is( join( '', $file->lines_utf8( { count => -3, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); +}; + subtest "spew -> lines (count, chomp, UTF-8)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_lines), "spew" ); @@ -206,6 +364,17 @@ subtest "spew -> lines (count, chomp, UTF-8)" => sub { join( '', @exp[ 1 .. 2 ] ), "lines" ); }; +subtest "spew -> lines (count, chomp, UTF-8)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_utf8(_utf8_lines), "spew" ); + my $re2 = _re2; + my @exp = map { s/[\r\n]+//; $_ } _utf8_lines; + is( join( '', $file->lines_utf8( { chomp => 1, count => 2, pattern => $re2 } ) ), + join( '', grep { m/$re2/ } @exp[ 0 .. 1 ] ), "lines" ); + is( join( '', $file->lines_utf8( { chomp => 1, count => -2, pattern => $re2 } ) ), + join( '', grep { m/$re2/ } @exp[ 1 .. 2 ] ), "lines" ); +}; + subtest "spew -> lines (chomp, only newlines)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew( "\n" x 5 ), "spew" ); @@ -213,6 +382,8 @@ subtest "spew -> lines (chomp, only newlines)" => sub { is( join( '|', $file->lines_utf8( { chomp => 1 } ) ), join( '|', @exp ), "lines" ); }; +# not needed "spew -> lines (chomp, only newlines, pattern)" + subtest "spew -> lines (chomp, UTF-8)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_lines), "spew" ); @@ -220,6 +391,15 @@ subtest "spew -> lines (chomp, UTF-8)" => sub { is( join( '', $file->lines_utf8( { chomp => 1 } ) ), join( '', @exp ), "lines" ); }; +subtest "spew -> lines (chomp, UTF-8, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_utf8(_utf8_lines), "spew" ); + my $re1 = _re1; + my @exp = map { s/[\r\n]+//; $_ } _utf8_lines; + is( join( '', $file->lines_utf8( { chomp => 1, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); +}; + subtest "spew -> lines (count, UTF-8, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_no_end_of_newline_lines), "spew" ); @@ -228,6 +408,17 @@ subtest "spew -> lines (count, UTF-8, no end of newline)" => sub { is( join( '', $file->lines_utf8( { count => -4 } ) ), join( '', @exp ), "lines" ); }; +subtest "spew -> lines (count, UTF-8, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_utf8(_utf8_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my @exp = _utf8_no_end_of_newline_lines; + is( join( '', $file->lines_utf8( { count => 4, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); + is( join( '', $file->lines_utf8( { count => -4, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); +}; + subtest "spew -> lines (count, chomp, UTF-8, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_utf8(_utf8_no_end_of_newline_lines), "spew" ); @@ -238,6 +429,18 @@ subtest "spew -> lines (count, chomp, UTF-8, no end of newline)" => sub { join( '', @exp[ 2 .. 3 ] ), "lines" ); }; +subtest "spew -> lines (count, chomp, UTF-8, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_utf8(_utf8_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my $re3 = _re3; + my @exp = map { s/[\r\n]+//; $_ } _utf8_no_end_of_newline_lines; + is( join( '', $file->lines_utf8( { chomp => 1, count => 2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp[ 0 .. 1 ] ), "lines" ); + is( join( '', $file->lines_utf8( { chomp => 1, count => -2, pattern => $re3 } ) ), + join( '', grep { m/$re3/ } @exp[ 2 .. 3 ] ), "lines" ); +}; + subtest "spew -> lines (count, raw)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_raw(_lines), "spew" ); @@ -246,6 +449,17 @@ subtest "spew -> lines (count, raw)" => sub { is( join( '', $file->lines_raw( { count => -2 } ) ), join( '', @exp ), "lines" ); }; +subtest "spew -> lines (count, raw, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_raw(_lines), "spew" ); + my $re1 = _re1; + my @exp = _lines; + is( join( '', $file->lines_raw( { count => 2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); + is( join( '', $file->lines_raw( { count => -2, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); +}; + subtest "spew -> lines (count, raw, no end of newline)" => sub { my $file = Path::Tiny->tempfile; ok( $file->spew_raw(_no_end_of_newline_lines), "spew" ); @@ -254,6 +468,17 @@ subtest "spew -> lines (count, raw, no end of newline)" => sub { is( join( '', $file->lines_raw( { count => -3 } ) ), join( '', @exp ), "lines" ); }; +subtest "spew -> lines (count, raw, no end of newline, pattern)" => sub { + my $file = Path::Tiny->tempfile; + ok( $file->spew_raw(_no_end_of_newline_lines), "spew" ); + my $re1 = _re1; + my @exp = _no_end_of_newline_lines; + is( join( '', $file->lines_raw( { count => 3, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); + is( join( '', $file->lines_raw( { count => -3, pattern => $re1 } ) ), + join( '', grep { m/$re1/ } @exp ), "lines" ); +}; + subtest "append -> slurp" => sub { my $file = Path::Tiny->tempfile; ok( $file->append(_lines), "append" );