Env-PS1

 view release on metacpan or  search on metacpan

lib/Env/PS1.pm  view on Meta::CPAN

package Env::PS1;

use strict;
use Carp;
use AutoLoader 'AUTOLOAD';

our $VERSION = 0.06;

our $_getpwuid = eval { getpwuid($>) }; # Not supported on some platforms

sub import {
	my $class = shift;
	return unless @_;
	my ($caller) = caller;
	for (@_) {
		/^\$(.+)/ or croak qq/$class can't export "$_", try "\$$_"/;
		no strict 'refs';
		tie ${"$caller\::$1"}, $class, $1;
	}
}

sub TIESCALAR {
	my ($class, $var) = @_;
	my $self = bless {
		var    => $var || 'PS1',
		format => '',
	}, $class;
	$self->cache();
	return $self;
}

sub STORE {
	my $self = shift;
	if (ref $$self{var}) { ${$$self{var}} = shift }
	else { $ENV{$$self{var}} = shift }
}

sub FETCH {
	my $self = shift;
	my $format = ref($$self{var}) ? ${$$self{var}} : $ENV{$$self{var}} ;
	$format =~ s#(\\\\)|(?<!\\)\$(?:(\w+)|\{(.*?)\})#
		$1 ? '\\\\' : $2 ? $ENV{$2} : $ENV{$3}
	#ge;
        unless ($format eq $$self{format} and exists $ENV{CLICOLOR}
                and $ENV{CLICOLOR} eq $$self{clicolor}) {
		@$self{qw/format clicolor/} = ($format, $ENV{CLICOLOR});
		$$self{cache} = [ $self->cache($format) ];
	}
	my $string = join '', map { ref($_) ? $_->() : $_ } @{$$self{cache}};
        $string =~ s#\$\((.+)\)#
          `$1`;
        #ge;
	return $string;
}

sub sprintf {
	my $format = pop;
	$format =~ s#(\\\\)|(?<!\\)\$(?:(\w+)|\{(.*?)\})#
		$1 ? '\\\\' : $2 ? $ENV{$2} : $ENV{$3}
	#ge;
	return join '', map { ref($_) ? $_->() : $_ } Env::PS1->cache($format);
}

our @user_info; # ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire)
our %map; # for custom stuff
our %alias = (
	'$' => 'dollar',
	'@' => 'D', t => 'D', T => 'D', A => 'D',
);

sub cache {
	my ($self, $format) = @_;
	return '' unless defined $format; # get rid of uninitialised warnings
	@user_info = getpwuid($>) if $_getpwuid;
	my @parts;
	#print "# string: $format\n";
	while ($format =~ s/^(.*?)(\\\\|\\([aenr]|0\d\d)|\\(.)|!)//s) {
		push @parts, $1 || '';
		if ($2 eq '\\\\') { push @parts, '\\' } # stripped when \! is substitued
		elsif ($2 eq '!') { push @parts, '!!' } # posix prompt escape :$
		elsif ($3) { push @parts, eval qq/"\\$3"/ }
		elsif (exists $map{$4}) {
			my $item = $map{$4};
			if (ref $item and $format =~ s/^\{(.*?)\}//) {
				push @parts, $item->($1); # obscure foo
			}
			else { push @parts, $item }
	       	}
		elsif (grep {$4 eq $_} qw/C D P/) { # special cases
			my $sub = $4 ;
			$format =~ s/^\{(.*?)\}//;
			push @parts, $self->$sub($sub, $1);
		}
		elsif ($4 eq '[' or $4 eq ']') { next }
		else {
			my $sub = exists($alias{$4}) ? $alias{$4} : uc($4) ;
			push @parts, $self->can($sub) ? ($self->$sub($4)) : $4;
		}
	}
	push @parts, $format;
	my @cache = ('');
	for (@parts) { # optimise: join strings, push code refs
		if (ref $_ or ref $cache[-1]) { push @cache, $_ }
		else { $cache[-1] .= $_ }
	}
	return @cache;
}

## format subs

sub U { $user_info[0] || $ENV{USER} || $ENV{LOGNAME} }

sub W { 
	return sub { $ENV{PWD} eq $ENV{HOME} ? "~" : $ENV{PWD} } if $_[1] eq 'w';
	return sub {
		return '/' if $ENV{PWD} eq '/';
                if($ENV{PWD} eq $ENV{HOME}) {
                  return "~";
                }
		$ENV{PWD} =~ m#([^/]*)/?$#;
		return $1;
	};
}

## others defined below for Autoload

1;

__END__

=head1 NAME

Env::PS1 - prompt string formatter



( run in 2.441 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )