Carp::Diagnostics - Carp with a diagnostic message


Carp-Diagnostics documentation Contained in the Carp-Diagnostics distribution.

Index


Code Index:

NAME

Top

Carp::Diagnostics - Carp with a diagnostic message

SYNOPSIS

Top

	use Carp::Diagnostics qw(cluck carp croak confess) ;

	CroakingSub() ;

	#---------------------------------------------------------------------------

	sub CroakingSub
	{

	=head2 CroakingSub

	An example of how to use Carp::Diagnostics.

	=head3 Diagnostics

	=cut

	my ($default_rule_name, $name) = ('c_objects', 'o_cs_meta') ;

	confess
		(
		"Default rule '$default_rule_name', in rule '$name', doesn't exist.\n",

		<<END_OF_POD,

	=over

	=item Default rule '$default_rule_name', in rule '$name', doesn't exist!

	The default rule of a I<FirstAndOnlyOneOnDisk> B<META_RULE> must be registrated before
	the B<META_RULE> definiton. Here is an example of declaration:

	 AddRule 'c_o', [ '*/*.o' => '*.c' ], \&C_Builder ;
	 AddRule 'cpp_o', [ '*/*.o' => '*.cpp' ], \&CPP_Builder ;

	 AddRule [META_RULE], 'o_cs_meta',
		[\&FirstAndOnlyOneOnDisk, ['cpp_o', 'c_o' ], 'c_o'] ;
					  ^- slave rules -^    ^-default

	=back

	=cut

	END_OF_POD
		) ;

	}

DESCRIPTION

Top

This module overrides the subs defined in Carp to allow you to give informative diagnostic messages.

DOCUMENTATION

Top

Perl Best Practices recommends to have a DIAGNOSTIC section, in your POD, where all your warnings and errors are explained in details. Although I like the principle, I dislike its proposed implementation. Why should we display cryptic messages at run time that the user have to lookup in the documentation? I also dislike to have the diagnostics grouped far from where the errors are generated, they never get updated.

This modules implements the four subs exported by the Carp module (carp, croak, cluck, confess). The new subs take zero, one or two arguments.

No argument

* No message

One argument

* A message

Two arguments

* A short message
* A diagnostic message

The long message is a diagnostic and is the one normally displayed.

You can direct Carp::Diagnostics to display the short message; this is useful when developing modules. You, the module author, understand short warnings. See UseLongMessage.

Having the possibility to pass one argument or two gives you the possibility to drop-in Car::Diagnostics in your module without having to modify all the call to the carping subs. if you decide to add Diagnostics to any of your subs, just add the second argument to, your already existing, carp call.

The podification functionality is always on.

Carp is used internally so you get an identical functionality.

POD: Eating your cake and having it too.

The good news is that you are going to do two things in one shot. You'll be giving better diagnostics to your users and you'll be documenting your modules too.

If the long message (diagnostic) is POD (the first non space character is an '=' at the start of the line), Carp::Diagnostics will convert the pod to text and pass it to Carp::.

 $ perl cd_test.pl 

     Default rule 'c_objects', in rule 'o_cs_meta', doesn't exist!
        The default rule of a *FirstAndOnlyOneOnDisk* META_RULE must be registrated before the
        META_RULE definiton. Here is an example of declaration:

          AddRule 'c_o', [ '*/*.o' => '*.c' ], \&C_Builder ;
          AddRule 'cpp_o', [ '*/*.o' => '*.cpp' ], \&CPP_Builder ;

          AddRule [META_RULE], 'o_cs_meta',
	     [\&FirstAndOnlyOneOnDisk, ['cpp_o', 'c_o' ], 'c_o'] ;
                                        ^- slave rules -^    ^-default

	at cd_test.pl line 26
	   main::CroakingSub() called at cd_test.pl line 11					   

Since the diagnostic is valid pod, it will be extracted when you generate your documentation.

 $ pod2text cd_test.pl 

  CroakingSub
    An example of how to use Carp::Diagnostics.

   Diagnostics
     Default rule '$default_rule_name', in rule '$name', doesn't exist!
        The default rule of a *FirstAndOnlyOneOnDisk* META_RULE must be
        registrated before the META_RULE definiton. Here is an example of
        declaration:

          AddRule 'c_o', [ '*/*.o' => '*.c' ], \&C_Builder ;
          AddRule 'cpp_o', [ '*/*.o' => '*.cpp' ], \&CPP_Builder ;

          AddRule [META_RULE], 'o_cs_meta',
	     [\&FirstAndOnlyOneOnDisk, ['cpp_o', 'c_o' ], 'c_o'] ;
                                        ^- slave rules -^    ^-default

SUBROUTINES/METHODS

Top

UseLongMessage

Give 0 as argument if you want to display the short message. The only reason to use this is when developing modules which use Carp::Diagnostics. Even then it's not a very good reason for not displaying a complete diagnostic.

This setting is global.

croak

arguments

short_message
diagnostic (long message)

if the diagnostic is POD, it will be converted to text.

Calls Carp::croak to display the message.

confess

arguments

short_message
diagnostic (long message)

if the diagnostic is POD, it will be converted to text.

Calls Carp::confess to display the message.

carp

arguments

short_message
diagnostic (long message)

if the diagnostic is POD, it will be converted to text.

Calls Carp::carp to display the message.

cluck

arguments

short_message
diagnostic (long message)

if the diagnostic is POD, it will be converted to text.

Calls Carp::cluck to display the message.

Podify

Transforms the passed string from POD to text if it looks like POD. Returns the string. Transformed or not.

This is used internally by this module.

GetTerminalWidth

Return the terminal width or 78 if it can't compute the width (IE: redirected to a file).

This is used internally by this module.

BUGS AND LIMITATIONS

Top

None so far.

AUTHOR

Top

	Khemir Nadim ibn Hamouda
	CPAN ID: NKH
	mailto:nadim@khemir.net

LICENSE AND COPYRIGHT

Top

SUPPORT

Top

You can find documentation for this module with the perldoc command.

    perldoc Carp::Diagnostics

You can also look for information at:

* AnnoCPAN: Annotated CPAN documentation

http://annocpan.org/dist/Carp-Diagnostics

* RT: CPAN's request tracker

Please report any bugs or feature requests to L <bug-carp-diagnostics@rt.cpan.org>.

We will be notified, and then you'll automatically be notified of progress on your bug as we make changes.

* Search CPAN

http://search.cpan.org/dist/Carp-Diagnostics

SEE ALSO

Top

Perl Best Practice by Damian Conway ISBN: 0-596-00173-8, a tremendous job.


Carp-Diagnostics documentation Contained in the Carp-Diagnostics distribution.
package Carp::Diagnostics ;

use strict;
use warnings ;

my $WIN32_CONSOLE ;

BEGIN 
{
use English qw( -no_match_vars ) ;
use Sub::Exporter -setup => { exports => [ qw(carp cluck croak confess UseLongMessage) ] } ;
    
use vars qw ($VERSION);
$VERSION = 0.04 ;

#-------------------------------------------------------------------------------

if($OSNAME ne 'MSWin32')
	{
	eval "use Term::Size;" ; ## no critic
	Carp::croak $EVAL_ERROR if $EVAL_ERROR;
	}
else
	{
	eval "use Win32::Console;" ; ## no critic
	Carp::croak $EVAL_ERROR if $EVAL_ERROR ;
	
	$WIN32_CONSOLE= new Win32::Console;
	}
}

#-------------------------------------------------------------------------------

use Readonly ;
Readonly my $EMPTY_STRING => q{} ;

use Carp qw() ;

use IO::String ;
use Pod::Text ;

{
my $use_long_message = 1 ;

sub UseLongMessage
{

$use_long_message = $_[0] if defined $_[0] ;
return($use_long_message) ;
}

}

#-------------------------------------------------------------------------------

sub croak  
{

local $Carp::CarpLevel = 1; ## no critic

Carp::croak
	(
	Podify
		(
		@_ == 1 || (! UseLongMessage()) 
			? $_[0] # user wants short message or there is only one message
			: $_[1]
		)
	) ;


return ;
}

#-------------------------------------------------------------------------------

sub confess
{

local $Carp::CarpLevel = 1; ## no critic
Carp::confess
	(
	Podify
		(
		@_ == 1 || (! UseLongMessage()) 
			? $_[0] # user wants short message or there is only one message
			: $_[1]
		)
	) ;

return ;
}

#-------------------------------------------------------------------------------

sub carp
{

local $Carp::CarpLevel = 1; ## no critic
Carp::carp
	(
	Podify
		(
		@_ == 1 || (! UseLongMessage()) 
			? $_[0] # user wants short message or there is only one message
			: $_[1]
		)
	) ;

return ;
}

#-------------------------------------------------------------------------------

sub cluck
{

local $Carp::CarpLevel = 1; ## no critic
Carp::cluck
	(
	Podify
		(
		@_ == 1 || (! UseLongMessage()) 
			? $_[0] # user wants short message or there is only one message
			: $_[1]
		)
	) ;

return ;
}

#-------------------------------------------------------------------------------

sub Podify
{

my ($message) = @_ ;

if(defined $message)
	{
	if($message =~ /\A\s*^=/xsm)
		{
		my ($in, $out) = (IO::String->new($message), IO::String->new());

		Pod::Text->new (width => GetTerminalWidth() - 2 )->parse_from_filehandle($in, $out) ;
		
		return(${$out->string_ref()}) ;
		}
	else
		{
		return($message) ;
		}
	}
else
	{
	return ;
	}
}

#-------------------------------------------------------------------------------

sub GetTerminalWidth
{

my ($columns, $rows) ;

if($OSNAME ne 'MSWin32')
	{
	eval "(\$columns, \$rows) = Term::Size::chars *STDOUT{IO} ;" ; ## no critic
	}
else
	{
	($columns, $rows) = $WIN32_CONSOLE->Size();
	}

$columns = 78 if($columns eq $EMPTY_STRING) ;
	
return($columns) ;
}

#-------------------------------------------------------------------------------

1 ;