ARGSのparser(2)

http://d.hatena.ne.jp/shokai/20091020/1256064111 から進化させた。

  • 整形された引数のヘルプの表示
  • 実行前に引数が足りているかチェックするためのメソッド

を追加。


こんな感じで使える


test.rb

#!/usr/bin/env ruby
require 'ArgsParser'

parser = ArgsParser.new
parser.bind(:help, :h, "show help") # -hでも-helpでも--helpでも-----hでもいい
parser.bind(:frame, :f) # 第3引数無しでもいい
parser.bind(:motion, :m, "MotionEffect") # 第3引数でhelp用のコメントをつけれる
parser.bind(:motion_scale, :mscale, "MotionEffectのサイズ調整")
parser.comment(:motion_min, "MotionEffect適応の最小サイズ") # コメントだけつける
parser.comment(:motion_max, "MotionEffect適応の最大サイズ")
parser.bind(:analyzed_yaml, :a, "解析結果ファイル")
parser.bind(:source, :s, "元動画連番ファイル")
parser.bind(:output, :o, "出力先ディレクトリ")
parser.bind(:theme, :t, "テーマファイル")
parser.bind(:preview, :p, "show preview")
parser.comment(:debug, "debug mode")

params = parser.parse(ARGV)

if parser.has_option(:help) ||
    !parser.has_params([:frame, :motion, :source, :output]) || # 引数が足りているかチェック
    !parser.has_options( [:preview, :debug])
  puts parser.help # ヘルプの表示
end

if parser.has_param(:motion_min)
  puts 'motion_minに値が指定されました : ' + params[:motion_min]
end

# 引数を全て表示
p params


実行

ruby test.rb -a hogehoge.yaml -output output.txt -debug -p

出力

options:
 -analyzed_yaml (-a)      解析結果ファイル
 -debug                   debug mode
 -help (-h)               show help
 -motion (-m)             MotionEffect
 -motion_max              MotionEffect適応の最大サイズ
 -motion_min              MotionEffect適応の最小サイズ
 -motion_scale (-mscale)  MotionEffectのサイズ調整
 -output (-o)             出力先ディレクトリ
 -preview (-p)            show preview
 -source (-s)             元動画連番ファイル
 -theme (-t)              テーマファイル
{:analyzed_yaml=>"hogehoge.yaml", :preview=>true, :debug=>true, :output=>"output.txt"}

ArgsParser.rb

class ArgsParser

  def params
    @params
  end
  
  def initialize
    @binds = Hash.new
    @comments = Hash.new
  end

  def parse(argv)
    # parse
    @params = Hash.new
    for i in 0...argv.size do
      if argv[i].match(/-+.+/)
        term = argv[i].match(/-+(.+)/)[1].to_sym
        if i == argv.size-1 || argv[i+1].match(/-+.+/)
          @params[term] = true # option
        else
          @params[term] = argv[i+1] # param
        end
      end
    end
    
    @binds.keys.each{|name|
      fullname = @binds[name]
      if @params[fullname] == nil && @params[name] != nil
        @params[fullname] = @params[name]
        @params.delete(name)
      end
    }
    
    return @params
  end

  def bind(fullname, name, comment=nil)
    @binds[name.to_sym] = fullname.to_sym
    if comment != nil
      comment(fullname, comment)
    end
  end

  def has_param(name)
    @params[name].class == String
  end

  def has_params(params_arr)
    params_arr.each{|name|
      return false if !has_param(name)
    }
    return true
  end

  def has_option(name)
    @params[name] == true
  end

  def has_options(options_arr)
    options_arr.each{|name|
      return false if !has_option(name)
    }
    return true
  end

  def comment(name, comment)
    @comments[name.to_sym] = comment.to_s
  end
  
  def comments
    @comments
  end

  def help
    binds_reversed = Hash.new
    most_longname_size = 0
    @binds.keys.each{|key|
      value = @binds[key]
      binds_reversed[value] = key
      if most_longname_size < len = key.to_s.size + value.to_s.size
        most_longname_size = len
      end
    }

    s = "options:\n"
    @comments.keys.sort{|a,b| a.to_s <=> b.to_s }.each{|name|
      comment = @comments[name]
      if shortname = binds_reversed[name]
        s += " -#{name} (-#{shortname})" +
          " "*(most_longname_size-name.to_s.size-shortname.to_s.size+2) + "#{comment}\n"
      else
        s += " -#{name}" + " "*(most_longname_size-name.to_s.size+6) + "#{comment}\n"
      end
    }
    return s
  end

end