[Ruby] コマンドラインオプションを簡単に扱うライブラリ optparselet

by tanabe on April 28, 2007

optparse は便利なんだけど、ぱっと使うには少し機能が重たく感じるときがあった。

で、機能削って使うときに簡単なやつを書いてみた。(実装は optparse に依存しまくり。)

使い方はこんなかんじ。

# 1. フラグ扱い(指定されていれば true)したければ :act_as_flag 指定
# 2. ショートネームを独自に指定したければ :short_names 指定
# 3. 数字は整数型扱い
# 4. 少数は浮動小数点型扱い
# 5. ただし 0 から始まる数値は文字列扱い
# 6. 他は文字列扱い
# 7. 省略されたオプションをトラックしたいときはブロック渡してその中で適当に処理
# 8. すべてのオプションはデフォルトで省略可

require 'lib/optparselet'

# 一番単純な使い方

parser = OptionParserlet.new([:ability, :bicycle, :cycle])

argv = %w{ -a foo -b bar -c baz }
parser.parse(argv) # => {:ability => "foo", :bicycle => "bar", :cycle => "baz"}

# 1. フラグ扱い(指定されていれば true)したければ :act_as_flag 指定

parser = OptionParserlet.new([:ability, :bicycle, :cycle], :act_as_flag => [:cycle])

argv = %w{ -a foo -b bar -c }
parser.parse(argv) # => {:ability => "foo", :bicycle => "bar", :cycle => true}

# 2. ショートネームを独自に指定したければ :short_names 指定

parser = OptionParserlet.new([:ability, :bicycle, :cycle], :short_names => [:r, :e, :m])

argv = %w{ -a foo -b bar -c baz } # Long Name の短縮も使える
parser.parse(argv) # => {:ability => "foo", :bicycle => "bar", :cycle => "baz"}

argv = %w{ -r foo -e bar -m baz } # 当然、Short Name も使える
parser.parse(argv) # => {:ability => "foo", :bicycle => "bar", :cycle => "baz"}

# 3. 数字は整数型扱い
# 4. 少数は浮動小数点型扱い
# 5. ただし 0 から始まる数値は文字列扱い

parser = OptionParserlet.new([:ability, :bicycle, :cycle])

argv = %w{ -a 23 -b 43.150 -c 0123 }
parser.parse(argv) # => {:ability => 23, :bicycle => 43.15, :cycle => "0123"}

# 7. 省略されたオプションをトラックしたいときはブロック渡してその中で適当に処理

parser = OptionParserlet.new([:ability, :bicycle, :cycle])

argv = %w{ -a foo -b bar } # -c を省略して呼出し
options = parser.parse(argv) do |options|
  options[:cycle] = "default value"
end
options # => {:ability => "foo", :bicycle => "bar", :cycle => "default value"}

# 8. すべてのオプションはデフォルトで省略可

parser.parse(argv) # => {:ability => "foo", :bicycle => "bar"} (エラーにならない)

オプションの取り回しが野暮ったくて拡張性がつぶされてるとか、実装で修正したいところはあるけど、とりあえず公開。

てことで、コードはこちら。

require 'optparse'

class OptionParserlet

  def self.parse(argv, names, options = {}, &block)
    new(names, options).parse(argv, &block)
  end

  def parse(argv, &block)
    argv = ['--help'] if argv.size.zero?

    options = @options
    names = @names

    params = {}
    @parser = OptionParser.new do |opts|
      opts.banner = options[:help] || options[:banner] || "Usage: #{File.basename($0)} [options]"

      if options[:short_names]
        define_option_with_short_name( name_pair(names, options[:short_names]), opts, options, params )
      else
        define_option(names, opts, options, params)
      end
      opts.parse(argv)
    end

    block.call(params) if block
    params
  end

  def initialize(names, options = {})
    @names = names
    @options = options
  end

  private
  def define_option(names, optparse, options, params)
    names.each do |id|
      if flag_option?(id, options)
        optparse.on("--#{id.to_s}") {|f| params[id] = f }
      else
        optparse.on("--#{id.to_s} [val]") {|v| params[id] = parse_val(v) }
      end
    end
  end

  def define_option_with_short_name(names, optparse, options, params)
    names.each_pair do |id, short_name|
      if flag_option?(id, options)
        optparse.on("-#{short_name.to_s}", "--#{id.to_s}") {|f| params[id] = f }
      else
        optparse.on("-#{short_name.to_s}", "--#{id.to_s} [val]") {|v| params[id] = parse_val(v) }
      end

    end
  end

  def flag_option?(id, options)
    options[:act_as_flag] && options[:act_as_flag].include?(id)
  end

  def name_pair(long_names, short_names)
    alist = [long_names, short_names].transpose
    Hash[*alist.flatten]
  end

  def parse_val(str)
    case str
    when /\A0(?:\d+\.\d+|\d+)\z/
      str.to_s
    when /\A\d+\z/
      str.to_i
    when /\A\d+\.\d+\z/
      str.to_f
    else
      str.to_s
    end
  end
end

ショートカットでクラスメソッドを定義したから、実際はそっちだけ使ってれば十分かと。

  

高橋メソッド in 台湾

by tanabe on April 23, 2007

ピザ。ハルヒ。高橋会長。百聞不如一見。

http://www.slideshare.net/takahashim/diligent-people-lightweight-people/

こんなイベントやってたのか。Open Source Developer Conference in Taiwan らしい。

内容の濃さはっていうとあれなんだけどw そちらは日本Ruby会議で期待しましょう。

  

とても今さらだけど LDR の速さは異常

by tanabe on April 20, 2007

たまたま b-mobile でつなぎながら LDR でブログを読んでみたんだけど、ストレス皆無。すごすぎ。

  

日本 Ruby 会議 2007 予約完了〜!

by tanabe on April 14, 2007

こんな時間でも無事予約できた!

やたっ!

  

人材教育界の猛犬、HBRで吠える。

by tanabe on April 12, 2007

HBR May 2007に場違いなすてき記事が載っていた。主役の名は Larry Winget. 人呼んで「人材教育界の猛犬」

この時点ですでに少しおかしい。誌面ではさらに写真が載っている。これがまたおかしい。

こんなかんじ。けして週刊プロレスとかを読んでたわけじゃない。

では四の五の言わずに語録を。

  • 「社員が最低なのは、お前ら経営者や管理職が最低だからだ」。そう言い放った瞬間、聞き手にとって現実的(リアル)な問題になるのです。
  • 「お前らをいい気分にさせて、きっとよくなるから頑張りましょうなんて言うのは、もううんざりだ。よくなろうという気のある奴は、放っておいてもよくなる。その気がない奴は他人の邪魔をしないで、引っ込んでろ」
  • 「業績が悪いのは、だれのせいでもない。お前ら自身の責任だ。お前らがそのような結果を招いたんだ。客が悪い、ウォルマートが悪い、景気が悪い、共和党が悪い、民主党が悪い。いくらでも他人のせいにすればいい。いいか、これだけは言っておく。同じ業界のなかに成功している企業があるならば、そいつらにできることがお前らにできないわけがない」。

歯切れのよい言葉を読んでいても気持ちがいいが、実は単なるパフォーマーに終わらず良いことを言っているのが本文を読むとよくわかる。

現状がぬるま湯ではなく、危機的状態だということを認識させること。そしてそこから抜け出すための覚悟を決めさせること。という辺りの話は三枝匡さんの「V字回復の経営」を思い出した。

「ソースコードが最低なのは、だれのせいでもない。お前ら自身の責任だ。お前らがそのような結果を招いたんだ。Dave Thomas や Kent Beck にできてお前らにできないわけがない。」とか吠えてほしい。

Harvard Business Review (ハーバード・ビジネス・レビュー) 2007年 05月号 [雑誌]

ダイヤモンド社 (2007/04/10)
売り上げランキング: 190
V字回復の経営―2年で会社を変えられますか
三枝 匡
日本経済新聞社 (2006/04)
売り上げランキング: 2450
  

RSSという名前が忘れられる日

by tanabe on April 11, 2007

ちょっと遅いけど、On Off and Beyond のコメント欄からメモ。

RSSを能動的に巡回する人は少数派だとか、今後もRSSリーダー使用者が増えるはずがないとか、よく誤解している人が居ますが。それは一面的な見方で。RSSは能動的ではなく、検索エンジンやツールによって間接的に使われることになると思います。つまりユーザーは意識せずにRSSを使うようになる。そのときは全文配信RSSのほうがSEO的にも有利になるかも 「RSS購読者の何割が本当にブログを読んでいるか」

という otsune さんのコメント。

RSS配信しない企業サイトのニュース、プレスリリースなんてゴミ同然という時代になるわけか。

  

「メールを処理する時間」を一日のスケジュールの中に決める

by tanabe on April 10, 2007

最悪の習慣は、朝一番に電子メールを読むことである。種々雑多なことで頭が乱されてしまう。朝は重要なことに集中し、昼までに一仕事終えるべきだ。
http://d.hatena.ne.jp/himazublog/20070408/1175994799

これに大いに同意。

ぼくも昨年の暮れくらいからメールの扱いを変えた。一日に決めた時間にだけメーラーを開いて読んで返信している。これでメールを読んでいない時間の作業効率(というより、密度)が大きく上がった。

朝からメーラーを開いていると、どうしても仕事の仕方がメールドリブンになる。これは降ってきた仕事を片付けるという形で、仕事の順が到着順になりやすく(順にやらないと返信ができないから)優先順位によるコントロールは効きにくい。一日の終わりに「なんだか一日中忙しく仕事をしていたけど、よく考えると何もしていない」ということが何度かあり、ぼくは仕事のやり方を変えることにした。

メールを貯めて処理する方式は、一度すべてのタスクを見ることができる点がよい。メールとして降ってきた仕事をすべて同じレベルから比べて、実際にどれから手をつけるかは別途その後の仕事の優先順位を整理してから決めればいい。

このやり方に変えてからすぐに気付いたことは、メールの返信の半分以上は必ずしも自分が頭を使って気にする必要のないものだということ。プロセスでもオブジェクトの生成でもいいが、何事も0から動き始めるまでが特にパワーを必要とする。一日に50通メールを受け取るとしたら、多少なりとも自分に関わるメールとしてそれらを随時処理していく労力というのは馬鹿にならない。ましてそれが何の価値も生み出さないならなおさらだろう。

ということで、「メールを処理する時間」を一日のスケジュールの中に取るのはおすすめ。もちろん、それ以外の時間はメーラーを閉じること。

今のところ、これで「本当に困った」と言われたことはない。いずれにせよ急ぎのときは電話が鳴るのだし。

  

構造化プログラミングを徹底するのは文化じゃないか。

by tanabe on April 05, 2007

職場で「あまり関数を作りすぎるとかえってコードが分かりにくくなる(処理が細かくなりすぎて)」みたいな話を聞いて、「それって分かりにくくならないような名前を付ければ良いだけなんじゃ。」と思った。それは関数一つで数百行もあるコードを放置する言い訳にはならないよなぁ。

でも一方で、適切な構造化プログラミングが本当に徹底的にできない人はそれほどいなくて、実は徹底的な構造化プログラミングをすべきだという文化に属している人が少ないだけな気がする。

その証拠にコメントだけを追っかけると、中々悪くない単位でコメントを入れて”きれい”なコードを書いている人はけっこう要るし。あとは文化とちょっとしたやり方だと思う。