405 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
		
		
			
		
	
	
			405 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| 
								 | 
							
								#!/usr/bin/perl
							 | 
						||
| 
								 | 
							
								package IPL::Shell;
							 | 
						||
| 
								 | 
							
								use strict;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BEGIN {
							 | 
						||
| 
								 | 
							
								    use vars qw{$VERSION $RCSID};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $VERSION    = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
							 | 
						||
| 
								 | 
							
								    $RCSID      = q$Id: ipl,v 1.3 2004/11/11 00:51:38 deveiant Exp $;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    use base qw{Shell::Base};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    use Carp            qw{carp croak confess};
							 | 
						||
| 
								 | 
							
								    use Data::Dumper    qw{};
							 | 
						||
| 
								 | 
							
								    use Term::ANSIColor qw{color};
							 | 
						||
| 
								 | 
							
								    use Cwd             qw{cwd};
							 | 
						||
| 
								 | 
							
								    use File::Basename  qw(basename);
							 | 
						||
| 
								 | 
							
								    use Net::Domain     qw(hostfqdn);
							 | 
						||
| 
								 | 
							
								    use String::Format  qw(stringf);
							 | 
						||
| 
								 | 
							
								    use Sys::Hostname   qw(hostname);
							 | 
						||
| 
								 | 
							
								    use Devel::Symdump  qw{};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $Shell::Base::RE_QUIT = '(?i)^\s*(exit|q(uit)?|logout)';
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								###	C L A S S   G L O B A L S
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Default configuration values
							 | 
						||
| 
								 | 
							
								our %Defaults = (
							 | 
						||
| 
								 | 
							
								    prompt_fmt  => '%{bold cyan}C%p%{white}C %!> ',
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								###	I N S T A N C E   M E T H O D S
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Shell initialization
							 | 
						||
| 
								 | 
							
								sub init {
							 | 
						||
| 
								 | 
							
								    my ( $self, $args ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Merge defaults
							 | 
						||
| 
								 | 
							
								    %$args = ( %Defaults, %$args );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Add instance vars
							 | 
						||
| 
								 | 
							
								    $self->{result_history} = [];
							 | 
						||
| 
								 | 
							
								    $self->{package} = 'main';
							 | 
						||
| 
								 | 
							
								    $self->{prompt_fmt} = $args->{prompt_fmt};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: init_completions()
							 | 
						||
| 
								 | 
							
								### Initialize the internal COMPLETIONS list.
							 | 
						||
| 
								 | 
							
								sub init_completions {
							 | 
						||
| 
								 | 
							
								    my $self = shift;
							 | 
						||
| 
								 | 
							
								    $self->SUPER::init_completions;
							 | 
						||
| 
								 | 
							
								    $self->completions( map { ":$_" } $self->completions );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Intro/outro message
							 | 
						||
| 
								 | 
							
								sub intro { return qq{IPL: Interactive Perl Shell $VERSION} }
							 | 
						||
| 
								 | 
							
								sub outro { "" }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Prompt callback
							 | 
						||
| 
								 | 
							
								sub prompt {
							 | 
						||
| 
								 | 
							
								    my $self = shift;
							 | 
						||
| 
								 | 
							
								    my $fmt = $self->{prompt_fmt};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    my $prompt = stringf $fmt => {
							 | 
						||
| 
								 | 
							
								        '!' => $self->term->{history_length},
							 | 
						||
| 
								 | 
							
								        '$' => $$,
							 | 
						||
| 
								 | 
							
								        '0' => $self->progname,
							 | 
						||
| 
								 | 
							
								        'C' => sub { color($_[0]) },
							 | 
						||
| 
								 | 
							
								        'H' => hostfqdn,
							 | 
						||
| 
								 | 
							
								        'W' => basename(cwd),
							 | 
						||
| 
								 | 
							
								        'c' => ref($self),
							 | 
						||
| 
								 | 
							
								        'g' => scalar getgrgid($(),
							 | 
						||
| 
								 | 
							
								        'h' => hostname,
							 | 
						||
| 
								 | 
							
								        'p' => $self->{package},
							 | 
						||
| 
								 | 
							
								        'u' => scalar getpwuid($<),
							 | 
						||
| 
								 | 
							
								        'w' => cwd,
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Append a reset to clean up if there are color escapes in the prompt
							 | 
						||
| 
								 | 
							
								    $prompt .= color( 'reset' ) if $prompt =~ m{\e\[};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return "\n$prompt";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: print( $output )
							 | 
						||
| 
								 | 
							
								### Output method.
							 | 
						||
| 
								 | 
							
								sub print {
							 | 
						||
| 
								 | 
							
								    my $self = shift;
							 | 
						||
| 
								 | 
							
								    my $output = join( "", @_ );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    my $nlcount = $output =~ tr/\n/\n/;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( $nlcount >= $self->{ROWS} - 3 ) {
							 | 
						||
| 
								 | 
							
								        my $pager = $self->pager;
							 | 
						||
| 
								 | 
							
								        open my $P, "|$pager" or carp "Can't open $pager: $!";
							 | 
						||
| 
								 | 
							
								        CORE::print $P $output;
							 | 
						||
| 
								 | 
							
								        close $P;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        CORE::print $output;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: parseline( $input )
							 | 
						||
| 
								 | 
							
								### Command-parsing method: parse the specified I<input>, run the specified
							 | 
						||
| 
								 | 
							
								### command, and output the result.
							 | 
						||
| 
								 | 
							
								sub parseline {
							 | 
						||
| 
								 | 
							
								    my ( $self, $input ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( $input =~ m{^:(\S+.*)} ) {
							 | 
						||
| 
								 | 
							
								        return $self->SUPER::parseline( $1 );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        return ( "eval", {}, $input );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: prettyPrint( $value )
							 | 
						||
| 
								 | 
							
								### Return the given I<value> as a pretty-printed string.
							 | 
						||
| 
								 | 
							
								sub prettyPrint {
							 | 
						||
| 
								 | 
							
								    my ( $self, $val ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    local $Data::Dumper::Terse = 1;
							 | 
						||
| 
								 | 
							
								    local $Data::Dumper::Indent = 1;
							 | 
						||
| 
								 | 
							
								    local $Data::Dumper::Pad = "    ";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    my $rval = Data::Dumper->Dumpxs( [$val] );
							 | 
						||
| 
								 | 
							
								    $rval =~ s{^\s+}{};
							 | 
						||
| 
								 | 
							
								    $rval = " => $rval ";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $rval;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								###	C O M M A N D   M E T H O D S
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_shellobj( undef )
							 | 
						||
| 
								 | 
							
								### Implementation of the 'shellobj' command
							 | 
						||
| 
								 | 
							
								sub do_shellobj {
							 | 
						||
| 
								 | 
							
								    my $self = shift;
							 | 
						||
| 
								 | 
							
								    return Data::Dumper->Dumpxs( [$self], [qw{self}] );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: help_shellobj( undef )
							 | 
						||
| 
								 | 
							
								### Callback for help on the 'shellobj' command.
							 | 
						||
| 
								 | 
							
								sub help_shellobj {
							 | 
						||
| 
								 | 
							
								    return q{Show a dump of the IPL shell object itself.};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_eval( @args )
							 | 
						||
| 
								 | 
							
								### Implementation of the 'eval' command.
							 | 
						||
| 
								 | 
							
								sub do_eval {
							 | 
						||
| 
								 | 
							
								    my ( $self, @args ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    my (
							 | 
						||
| 
								 | 
							
								        $input,
							 | 
						||
| 
								 | 
							
								        $res,
							 | 
						||
| 
								 | 
							
								        $rval,
							 | 
						||
| 
								 | 
							
								       );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $input = join( ' ', @args );
							 | 
						||
| 
								 | 
							
								    #$self->print( "[Evaluating '$input']\n" );
							 | 
						||
| 
								 | 
							
								    $res = eval qq{
							 | 
						||
| 
								 | 
							
								        package $self->{package};
							 | 
						||
| 
								 | 
							
								        no strict;
							 | 
						||
| 
								 | 
							
								        $input ;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Show error message for errors
							 | 
						||
| 
								 | 
							
								    if ( $@ ) {
							 | 
						||
| 
								 | 
							
								        ( $rval = $@ ) =~ s{at \S+ line \d+\..*}{};
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Dump everything else
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        $rval = $self->prettyPrint( $res );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $rval;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: help_eval( undef )
							 | 
						||
| 
								 | 
							
								### Provide help text for the 'eval' command.
							 | 
						||
| 
								 | 
							
								sub help_eval {
							 | 
						||
| 
								 | 
							
								    return q{Evaluate the input as Perl and display the result.};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_rl( $subcmd, @args )
							 | 
						||
| 
								 | 
							
								### Implementation of the 'readline' command.
							 | 
						||
| 
								 | 
							
								sub do_rl {
							 | 
						||
| 
								 | 
							
								    my ( $self, $subcmd, @args ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    my $rval = '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( $subcmd =~ m{features} ) {
							 | 
						||
| 
								 | 
							
								        $rval = $self->prettyPrint( $self->term->Features );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    elsif ( $subcmd =~ m{module} ) {
							 | 
						||
| 
								 | 
							
								        $rval = "Readline features provided by: " .
							 | 
						||
| 
								 | 
							
								            $self->term->ReadLine;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    elsif ( $subcmd =~ m{completions} ) {
							 | 
						||
| 
								 | 
							
								        $rval = "Tab-completions: \n" .
							 | 
						||
| 
								 | 
							
								            $self->prettyPrint( [sort $self->completions] );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    else {
							 | 
						||
| 
								 | 
							
								        $rval = $self->prettyPrint( $self->term );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $rval;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: help_rl( undef )
							 | 
						||
| 
								 | 
							
								### Return help text for the 'rl' (readline) command.
							 | 
						||
| 
								 | 
							
								sub help_rl {q{
							 | 
						||
| 
								 | 
							
								rl [<subcommand>]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Provide information about the readline implementation used by the shell. The
							 | 
						||
| 
								 | 
							
								<subcommand> can be one of:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								features    Dump the hash of features understood by the implementation.
							 | 
						||
| 
								 | 
							
								module      Show the name of the actual module that is providing readline
							 | 
						||
| 
								 | 
							
								            features.
							 | 
						||
| 
								 | 
							
								completions Dump the list of tab-completions.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_perldoc( @args )
							 | 
						||
| 
								 | 
							
								### Implementation of the 'perldoc' command.
							 | 
						||
| 
								 | 
							
								sub do_perldoc {
							 | 
						||
| 
								 | 
							
								    my ( $self, @args ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( @args ) {
							 | 
						||
| 
								 | 
							
								        system 'perldoc', @args;
							 | 
						||
| 
								 | 
							
								        return undef;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        return "'perldoc' requires at least one argument.";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: help_perldoc()
							 | 
						||
| 
								 | 
							
								### Help method for the 'perldoc' command.
							 | 
						||
| 
								 | 
							
								sub help_perldoc {q{
							 | 
						||
| 
								 | 
							
								Run the 'perldoc' program.
							 | 
						||
| 
								 | 
							
								}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_package( $newpkg )
							 | 
						||
| 
								 | 
							
								### Change the package future evals will take place in.
							 | 
						||
| 
								 | 
							
								sub do_package {
							 | 
						||
| 
								 | 
							
								    my ( $self, $package ) = @_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( $package ) {
							 | 
						||
| 
								 | 
							
								        return "Invalid package name '$package'"
							 | 
						||
| 
								 | 
							
								            unless $package =~ m{^[a-z]\w+(?:::[a-z]\w+)*$}i;
							 | 
						||
| 
								 | 
							
								        $self->{package} = $package;
							 | 
						||
| 
								 | 
							
								        return "Set eval package to: '$package'.";
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        return "Current package is: '$self->{package}'.";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: help_package()
							 | 
						||
| 
								 | 
							
								### Help method for the 'package' command.
							 | 
						||
| 
								 | 
							
								sub help_package {q{
							 | 
						||
| 
								 | 
							
								  package [<newpackage>]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Set the package future evaluations will occur in to 'newpackage' if the optional
							 | 
						||
| 
								 | 
							
								argument is given, else just print the name of the current package.
							 | 
						||
| 
								 | 
							
								}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_reload()
							 | 
						||
| 
								 | 
							
								### Implementation of the 'reload' command.
							 | 
						||
| 
								 | 
							
								sub do_reload {
							 | 
						||
| 
								 | 
							
								    my $self = shift;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( my $h = $self->histfile ) {
							 | 
						||
| 
								 | 
							
								        $self->term->WriteHistory( $h );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $self->print( "Re-execing shell...\n" );
							 | 
						||
| 
								 | 
							
								    local $ENV{IPL_RELOAD} = 1;
							 | 
						||
| 
								 | 
							
								    exec $0;
							 | 
						||
| 
								 | 
							
								    return "Hmmm... something funky happened.";
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub help_reload {q{
							 | 
						||
| 
								 | 
							
								  reload
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Reload the shell.
							 | 
						||
| 
								 | 
							
								}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### METHOD: do_inspect( [$package] )
							 | 
						||
| 
								 | 
							
								### Implementation of the 'inspect' command.
							 | 
						||
| 
								 | 
							
								sub do_inspect {
							 | 
						||
| 
								 | 
							
								    my $self = shift;
							 | 
						||
| 
								 | 
							
								    my $package = shift || $self->{package};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    my $inspector = new Devel::Symdump $package;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    no strict;
							 | 
						||
| 
								 | 
							
								    my @out = ( "Symbol table for $package" );
							 | 
						||
| 
								 | 
							
								    my ( %scalars, %arrays, %hashes, %functions, %packages, %filehandles );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Grab entries for each type from the symbol table for the inspected
							 | 
						||
| 
								 | 
							
								    # package.
							 | 
						||
| 
								 | 
							
								    %scalars     = map { $_ => ${*{$_}{SCALAR}} } $inspector->scalars;
							 | 
						||
| 
								 | 
							
								    %arrays      = map { $_ => *{$_}{ARRAY} } $inspector->arrays;
							 | 
						||
| 
								 | 
							
								    %hashes      = map { $_ => *{$_}{HASH} } $inspector->hashes;
							 | 
						||
| 
								 | 
							
								    %functions   = map { $_ => *{$_}{CODE} } $inspector->functions;
							 | 
						||
| 
								 | 
							
								    %packages    = map { $_ => undef } $inspector->packages;
							 | 
						||
| 
								 | 
							
								    %filehandles = map { $_ => *{$_}{IO} } $inspector->filehandles;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # Build displays for each entry in the symbol table, sorted by type,
							 | 
						||
| 
								 | 
							
								    # prepending the sigil for each one. In part stolen from Matthew Simon
							 | 
						||
| 
								 | 
							
								    # Cavalletto's Term::ShellKit::Dev
							 | 
						||
| 
								 | 
							
								    foreach my $output (
							 | 
						||
| 
								 | 
							
								        [ 'Scalars', \%scalars, '$', ],
							 | 
						||
| 
								 | 
							
								        [ 'Arrays', \%arrays, '@'],
							 | 
						||
| 
								 | 
							
								        [ 'Hashes', \%hashes, '%'],
							 | 
						||
| 
								 | 
							
								        [ 'Subs', \%functions, 'sub '],
							 | 
						||
| 
								 | 
							
								        [ 'Packages', \%packages, '::'],
							 | 
						||
| 
								 | 
							
								        [ 'Filehandles', \%filehandles, '*'],
							 | 
						||
| 
								 | 
							
								       ) {
							 | 
						||
| 
								 | 
							
								        next unless scalar keys %{$output->[1]};
							 | 
						||
| 
								 | 
							
								        push @out, "$output->[0]:", '-' x length($output->[0]);
							 | 
						||
| 
								 | 
							
								        foreach ( sort keys %{$output->[1]} ) {
							 | 
						||
| 
								 | 
							
								            if ( defined $output->[1]{$_} ) {
							 | 
						||
| 
								 | 
							
								                push @out, qq{  $output->[2]$_ = "$output->[1]{$_}"};
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                push @out, qq{  $output->[2]$_};
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return join "\n", @out;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								sub help_inspect {q{
							 | 
						||
| 
								 | 
							
								  inspect [<package>]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Inspect the contents of the specified package, or the current package if no
							 | 
						||
| 
								 | 
							
								package is given.
							 | 
						||
| 
								 | 
							
								}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								###	R U N T I M E   P A C K A G E
							 | 
						||
| 
								 | 
							
								#####################################################################
							 | 
						||
| 
								 | 
							
								package ipl;
							 | 
						||
| 
								 | 
							
								use strict;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BEGIN {
							 | 
						||
| 
								 | 
							
								    use Getopt::Long qw{GetOptions};
							 | 
						||
| 
								 | 
							
								    $GetOpt::Long::Bundling = 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								if ( $0 eq __FILE__ ) {
							 | 
						||
| 
								 | 
							
								    my %opts = (
							 | 
						||
| 
								 | 
							
								        HISTFILE => glob("~/.ipl_history"),
							 | 
						||
| 
								 | 
							
								        RCFILES => [glob("~/.iplrc"), ".iplrc"],
							 | 
						||
| 
								 | 
							
								       );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    IPL::Shell->new( %opts )->run;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |