2010/10/08

How to use App::CLI

App::CLIの使い方

前置き

Web Applicationを書いていると管理用だったり,集計用だったりのscriptが必要になります.
今まではこれをbatch/とかに書き散らかしていました
これはメンテナンス性も悪いし,svnとかgitみたいにサブコマンドでなんとかしたい

そこでApp::CLI.

  • メリット

    1. 簡潔にCLIプログラムを作成することが可能.
    2. 依存モジュールも少ないため気兼ねなくインストールもできる.
    3. SVKとかで使われてるようなので多分それなりに安定しているはず.
    4. コマンドラインオプションの書き方はGetopt::Long
  • デメリット

    1. ドキュメントが少ない

実際に使ってみる

大きなモジュールじゃないので使いながら覚える. とりあえずこんな感じになるようなCLIを作ります

 
$ myapp.pl help
# なんかヘルプメッセージ表示
 
$ myapp.pl print hoge
hoge
$ myapp.pl print --uc hoge
HOGE
$ myapp.pl print --ucfirst hoge
Hoge
 
$ myapp.pl sum 1 2 3
Sum 6

できた!!

こんな感じのファイル構成.

 
yoshi@mb app-cli% tree
.
|-- lib
|   `-- MyApp
|       |-- Command
|       |   |-- Help.pm
|       |   |-- Print.pm
|       |   `-- Sum.pm
|       `-- Command.pm
`-- script
    `-- myapp.pl

解説

起動スクリプト

script/myapp.plの中身はすっきり

 
#!/usr/bin/env perl
 
use strict;
use warnings;
use FindBin qw($Bin);
use File::Spec::Functions qw/catfile/;
use lib catfile($Bin,'../lib');
use MyApp::Command;
 
MyApp::Command->dispatch;

Dispatcher

DispatcherのMyApp::Commandの中身もすっきり
App::CLIを継承して終了

 
package MyApp::Command;
 
use strict;
use warnings;
use base qw(App::CLI);
 
1;

Command

では肝心のコマンド部分.
こちらはApp::CLI::Commandを継承して作成する

myapp.pl print hoge

このprint部分がucfirstされ,MyApp::Commandとあわせてクラス名を生成する.
結果,MyApp::Command::Print->run(@args)が実行されます.
runは固定.

MyApp::Command::Printはこちら.

 
package MyApp::Command::Print;
use strict;
use warnings;
use base qw(App::CLI::Command);
 
sub subcommands {
    qw/uc ucfirst/;
}
 
sub options {
    ( 'strings|s=s' => 'strings' );
}
 
sub run {
    my $self = shift;
    my $strings = shift || $self->{strings} || $self->usage;
 
    print $strings, "\n";
}
 
package MyApp::Command::Print::uc;
use strict;
use warnings;
use base qw(App::CLI::Command);
 
sub run {
    my $self = shift;
    my $strings = shift || $self->{strings} || $self->usage;
 
    print uc $strings, "\n";
}
 
package MyApp::Command::Print::ucfirst;
use strict;
use warnings;
use base qw(App::CLI::Command);
 
sub run {
    my $self = shift;
    my $strings = shift || $self->{strings} || $self->usage;
 
    print ucfirst $strings, "\n";
}
 
1;
 
__END__
 
=head1 NAME
 
MyApp::Command::Print - apply uc(first)? to string and print it
 
=head1 SYNOPSIS
 
myapp.pl [--strings|-s STRINGS] [--uc] [--ucfirst] STRINGS
 
=cut

順番に解説

  1. options
  2. subcomands
  3. pod

options

Getopt::Longに食わせるオプション設定を配列で定義する.
細かい使い方はGetopt::Longを参照すること

指定したオプションはモジュール内で$self->{$key}で利用できる.

subcommands

ここで定義したサブコマンドはそのままBool型のコマンドラインオプションになる.
この場合は--uc, --ucfirstがオプションに追加される.

定義したサブコマンドはMyApp::Command::Print::$subcommandとして実装する.

注意点はこのサブコマンド側でオプション定義等ができないこと.
必要であれば親コマンド側で定義しなければならない

pod

helpコマンドで表示されるのでNAME, SYNOPSISは書いておくといい感じ.

 
yoshi@mb app-cli% perl script/myapp.pl help
   help - show help message
   print - apply uc(first)? to string and print it
   sum - sum rest arguments
yoshi@mb app-cli% perl script/myapp.pl help print
NAME
 
    print - apply uc(first)? to string and print it
 
SYNOPSIS
 
    myapp.pl [--strings|-s STRINGS] [--uc] [--ucfirst] STRINGS
 

最後にhelpコマンドの実装

これだけ特殊.
最初からApp::CLI::Command::Helpというモジュールがあるので,これを継承して終了.

MyApp::Command::Helpの中身

 
package MyApp::Command::Help;
use strict;
use warnings;
use base qw(App::CLI::Command::Help);
 
1;
 
__END__
 
=head1 NAME
 
MyApp::Command::Help - show help message
 
=head1 SYNOPSIS
 
myapp.pl COMMAND
 
=head1 COMMAND
 
help, sum, print
 
=cut

まとめ

思ったより小粒なモジュールなので楽に読めた.
依存が少ないのは利用しやすい.
App::Cmdよりわかりやすい.

他にお勧めフレームワークがあれば教えてください.

作成したコードはgithubにupしてあります.
URL: http://github.com/ysasaki/p5-testing-app-cli

0 件のコメント:

コメントを投稿