diff -r 437a0c43f198 MANIFEST
--- a/MANIFEST	Mon Nov 11 13:28:39 2013 +0000
+++ b/MANIFEST	Mon Nov 11 14:18:09 2013 +0000
@@ -4,7 +4,6 @@
 LICENSE
 Makefile.PL
 lib/P.pm
-t/P.sh
 t/P.t
 
 META.yml                                 Module YAML meta-data (added by MakeMaker)
diff -r 437a0c43f198 Makefile.PL
--- a/Makefile.PL	Mon Nov 11 13:28:39 2013 +0000
+++ b/Makefile.PL	Mon Nov 11 14:18:09 2013 +0000
@@ -1,18 +1,20 @@
+use ExtUtils::MakeMaker 6.56;
 
-
-use ExtUtils::MakeMaker;
-# See lib/ExtUtils/MakeMaker.pm for details of how to influence
-# the contents of the Makefile that is written.
 WriteMakefile(
-    NAME         => 'P',
-		BUILD_REQUIRES => { mem => '0.3.2' },
-    VERSION_FROM => 'lib/P.pm', # finds \$VERSION
-    AUTHOR       => 'Linda Walsh (perl-diddler@tlinx.org)',
-    ABSTRACT     => 'printf, sprintf & say all-in-1; safer & easier!',
-    PREREQ_PM    => {
-                     'Test::Simple' => 0.44,
-										 'mem'	=> '0.3.2',
-                    },
-		dist				=> { TARFLAGS=> 'c --format=v7 -f' },
-		test				=> { TESTS => 't/*.sh' }
+	NAME         => 'P',
+	BUILD_REQUIRES => {
+		'mem'           => '0.3.2',
+		'Capture::Tiny' => 0,
+		'Test::Fatal'   => 0,
+		'Test::Simple'  => 0.44,
+	},
+	VERSION_FROM => 'lib/P.pm',
+	AUTHOR       => 'Linda Walsh (perl-diddler@tlinx.org)',
+	ABSTRACT     => 'printf, sprintf & say all-in-1; safer & easier!',
+	PREREQ_PM    => {
+		'mem'           => '0.3.2',
+	},
+	dist         => {
+		TARFLAGS        => 'c --format=v7 -f',
+	},
 );
diff -r 437a0c43f198 lib/P.pm
--- a/lib/P.pm	Mon Nov 11 13:28:39 2013 +0000
+++ b/lib/P.pm	Mon Nov 11 14:18:09 2013 +0000
@@ -332,24 +332,6 @@
 		$p }
 1;}		#value 1 placed at as w/most of my end-of-packages (rt#89054)
 
-{
-	package main;
-
-	unless ((caller 0)[0]) {
-		binmode P::DATA, ":utf8";
-		binmode *STDOUT, ":utf8";
-    $_=do{ $/=undef, <P::DATA>};
-		close P::DATA;
-		our @globals;
-		eval $_;
-    die "self-test failed: $@" if $@;
-		1;
-	} else {
-		close P::DATA;
-	}
-1;
-}
-
 ############################################################################
 #							Pod documentation						{{{1
 #    use P;
@@ -560,117 +542,3 @@
 =cut
 #}}}1
 
-package P;
-__DATA__
-# line ' .__LINE__ . ' "' ' __FILE__ . "\"\n" . '
-use utf8;
-use open IN => q(:utf8);
-use open OUT => q(:utf8);
-foreach (qw{STDERR STDOUT}) {select *$_; $|=1};
-use strict; use warnings; 
-use P;
-my %tests;
-my $MAXCASES=13;
-{ my $i=1;
-  foreach (@ARGV) {
-    if (/^\d+/ && $_<=$MAXCASES) {$tests{$_}=1}
-		else {die P "%s: no such test case", $_}
-  }
-}
-exists $tests{7} and $tests{6}=1;
-
-my $format="#%-2d %-25s: ";
-{	#mini-package
-  my $case=0;
-  sub newcase() {++$case}
-  sub caseno() {$case};
-  sub iter(){"Hello Perl ${\(0+&caseno)}"}
-}
-
-sub case ($) {
-  &newcase;
-  if (!@ARGV || $tests{&caseno}) {
-	  P ("$format\x83",  &caseno, "(".$_[0].")");
-    1
-  } else {
-    0;
-  }
-}
-
-
-case "ret from func" &&
-  P iter;                         			# case 1: return from func
-
-
-case "w/string" &&
-  P "${\(+iter())}";                   	# case 2 w/string
-
-case "passed array" && do {
-  my @msg = ("%s", &iter ); 
-  P  @msg;                              # case 3 -- being passed Array
-};
-
-case "w/fmt+string" &&
-  P "%s",iter;                       		# case 4
-
-case "to STDERR" &&
-  Pe iter;                           		# case 5 #needs redirection to see
-
-our $str;
-
-case "to strng embedded in #7" && do {	# case 6 to string; prints in case 7
-	$str = P "%s",iter; 
-  P "";
-};
-
-sub timed_read($$) {
-	my ($fh, $timeout)= @_;
-	my $result;
-	eval {
-		local $SIG{ALRM} = sub {die P "timeout"};
-		alarm $timeout;
-		$result=<$fh>; 
-		alarm 0;
-	};
-	return $result unless $@;
-	die P "unexpected error in read: $@" unless $@ eq "timeout";
-	$result="timeout";
-}
-
-sub rev{ 1 >= length $_[0] ?	$_[0] : 
-							substr( $_[0], -1) .  rev(substr $_[0], 0, -1) } 
-
-case "prev string" &&										# case 7 - print embedded P output
-  P "prev str=\"%s\" (no LF) && ${\(+iter())}", $str;
-
-case "P && array ref"  && do {
-  my @ar=qw(one two three 4 5 6);
-  P "%s",\@ar;													# case 8 - array expansion
-};
-
-my %hash=(a=>'apple', b=>'bread', c=>'cherry');
-case "P HASH ref" &&										# case 9 - hash expansion
-  P "%s", \%hash;
-
-case "P Pkg ref" && do									# case 10 - blessed object
-{	my $hp;
-	bless $hp={a=>1, b=>2, x=>'y'}, 'Pkg';
-	P "%s", $hp;
-};
-
-case "P \@{[FH,[\"fmt:%s\",…]]}" && do	# case 11 - embed (FH,[fmt,parms])
-{																				# (rt#89056)
-	P @{[\*STDOUT, ["fmt:%s", &iter]]};
-};
-
-case "truncate embedded float" && do		# case 12 - embedded float
-{	my $pi=4*atan2(1,1);
-	P "norm=%s, embed=%s", $pi, {pi=>$pi};
-};
-
-case "test mixed digit string" && do		# case 13 - embed foreign digits
-{	use utf8;my $p="3.ⅰⅳⅰⅴⅸ";
-	P "embed roman pi = %s", [$p];
-};
-# vim: ts=2 sw=2
-
diff -r 437a0c43f198 t/P.sh
--- a/t/P.sh	Mon Nov 11 13:28:39 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#!/bin/sh
-
-unset PERL5OPT
-
-
-mydir=`dirname "$0"`
-fc=`echo "$mydir"|cut -c1`
-
-if [ "${mydir}" = "" ] ; then
-	mydir = "$PWD"
-fi
-
-dn=/dev/null
-if [ ! -e /dev/null ]; then dn="NUL:" ; fi
-
-myprog=`basename $0 ".sh"`
-
-PATH="$mydir:$PATH"
-
-PERL5LIB="$mydir/../blib/lib"
-
-export PERL5LIB
-export PATH
-
-unset -v PERL5OPT
-
-exec "$myprog.t" "@_"
-
diff -r 437a0c43f198 t/P.t
--- a/t/P.t	Mon Nov 11 13:28:39 2013 +0000
+++ b/t/P.t	Mon Nov 11 14:18:09 2013 +0000
@@ -1,135 +1,134 @@
-#!/usr/bin/perl
-use strict; use warnings;
+use strict;
+use warnings;
+use utf8;
+use Test::More tests => 13;
 
-# vim=:SetNumberAndWidth
+use Test::Fatal qw(exception);
+use Capture::Tiny qw(capture);
 
-## Before 'make install' is performed this script should be runnable with
-# 'make test'. After 'make install' it should work as 'perl P.t'
+use P;
 
-#########################
+binmode STDOUT, q(:utf8);
+binmode STDIN, q(:utf8);
 
-# change 'tests => 1' to 'tests => last_test_to_print';
+my $format = "#%-2d %-25s: ";
 
-#########################
-
-
-# Insert your test code below, the Test::More module is use()ed here so read
-# its man page ( perldoc Test::More ) for help writing this test script.
-
-our $num_tests;
-our @answers;
-our $sample_strlen;
-our $tp;
-
-BEGIN{
-	$tp="lib/P.pm";
+# Runs a coderef and returns an arrayref of:
+# [ $exception, $stdout, $stderr, @return_values ]
+sub capture_all (&)
+{
+	my $code = shift;
+	my ($exception, $stdout, $stderr, @return);
 	
-	$sample_strlen=length "Hello Perl 0";
-
-	$_=1;
-	push (@answers, [$_, qr{Hello\sPerl\s$_}]) for 1 .. 5;
-	push @answers, [6, ""];
-	push @answers, [7, qr{Hello Perl \d.*Perl 7}];
-	push @answers, [8, qr{^\s*\[.*three.*4.*\]\s*$} ];
-	push @answers, [9, qr{^\s*\{.*a.?=>.apple.*\}$} ];
-	push @answers, [10, qr{Pkg.*\{.*=>.*\}} ];
-	push @answers, [11, qr{fmt:Hello Perl}];
-	push @answers, [12, qr(norm=3\.14159.*embed.*3.14)];
-	push @answers, [13, qr{embed.*ⅴⅸ.*$}];
-
-	#	3 setup tests, all answers have two parts except for 1 (#6)
+	$exception = exception {
+		($stdout, $stderr, @return) = capture { $code->() };
+	};
 	
-	$num_tests=3+2*@answers-2;
-
+	return [$exception, $stdout, $stderr, @return];
 }
 
-use Test::More tests => $num_tests+2;
-#BEGIN {
-#my $builder = Test::More->builder;
-#binmode $builder->output,         ":utf8";
-#binmode $builder->failure_output, ":utf8";
-#binmode $builder->todo_output,    ":utf8";
-#}
-
-
-BEGIN { use_ok('mem') || BAIL_OUT("missing pre-req mem");};
-
-BEGIN { use_ok('P') || BAIL_OUT("missing module to test");};
-
-BEGIN { ok(!defined $ENV{PERL5OPT} || $ENV{PERL5OPT} !~ /utf8/, "check for utf8 in ENV (causes probs)") ||
-				BAIL_OUT("\nincompat utf8 set in PERL5OPT");}
-
-my $match_case_n_name=qr{^.(\d+)\s*\(([^\)]+)\)[^:]*:};
-my $match_testout=qr{\s*(.*)$};
-my $match_expr=qr{^.(\d+)\s*\(([^\)]+)\)[^:]*:\s*(.*)$};
-my $weak_match_expr=qr{^(?:.(\d+)\s*)?\(?([^\)]*)\)?[^:]*:?\s*(.*)$};
-
-ok( -e $tp , "P.pm exist?");
-chmod( 0755, $tp); 
-#ok( -x $tp , "P.pm executable?");		#3
-
-sub get_case($;$) {
-	my $case = shift;
-	my $cmd = @_? "perl $tp $case ".$_[0]."|" : "perl $tp $case |";
-	open(my $fh, $cmd) || return undef;
-	my $out;
-	{ local $/=undef;
-		$out = <$fh>;
-	}
-	chomp $out;
-	$out;
+{
+	my $case = 0;
+	sub newcase () { ++$case }
+	sub caseno  () { $case }
+	sub iter    () { my $r = "Hello Perl ${\(0+&caseno)}"; newcase; $r }
 }
 
-sub sv($) { defined $_[0] ? $_[0] : "(undef)" }
+is_deeply(
+	capture_all { P iter },
+	[ undef, '', '', 'Hello Perl 0' ],
+	'P($string) in non-void context acts like sprintf',
+);
 
-my $caseno=0;
-for my $matchp (@answers) {
-	my ($rcase, $name, $rstr);
-	my $re = $matchp->[1];
-	++$caseno;
-	if ($caseno == 5) {	# see if output was on STDERR
-		my $null;
-		my $dev;
-		open($null, ">", $dev="/dev/null") or
-			open($null, ">", $dev="NUL:") or 
-			die "Cannot open /dev/null nor NUL:";
-		close ($null);
-		my $resp = get_case($matchp->[0],"2>$dev");
-		$resp =~ m{$weak_match_expr};
-		($rcase,$name, $rstr) = ($1,$2,$3);
-		$resp = get_case($matchp->[0],"2>&1 >$dev");
-		$resp =~ m{$weak_match_expr};
-		$rstr = $2;
-	} elsif ($caseno == 6) {
-		my $resp = get_case($matchp->[0]);
-		$resp =~ m{$match_expr};
-		($rcase,$name, $rstr) = ($1,$2,$3);
-		ok($caseno == $rcase, "received testcase $caseno");
-		next;
-	} elsif ($caseno == 7) { 
-		get_case($matchp->[0]-1);
-		my $resp = get_case($matchp->[0]);
-		my @lns=split /\n/, $resp;
-		$resp = $lns[1];
-		$resp =~ m{$match_expr};
-		($rcase,$name, $rstr) = ($1,$2,$3);
-	} else {
-		&saveSTD_n_redirect_err if $caseno==5;
-		my $resp = get_case($matchp->[0]);
-		$resp =~ m{$match_expr};
-		($rcase,$name, $rstr) = ($1,$2,$3);
-		&restoreSTDs if $caseno==5;
-	}
-	ok($rcase && $caseno == $rcase, "received testcase $caseno");
-	if (length($re)) {
-		ok($rstr =~ m{$re}, $name) || 
-			diag( sprintf "Regex \"%s\" did not match string \"%s\" in case \"%s\".", 
-				sv($re), sv($rstr), sv($name) );
-	}
+is_deeply(
+	capture_all { P iter; 1 },
+	[ undef, "Hello Perl 1\n", '', 1 ],
+	'P($string) in void context acts like say',
+);
+
+is_deeply(
+	capture_all { my @msg = ("%s", &iter); P @msg },
+	[ undef, '', '', "Hello Perl 2" ],
+	'P(@array) acts like sprintf',
+);
+
+is_deeply(
+	capture_all { P "%s", iter },
+	[ undef, '', '', "Hello Perl 3" ],
+	'P($fmt, @array) acts like sprintf',
+);
+
+is_deeply(
+	capture_all { Pe iter },
+	[ undef, '', 'Hello Perl 4', 'Hello Perl 4' ],
+	'Pe($string) in non-void context acts like warn but with no line break, and also returns the string',
+);
+
+is_deeply(
+	capture_all { Pe iter; 1 },
+	[ undef, '', "Hello Perl 5\n", 1 ],
+	'Pe($string) in void context acts like warn',
+);
+
+{
+	my $tmp = iter;
+	is_deeply(
+		capture_all { P "prev str=\"%s\" (no LF) && ${\(+iter())}", $tmp },
+		[ undef, '', '', 'prev str="Hello Perl 6" (no LF) && Hello Perl 7' ],
+		'print embedded P output',
+	);
 }
 
+is_deeply(
+	capture_all {
+		my @ar = qw(one two three 4 5 6);
+		P "%s", \@ar;
+	},
+	[ undef, '', '', '["one", "two", "three", 4, 5, 6]' ],
+	'array expansion',
+);
 
+is_deeply(
+	capture_all {
+		my %hash = (a=>'apple', b=>'bread', c=>'cherry');
+		P "%s", \%hash;
+	},
+	[ undef, '', '', '{a=>"apple", b=>"bread", c=>"cherry"}' ],
+	'hash expansion',
+);
 
+is_deeply(
+	capture_all {
+		my $obj = bless {a=>1, b=>2, x=>'y'}, 'Pkg';
+		P "%s", $obj;
+	},
+	[ undef, '', '', "Pkg{a=>1, b=>2, x=>'y'}" ],
+	'blessed object',
+);
 
+is_deeply(
+	capture_all {
+		P @{[\*STDOUT, ["fmt:%s", &iter]]};
+	},
+	[ undef, 'fmt:Hello Perl 8', '', 'fmt:Hello Perl 8' ],
+	'embed (FH,[fmt,parms])',
+);
 
+is_deeply(
+	capture_all {
+		my $pi = 4 * atan2(1, 1);
+		P "norm=%s, embed=%s", $pi, { pi => $pi };
+	},
+	[ undef, '', '', 'norm=3.14159265358979, embed={pi=>3.14}' ],
+	"truncate embedded float",
+);
 
+is_deeply(
+	capture_all {
+		my $p="3.ⅰⅳⅰⅴⅸ";
+		P "embed roman pi = %s", [$p];
+	},
+	[ undef, '', '', 'embed roman pi = ["3.ⅰⅳⅰⅴⅸ"]' ],
+	"embed foreign digits",
+);
+
