- 短いオプションには、長いオプションを付けたほうがいいけど、その逆は真ではないという話がP74から書かれている。
- 理由は2つ述べられていて、ひとつは文字数の問題、もうひとつは危険なものは短いオプションで指定させないということ。
- 例えば、db_backupアプリについて。ダンプファイルの圧縮はデフォルトでするが、非圧縮は長いオプションでしか用意していない。
- P75の後半では、todoアプリについて。
listというサブコマンドに対して、lsという名前も追加している。 - 馴染みのある名前にそって別名を用意する方がいいって話かな?
- 第5章。いきなり英文がわからなくなった。すげぇ難しい。
- コマンドラインアプリケーションの使いやすさのためには、アプリが取るオプションやデフォルト値、デフォルトの挙動が命運を分ける
- db_backupアプリについて。
-iオプションがあるけど、これだけでは全くわからない。- 私もこの本読んでいて未だに意味がわからない。
- 短いオプションはそのアプリを使い慣れると使い勝手がいいんだけど、他のアプリからこのアプリを使うときなどは、長いオプション(かつ、意味がわかるもの)が必要
- そこで、
-iや-uや-pに対して長い名前のオプションを追加する。
- P67の4.4 Trapping Signals Sent from Other Appsから。
- プログラムを終了させるときによく使うCtrl+C。Rubyのプログラムもこのキーを押されると終了するのだが、プログラムの終了する直前に処理をしたい。
- 例えば、db_backupだと途中まで生成していたダンプファイルとかを削除するとか。
- そこで、Rubyの標準ライブラリにある
Signalのtrapメソッドを使って、終了時の処理を挟み込む。 - シグナルについては、Wikipediaに情報があるので、ちょっと目を通しておこう。
- 機械で処理するものと、人の目で見やすいものとは違うので、プログラムのオプションで分けることにする。
- 今回の例では、
formatオプションで指定する。prettyを指定した場合は人が読める形に、csvを指定した場合はマシンが処理できる形に。 - P67からはシグナルの取得について。
- P63からは出力するデータのフォーマット(整形)について。
- ポイントは、他のプログラムが操作しやすいフォーマットであるかどうか。
- ここでの例は、
lsコマンドでファイル名が番号順に並ばないということを上げている。それを解決するには、sortコマンドを使用している。 - こんなことができるのは、
lsコマンドの出力がシンプルだから。他のプログラムが使いやすい。 - ここで、我々が作っていた
todoアプリについて見てみると、人間の目からするとわかりやすいが、プログラムとしては使いにくい。例えばソートが出来ない。 - そこで、出力する情報を1行にまとめる。
- 1行にまとめるだけだと各項目の区切りがわからないので、ここではカンマ区切りをする。
- これでOK?って思っていたら、例えば、終了したものだけをgrepで取り出すには大変という問題があるので、その対策が必要。
- 今日はP66まで。
- P59からは標準出力と標準エラー出力について。
mysqldumpコマンドで失敗したときに、エラーメッセージがリダイレクト先のファイルに出力されずに、画面に出る例を出している。- というわけで、まずは外部コマンドを実行した時に標準エラー出力を取得する方法として、ここでは
Open3標準ライブラリを紹介している。 - ちなみに、各種外部コマンドの呼び出し方法のうち、標準出力や標準エラー出力の取り方などをまとめたのがここにある。
- アプリケーションで標準エラー出力を出すためには、
STDERR.putsとすればよい。
- 複数のエラーコードを返す方法について
- 今回の例だと複数のエラーコードを返すってあまり意味が無いような。
ARGV.empty?がtrueとなるときと、OptionParser::InvalidArgumentが同時に成り立つ場合ってどんなケースだろう。 - やり方は、ビット演算。
- これでコマンドを呼び出す側もビット演算でどのようなエラーが起きたのか検出できる
- exitメソッドに与える値について。
- エラーの場合は0以外の正の値を与えれば良いってわけではなくて、エラーの種別ごとにユニークに保つとよい。
- ユニークに保つことで、そのプログラムを使う人(特に開発者)においては、その戻り値によって何が起きたのかが把握しやすくなる。
- 例として書かれているのがP57。
- 今回作ったプログラムを利用するプログラムにおいて、
exitstatusが1のときはバックアップが取れていない。 - それ以外でかつ0でない場合はプログラムの起動が失敗していることを意味している。
- 今回作ったプログラムを利用するプログラムにおいて、
- P55では自身のExit Codeを呼び出したプロセスに渡すことについて記している。
- 単純に
exitメソッドを呼び出せばOK。 - となると、ここで
putメソッドで標準出力にメッセージを出しているんだけど、エラーメッセージの場合は標準エラー出力にメッセージを出すべきでは?と思ったりするんだけど、このような修正は後で出てくるのかな?
- P55では戻り値を取るための方法が書かれている。
$?で取れるんだけど、変数名としてはわかりにくいので、これを何とかしたい。 - それを何とかするのがEnglishライブラリ。
- 特殊変数に英語名の別名を付けてくれる。
- 今回の戻り値の例で言えば、
$?が$CHILD_STATUSとなる。戻り値は、exitstatusで参照できる(参考)。
- 今日はP53。Chapter4のPlay Well with Othersから。他のものとうまく動くって感じかな。
- 4.1ではUsing Exit Codes to Resport Success or Failure、終了コードによって成功か失敗かを報告することについて記してある。
- 終了コード(終了ステータス)については、WikiPediaに解説があるのでそれも合わせて読んでおく。
- 慣例的に0が成功でそれ以外を失敗と考えれば良いかなと思う。
- サンプルコードが付いているけど、これまでのものの流れが考慮されていない気がする。
- P47のWriting Good Help Text and Documentationから。
- 良いヘルプテキストやドキュメントの書き方について。
- usageの書き方とか、そもそもドキュメントに何を書くのかについて。
GLIで生成するとドキュメントはテンプレートとしてある程度生成されるので、それに沿って書けば良さそう。- P50とP51に書かれているTable2の内容をひと通り書く、つまりは、
ronnで生成されるドキュメントに沿って書けば良さそう。 - 次回は、第4章 Play Well with Others。
- P42の3.3 Including a Man Pageから。
- manページを書くには、また独自のフォーマットを覚えなきゃいけないよなぁと思っていたら、Markdownからmanページのフォーマットに変換してくれるツールがGemで配布されているらしい。
それが、gem-man。- P45でそのmanページの元になっているファイルを作成している。
- 実際にmanページの生成については、P46に記載されている。
man man/db_backup.1って実行するとmanページが表示される。- って、ここまで書いて違うことに気がついた。
- gem-manは、gemにman表示機能を追加する感じ。
- Markdownからmanページのフォーマットに変換するのはronn
- 今日はここまで。次回はP47 3.4 Writing Good Help Text and Documentation
- 久しぶりの再開。多分、P38の「3.2 Documenting a Command Suite」から再開。
- ヘルプメッセージの作り方について。今回はtodoアプリ。
- todoアプリは、GLIというツールを使った。このGLIはヘルプメッセージも丁寧に作ってくれる。
- 詳細は、P40から。
descには短めの説明、long_descには長い説明ってな感じで記述していく。 - P42には
arg_nameやdefault_valueの設定が書かれている。- ここを見ずに、前のソースコードだけで「あれ?default:のところがうまく表示されない」ってなっていろいろと探し回った。
- 次は、P42の3.3 Including a Man Pageから。
- OptionParserは
parse!メソッドを実行するとコマンドライン引数であるARGVを直接編集し、オプションのものは削除する。 - OptionParserは定義していないオプションが指定された場合は、
parse!の時点で例外を吐くので、ARGVに残るものはデータベース名だけだと考えてよいっぽい。
-hメッセージにMySQLを対象としているということを明示する。そのためにはbanner=に設定する値を編集する。
- 3章。
-hをつけて表示されるヘルプメッセージを作成する。 - ヘルプメッセージは、自分で全部作るんじゃなくて、
optionparserのonメソッドにおいてメッセージを追加することで、オプションのメッセージが作れる。 - これだと、プログラム自身の使い方は表示されないので、
banner=メソッドで値を指定する。
- P29では
listの実装例があるけど、read_todoメソッドを実装していないのでこれは動かない。- 動かすためには、
read_todoが返す値のデータ構造も考えないといけない。ちょっと面倒臭い。
- 動かすためには、
- GLIで作成したアプリは動的にヘルプオプションを取れるようになっている。
- 動かしてみると、
_docというオプションが出てきた。これ、どこで定義されているのだろう。 - このヘルプページが作られる機能を使って、bashでの補完機能を追加するということをやっている。
- GLIの
scaffoldで生成されたソースコードの解説がP27から。 - P28から生成されたソースコードに対して手を加えていく。
- グローバルオプションとして、
fオプション。ファイル名の指定。 newサブコマンドに対してpriorityオプションとfスイッチを追加する。- グローバルオプションの
fオプションとfスイッチの違いはどうやって判断するんだろう。- サブコマンドの前に
fオプションがあればグローバルオプションとして判断される。 - サブコマンドの後に
fオプションがあればスイッチとして判断される。
- サブコマンドの前に
- グローバルオプションの
listサブコマンドに対しては、sオプション。doneサブコマンドに対しては、特に何も追加しない。- P29の実行ログで
pオプションがあるけど、実際にはpriorityではないかな?
- P23にてserverオプションを追加。serverオプションの妥当性はハッシュで指定できる。
- ここでserverオプションを追加するときに既存のコードがsyntaxエラーで落ちることがわかった。
- テストを書かないとあかんなぁ。
end_if_iterの役割がやっぱりわからない。true/falseなのか、なにか値を取るのか。途中で意味が変わっている気がする。
- todoアプリに対してもオプション解析機能を追加することに。
- オプション解析機能として今回は、GLIというGemを使うらしい。
- GLIで
scaffoldして動かそうとしたらarubaっていうGemが追加で必要らしい。これは追加でgem installする。
- ここらでテストを書こうとしたけど、どうにもこうにも書きにくい。
optparseの解析結果をテストしようとしたけど、どうやってテストを書けばいいか分からなかった。- というわけで、ここでテストを書くのはやめ。
opts.on("-u USER", /^.+\..+$/)でオプションの引数の正規表現validationが可能。- これにマッチしない引数を指定すると、
invalid argument: -u hoge (OptionParser::InvalidArgument)と出てくる。
- オプションの実装は、
optparseを使うと楽に書ける。 optparseの説明はるりま(http://docs.ruby-lang.org/ja/2.1.0/library/optparse.html)を参照。- P22では、userオプションの引数にとるUSERのvalidationを追加している。
- validationはファーストネーム + ピリオド(.) + ラストネームの形とする。
- db_backup.rbをより使いやすくするために、オプション解析機能をつける。
-pはパスワード、-uはユーザ名、-iは繰り返すかそうでないかのオプション。end-of-iterationの役割。- データベース名にはオプション名を付けない
- P13から第2章。使いやすくするために、まずはコマンドラインのオプションや引数やコマンドなどを実装する
- オプションの指定は様々。オプションごとに一つ一つ分けたり(
-l -a -t)、一個に統一(-lat)したり。 - 短いバージョン以外にも長いバージョンが有る。
- 引数は、オプションではないものって書いてあるんだけど、これだと次のコマンドと区別がつかないような
- コマンドは、executableに対する命令ってな感じかな?
gitコマンドだとcommitとかaddとか。 - コマンドというよりかはサブコマンドって言ったほうがしっくり来る。
- todo-*.rbは3つに分かれているけど、似たようなソースがそれぞれに実装されていたりする。
- そこで、todoというアプリを作ってこの3つをまとめることにする。
- 第一引数でnew、list、doneを取るようにして、処理内容を変えることにする。
- 実装がP9。
- P5では最初のプログラムを修正して、データベース名、ユーザ名、パスワードなどを引数で取れるようにしている。
- 他のデータベースをバックアップの対象としたいときなどプログラムの修正する必要がなくなる。
- このプログラムはこの本を通して改善を続けるようだ。
- 1.2でタスクマネジメントツール。色々あるけど、すっごくシンプルなものを作る。メモ紙に書き殴る感じのもの。
- そのために3つのプログラムを作る。todo-new.rb、todo-list.rb、todo-done.rbの3つ。
- コマンドラインのアプリケーションの例として、MySQLのデータバックアッププログラムツールを作っていく。
- end-of-iterationってなんだろう。
- とりあえず、最初の実装がP3にある。