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";
}


[INDEX]