Perl 小品集 ─ pcal
#!/usr/bin/perl
# pcal.pl
#
# カレンダー
# モジュール Term::ReadKey とカラー表示可能なターミナルが必要
# モジュールの宣言
use Term::ReadKey;
# 月の名前のテーブル
@month_name = ("", " January", " February", " March", " April", " May",
" June", " July", " August", "September", " October", " November", " December");
# 現在年月日の取得(サブルーチンへ)
&get_current_time();
# 表示月の取得
$input = @ARGV[0];
if ($input ne ""){
$month = $input % 100;
$year = ($input - $month) / 100;
if($year < 100 ){
$year = 2000 + $year;
}
}
&select;
ReadMode 0;
print "\n";
exit 0;
sub select()
{
&calendar_body ();
# カレンダーの下に置くメニュー
# カラー表示のためのエスケープシーケンス(使えないターミナルもある)
print " \033[1;34m←\033[35mPrvM \033[1;34m↓\033[35mNxtY \033[1;34m→\033[35mNxtM\33[0m\r";
ReadMode 3;
$key = ReadKey;
# 終了
if ($key eq 'q' or $key eq 'Q') {
return;
}
# 現在
elsif ($key eq 't' or $key eq 'T' or ord $key == 8) {
&get_current_time();
}
# 前の年
elsif ($key eq 'A') {
$year--;
}
# 次の年
elsif ($key eq 'B') {
$year++;
}
# 次の月
elsif ($key eq 'C') {
$year = $year + ($month == 12);
$month = $month + ($month < 12) - 11 * ($month == 12);
}
# 前の月
elsif ($key eq 'D') {
$year = $year - ($month == 1);
$month = $month - ($month > 1) + 11 * ($month == 1);
}
# 任意の年月
elsif ($key eq ' ') {
&anytime;
}
# ヘルプの表示
elsif ($key eq 'h' or $key eq 'H') {
&show_help;
}
&select;
}
# 任意の年月
sub anytime
{
$current_year = $year;
$current_month = $month;
ReadMode 0;
print "\033[2K\033[1;35mYear/Month>\033[0m";
$input = <STDIN>;
chomp $input;
if ($input eq "") {
return;
}
($year, $month) = split /[^\d]+/, $input;
if($month > 12 or $month < 1) {
$year = $current_year;
$month = $current_month;
}
else {
if($year < 100 ) {
$year = 2000 + $year;
}
}
}
# 一カ月分の表示
sub calendar_body
{
&find_first_last;
print "\n\n \033[1;31m$month_name[$month], $year\033[0m\n";
print " \033[1;34mSu Mo Tu We Th Fr Sa\033[0m\n";
my $i = 0;
while ($i <= $first_day - 1) {
print " ";
$i++;
}
$date = 1;
while ($date <= $last_date) {
print " ";
if ($date < 10) {
print " ";
}
if ($year == $this_year && $month == $this_month && $date == $today) {
print "\033[1;32m$date\033[0m";
}
else {
print $date;
}
if (($first_day + $date) % 7 == 0) {
print "\n";
}
$date++;
}
if (($first_day + $date - 1) % 7 != 0) {
print "\n";
}
}
# 日付と曜日の計算
sub find_first_last
{
@month_day = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
if(($year%4)==0 && ($year % 100) != 0 || ($year % 400) == 0) {
$month_day[2] = 29;
}
local ($days) = $year + ($year-1)/4 - ($year-1)/100 + ($year-1)/400;
my $i = 0;
while ($i < $month ){
$days += $month_day[$i];
$i++;
}
$first_day = $days % 7;
$last_date = $month_day[$month];
}
# 現在時刻の取得
sub get_current_time
{
($sec, $min, $hour, $date, $month, $year, $day) = localtime(time);
$year = 2000 + $year - 100;
$month++;
$this_year=$year;
$this_month=$month;
$today = $date;
}
sub show_help
{
print "\n";
print "\n";
print "矢印キーを使うと、次の月や、次の年に移動できます。\n";
print "↑印キーで前年に移動できます。\n";
print "[T] または [BS] キーで今月のカレンダーに戻ります。\n";
print "スペースキーを押すと任意の年月を入力できます。\n";
print "年と月の間には、句切りをいれてください。\n";
print "句切にはスペース、スラッシュ、カンマなどが使えます。\n";
print "100年 より少ない年は 2000 年代と解釈します。\n";
print "不正な数字の場合は表示されません。\n";
}