The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Devel::Kit - Handy toolbox of things to ease development/debugging.

VERSION

This document describes Devel::Kit version 0.81

SYNOPSIS

use Devel::Kit; # strict and warnings are now enabled

d($something); # d() and some other useful debug/dump functions are now availble!

perl -e 'print @ARGV[0];' # no warning
perl -e 'print $x;' # no strict error

perl -MDevel::Kit -e 'print @ARGV[0];'# issues warnings: Scalar value @ARGV[0] better written as $ARGV[0] …
perl -MDevel::Kit -e 'print $x;' # Global symbol "$x" requires explicit package name …

perl -MDevel::Kit -e 'd();d(undef);d("");d(1);d("i got here");d({a=>1},[1,2,3],"yo",\"howdy");ud("I \x{2665} perl");bd("I \xe2\x99\xa5 perl");gd("I ♥ perl");'

See where you are or are not getting to in a program and why, for example via this pseudo patch:

+ d(1);
+ d(\$foo);

bar();

if ($foo) {
+    d(2);
    …
}
else {
+    d(3);
    …
}
+ d(4);

If it outputs 1, $foo’s true value, 3,4 you know to also dump $foo after bar() since it acts like bar() is modifying $foo (action at a distance). If $foo is false after the call to bar() then you can add debug statements to bar() to see where specifically $foo is fiddled with.

Visually see if a string is a byte string or a Unicode string:

perl -MDevel::Kit -e 'd(\$string);'

If it is a Unicode string the \x{} codepoint notation will be present, if it is a byte string it will not be present:

[dmuey@multivac ~]$ perl -MDevel::Kit -e 'd(\"I \x{2665} perl");'
debug() ref(SCALAR(0x100804fc0)) at -e line 1:
    \"I \x{2665} perl"
[dmuey@multivac ~]$ perl -MDevel::Kit -e 'd(\"I ♥ perl");'
debug() ref(SCALAR(0x100804fc0)) at -e line 1:
    \'I ♥ perl'
[dmuey@multivac ~]$ perl -MDevel::Kit -e 'd(\"I \xe2\x99\xa5 perl");'
debug() ref(SCALAR(0x100804fc0)) at -e line 1:
    \'I ♥ perl'
[dmuey@multivac Devel-Kit]$ perl -Mutf8 -MDevel::Kit -e 'd(\"I ♥ perl");'
debug() ref(SCALAR(0x100804ff0)) at -e line 1:
	\"I \x{2665} perl"
[dmuey@multivac Devel-Kit]$

DESCRIPTION

From one line data dumping sanity checks to debug print statements in a large body of code I often found myself reinventing these basic solutions.

Hence this module was born to help give a host of functions/functionality with a minimum of typing/effort required.

Any modules required for any functions are lazy loaded if needed so no need to manage use statements!

SHELL ALIAS

This is a handy alias I put in my shells’ profile/rc file(s) to make short debug/test commands even shorter!

alias pkit='perl -MDevel::Kit'

Then you can run:

pkit -e 'vd("I ♥ perl");'
pkit -Mutf8 -e 'vd("I ♥ perl");'

To get a better ci():

alias pkit_ops='perl -mDevel::CountOps -MDevel::Kit'

(TERSE) INTERFACE

You'll probably note that every thing below is terse (i.e. not ideally named for maintenance).

That is on purpose since this module is meant for one-liners and development/debugging: NOT for production.

strict/warnings

import() enables strict and warnings in the caller unless you pass the string “no” to import().

use Devel::Kit; # as if you had use strict;use warnings; here
use Devel::Kit qw(no); # no strict/warnings

perl -MDevel::Kit -e 'print @ARGV[0];print $x;' # triggers strict/warnings
perl -MDevel::Kit=no -e 'print @ARGV[0];print $x;' # no strict/warnings happen

imported functions

If you already have a function by these names you can pass "_" to import() which will import them all w/ an underscore prepended. You can pass "__" to have it prepend 2, "___" to prepend 3, ad infinitum.

a() App::Kit

You can get a lazy loaded and reused App::Kit object via a().

pkit -e 'd( a->ctype->get_ctype_of_ext(".pm") )'

d() General debug/dump

Takes zero or more arguments to do debug info on.

The arguments can be a scalar or any perl reference you like.

It’s output is handled by "Devel::Kit::o()" and references are stringified by "Devel::Kit::p()".

Perly Info dumpers

ci() coderef stat info

Runs the given code ref and takes some measurements.

perl -MDevel::Kit -e 'ci(sub {…})'
perl -MDevel::Kit -e 'ci(sub {…},1)' # … also include a diff of the symbol table before and after running

Caveat: Observer effect

Some things might not be apparent due the current state of things. For example, a module might be loaded by the coderef but since it is already loaded it is not factored in the results.

Caveat: You get more accurate results if Devel::CountOps is loaded during BEGIN before you call ci()

You could use the pkit_ops alias or -mDevel::CountOps first:

perl -mDevel::CountOp -MDevel::Kit -e 'ci(sub {…})'

ni() name space info

perl -MDevel::Kit -e 'ni('Foo::Bar')'
perl -MDevel::Kit -e 'ni('Foo::Bar',1)' # … also include ci() info (via system() to cut down on the 2 caveats noted for ci())
perl -MDevel::Kit -e 'ni('Foo::Bar',2)' # … also include verbose ci() info (via system() to cut down on the 2 caveats noted for ci())

ei() environment info

perl -MDevel::Kit -e 'ei()'
perl -MDevel::Kit -e 'ei(1)' # … also dump %ENV
perl -MDevel::Kit -e 'ei(2)' # … also dump %Config

ri() ref info

like Devel::Kit::p() but w/ Devel::Size and/or Devel::Peek info as well

perl -MDevel::Kit -e 'ri($your_ref_here)'

si() system command info

perl -MDevel::Kit -e 'si(@system_cmd)'

Execute’s @system_cmd, displays its output labeled as STDOUT/STDERR, and describes its child error and errno states.

Currently there is no interface to the command’s STDIN but it could be added, let me know if you’d find that useful.

rx() interactive Regex debugging

Lazy loaded Regexp::Debugger::rxrx() wrapper. See Regexp::Debugger for more info.

perl -MDevel::Kit -e 'rx()'

Data Format dumpers

If a function ends in “d” it is a dumper. Each takes one argument, the string in the format we’re dumping.

Like d() it’s output is handled by "Devel::Kit::o()" and references are stringified by "Devel::Kit::p()".

yd() YAML dumper

perl -MDevel::Kit -e 'yd($your_yaml_here)'

jd() JSON dumper

perl -MDevel::Kit -e 'jd($your_json_here)'

xd() XML dumper

perl -MDevel::Kit -e 'xd($your_xml_here)'

sd() Storable dumper

perl -MDevel::Kit -e 'sd($your_storable_here)'

id() INI dumper

perl -MDevel::Kit -e 'id($your_ini_here)'

md() MessagePack dumper

perl -MDevel::Kit -e 'md($your_message_pack_here)'

pd() Perl (stringified) dumper

perl -MDevel::Kit -e 'pd($your_stringified_perl_structure_here)'

File system

These dump information about the path given.

fd() File dumper

perl -MDevel::Kit -e 'fd($your_file_here)'

dd() Directory dumper

perl -MDevel::Kit -e 'dd($your_directory_here)'
perl -MDevel::Kit -e 'ld($your_symlink_here)'

String Representations

These can take a utf-8 or Unicode string and show the same string as the type being requested.

ud() Unicode string dumper

perl -MDevel::Kit -e 'ud($your_string_here)'

bd() Byte string utf-8 dumper

perl -MDevel::Kit -e 'bd($your_string_here)'

gd() Grapheme byte string utf-8 dumper

perl -MDevel::Kit -e 'gd($your_string_here)'

vd() Verbose Variations of string dumper

perl -MDevel::Kit -e 'vd($your_string_here)'

perl -MDevel::Kit -e 'vd($your_string_here, 1)' # verbose flag shows Devel::Size and/or Devel::Peek info as possible

Serialize/Sum/haSh

Unicode strings are turned into utf-8 before summing (since you can’t sum a Unicode string)

ms() MD5

perl -MDevel::Kit -e 'ms($your_string_here)'

ss() SHA1

perl -MDevel::Kit -e 'ss($your_string_here)'

Escape/Unescape Encode/Unencode

Unicode strings are turned into utf-8 before operating on it for consistency and since some, if not all, need to operate on bytes.

be() bu() Base64

perl -MDevel::Kit -e 'be($your_string_here)'
perl -MDevel::Kit -e 'bu($your_base64_here)'

ce() cu() Crockford (Base32)

perl -MDevel::Kit -e 'ce($your_string_here)'
perl -MDevel::Kit -e 'cu($your_crockford_here)'

xe() xu() Hex

perl -MDevel::Kit -e 'xe($your_string_here)'
perl -MDevel::Kit -e 'xu($your_hex_here)'

xe() takes a second boolean arg that when true dumps it as a visual mapping of each character to its hex value.

ue() uu() URI

perl -MDevel::Kit -e 'ue($your_string_here)'
perl -MDevel::Kit -e 'uu($your_uri_here)'

he() hu() HTML

perl -MDevel::Kit -e 'he($your_string_here)'
perl -MDevel::Kit -e 'hu($your_html_here)'

pe() pu() Punycode string

perl -MDevel::Kit -e 'pe($your_string_here)'
perl -MDevel::Kit -e 'pu($your_punycode_here)'

qe() qu() quoted-printable

perl -MDevel::Kit -e 'qe($your_string_here)'
perl -MDevel::Kit -e 'qu($your_quoted_printable_here)'

se() su() String escaped for perl

perl -MDevel::Kit -e 'se($your_string_here)'
perl -MDevel::Kit -e 'su($your_escaped_for_perl_string_here)'

non-imported functions

Feel free to override these with your own if you need different behavior.

Devel::Kit::o()

Outputs the first and only arg.

Goes to STDOUT and gaurantees it ends in one newline.

Devel::Kit::p()

Returns a stringified version of any type of perl ref() contained in the first and only arg.

DIAGNOSTICS

Errors are output in the various dumps.

CONFIGURATION AND ENVIRONMENT

Devel::Kit requires no configuration files or environment variables.

DEPENDENCIES

Import::Into for the strict/warnings.

String::UnicodeUTF8 for string fiddling

Module::Want to lazy load the various parsers and what not:

Data::Dumper
File::Slurp
YAML::Syck
JSON::Syck
XML::Parser
Storable
Data::MessagePack
Digest::MD5
Digest::SHA
MIME::QuotedPrint
HTML::Entities
URI::Escape
MIME::Base64
Devel::Symdump
Time::HiRes
Unix::PID::Tiny
Devel::CountOps
Devel::Size
Devel::Peek
Cwd
Config
Regexp::Debugger

SUBCLASSES

It includes 2 sub classes that can be used as guides on how to create your own context specific subclass:

Devel::Kit::TAP for testing context (using a function based output).

Devel::Kit::cPanel for cPanel context (using a method based output).

INCOMPATIBILITIES

None reported.

BUGS AND LIMITATIONS

No bugs have been reported.

Please report any bugs or feature requests to bug-devel-kit@rt.cpan.org, or through the web interface at http://rt.cpan.org.

TODO

  • auto-detect and switch to correct subclass

  • *d() functions could use corresponding d*() functions (e.g. dy() would dump as YAML …)

  • Stringified Data dumpers also take path or handle in addition to a string.

  • string parser/dumpers make apparent what it was (i.e. YAML, XML, etc)

AUTHOR

Daniel Muey <http://drmuey.com/cpan_contact.pl>

LICENCE AND COPYRIGHT

Copyright (c) 2012, Daniel Muey <http://drmuey.com/cpan_contact.pl>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.