【しばらく編集不可モードで運営します】 編集(管理者用) | 差分 | 新規作成 | 一覧 | RSS | FrontPage | 検索 | 更新履歴

Term::ReadLine.pm - あなたのPerlプログラムに、シェルライク インターフェイスはいかが?

目次

あなたのPerlプログラムに、シェルライク インターフェイスはいかが?

はじめに

あなたがPerlを知っていて、何度かプログラムを書いたことがあるのでしたら、 きっとこういう決まり文句を見たことがあるでしょう。

 while (<STDIN>) {
  chomp;
  ...
 }

これはユーザの入力を行単位で受け付けます。<STDIN>は標準入力から一行を読み取り、 それはデフォルト変数$_に格納されます。引数なしのchomp関数は、デフォルト変数に作用し、 改行があれば切捨てを行います。

開発者は、行単位の入力を受け取り、入力に対応する処理を行うように実装することができます。 そうした場合、そのプログラムは小さなシェルのように動きます。

しかしちょっと待ってください。この仕事に最適なモジュールがあるのです。

Term::ReadLine?

あなたの大事な睡眠時間を削ってコーディングをするかわりに、 Perlの標準ライブラリの中のモジュールを使うことができます。

 use Term::ReadLine;
 $term = new Term::ReadLine 'my_term';
 $prompt = "input :";
 $OUT = $term->OUT || STDOUT;
 while ( defined ($_ = $term->readline($prompt)) ) {
  print $OUT "output:$_\n";
  $term->addhistory($_) if /\S/;
 }

これはほとんどあなたの予想通りの動作を提供してくれます。

実装の手引き

あなたのプログラムがサブルーチンの集合として実装されているのであれば、 たとえば以下のようにしてコマンドとサブルーチン呼び出しを対応させることができます。

 %cmds;
 $cmds{copy} = \&copy; # copy関数へのリファレンス
 # please add some commands ...
 $cmds{help} = sub{ print join(' ', sort keys %cmds); }; # コマンドの一覧を表示する

 while ( defined ($_ = $term->readline($prompt)) ) {
  if(exists $cmds{$_}) { # 入力に対応するコマンドがあれば、
   &$cmds{$_}(); # それを実行する
  } else {
   print <<END_OF_MESSAGE; # 警告:もっと気の利いたメッセージを出力してください!
 '$_' は、内部コマンドまたは外部コマンド、
 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
 END_OF_MESSAGE
  }
 }

コマンドの短いエイリアスを作るには、リファレンスを別名で登録すればいいでしょう。

 $cmds{copy} = \&copy;
 $cmds{cp} = \&copy;

コマンドが引数を取るようにするには、簡単なものならsplit関数で対応することができます。 少しだけ複雑な場合には、正規表現を使うことができます。 しかし、自分で実装する前にCPANを探してみましょう。 自分で書かなくてよいなら、それが最良の解決策です。

 

おわりに

Perlを使えば、シェルライクなプログラムはとても簡単に書けます。 今回はまさにそのために用意されたモジュールを通して、それらしい外観と機能を備えた プログラムが、ほんとうに簡単に書けることを示しました。

もちろん、開発者がシェルライクなプログラムに何をさせるかは自由です。 一連のモジュールのラッパー・インターフェイスとするのも良いでしょう。 特定目的に特化したシェルを書くこともできるでしょう。(CPANモジュールを見てください。)

しかし、

 [guest@super_computer ~]$ 秘密のファイルにアクセスせよ

とタイプしたときに直ちにそれを表示するようなシェルは、(例え簡単に書けたとしても) 映画の中だけに留めておいたほうが賢明です。

リンク

メモ