#!/usr/bin/perl package Devel::STDERR::Indent; use base qw/Exporter/; use strict; use warnings; use vars qw/$VERSION @EXPORT_OK $STRING/; BEGIN { $VERSION = "0.04"; @EXPORT_OK = qw/indent $STRING/; $STRING = "\t"; } sub indent () { __PACKAGE__->new; } my $count = 0; my $old; sub new { my $class = shift; if (++$count == 1) { $old = $SIG{__WARN__}; my $delegate = $old || sub { my $str = shift; print STDERR $str }; $SIG{__WARN__} = sub { my $str = shift; $str =~ s/^/$STRING x ($count - 1)/gme; &$delegate($str); }; } bless { }, $class; } sub DESTROY { my $self = shift; if (--$count == 0) { $SIG{__WARN__} = $old; } } __PACKAGE__; __END__ =pod =head1 NAME Devel::STDERR::Indent - Indents STDERR to aid in print-debugging recursive algorithms. =head1 SYNOPSIS use Devel::STDERR::Indent qw/indent/; sub factorial { my $h = indent; # causes indentation my $n = shift; warn "computing factorial $n"; # indented based on call depth if ($n == 0) { return 1 } else { my $got = factorial($n - 1); warn "got back $got, multiplying by $n"; return $n * $got; } } =head1 DESCRIPTION When debugging recursive code it's useful, but often too much trouble to have your traces indented. This module makes it easy - call the indent function, and keep the thing you got back around until the sub exits. This will wrap $SIG{__WARN__} with something that adds as many repetitions of C<$Devel::STDERR::Indent::STRING> as there are live instances of the class (minus one): s/^/$STRING x ($count - 1)/ge When the handle is destroyed (due to garbage collection), $count is decremented. =head1 EXPORTS All exports are optional, and may be accessed fully qualified instead. =over 4 =head1 indent Returns an object which you keep around for as long as you want another indent level: my $h = $indent; # ... all warnings are indented by one additional level $h = undef; # one indentation level removed =head1 $STRING The string to repeat (defaults to C<"\t">). =back =head1 VERSION CONTROL This module is maintained using Darcs. You can get the latest version from L, and use C to commit changes. =cut