オプション
コマンドの追加とコマンドの作成(#1) では非常に単純な hello コマンドについて説明した。ここではコマンドのオプションが、そこで説明したトークンとして処理されることを示す。
ここでは四つのオプションをもつ quote コマンドを例に説明する。このコマンドは以下のように指定したオプションにしたがってそれらしくセリフを言ってくれる。
localhost>quote vader
It is your destiny.
localhost>
オプションは他に harry, vader, solo, smith があり、合計四種類ある。これらのオプションは排他的に並立であり、どれか一つだけを選択する必要がある。具体的に列挙すれば
quote
quote harry
quote vader
quote solo
quote smith
の五種類の指定によるコマンド実行が可能である。つまりそのような構造のオプションを持つコマンドを、CliParser.OrRule() 関数を用いて作成する。
コード
以下に quote コマンドを CLI に登録するためのプログラムを示す。実際にこの Quote.py コマンドを自分のシステムに設置し、テストする手順などについては コマンドの追加 を参照のこと。
bash-3.2# cat -n Quote.py
1 import BasicCli, CliParser
2
3 tokenQuote = CliParser.KeywordRule( 'quote', helpdesc='Quote a nice phrase from a movie.' )
4
5 quoteOpt = CliParser.OrRule()
6 quoteOpt |= CliParser.KeywordRule( 'harry', helpdesc='Inspector Harry Callahan' )
7 quoteOpt |= CliParser.KeywordRule( 'vader', helpdesc='Lord Vader' )
8 quoteOpt |= CliParser.KeywordRule( 'solo', helpdesc='Captain Han Solo' )
9 quoteOpt |= CliParser.KeywordRule( 'smith', helpdesc='Agent Smith' )
10
11 def quoteCompat( mode, who ):
12 if who == 'harry' or who is None:
13 print "I know what you are thinking.\n"
14 elif who == 'vader':
15 print "It is your destiny.\n"
16 elif who == 'solo':
17 print "Uh, uh, negative, negative. We had a reactor leak here now.\n"
18 elif who == 'smith':
19 print "Mr. Anderson. Welcome back. We missed you.\n"
20
21 BasicCli.UnprivMode.addCommand( ( tokenQuote, [ '>>who', quoteOpt ], quoteCompat ) )
bash-3.2#
このプログラムの内容を示す。
1: まずコマンド処理に最低限必要な BasicCli, CliParser クラスを読み込み、
3: quote という名前と、そのコマンドが help として出すべき文字列をトークンとして作成する。
5: オプション用のトークンを OrRule() によって作成する。まず空の OrRule インスタンスを用意する。
6: KeywordRule() によって harry というキーワード(これがオプション名になる)と、そのオプションに対して help として出すべき文字列をトークンとして作成し、これを先に作成した OrRule によるオプションに |= によって追加する。(この |= 演算子は OrRule インスタンスによって解釈され、それらしく内部処理が行われます。)
7-9: 以下、vader, solo, smith オプションについてもそれぞれ OrRule に |= によって追加する。
11: quote コマンドの実体となる関数を定義する。第二引数(who)に選択されたオプションが格納されている。
12-19: 第二引数 (who) を手がかりに処理を分岐。特にオプションが無かった場合、デフォルトで 13 行目の処理をするように 12 行目の if 文には who is None の条件を設定した。
21: addCommand() によって非特権モードにコマンドを追加する。これで複数のオプションを含む quote コマンドがシステムに登録される。実際に実行されると、who 変数にマッチしたキーワード(すなわちオプション文字列)を格納して quoteCompat() 関数を呼び出してくれる。
addCommand() 関数
addCommand() の引数は以下の通り。
- 第一引数
- quote コマンドそのもの(コマンド名と help メッセージ)の登録
- 第二引数
- オプションに相当するここでは OrRule で複数登録されたルールセット tokenQuote を付けて、その結果を who と言う名前の変数に入れる
- 第三引数
- quoteコマンドの実体。引数に who が追加されており、ここで OrRule で設定したどのオプションが入ったかを調べられる。
今回は三つしか引数がない状態であるが、実際には引数はそれ以上に増やせる。たとえば N 個の引数を与えた場合、2〜(N-1)引数までが第二引数部分に相当する役割を果たす。つまり上の三種類の引数の役割は「最初の引数」「中間の引数 (群)」「最後の引数」と表現しても良い。
なお、コマンドの作成(#1)で紹介した hello コマンドでは、第二引数がない、引数を二つしかとらない場合の addCommand() 関数の使い方を示した。同じく特権モードへの登録、show コマンドへの登録についても説明があるので参照されたい。
動作
quote コマンドは以下のような挙動を示す。
- quote コマンドは実行されると quoteCompat() 関数を呼び出すが、その時 who 変数にどのオプション指定にマッチして実行されたのかを与えてくれる。
- 単に quote とだけ入力して実行すると who には None が入り、12 行目の who is None 条件に該当して( harry と指定したときと同様に)動作する。すなわちこれがデフォルトとなる。
- quote harry, quote vader などオプションを指定して実行すると、12行目以降の if 文によって who 変数の内容に応じて分岐して処理が実行される。
- quote harry vader など、複数のオプションを同時に指定することはできない。
ヘルプメッセージなどもこの挙動に合致するように自動的に設定される。
? によるヘルプ
quote コマンドの直後に ? キーを押すと以下のように表示される。
localhost>quote ?
harry Inspector Harry Callahan
smith Agent Smith
solo Captain Han Solo
vader Lord Vader
<cr>
localhost>
オプションに関する help メッセージは登録順ではなくアルファベット順に現れる点に注意。
TAB による補完
quote va までタイプすれば TAB キーによる補完を行ってくれる。その後に ? キーを押せば、それ以降は改行するしかないことが示される。実際に改行すれば、上に示したとおりオプションによって分岐して処理が行われる。
localhost>quote va
localhost>quote vader ?
<cr>
localhost>quote vader
It is your destiny.
localhost>
実装
OrRule(), KeywordRule() などは /usr/lib/python2.5/site-packages/CliParser.py に実装されている。コメントなどもあるので、どのようなルールのトークンが使えるか調べてみると良い。(このサイトにもできるだけ簡単なサンプルを集めて いく。)
next step
今回のサンプルではオプション無しで実行することが可能だった。quote ? とすると help メッセージにもオプションの候補の後に <cr>(オプション無しで単に改行キーを押す)が表示されることでも確認できる。
次はオプション無しを認めないケースを例に、Arista がコマンドに対して用意しているトークンのツリー構造について説明する。