ビット表示スクリプト2

前回スクリプトを実際に使っていたら不満が出てきたので修正。


不満点は実際に使ってみるとビットのシフト計算がどうしても必要になってくる。
けど計算してからスクリプトを使うのは使い勝手が悪い。
そこでevalを使えるように修正。これなら引数に計算式を直接渡しても問題無し。

#!/usr/bin/env ruby

#このArray部分はネットで見つけて使っているもの
#どこのサイトで頂いたかは失念。
class Array
  def sandwich(sep)
    sep + join(sep) + sep
  end

  #asciiのテーブルを作成する
  #print CSV::Reader.parse(File.read("hoge.csv")).to_a.to_ascii_table
  def to_ascii_table
    col_length = self.transpose.map{|cols| cols.map{|col| col.to_s.length}.max}

    rule = col_length.map{|len| '-'*len}.sandwich('+')+"\n"

    self.map{|row|
      row.zip(col_length).map{|col,len| col.ljust(len)}.sandwich('|')+"\n"
    }.sandwich(rule)
  end
end

option = nil
parser = OptionParser.new
parser.banner = "Usage: #{File.basename($0)} [-e] arg {arg}|[-h]"
parser.on("-e", "--eval", "eval"){
  option = :eval
}
begin
  parser.parse!
rescue OptionParser::ParseError => err
  $stderr.puts err.message
  $stderr.puts parser.help
  exit
end

#引数のチェック用
#邪魔なので分けてあるだけ
def check(val)
  if val == 0
    puts "Error!! zero or strings."
    exit
  end

  if val.to_s(2).size > 32
    puts "Error!! value's length is over 32bit."
    exit
  end
end


while val = ARGV.shift
  if option == :eval
    puts val
    val = eval(val)
  end

  val = val.to_s.to_i(0)
  check(val)

  printf("0x%s\n", val.to_s(16))
  printf("0b%s\n", val.to_s(2))

  ary = []
  tmp = ["bit"]
  tmp += Array.new(32){|i|("0"*2+i.to_s)[-2..-1]}.reverse
  ary << tmp

  tmp = ["value"]
  str = "0"*32+val.to_s(2)
  tmp += str.split(//)[-32..-1]
  ary << tmp

  puts ary.to_ascii_table+"\n"
end