File Coverage

blib/lib/P.pm
Criterion Covered Total %
statement 167 214 78.0
branch 66 114 57.8
condition 12 29 41.3
subroutine 36 42 85.7
pod 0 4 0.0
total 281 403 69.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             # vim=:SetNumberAndWidth
3              
4             =encoding utf-8
5              
6             =head1 NAME
7             P - Safer, friendlier printf/print/sprintf + say
8              
9             =head1 VERSION
10              
11             Version "1.1.41"
12              
13             =cut
14              
15             ################################################################################
16             { package P;
17 2     2   167696 use warnings; use strict;use mem;
  2     2   23  
  2     2   54  
  2         17  
  2         4  
  2         34  
  2         402  
  2         195  
  2         8  
18             our $VERSION='1.1.41';
19              
20             # RCS $Revision: 1.57 $ - $Date: 2019-06-02 01:58:47-07 $
21             # 1.1.41 - Attempt to fix bug in Metacpan, that was reported fixed in
22             # Mar, 2013 (over 6 years ago), but seems to still be a problem
23             # It was suggested that Megacpan copy the working code from
24             # Cpan's search section as it worked correctly, but apparently
25             # that never happened.
26             # 1.1.40 - remove check for parent pid in test phase -- not important
27             # and caused win platform to fail
28             # 1.1.39 - fix in carat encoding; had Single Quote (SQ) included in string
29             # of chars to match for encoding resulting in SQ being converted
30             # for carat encoding (print SQ though %s printed ^G )
31             # 1.1.38 - split declare + definition in "local *fn=sub" to
32             # "local (*fn); *fn=sub"
33             # - expand SCALAR refs even past limit as they don't take much space
34             # and shouldn't cause more recursion
35             # - moderate code cleanups
36             # - handle 'undef' if 1st param passed:
37             # - 1) if only parm, unshift in a format "%s", so undef will print
38             # - 2) if 2nd parm looks like format, discard the null(ignore)
39             # - OUTPUT CHANGE: if 1st char of a variable is a control character
40             # then print it as carat(0x40+cc), so ctl-W, becomes ^W.
41             # - remove unneeded reference to '@ISA' (Xporter doesn't need it)
42             # - refactor module-default handling; have global default module
43             # default and single-usage OO method to supply non-default params
44             # 1.1.37 - instead of trying to disable non-working tests in early perl's,
45             # require perl 5.8.5 and perlIO 1.0.3 to build;
46             # - only do win32 checks in P.Pt
47             # 1.1.36 - instead of disabling broken perl's, in a Major series, disable code
48             # was set to diable all: fixed that (changes in P.Pt test).
49             # 1.1.35 - Add per-MAJOR-series min req'd. perl (else skip test)
50             # 1.1.34 - Compensating for odd Strawberry Perl var-values...
51             # 1.1.33 - Trying to Compensate for Strawberry Perl bugs...
52             # 1.1.32 - Change FAILS in 1.1.31 for bad env's to "skips"
53             # 1.1.31 - More pruning of bad test environments
54             # 1.1.30 - Attempt to prune unsupported OS's (WinXP)
55             # 1.1.29 - sprintf broken: include zero-width string spec to workaround
56             # 1.1.28 - testsuite fix - unknown failure case in sprintf:
57             # "Redundant argument in sprintf "... for "return sprintf $fmt, $v";
58             # Trying parens around sprintf($fmt, $v);
59             # (shot in dark for strawberry win32 perl on win10...)
60             # 1.1.27 - test fix -- Makefile.PL improperly specified "test", rather
61             # rather than using t/*.*t as pattern
62             # 1.1.26 - add code to allow changing defaults for literals and run-time
63             # constants previously only accessible through the OO method
64             # - Allow setting defaults globally as well as per-package
65             # - fix for bug in testcase 5 in "P.t" in some later versions
66             # of Strawberry Perl (5.22, 5.20?). Where the perlvar '$^X'
67             # contained a win32-backslash-separated path to perl. In double
68             # quotes, the backslashes are removed as literalizing the next
69             # character. Changing the path usage to not have double-quotes
70             # around the path should prevent the backslash-removal and pass
71             # the literal string to the perl 'system' call.
72             # 1.1.25 - put initial POD w/VERSION @ top to keep version #'s together
73             # - remove BEGIN that was needed for running/passing tests
74             # and instead use 'mem'
75             # - move changelog to column one and use vim markers to hide
76             # older changes
77             # - add dflts hash to allow 'use' time change of defaults (W.I.P.)
78             # - split local define+assignment ~#283 due to side effects
79             # 1.1.24 - respin for another Makefile change
80             # 1.1.23 - respin for a Makefile change
81             # 1.1.22 - respin to use alt version format
82             # 1.1.21 - respin to have BUID_REQ include more modern Ext:MM
83             # 1.1.20 - respin to have Makefile rely on Xporter 1.0.6
84             # 1.1.19 - Prereqs not being loaded in Cpantesters; attempt fix
85             # 1.1.18 - Unreported bugfix:
86             # the words HASH & ARRAY were sometimes printed in ref notation
87             # - remove included 'Types' code to use Types::Core (now published)
88             # 1.1.17 - Documentation refinements/fixes; Found possible culprit as to
89             # why Windows native tests could fail -- my source files in
90             # lib have pointed back to my real lib dir via a symlink.
91             # Windows wouldn't like those. Why any other platform did is
92             # likely some fluke of directory organization during test
93             # 1.1.16 - Different shot in dark to see if a change in P.env can make
94             # things work on Win-native
95             # 1.1.15 - Shot in dark to get 5.8.x to work(5.10 and newer seem to
96             # be working!
97             # 1.1.14 - and write out buffer from editor! (arg!)
98             # 1.1.13 - get perl w/ ^X rather than config
99             # 1.1.12 - Found another potential problem in the test prog.
100             # 1.1.11 - May have found another test bug.... trying fix for some fails
101             # 1.1.10 - Another internal format error bug (unreported), but caught
102             # in testing.
103             # 1.1.9 - Try to fix paths for test
104             # 1.1.8 - use ptar to generate Archive::tar compat archives
105             # 1.1.7 - Fix Makefile.PL
106             # 1.1.6 - Use t/P.env for premodifying ENV
107             # Document effect of printing to a FH & recording return val;
108             # 1.1.5 - Distribution change: use --format=v7 on tar to produce tarball
109             # (rt#90165)
110             # - Use shell script to preset env for test since
111             # Test::More doesn't set ENV
112             # 1.1.4 - Quick patch to enable use of state w/CORE::state
113             # 1.1.3 - [#$@%&!!!]
114             # 1.1.2 - Second try for test in P.t to get prereq's right
115             # 1.1.1 - Fix rest of (rt#89050)
116             # 1.1.0 - Fixed Internal bug#001, below & embedded \n@end of int. str
117             # (rt#89064)
118             # Version history continued... #{{{
119             # 1.0.32 - Fix double nest test case @{[\*STDERR, ["fmt:%s", "string"]]}
120             # (rt#89056)
121             # only use sprintf's numeric formats (e.g. %d, %f...) on
122             # numbers supported by sprintf (for now only arabic numerals).
123             # Otherwise print as string. (rt#89063)
124             # its numeric formats (ex "%d", "%f"...)
125             # 1.0.31 - Fix check for previously printed items to apply only to
126             # - the current output statement;
127             # 1.0.30 - Fix LF suppression -- instead of suppressing EOL, suppressed
128             # all output in the case where no FD was specified (code was
129             # confused in deciding whether or not to suppress output and
130             # return it as a string. (rt#89058)
131             # - Add missing quote in Synopsis (rt#89047)
132             # - Change NAME section to reference module following CPAN
133             # standard to re-list name of module instead of functions
134             # (rt#89046)
135             # - Fix L<> in POD that referenced "module" P::P instead of name, "P"
136             # (forms bad link in HTML) (rt#89051)
137             # - Since ($;@) prototypes cause more problems than (@), clean p
138             # proto's to use '@'; impliciation->remove array variations
139             # (rt@89052, #89055) (rt#89058)
140             # - fix outdated and inconsistent doc examples regarding old protos
141             # (rt#89056)(rt#89058)
142             # Had broken P's object oriented flag passing in adding
143             # the 'seen' function (to prevent recursive outptut. Fixed this
144             # while testing that main::DATA is properly closed (rt#89057,#89067)
145             # - Internal Bug #001
146             # #our @a = ("Hello %s", "World");
147             # #P(\*STDERR, \@a);
148             # # prints-> ARRAY(0x1003b40)
149             # 1.0.29 - Convert to using 'There does not exist' sign (∄), U+2204
150             # instead of (undef); use '🔁 ' for recursion/repeat;
151             # U+1F500
152             # 1.0.28 - When doing explicit out (FH specified), be sure to end
153             # with newln.
154             # 1.0.27 - DEFAULT change - don't do implicit IO reads (change via
155             # impicit_io option)
156             # - not usually needed in debugging or most output;
157             # could cause problems
158             # reading data from a file and causing desychronization problems;
159             # 1.0.26 - detect recursive data structs and don't expand them
160             # 1.0.25 - Add expansion for 'REF';
161             # - WIP: Trying to incorporate enumeration of duplicate adjacent
162             # data: Work In Progress: status: disabled
163             # 1.0.24 - limit default max string expanded to 140 chars (maybe want to
164             # do this only in brace expansions?) Method to change in OOO
165             # not documented at this time. NOTE: limiting output by default
166             # is not a great idea.
167             # 1.0.23 - When printing contents of a hash, print non-refs before
168             # refs, and print each subset in alpha sorted order
169             # 1.0.22 - Switch to {…} instead of HASH(0x12356892) or
170             # […] for arrays
171             # 1.0.21 - Doc change: added example of use in "die".
172             # 1.0.20 - Rewrite of testcase 5 in self-execution; no external progs
173             # anymore: use fork and print from P in perl child, then
174             # print from FH in parent, including uses of \x83 to
175             # inhibit extra LF's;
176             # 1.0.19 - Regretting fancy thru 'rev' P direct from FH test case (a bit)
177             # **seems** like some people don't have "." in path for test
178             # cases, so running "t/prog" doesn't work, trying "./t/prog"
179             # (1 fail on a Win32 base on a x64 system...so tempted
180             # to just ignore it...) >;^); guess will up this for now
181             # and think about that test case some more...
182             # I'm so gonna rewrite that case! (see xtodox below)
183             # 1.0.18 - convert top format-case statement to load-time compile
184             # and see if that helps BSD errors;
185             # - change test case w/array to use P & not old Pa-form
186             # - change test case to print to STDERR to use Pe
187             # - fix bug in decrement of $lvl in conditional (decrement must
188             # be in first part of conditional)
189             # - xtodox fix adaptation of 'rev' test case to work w/o
190             # separate file(done)
191             # 1.0.17 - another try at fixing pod decoding on metacpan
192             # 1.0.16 - pod '=encoding' move to before '=head'
193             # (ref:https://github.com/CPAN-API/metacpan-web/issues/800 )
194             # 1.0.15 - remove 'my $_' usage; old perl compat probs; use local
195             # in once instance were needed local copy of $_
196             # 1.0.14 - arg! misspelled Win nul: devname(fixed)
197             # 1.0.13 - test case change only to better test print to STDERR
198             # 1.0.12 - test case change: change of OBJ->print to print OBJ to
199             # try to get around problem on BSD5.12 in P.pm (worked!)
200             # - change embedded test case to not use util 'rev', but
201             # included perl script 'rev' in 't' directory...(for native win)
202             # 1.0.11 - revert printing decimals using %d: dropped significant leading
203             # zero's; Of NOTE: floating point output in objects is
204             # not default: we use ".2f"
205             # - left off space after comma in arrays(fixed)
206             # - rewrite of sections using given/when/default to not use
207             # them; try for 5.8 compat
208             # - call perl for invoking test vs. relying on #! invokation
209             # - pod updates mentioning 'ops'/depth
210             # 1.0.10 - remove Carp::Always from test (wasn't needed and caused it
211             # to fail on most test systems)
212             # add OO-oriented way to set internal P ops (to be documented)
213             # - fixed bug in logic trimming recursion depth on objects
214             # 1.0.9 - Add Px - recursive object print in squished form;
215             # Default to using Px for normal print
216             # 1.0.8 - fix when ref to IO -- wasn't dereferenced properly
217             # - upgrade of self-test/demo to allow specifying which test
218             # to run from cmd line; test numbers are taken from
219             # the displayed examples when run w/no arguments
220             # B:still doesn't run cleanly under test harness may need to
221             # change cases for that (Fixed)
222             # - POD update to current code
223             # 1.0.7 - (2013-1-9) add support for printing blessed objects
224             # - pod corrections
225             # - strip added LF from 'rev' example with tr (looks wrong)
226             # 1.0.6 - add manual check for LF at end (chomp doesn't always work)
227             # 1.0.5 - if don't recognize ref type, print var
228             # 1.0.4 - added support for printing contents of arrays and hashes.
229             # (tnx 2 MidLifeXis@prlmnks 4 brain reset)
230             # 1.0.3 - add Pea
231             # 1.0.2 - found 0x83 = "no break here" -- use that for NL suppress
232             # - added support for easy inclusion in other files
233             # (not just as lib);
234             # - add ISA and EXPORT to 'mem' so they are available @ BEGIN time
235             #
236             # 1.0.1 - add 0xa0 (non breaking space) to suppress NL
237             # #}}}
238              
239 2     2   199 use utf8;
  2         3  
  2         12  
240 2     2   44 { no warnings "once"; *IO::Handle::P = \&P::P }
  2         2  
  2         99  
241            
242 2     2   391 use Types::Core qw(blessed);
  2         4593  
  2         12  
243              
244             our @EXPORT;
245 2     2   720 use mem(@EXPORT=qw(P Pe));
  2         3  
  2         9  
246 2     2   56 use Xporter;
  2         3  
  2         6  
247              
248             my $ignore=<<'IGN' #{{{
249             BEGIN {
250             use constant EXPERIMENTAL=>0;
251             if (EXPERIMENTAL) {
252             sub rm_adjacent {
253             my $c = 1;
254             ($a, $c) = @$a if ref $a;
255             $b //= "∄";
256             if ($a ne $b) { $c > 1 ? "$a × $c" : $a , $b }
257             else { (undef, [$a, ++$c]) }
258             }
259             sub reduce(&\[@$]) { my $f = shift;
260             my (@final, $i) = ((), 0);
261             my ($cnt, $term) = (0, undef);
262             my ($parms, $rv);
263             if (@_ < 2 && ARRAY $_[0] ? $_[0] : \@_;
264             $parms = q(ARRAY) eq
265             $rv =
266              
267             while (@_ >= 2) {
268             my $res = $f->($_[0], $_[1])) {
269             if ($f->($_[0], $_[1])) {
270             if ($cnt == 0) {
271             $term = $_[0];
272             ++$cnt;
273             } else { ++$cnt};
274             } else {
275             if ($cnt) {
276             push @final, "\"$term\" × $cnt";
277             ($cnt, $term) = (undef, 0);
278             }
279             }
280             shift;
281             }
282             @final
283              
284             for (my $i=0; $i < (@$ar-1); ++$i ) {
285             my ($x, $y) = ($ar->[$i], $ar->[$i+1]);
286             my @r = &$f($ar->[$i], $ar->[$i+1]);
287             push @final, $r[0] if $r[0];
288             $ar->[$i+1] = $r[1];
289             }
290             @final;
291             }
292             }
293             }
294             IGN
295             ||undef; #}}}
296              
297            
298              
299 2     2   155 use constant NoBrHr => 0x83; # Unicode codepoint="No Break Here"
  2         4  
  2         536  
300             our %_dflts;
301             our (%mod_dflts, %types);
302             BEGIN {
303 2     2   19 %_dflts=(
304             depth => 3,
305             ellipsis => '…',
306             expand_duprefs => 0,
307             implicit_io => 0,
308             maxstring => undef,
309             noquote => 1,
310             seen => '🔁', # 🔁
311             undef => '∄',
312             );
313              
314 2 0       7 my $bool = sub { $_[0] ? 1 : 0 };
  0         0  
315 2 0       4 my $intnum = sub { $_[0] =~ m{^([0-9]+)$} ? 0 + $1 : 0 };
  0         0  
316 2 0       11 my $string = sub { length($_[0]) ? "$_[0]" : '' };
  0         0  
317 2         4 my $true = sub { 1 };
  0         0  
318              
319 2         9 %types=(
320             default => $true,
321             depth => $intnum,
322             ellipsis => $string,
323             expand_duprefs => $bool,
324             implicit_io => $bool,
325             maxstring => $intnum,
326             noquote => $bool,
327             seen => $string,
328             undef => $string,
329             );
330              
331             #global default copy
332 2         39 $mod_dflts{""} = \%_dflts;
333             }
334              
335              
336 2     2   10 use constant cc => '\x00-\x1f'; ## cc = caret class
  2         3  
  2         2691  
337              
338             sub vrfmt($) {
339 0   0 0 0 0 my ($v, $pkg) = (shift || "", "");
340             #my ($vl, $ic) = (length $v, 2+index $v, "::");
341             #if ($ic >= 2 && $vl - $ic > 0) {
342             # $pkg = substr $v, 0, $ic;
343             # $v = substr $v, $ic;
344             #} # here, 'v' is a var name
345             #if ( $v =~ m{^([\x00-\x1f])(\w*)$} ) { # varname starting w/ctl-ch
346             # $v = "^" . chr(0x40 + ord $1) . $2; # use carot encoding
347             #}
348 0         0 $pkg . $v;
349             }
350              
351             ################################################################################
352              
353              
354             sub sw(*):lvalue;
355             # sub sw_decr(*);
356              
357 218     218   331 sub _Px($$;$) { my ($p, $v) = (shift, shift);
358 218         308 local (*sw); *sw = sub (*):lvalue {
359             defined($p->{$_[0]})
360             ? $p->{$_[0]}
361 231 100   231   1298 : ($p->{$_[0]} = $mod_dflts{""}->{$_[0]});
362 218         537 };
363             # local (*sw_decr); *sw_decr = sub(*) { my $res;
364             # 0 >= ($res = sw($_[0])) and return $res;
365             # --sw($_[0]); $res };
366              
367 218 50       306 unless (sw(expand_duprefs)) {
368 218 100 66     544 if (ref $v && ! SCALAR $v) {
369 50 50       593 if ($p->{__P_seen}{$v}) { return "*". sw(seen) . ":" . $v . "*" }
  0         0  
370 50         96 else { $p->{__P_seen}{$v} = 1 }
371             }
372             }
373 218         403 my ($nargs, $lvl, $ro) = (scalar @_, 2, 0);
374 218 50       331 if ($nargs) {
375 218         214 $lvl = $_[0];
376 218 100       292 if ($nargs>1) { $ro = $_[1] }
  155         147  
377             }
378 218 100       272 return sw('undef') unless defined $v;
379 209         218 my $rv = ref $v;
380 209 100 100     475 if (1 > $lvl-- || !$rv) { # LAST level actions:
381 163         184 my $fmt; # prototypes are documentary (rt#89053)
382             my $given = [
383 163 100   163   763 sub ($$) { $_[0] =~ /^[-+]?[0-9]+\.?\z/ && q{%s} },
384             #sub ($$) { $_[1] && ($_[0] = vrfmt($_[0])), $_[1] && qq{%s} },
385 95 100   95   252 sub ($$) { $_[1] && qq{%s} },
386 27 100   27   82 sub ($$) { 1 == length($_[0]) && q{'%s'} },
387 18 50   18   67 sub ($$) { $_[0] =~ m{^(?:[+-]?(?:\.\d+)
388             |(?:\d+\.\d+))\z}x && q{%.2f} },
389 18 100   18   68 sub ($$) { substr($_[0],0,5) eq 'HASH(' &&
390             '{'. sw(q(ellipsis)) .'}' . q{%.0s} },
391 14 50   14   45 sub ($$) { substr($_[0],0,6) eq 'ARRAY(' &&
392             '['. sw(q(ellipsis)) .']' . q{%.0s} },
393             sub ($$) { substr($_[0],0,7) eq 'SCALAR(' &&
394 14 50   14   34 do {'\\' . $p->_Px(${$_[0]}, $lvl) .' ' } },
  0         0  
  0         0  
395             # sub ($$) { $mxstr && length ($_[0])>$mxstr && qq("%.${mxstr}s")},
396 14 50   14   32 sub ($$) { ref $_[0] && q{%s} },
397 14     14   24 sub ($$) { 1 && q{"%s"} },
398 163         1247 ];
399              
400 163 100       305 do { $fmt = $_->($v, $ro) and last } for @$given;
  377         477  
401 163         1675 return sprintf($fmt, $v);
402             } else {
403 46         49 my $pkg = '';
404              
405 46 50 33     144 ($pkg, $rv) = ($1, $2) if 0 <= (index $v, '=') &&
406             $v =~ m{([\w:]+)=([cc\w][\w:]+)};
407              
408 46         118 local * nonrefs_b4_refs ; * nonrefs_b4_refs = sub {
409 48 100   48   160 ref $v->{$a} cmp ref $v->{$b} || $a cmp $b
410 46         154 };
411              
412 46         113 local (*IO_glob, *NIO_glob, *IO_io, *NIO_io);
413             (*IO_glob, *NIO_glob, *IO_io, *NIO_io) = (
414 0     0   0 sub(){'<*'.<$v>.'>'}, sub(){'<*='.$p->_Px($v, $lvl-1).'>'},
  0         0  
415 0     0   0 sub(){'<='.<$v>.'>'}, sub(){'<|'.$p->_Px($v, $lvl-1).'|>'},
  0         0  
416 46         264 );
417 2     2   16 no strict 'refs';
  2         4  
  2         1453  
418             my %actions = (
419             GLOB => ($p->{implicit_io}? *IO_glob: *NIO_glob),
420             IO => ($p->{implicit_io}? *IO_io : *NIO_io),
421 0     0   0 REF => sub(){ "\\" . $p->_Px($$_, $lvl-1) . ' '},
422 0     0   0 SCALAR=> sub(){ $pkg.'\\' . $p->_Px($$_, $lvl).' ' },
423             ARRAY => sub(){ $pkg."[".
424             (join ', ',
425             # not working: why? #reduce \&rm_adjacent, (commented out)
426 9     9   20 map{ $p->_Px($_, $lvl) } @$v ) ."]" },
  63         114  
427 37     37   58 HASH => sub(){ $pkg.'{' . ( join ', ', @{[
428 37         134 map { $p->_Px($_, $lvl, 1) . '=>'.
429 73         170 $p->_Px($v->{$_}, $lvl,0) }
430             sort nonrefs_b4_refs keys %$v]} ) . '}' },
431 46 50       543 );
    50          
432 46 50       100 if (my $act=$actions{$rv}) { &$act }
  46         65  
433 0         0 else { return "$v" }
434             }
435             }
436              
437 14     14   19 sub _init_p($) { my $p; my $caller = $_[0];
  14         17  
438 14 50       33 croak P "FATAL: P::_init_p called with wrong# args (%s)", 0+@_
439             unless (@_ == 1);
440 14 100       48 if (blessed $mod_dflts{$caller}) { # blessed caller already stored
    50          
441 8         69 $p = $mod_dflts{$caller};
442             } elsif (HASH $mod_dflts{$caller}) { # have hash, so bless it
443 0         0 bless $p = $mod_dflts{$caller};
444             } else {
445 6         103 bless $p = $mod_dflts{$caller} = {}; # init caller's flag hash
446             }
447 14         25 $p;
448             }
449              
450            
451             sub P(@) {
452 9     9 0 26456 my $undef_cnt=0;
453 9 50       26 if (!defined($_[0])) {
454 0         0 my $fmt = ("%s, " x (@_-1))."%s";
455 0         0 unshift @_, $fmt;
456             }
457              
458 9 100       34 my $p = ref $_[0] eq 'P' ? shift : _init_p(caller);
459              
460 9         20 local (*sw); *sw = sub (*):lvalue {
461             defined($p->{$_[0]})
462             ? $p->{$_[0]}
463 18 100   18   69 : ($p->{$_[0]} = $mod_dflts{""}->{$_[0]});
464 9         33 };
465              
466 9 50       39 $p->{__P_seen} = {} unless ref $p->{__P_seen};
467              
468             local * unsee_ret = sub ($) {
469 9 50   9   87 delete $p->{__P_seen} if exists $p->{__P_seen};
470 9         26 $_[0] };
  9         72  
471              
472 9         13 my $v = $_[0];
473 9         12 my $rv = ref $v;
474 9         14 my ($depth, $noquote) = (sw(depth), sw(noquote));
475              
476 9 50       22 if (HASH eq $rv) {
477 0         0 my $params = $v; $v = shift; $rv = ref $v;
  0         0  
  0         0  
478 0 0       0 $depth = $params->{depth} if exists $params->{depth};
479             }
480 9 50       43 if (ARRAY eq $rv ) { $v = shift;
  0         0  
481 0         0 @_ = (@$v, @_); $v = $_[0]; $rv = ref $v }
  0         0  
  0         0  
482              
483 9         29 my ($fh, $explicit_out);
484 9 50 33     17 if ($rv eq GLOB || $rv eq IO) {
485 0         0 ($fh, $explicit_out) = (shift, 1);
486 0         0 $v = $_[0]; $rv = ref $v;
  0         0  
487 9         69 } else { $fh =\*STDOUT }
488            
489 9 50       15 if (ARRAY eq $rv ) { $v = shift;
  0         0  
490 0         0 @_=(@$v, @_); $v=$_[0]; $rv = ref $v }
  0         0  
  0         0  
491            
492 9         31 my $fmt = shift;
493 9         11 my $res = do {
494 2     2   13 no warnings;
  2         3  
  2         296  
495             sprintf $fmt,
496 9         14 map {local $_ = $p->_Px($_, $depth, $noquote) } @_
  9         18  
497             };
498              
499 9         22 chomp $res;
500            
501 9 50       20 my ($nl, $ctx) = ("\n", defined wantarray ? 1 : 0);
502            
503             # our $Pcount;
504             # sub Pe(@);
505             # if (!$Pcount) {
506             # ++$Pcount;
507             # my $from = caller ;
508             # #Pe "cts=%s, from=%s", $ctx, $from;
509             # $ctx=0 if $from =~ /^DB/;
510             # }
511            
512              
513              
514 9 50       85 ($res, $nl, $ctx) = (substr($res, 0, -1 + length $res), "", 2) if
515             ord(substr $res,-1) == NoBrHr; #"NO_BREAK_HERE"
516              
517 9 50 33     26 if (!$fh && !$ctx) { #internal consistancy check
518 0 0       0 ($fh = \*STDERR) and
519             P $fh "Invalid File Handle presented for output, using STDERR";
520 0         0 ($explicit_out, $nl) = (1, "\n") }
521              
522 9 50 33     34 else { return unsee_ret($res) if (!$explicit_out and $ctx == 1) }
523              
524 2     2   11 no warnings 'utf8';
  2         3  
  2         980  
525 0 0 0     0 print $fh ($res . (!$ctx && (!$\ || $\ ne "\n") ? "\n" : "") );
526 0         0 unsee_ret($res);
527             }
528              
529              
530             sub Pe(@) {
531 0 0   0 0 0 my $p = ref $_[0] eq 'P' ? shift : _init_p(caller);
532 0         0 unshift @_, \*STDERR;
533 0 0       0 unshift @_, $p if ref $p;
534 0         0 goto &P
535             }
536              
537              
538 6 50   6   1615 sub import { my $p = ref $_[0] eq 'P' ? $_[0] : _init_p(caller);
539 6         13 my ($modname, @args) = @_;
540 6 50       16 goto &Xporter::import if caller eq 'P';
541 6 100       11 if (@args) {
542 4         5 my @others;
543 4         6 my $default = 0;
544 4         4 my $got_default = 0;
545 4         5 my $save_p = [];
546             my @tags = grep {
547 4         6 my $full_switch; # has tag+args, but no colon
  5         5  
548 5 50       11 if (0 == index $_, ':') {
549 5         7 $_ = substr $_, 1;
550 5         7 $full_switch = $_; # includes any '=' fields
551 5         9 my ($l, $tag, $val) = (-1, $_);
552 5 100       11 if (($l = index $_, '=') > 0) {
553 4         6 $tag = substr $_, 0, $l;
554 4         15 $val = substr $_, $l+1;
555             }
556 5 100 66     15 if ($tag eq 'default' && !$got_default) { #can only have 1 dflt sec.
    50          
557 1         2 $default = 1;
558 1         2 push @$save_p, $p;
559 1         3 $p = $mod_dflts{""};
560             } elsif ($tag eq '--') { #end of dflts (:--)
561 0         0 $p = pop @$save_p;
562 0         0 $default = 0;
563 0         0 $got_default = 1;
564             } else {
565             warnings::warn P "Unrecognized flag: %s", $tag unless
566 4 50       10 exists $mod_dflts{""}->{$tag};
567 4 50       33 $p->{"$tag"} = defined("$val") ? "$val" : -1;
568             }
569             } else {
570 0         0 push @others, $_;
571             }
572             } @args;
573 4         11 @_=($modname, @others);
574             }
575 6         20 goto &Xporter::import;
576             }
577              
578              
579              
580              
581 1   33 1 0 513 sub ops($) { my $p = shift; my $c = ref $p || $p;
  1         6  
582 1         3 bless $p = {};
583 2     2   14 use Carp qw(croak);
  2         3  
  2         357  
584 1         4 my $caller = (caller)[0];
585 1         2 my $args = $_[0];
586 1 50       4 croak "ops takes a hash to pass arguments" unless HASH $args;
587 1         15 foreach (sort keys %$args) {
588 1 50       3 if (defined $_dflts{$_}) { $p->{$_} = $args->{$_} }
  1         5  
589             else {
590 0         0 warn "Unknown key \"$_\" passed to ops";}
591             }
592             $p
593 1         2 }
594             1}
595              
596             {
597             package main;
598 2     2   13 use utf8;
  2         11  
  2         23  
599              
600             unless ((caller 0)[0]) {
601             binmode P::DATA, ":utf8";
602             binmode *STDOUT, ":utf8";
603             binmode *STDERR, ":utf8";
604             $_=do{ $/=undef, };
605             close P::DATA;
606             our @globals;
607             eval $_;
608             die "self-test failed: $@" if $@;
609             1;
610             } else {
611             close P::DATA;
612             }
613             1;
614             }
615             ###########################################################################
616             # Pod documentation {{{1
617             # use P;
618              
619             =head1 SYNOPSIS
620              
621             use P qw[:depth=5 :undef="(undef)"];
622              
623             P FILEHANDLE FORMAT, LIST
624             P FILEHANDLE, LIST # comma is not disallowed
625             P FORMAT, (LIST)
626             P (LIST)
627             P @ARRAY # may contain File Handle, Format and ARGS
628             # all in 1 array.
629             $s = P @ARRAY; P $s; # can be same output as "P @ARRAY"
630             Pe # same as P STDERR,...
631             $s = P FILEHANDLE ... # sends same output to $s and FILEHANDLE
632              
633             =head1 DESCRIPTION
634              
635             C

is a combined print, printf, sprintf & say in 1 routine. It saves

636             tremendously on development time. It's not just a 1 character 'verb',
637             but has other time-saving and powerful features. It has the convenience
638             of C in adding a newline when needed but also allows specifying
639             a File Handle and format statement.
640             C

accepts a filehandle with or without a comma after the filehandle.

641              
642             =over
643              
644             =item o B
645              
646             =back
647              
648             A fixed string can be changed to formatted output with no change of
649             verb:
650              
651             Example:
652             # Starting with a "die" statement.
653             1) die "Wrong number of params";
654             # Then number of arguments passed is added:
655             2) die P "Expecting 2 params, got %s", scalar @ARGV;
656             # Then contents of @ARGV can be printed as well (no loop needed):
657             3) die P "Expecting 2 params, got %s (ARGV=%s), 0+@ARGV, \@ARGV;
658              
659              
660             C

can replacing C without the need for a temporary

661             variable and without printing cryptic representations for @ARGV,
662             like "C". Instead,
663             C

displays the actual contents of the array, showing

664             ["arg1", "arg2"].
665              
666              
667             =over
668              
669             =item B<· Auto-Newline Handling>
670              
671             =back
672              
673             When it comes to C's, or "\n" at the end of line, C

674             attempts to look at context. If output is assigned to a variable,
675             then C

acts like C. If it is to a file handle, then

676             it will act like C and automatically append a C.
677             Unlike C, C

can use formatted output and print to a file

678             handle. Printing to STDERR is simplified with the C form of
679             C

, which is a short form of 'P STDERR, "..."'.

680              
681             When C

prints to strings, any one newline at the end of the

682             string will be suppressed. Conversely it will add one if
683             printing to a device. If printing to a string and a device
684             at the same time, it will favor suppression and not output
685             a newline to the device.
686              
687             =over
688              
689             =item B<· Trapping C>
690              
691             =back
692              
693             Rather than aborting output when C is part of the output,
694             C

prints a configurable symbol, '∄', by default, the symbol

695             for "does not exist" where the undef would have printed and the
696             rest of the string is printed normally.
697              
698             =over
699              
700             =item B<· Less restrictive syntax>
701              
702             =back
703              
704             C

tries not to have arbitrary restrictions on it's arguments.

705              
706             It handles cases that the equivalent perl statement won't.
707              
708              
709              
710             VERB -> P print printf sprintf say
711             V --FEATURE-- V --- ----- ------ ------- ---
712             1) to a FH Yes Yes Yes No Yes
713             2) to $fh Yes Yes Yes No No
714             3) to a string Yes No No Yes No
715             4) add EOL-NL to FH? Yes No No No Yes
716             5) sub EOL-NL in string Yes No No No No
717             6) FMT Yes No Yes Yes No
718             7) @[FMT,ARGS] Yes No Yes No No
719             8) undef to "%s" Yes No No No No
720             9) @[$fh,FMT,ARGS] Yes No No No No
721             10) like "tee" Yes No No No No
722              
723             (9) - File Handle in 1st member of ARRAY used for output.
724              
725             (10) - When P is being used as a string formatter like sprintf,
726             it can still have a "$fh" as the first argument that will
727             print the formatted string to the file handle as well as
728             returning it's value (note: this will force the string
729             to be printed w/o a trailing newline).
730              
731              
732              
733              
734             =head3 Undefs
735              
736              
737             When printed as strings (C<"%s">), undefs are automatically caught and
738             "E<0x2204>", (U+2204 - meaning "I") is
739             printed in place of "C"
740              
741             By default C

, prints the content of references (instead HASH

742             (or ARRAY)=(0x12345678). By default, it prints three levels deep with
743             deeper nesting replaced by by the unicode ellipsis character (U+2026).
744              
745             While designed for development use, it is useful in many more situations, as
746             tries to "do the right thing" based on context. It can usually be used
747             as a drop-in replacement the perl functions C, C, C,
748             and, C.
749              
750             P tries to smartly handle newlines at the end of the line -- adding them
751             or subtracting them based on if they are going to a file handle or to another
752             variable.
753              
754             The newline handling at the end of a line can be supressed by adding
755             the Unicode control char "Don't break here" (0x83) at the end of a string
756             or by assigning the return value B having a file handle as the first
757             argument. Ex: C">.
758              
759              
760             Ced objects, by default, are printed with the class or package name
761             in front of the reference. Note that these substitutions are performed only with
762             references printed through a string (C<"%s">) format -- features designed
763             to give useful output in development or debug situations.
764              
765             One difference between C

and C: C

can take

766             an array with the format in the 0th element, and parameters following.
767             C will cause an error to be raised, if you try passing an array
768             to it, as it will force the array into scalar context -- which as
769             the manpage says "is almost never useful", and the perl-developers
770             admit "is never useful". Rather than follow in the
771             design flaws of its predecessors, P I to do the right thing.
772              
773              
774             B A side effect of P being a contextual replacement for sprintf,
775             is if it is used as the last line of a subroutine. By default, this
776             won't print it's arguments to STDOUT unless you explicity specify the
777             filehandle, as it will think it is supposed to return the result -- not
778             print it. An alternate workaround -- return another value, like a
779             status value. OR use it as a feature. A subroutine that has
780             a C at the end can be used in string construction or
781             can be used for direct output.
782              
783             =head1 EXAMPLE: Duel-Use Subroutines for Strings or Printing
784              
785              
786             sub items_in_list() {
787             my $numitems = get_num();
788             P "num items=%s", $numitems;
789             } # can be used:
790              
791             my $s=items_in_list();
792             # or
793             $items_in_list(); # prints to STDOUT w/newline on end
794              
795              
796              
797              
798              
799             =head2 Special Use Features
800              
801              
802             While C

is normally called procedurally, and not as an object, there are

803             some rare cases where one would really like it to print "just 1 level
804             deeper". To do that, you need to get a pointer to C

's C.

805              
806             To get that pointer, call Cops({key=>value})> to set C

's options and

807             save the return value. Use that pointer to call P. See following example.
808              
809             =head1 EXAMPLE: (changing P's defaults)
810              
811             Suppose you had an array of objects, and you wanted to see the contents
812             of the objects in the array. Normally P would only print the first two levels:
813              
814              
815             my %complex_probs = (
816             questions =E [ "sqrt(-4)", "(1-i)**2" ],
817             answers =E [ {real => 0, i =>2 },
818             {real => 0, i => -2 } ] );
819             my $prob_ref = \%complex_problems;
820             P "my probs = %s", [$prob_ref];
821              
822              
823             The above would normally produce:
824              
825             my probs = [{answers=>[{…}, {…}], questions=>["sqrt(-4)", "(1-i)**2"]}]
826              
827              
828             Instead of the contents of the hashes, P shows the ellipses (a
829             1 char-width wide character) for the interior of the hashes. If you
830             wanted the interior to print, you'd need to raise the default data
831             expansion I for C

as we do here:

832              
833              
834             my %complex_probs = (
835             questions => [ "sqrt(-4)", "(1-i)**2" ],
836             answers => [ {real => 0, i =>2 }, { real => 0, i => -2 } ] );
837             my $p=P::->ops({depth=>4});
838             $p->P("my array = %s", \%complex_probs);
839              
840              
841             The above allows 1 extra level of depth to be printed, so the elements in the
842             hash are displayed producing:
843              
844             my probs = [{answers=>[{i=>2, real=>0}, {i=>-2, real=>0}], # extra "\n"
845             questions=>["sqrt(-4)", "(1-i)**2"]}]
846              
847              
848             B when referring to the B B>, a double colon is usually
849             needed to tell perl you are not talking about the function name.
850              
851             Please don't expect data printed by P to be "pretty" or parseable. It's not
852             meant to be a Perl::Tidy or Data::Dumper. I, when printing
853             references, it was designed as a development aid.
854              
855              
856              
857             =head2 Summary of possible OO args to "ops" (and defaults)
858              
859             =over
860              
861             =item C 3>
862              
863             =over
864              
865             Allows setting depth of nested structure printing. NOTE: regardless of depth,
866             recursive structures in the same call to C

, will not expand but be displayed

867             in an abbreviated form.
868              
869             =back
870              
871             =item C 0>
872              
873             =over
874              
875             When printing references, GLOBS and IO refs do not have their
876             contents printed (since printing contents of such refs may do I/O that
877             changes the object's state). If this is wanted, one would call C with C set to true (1).
878              
879             =back
880              
881             =item C 1>
882              
883             =over
884              
885             In printing items in hashes or arrays, data that are Read-Only or do not need
886             quoting won't have quoting (contrast to Data::Dumper, where it can be turned
887             off or on, but not turned on, only when needed).
888              
889             =back
890              
891             =item C undef>
892              
893             =over 2
894              
895             Allows specifying a maximum length of any single datum when expanded from an indirection expansion.
896              
897             =back
898              
899             =back
900              
901             =head2 Example 2: Not worrying about "undefs"
902              
903             Looking at some old code of mine, I found this:
904              
905             print sprintf STDERR,
906             "Error: in parsing (%s), proto=%s, host=%s, page=%s\n",
907             $_[0] // "null", $proto // "null", $host // "null",
908             $path // "null";
909             die "Exiting due to error."
910              
911             Too many words and effort in upgrading a die message! Now it looks like:
912              
913             die P "Error: in parsing (%s), proto=%s, host=%s, page=%s",
914             $_[0], $proto, $host, $path;
915              
916             It's not just about formatting or replacing sprintf -- but automatically
917             giving you sanity in places like error messages and debug output when
918             the variables you are printing may be 'undef' -- which would abort the
919             output entirely!
920              
921              
922              
923             =head1 MORE EXAMPLES
924              
925              
926             P "Hello %s", "World"; # auto NL when to a FH
927             P "Hello \x83"; P "World"; # \x83: suppress auto-NL to FH's
928             $s = P "%s", "Hello %s"; # not needed if printing to string
929             P $s, "World"; # still prints "Hello World"
930              
931             @a = ("Hello %s", "World"); # using array, fmt as 1st arg
932             P @a; # print "Hello World"
933             P 0 + @a; # prints #items in '@a': 2
934              
935             P "a=%s", \@a; # prints contents of 'a': [1,2,3...]
936              
937             P STDERR @a # use @a as args to a specific FH
938             # Uses indirect method calls when
939             # invoked like "print FH ARGS"
940             #
941             Pe "Output to STDERR" # 'Shortcut' for P to STDERR
942              
943             %H=(one=>1, two=>2, u=>undef); # P Hash bucket usage + contents:
944              
945             P "%H hash usage: %s", "".%H; # Shows used/total Hash bucket usage
946             P "%H=%s", \%H; # print contents of hash:
947              
948             %H={u=>(undef), one=>1, two=>2}
949              
950             bless my $h=\%H, 'Hclass'; # Blessed objects...
951             P "Obj_h = %s", $h; # & content:
952              
953             Obj_h = Hclass{u=>(undef), one=>1, two=>2}
954              
955              
956             =head1 Sample Code + Test + Demo
957              
958             To demonstrate the various usages of P, several examples are embedded
959             with this documenation in a special C section. If this module
960             is executed as with C or just C if the module is
961             set to be executable, it will run a short program that shows
962             different features of P as well as doing a short run-time test
963             (that is actually part of the test suite).
964              
965             The demo/example/test code embedded in this module is NOT compiled or
966             accessed when it is Ced in code.
967              
968             As of this writing there are 13 examples. The output of these
969             examples follows:
970              
971             =over
972              
973             #1 (ret from func) : Hello Perl 1
974             #2 (w/string) : Hello Perl 2
975             #3 (passed array) : Hello Perl 3
976             #4 (w/fmt+string) : Hello Perl 4
977             #5 (to STDERR) : Hello Perl 5
978             #6 (to strng embedded in #7):
979             #7 (prev string) : prev str="Hello Perl 6" (no LF) && Hello Perl 7
980             #8 (P && array ref) : ["one", "two", "three", 4, 5, 6]
981             #9 (P HASH ref) : {a=>"apple", b=>"bread", c=>"cherry"}
982             #10 (P Pkg ref) : Pkg{a=>1, b=>2, x=>'y'}
983             #11 (P @{[FH,["fmt:%s",…]]}) : fmt:Hello Perl 11
984             #12 (truncate embedded float): norm=3.14159265358979324, embed={pi=>3.14}
985             #13 (test mixed digit string): embed roman pi = ["3.ⅰⅳⅰⅴⅸ"]
986              
987             =back
988              
989             The code uses a function C that prints I followed by
990             an autoincrementing counter that also is used as the test or example
991             number.
992              
993             Putting the format + its arguments in an array is simple and does not
994             change if P is printing to output or to a string (cf. sprintf/printf).
995             P goes further than allowing the format specification in an array -- it
996             also allows putting the file handle as the 1st element in the array as
997             shown in #11.
998              
999             P is not picky about how file handles can be used -- they can be
1000             followed by a space or by a comma. No special syntax is needed for the
1001             arguments of P, it can follow the example of printf or the standard
1002             usage of using commas to separate arguments.
1003              
1004              
1005             =head1 NOTES
1006              
1007             Values given as args with a format statement, are checked for B
1008             and have "E<0x2204>" substituted for undefined values. If you print
1009             vars as in decimal or floating point, they'll likely show up as 0, which
1010             doesn't stand out as well.
1011              
1012             Sometimes the perl parser gets confused about what args belong to P and
1013             which do not. Using parentheses (I C) can help
1014             in those cases.
1015              
1016             Usable in any code, P was was designed to save typing, time and work of
1017             undef checking, newline handling, peeking at data structures in small
1018             spaces during development. It tries to do the "right thing" with the
1019             given input. It may not be suitable where speed is paramount.
1020              
1021             =cut
1022              
1023              
1024             #}}}1
1025              
1026             package P;
1027             __DATA__