optparseを使わずにオプション引数をパースしてみる
optparseは使いやすいです。引数は"-X"のショートタイプと"--xxxx"のロングタイプが使用できますし、すっきりとした記述で書けます。
ふと、"-test "のようなオプションはパースできないかと考えました。既に"-X"と"--xxxx"が処理できるのに"-xxxx"を処理する意味なんて。。いや、どうしてもハイフン1つでロングタイプを使いたいのです。
そこで自分向きの引数パーサを作ってみることにしました。
実はoptparseでもできるのかもしれませんが、お勉強ということで。
ウェブサイト上でいろいろ参考に。
引数の形は自分の好きなようにして、使い方はoptparseをベースに考えてみます。
class MiniOptparse def initialize(&block) @opt_list = [] @banner = "" instance_eval(&block) if block_given? end attr_accessor :banner def scan_for_value(val, desc="", regex=nil, &block) val_sp = val.split(' ') bool = val_sp.size > 1 @opt_list << { val: val_sp[0], val_full: val, bool: bool, regex: regex, desc: desc, block: block } end alias_method :on, :scan_for_value def parse(args) until args.size == 0 found = nil key = args.shift @opt_list.each do |opt| if (key.to_s == opt[:val].to_s) if opt[:bool] raise "Not Found argument" unless args.size > 0 value = args.shift opt[:block].call(value.to_s) else opt[:block].call end found = true break end end unless found raise "Not Found args : #{key}." end end end def usage str = "\n" str << @banner << "\n" str << "\nUsage : <options>\n" @opt_list.each do |opt| str << sprintf(" %-32s %s\n", opt[:val_full], opt[:desc]) end str << "\n" str end end if __FILE__ == $0 opts = {} MiniOptparse.new do |o| o.banner = " % #{__FILE__} <options>" o.on('-test <value>', "This is test option.") {|v| opts[:test] = v} o.on("-help" , "show this message." ) { usage } end.parse(ARGV) #puts po.usage p opts end
% ruby mini_optparse.rb -test sample
{:test=>"sample"}
いい感じにできました。
また、正規表現を実装できていませんが、それっぽくなったので良しとします。
とりあえず、ここまで。