概要
書籍 Build Awesome Command-Line Applications in Ruby2
章
Be Easy to Use
詳細
「OptionParserを利用した使いやすいCLIインターフェース(http://d.hatena.ne.jp/tbpg/20140526/1401109608)」で紹介したOptionParserは
シンプルなCLIツールを作るには十分ですが、サブコマンドを持つようなCommand suitを作るには不十分です。
そこで、thor gem を利用してサブコマンドを持つCLIアプリケーションを作成します。
※書籍では、著者のプロダクトであるGLIを用いた例を紹介していました。
サンプル仕様
※書籍に載っていたものとは全く別のものです。自分独自の仕様で考えました。
Personの関連情報を出力するコマンド群を作成する。
Personの情報は persons.txt にcsv形式で保存されている。
firstname | lastname | age |
---|---|---|
kazuo | tanaka | 34 |
ken | sato | 54 |
ichiro | suzuki | 45 |
Personの情報を取得し、
姓を出力する
名を出力する
姓名を出力する
年齢を出力する
名を元に persons.txt からデータを検索し、結果を表示する
コマンドを作成します。
Command | Long-From Option | 内容 |
---|---|---|
fir | firstname | 名を出力する |
l | lastname | 姓を出力する |
fu | fullname | 姓名を出力する |
a | age | 年齢を出力する |
fin | find_by_firstname | 姓で検索する |
サンプルコード
require 'csv' require 'thor' require 'pp' class PersonViewer < Thor package_name "person_viewer" VERSION = "0.0.1" class_option :help, type: :boolean, aliases: '-h', desc: 'help message.' class_option :version, type: :boolean, desc: 'version' PERSONALS = './personals.csv' desc "view firstname", "view firstname" option :upcase, type: :boolean, aliases: '-u' option :downcase, type: :boolean, aliases: '-d' def firstname table = CSV.table(PERSONALS) table.each do |row| row[:firstname] = row[:firstname].upcase if options[:upcase] row[:firstname] = row[:firstname].downcase if options[:downcase] puts row[:firstname] end end desc "find by firstname [FIRSTNAME]", "find by firstname [FIRSTNAME]" def find_by_firstname(text = '') target = CSV.table(PERSONALS).select { |row|row[:firstname] =~ /#{text}/ } pp target end desc "view lastname", "view lastname" option :upcase, type: :boolean, aliases: '-u' option :downcase, type: :boolean, aliases: '-d' def lastname table = CSV.table(PERSONALS) table.each do |row| row[:lastname] = row[:lastname].upcase if options[:upcase] row[:lastname] = row[:lastname].downcase if options[:downcase] puts row[:lastname] end end desc "view fullname", "view fullname" option :upcase, type: :boolean, aliases: '-u' option :downcase, type: :boolean, aliases: '-d' def fullname table = CSV.table(PERSONALS) table.each do |row| tmp_fullname = "#{row[:firstname]} #{row[:lastname]}" tmp_fullname = tmp_fullname.upcase if options[:upcase] tmp_fullname = tmp_fullname.downcase if options[:downcase] puts tmp_fullname end end desc "view age", "view age" option :upcase, type: :boolean, aliases: '-u' option :downcase, type: :boolean, aliases: '-d' def age table = CSV.table(PERSONALS) table.each { |row|puts row[:age] } end desc 'version', 'version' def version puts VERSION end end PersonViewer.start(ARGV)
サンプル出力
ヘルプ,バージョンの表示
$ ruby personal.rb person_viewer commands: personal.rb find by firstname [FIRSTNAME] # find by firstname [FIRSTNAME] personal.rb help [COMMAND] # Describe available commands or... personal.rb version # version personal.rb view age # view age personal.rb view firstname # view firstname personal.rb view fullname # view fullname personal.rb view lastname # view lastname Options: -h, [--help], [--no-help] # help message. [--version], [--no-version] # version $ ruby personal.rb v 0.0.1
姓、名、姓名、年齢の表示
$ ruby personal.rb fir kazuo ken ichiro $ ruby personal.rb l tanaka sato suzuki $ ruby personal.rb fu kazuo tanaka ken sato ichiro suzuki $ ruby personal.rb a 34 54 45
姓の表示にオプションを併用(大文字化、小文字化)
$ ruby personal.rb fu -u KAZUO TANAKA KEN SATO ICHIRO SUZUKI
サブコマンド+引数を利用した検索
$ ruby personal.rb fin ken [#<CSV::Row firstname:"ken" lastname:"sato" age:54>] $ ruby personal.rb fin k [#<CSV::Row firstname:"kazuo" lastname:"tanaka" age:34>, #<CSV::Row firstname:"ken" lastname:"sato" age:54>]