Perl には、簡単に使えるファンクションがたくさんありますが、それでも、あらゆるプログラムに対応できるようにはなっていません。もしそうしたら、膨大な数のファンクションになり、Perl をコンパクトに保つことができなくなるからです。Perl の基本的なファンクション以外のものは、ユーザが後で追加できるように、モジュールの形で用意されています。
カレンダープログラムの仕上げとして、メニューのキーを直接入力するようにしたい(つまり、リターン・キーを押さなくてもよいようにする)のですが、そのファンクションがないので、では、モジュールで対応しようということで、CPAN のウェブページをチェックしました。CPAN というのは Comprehensive Perl Archive Network の略で、Comprehensive というだけあって、Perl に関するものはここに何でもあります。本家のページは www.cpan.org なんですが、モジュールの検索などの場合は search.cpan.org で調べるほうがてっとりばやいと思い、そこをあたってみましたら、Term::ReadKey というモジュールがありました。termreadkey-2.15.tar.gz をダウンロードして、次の手順でモジュールを組み込みました。次のプロンプトの $ はユーザ、# はスーパーユーザをあらわします。スーパーユーザになるには su コマンドでパスワードをいれればいいですね。
$ tar -fvxz termreadkey-2.15.tar.gz $ cd termreadkey-2.15 $ perl Makefile.PL $ make $ make test $ su Password: # make install # exit $ cd .. $ perldoc Term::ReadKey最後の perldoc Term::ReadKey は、このモジュールのマニュアルを読むためのものです。マニュアルは man 形式で、スペースを押してページを進め、Q で終了です。
そのマニュアルによれば、「ReadMode で、入力モードを指定し、ReadKey でキーボードからの入力を読みとる」とありました。ここでは入力モード 3 を選び、キーボードからの入力を $key 入れ、入力モードに 0 を指定することによって、もとにもどしておくようにしました。これを select() サブルーチンの $input =
ReadMode 3;
$key = ReadKey;
ReadMode 0;
ただし、モジュールを使うには、プログラムの先頭で、use <モジュール名> の宣言をしておかなくてはなりません。
#!/usr/bin/perl
#
# calendar05.pl
#
use Term::ReadKey;
ここまで出来れば、あとは select() サブルーチンで の選択部分で $input を $key にかえればいいだけですが、ひとつだけ問題があります。if($input eq '') という部分を if($key eq '') としても駄目です。$key には「リターン」の価が入っているからです。'b' を押したかどうかは if($key eq 'b')で、「シフト」と'b'を押したかどうかは if($key eq 'B') でチェックできますが、文字を返さない「リターン」キーの場合は、コードで表して
if($key eq chr(10))としなければなりません。chr(10) は、「文字コード 10 番目の文字」という意味です。ある文字の文字コードが何番目かは ord('A') として得ることができます。'A' は 65 です。ですから、上の式は
if(ord($key) == 10)と書いても良いことになります
以下は書き換えた select() サブルーチンです。
sub select(){ local ($input, $year, $month); ($year, $month) = @_; # キーボードからの直接入力 ReadMode 3; $key = ReadKey; ReadMode 0; print "\n\n"; # 選択と年月の計算 if($key eq 'q'){ exit(0); } elsif($key eq 'b'){ $year = $year - ($month == 1); $month = $month - ($month > 1) + 11 * ($month == 1); } if($key eq 'B'){ $year--; } if($key eq 'n'){ $year = $year + ($month == 12); $month = $month + ($month < 12) - 11 * ($month == 12); } if($key eq 'N'){ $year++; } if($key eq chr(10)){ $year = $this_year; $month = $this_month; } return ($year, $month); }