package util;

use strict; use warnings;
use base 'Exporter';
use Data::Dumper;
use Cwd qw(cwd abs_path);
use File::Spec::Functions;

our @EXPORT = public_subs();

my $prog;
sub prog {
	use File::Basename;
  if (!$prog) {
		$prog = basename($0);
		$prog =~ s/\.(exe|pl|pm)$//;
	}
	return $prog;
}

sub run {
	my $pkg = caller();
	if (prog() eq $pkg) {
		my ($cmd, @args) = @ARGV;
		my $this = $pkg->new;
		$cmd = 'main' if !defined $cmd;
		my @return = $this->$cmd(@args);
		for (@return) { say($_); }
	}
}

sub say {
	fsay(\*STDOUT, @_);
}

sub fsay {
	my ($fh, @args) = @_;
	for (@args) { $_ = dumper($_) if ref $_ }
	print $fh "@args\n";
}

sub qi {
	my ($text) = @_;
	$text =~ s/^\n//;
	$text =~ s/\n[ \t]*$/\n/;
	my ($indent) = $text =~ /^([ \t]*)/;
	$text =~ s/^$indent//gm;
	return $text;
}

sub message {
	fsay(\*STDERR, @_);
}

sub subs {
	no strict 'refs';
	my ($package) = @_;
	$package = __PACKAGE__ if !defined $package;
	if (ref $package) { $package = ref $package; }
	my @subs;
	for my $key (keys %{"${package}::"}) {
		my $var = $package."::".$key;
		if (*{$var}{CODE}) {
			push @subs, $key;
		}
	}
	return @subs;
}

sub public_subs {
	return grep !/^_/, subs(@_);
}

sub dumper {
	local $Data::Dumper::Terse = 1;
	local $Data::Dumper::Indent = 0;
	return Dumper(@_);
}

sub relpath {
	my ($over, $under) = @_;
	$over = canonpath(abs_path($over));
	$under = canonpath(abs_path($under));
	my $rel;
	if (index($under, $over) != 0) {
		return undef;
	}
	$rel = "." . substr($under, length($over));
	return $rel;
}

sub nicetime {
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);
	$year += 1900;
	$mon += 1;
	return sprintf("%04d.%02d.%02d-%02d.%02d.%02d", $year, $mon, $mday, $hour, $min, $sec);
}

sub ls {
	my ($dir) = @_;
	opendir my $dh, $dir or die "can't opendir $dir\n";
	my @list = grep !/^\./, readdir($dh);
	return @list;
}

sub slurp {
	my ($filename) = @_;
	open my $fh, "<", $filename or die "can't open $filename to read";
	binmode($fh);
	local $/;
	undef $!;
	my $text = readline($fh);
	if ($!) {
		die "can't read from $filename: $!";
	}
	close($fh) or die "can't close file $filename (reading)";
	return $text;
}

sub spurt {
	my ($filename, $text) = @_;
	open my $fh, ">", $filename or die "can't open $filename to write";
	binmode($fh);
	print $fh $text or die "can't write to $filename";
	close($fh) or die "can't close (finish writing) $filename";
}

1
