ASquareClock/Devel-Bug
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
NAME
Devel::Bug - Transparent inline debugging probe (pure Perl)
SYNOPSIS
use Devel::Bug; # output to STDERR
use Devel::Bug out => *STDOUT; # redirect output
use Devel::Bug ':pfl'; # package + filename + lineno by default
use Devel::Bug ':pfl', out => *STDOUT; # label:flags with options
use Devel::Bug bug => 'dbg'; # export under a different name
# Scalar: value passes through; appears on STDERR (no label)
my $result = bug = substr($str, $offset);
# OUTPUT: (value)
# Inline in any expression
my $path = $dir . '/' . (bug('label') = substr($str, $offset));
# OUTPUT: label=(images/logo.png)
# List: parens around bug() are required to force list-context assignment
my @items = (bug 'items') = get_items();
# OUTPUT: items=(foo bar baz)
# Flags in the label string
my @items = (bug 'items:@') = get_items(); # N: index prefixes
my %hash = (bug 'data:%') = get_pairs(); # key => value format
my %hash = (bug 'data:@%') = get_pairs(); # both
my @items = (bug 'items:m') = get_items(); # multiline
# Per-call options
my $x = (bug 'result', vc => 'green') = compute();
DESCRIPTION
"Devel::Bug" exports bug(), named for the wiretap sense of the word:
plant it inline inside any existing assignment to tap into values as
they flow through your code. The value(s) assigned *through* bug() will
reach the left-hand side unmodified; the only side effect is output to
the configured filehandle. *For list assignments*, bug() must be
*wrapped in parentheses* to force list context: "(bug ...) =
list_expr()". Without them "bug" is called in scalar context and
captures only a single value.
Output format:
label=(value) # scalar
label=(v1 v2 v3) # list
label=(a => 1 b => 2) # keyval
pkg file line: label=(...) # with caller info enabled
By default, ANSI colors are applied when the output handle is a
terminal, and multiline layout is applied automatically when output
would overflow the terminal width. Both behaviors are configurable; see
"color", "delims", and "noterm".
IMPORT AND CALL OPTIONS
Options apply in two contexts: as import-time defaults via "use" or
import(), and as per-call overrides passed directly to bug().
use Devel::Bug out => *STDOUT, lineno => 1; # import-time defaults
my $x = (bug 'result', vc => 'green') = ...; # per-call override
Options follow an optional label:flags string as key/value pairs (see
"LABEL:FLAGS SYNTAX"). The "bug" option (export name) is only valid at
import time.
Output
out (aliases: output, o)
Filehandle to print to. Accepts anything "print" accepts as an
indirect filehandle: typeglobs, lexical filehandles, and filehandle
objects. Default: *STDERR.
use Devel::Bug out => *STDOUT; # typeglob
use Devel::Bug out => $fh; # lexical filehandle or object
Caller information
When enabled, the corresponding field is prepended to every line of
output.
package (aliases: pkg, p)
Calling package name.
filename (aliases: fn, f)
Source filename.
lineno (aliases: line, ln, l)
Source line number.
Display
multiline (aliases: ml, m)
Print each value on its own indented line.
indices (aliases: indexes, index, i, @)
Prefix each list element with "N:". Implies multiline.
keyval (aliases: kv, k, %)
Treat the list as alternating key/value pairs and format each as
"key => value". Combine with "indices"/"@" to add "N:" prefixes; the
index counts pairs, not individual elements. Implies multiline.
delims (aliases: delimiters, d)
Controls whether the value is wrapped in parentheses. Three states:
"on" (also 1)
Always wrap in parentheses.
"off" (also "undef")
Never wrap in parentheses.
"auto" (also '', default)
Wrap when output is not colored; omit when colored (color
already delineates the value visually).
Colors
color
Controls when ANSI colors are applied. Three states:
"on" (also 1)
Always apply colors, even to non-terminal output.
"off" (also "undef")
Never apply colors.
"auto" (also '', default)
Apply colors only when the output handle is a terminal.
infocolor (alias: ic)
Term::ANSIColor color specification for the caller-info prefix, e.g.
'bold', 'cyan on_black'. Default: none.
labelcolor (alias: lc)
Color specification for the label. Default: 'bold'.
valcolor (aliases: vc, valuecolor)
Color specification for values. Default: 'red on_grey23'.
Terminal detection
noterm (aliases: noterminal, n)
Disable terminal width detection. When set, neither "stty" nor
Term::Size::Perl is consulted, making both entirely optional. With
"noterm" enabled, terminal-width-based multiline layout is
suppressed, and "color => 'auto'" behaves as if the output is not a
terminal.
A warning is issued if terminal detection is attempted, "stty size"
fails, and Term::Size::Perl cannot be loaded. Set "noterm" to
suppress both the detection and the warning.
Pretty-printer
pp Fully-qualified name of the function used to format reference
values, in the form 'Module::Name::function'. The function is called
with the reference as its first argument and must return a string.
The module is loaded automatically on first use. If the specified
module cannot be loaded or the named sub does not exist, a warning
is issued and the default is used instead.
Default: 'Data::Dumper::Dumper'.
use Devel::Bug pp => 'Data::Dump::pp'; # import-time default
my $x = (bug 'data', pp => 'Data::Dump::pp') = get_data(); # per-call
Alternative display value
val (aliases: value, v, override)
Display a different value in the output than the one being assigned.
The actual assigned value still passes through unchanged.
Use this when the assigned value is opaque or uninteresting, but a
related value at the same point in the code is more informative.
Particularly useful in ternary expressions, where the probe fires
only when that branch is taken.
# Without bug(): a do {} block is needed to log and still return a value
my $installed =
$sub =~ /^(.+)::/
? do {
print "package=($1)\n";
*{ $caller . '::' . $name }= \&{ $sub }
}
: carp "Cannot determine package from '$sub'";
# With bug(): val => $1 is displayed; the glob assignment passes through
my $installed =
$sub =~ /^(.+)::/
? bug('package', val => $1)=
*{ $caller . '::' . $name }= \&{ $sub }
: carp "Cannot determine package from '$sub'";
Export name
bug Rename or suppress the exported function.
use Devel::Bug bug => 'tap'; # exports as tap()
use Devel::Bug bug => ''; # suppresses export ('', 0, undef all work)
The name must be a valid Perl identifier ("/^[a-z]\w*$/i" or
"/^_\w+$/"). This option is only valid at import time; it may not be
passed to bug().
LABEL:FLAGS SYNTAX
A label:flags string may optionally appear as the *first* argument to
bug() or "use" (import()).
The string has the form "label:flags", where both parts are optional. A
leading colon means an empty label; the characters after the colon each
enable a boolean option by its single-char alias.
use Devel::Bug ':pfl'; # empty label, flags p, f, l
use Devel::Bug 'app:pf'; # label 'app', flags p, f
use Devel::Bug 'app'; # label 'app', no flags
my @r = (bug 'data:@%') = ...; # label 'data', flags @ and %
my @r = (bug ':m') = ...; # empty label, flag m
Flag characters:
@ i indices % k keyval m multiline
p package f filename l lineno
d delims n noterm
CHAINING
Bug probes can be placed at different points in a pipeline to capture
each intermediate value independently.
my @data = (1, 2, 3, 4, 5, 6);
my @doubled =
(bug 'doubled')= # parens make this a list assignment; bug() passes the whole list through
map { $_ * 2 }
(bug 'evens')= # parens force list context; without them bug() captures only one value
grep { $_ % 2 == 0 } @data;
# OUTPUT:
# doubled=(4 8 12)
# evens=(2 4 6)
'evens' captures the elements that passed the grep; 'doubled' captures
those elements after multiplication. Output fires left-to-right as Perl
frees temporaries at end-of-statement, which is the reverse of data flow
- hence 'doubled' prints before 'evens'.
DEPENDENCIES
Term::ANSIColor, Data::Dumper.
Terminal width detection first tries "stty size". Term::Size::Perl is
loaded on demand only if "stty" is unavailable or returns no output, and
is never consulted when "noterm" is set.
Data::Dump and other pretty-printer modules are optional; see the "pp"
option.
AUTHOR
Kevin Shea
LICENSE
This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.