OptionParser底力+ARGFを使ったコマンド作り

前回からの続き。マニュアルがあるのだから、ちゃんと読めばそこにすべてが書かれているのだけど、自分はマニュアルを読むのが苦手。それよりもサンプルコードを実行して、その結果を体感しながら覚える方が好き。自分にとってはそうやって覚えた方が、忘れずに記憶が後々まで残るのだ。

RubyのOptionParserの使い方は、大体分かった。すると便利な機能を知った後では、以前のコードがずいぶん無駄な努力をしているように思えてくる。もっと楽して、もっと使いやすいコマンドに仕上げるのだ。

サンプルコード(悪い例)

  • 以下のコードは、以前作ったコマンドのRubyコードである。
  • Closure Compilerを利用してJavaScriptを圧縮・整形する。
#!/usr/bin/ruby

require 'optparse'
require 'net/http'
require 'uri'

compilation_level_names = Hash.new{|h,k| k}
compilation_level_names.merge!({'1'=>'WHITESPACE_ONLY', '2'=>'SIMPLE_OPTIMIZATIONS', '3'=>'ADVANCED_OPTIMIZATIONS'})
option_hash = {}
OptionParser.new do |opt|
  opt.on('-l','--compilation_level=STR|NUM', 'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)', 
                                             '1               | 2                    | 3                      (Default:1              )') {|v| option_hash[:compilation_level] = compilation_level_names[v]}
  opt.on('--output_format=STR', 'text | xml | json (Default:text)') {|v| option_hash[:output_format] = v }
  opt.on('--pretty_print', 'Add new line and indent for readable code.') {|v| option_hash[:formatting] = 'pretty_print'}
  opt.on('Example:', 
         '    cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print', 
         '    cat FILE_PATH | js-compile.rb -l1 --pretty_print', 
         '    cat FILE_PATH | js-compile.rb --pretty_print', 
         '    js-compile.rb --pretty_print "`cat FILE_PATH`"', 
         'The above commands output same compiled codes.')
  
  opt.parse!(ARGV)
end

url = URI('http://closure-compiler.appspot.com/compile')
input =  URI.decode(ARGV[0] || STDIN.gets(nil))
params = {js_code:input, 
          compilation_level:'WHITESPACE_ONLY',
          output_format:'text',
          output_info:'compiled_code'}
res = Net::HTTP.post_form(url, params.merge(option_hash))
puts res.body
STDERR.puts "", "Before: #{input.length}", "After : #{res.body.length}", "Rate  : #{res.body.length.to_f / input.length.to_f * 100}"
JavaScriptを圧縮・整形するコマンド作り - ザリガニが見ていた...。
  • optparseを使っているのに、その機能を使いこなしていないのだ。
  • もっと楽できるはずなのに、苦労して自前のコードで処理している。

オプション--compilation_level=STR|NUMの処理

現状
  • このオプションで設定したいことは、JavaScriptの圧縮レベルである。
  • Closure Compilerには3つの圧縮レベルがある。
    • WHITESPACE_ONLY
    • SIMPLE_OPTIMIZATIONS
    • ADVANCED_OPTIMIZATIONS
  • --compilation_levelに上記圧縮レベルのどれかを設定したのだ。
  • 圧縮レベルの名称の入力が面倒なので、数値1・2・3でも指定できるようにした。
  • それを実現するため、compilation_level_namesというハッシュを用意している。
...中略...
compilation_level_names = Hash.new{|h,k| k}
compilation_level_names.merge!({'1'=>'WHITESPACE_ONLY', '2'=>'SIMPLE_OPTIMIZATIONS', '3'=>'ADVANCED_OPTIMIZATIONS'})
option_hash = {}
OptionParser.new do |opt|
  opt.on('-l','--compilation_level=STR|NUM', 'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)', 
                                             '1               | 2                    | 3                      (Default:1              )') {|v| option_hash[:compilation_level] = compilation_level_names[v]}
...中略...
  • compilation_level_namesハッシュの動作
    • 1・2・3に対しては、WHITESPACE_ONLY・SIMPLE_OPTIMIZATIONS・ADVANCED_OPTIMIZATIONSを返し、
    • 1・2・3以外に対しては、指定されたキーそのものを値(文字列)として返す。
irb(main):001:0> compilation_level_names = Hash.new{|h,k| k}
=> {}
irb(main):002:0> compilation_level_names.merge!({'1'=>'WHITESPACE_ONLY', '2'=>'SIMPLE_OPTIMIZATIONS', '3'=>'ADVANCED_OPTIMIZATIONS'})
=> {"1"=>"WHITESPACE_ONLY", "2"=>"SIMPLE_OPTIMIZATIONS", "3"=>"ADVANCED_OPTIMIZATIONS"}
irb(main):003:0> compilation_level_names['1']
=> "WHITESPACE_ONLY"
irb(main):004:0> compilation_level_names['WHITESPACE_ONLY']
=> "WHITESPACE_ONLY"
改善
  • 実は、optparseのonメソッドでは、オプション引数の選択肢を与えることが可能である。
    • 配列で渡せば、配列に含まれる文字列を返す。
    • ハッシュで渡せば、キーに対応する値を返す。
  • よって、以下のように書けば、現状の仕様は満たされることになるのだ。
...中略...
option_hash = {}
OptionParser.new do |opt|
  opt.on('-l','--compilation_level=STR|NUM', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'], 
                                             {'1'=>'WHITESPACE_ONLY', '2'=>'SIMPLE_OPTIMIZATIONS', '3'=>'ADVANCED_OPTIMIZATIONS'}, 
                                             'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)', 
                                             '1               | 2                    | 3                      (Default:1              )') {|v| option_hash[:compilation_level] = v}
...中略...
  • と同時に便利な機能が追加される。
    • オプション引数に、配列に含まれる値以外、ハッシュに含まれるキー以外が指定されると、エラーになる。
    • オプション引数は、すべてを入力しなくてもよい。他の選択肢と区別できる必要最小限の入力でOK。
  • よって、WHITESPACE_ONLY・SIMPLE_OPTIMIZATIONS・ADVANCED_OPTIMIZATIONSは、W・S・Aだけの入力でもOKなのだ。
  • ならば、ショートカット用の選択肢1・2・3は不要になる!
...中略...
option_hash = {}
OptionParser.new do |opt|
  opt.on('-l','--compilation_level=STR', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'], 
                                          'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| option_hash[:compilation_level] = v}
...中略...

これでいいのだ!

オプション--output_format=STRの処理

現状
  • 同様に、output_formatにはtext・xmljsonのどれかを指定する。
  • しかし、現状はtext・xmljson以外も指定できてしまう状態である。
  opt.on('--output_format=STR', 'text | xml | json (Default:text)') {|v| option_hash[:output_format] = v }
改善
  • 配列['text', 'xml', 'json']を与えることで、text・xmljsonしか選択できなくなる。(それ以外を指定するとエラーになる)
  • また、他の選択肢と区別できる最小限の入力でOKなので、t・x・jの1文字指定でもOK。
  opt.on('--output_format=STR', ['text', 'xml', 'json'], 'text | xml | json (Default:text)') {|v| option_hash[:output_format] = v}

これでいいのだ!

オプション--no-newlineを追加する

現状
  • Closure Compilerは長いJavaScriptコードを圧縮する時に、所々に改行を追加する。(pritty_printでなくても)
  • それらの改行は、JavaScriptコードを実行する時には不要なので、現状まではパイプで繋いで削除していた。
$ js-compile.rb FILE_PATH | perl -pe 's/\n//g'
改善
  • わざわざPerlワンライナーを使うのなら、改行を削除するオプションを追加してみようと思い立つ。
--[no-]newline
require 'optparse'

option_hash = {}
OptionParser.new do |opt|
  opt.on('--[no-]newline', 'With new line, or without new line.') {|v| option_hash[:newline] = v}
  opt.parse!(ARGV)
end
p option_hash
  • '--[no-]newline'というオプション定義すると、--newlineと--no-newline両方のオプション指定が可能になる。
$ js-compile-test.rb --newline
{:newline=>true}

$ js-compile-test.rb --no-newline
{:newline=>false}
--no-newline
require 'optparse'

option_hash = {}
OptionParser.new do |opt|
  opt.on('--no-newline', 'With new line, or without new line.') {|v| option_hash[:newline] = v}
  opt.parse!(ARGV)
end
p option_hash
  • '--no-newline'というオプション定義すると、--no-newlineのみオプション指定が可能になる。--newlineではエラーになる。
$ js-compile-test.rb --newline
js-compile-test.rb:8:in `block in 
': invalid option: --newline (OptionParser::InvalidOption) from js-compile-test.rb:6:in `new' from js-compile-test.rb:6:in `
' $ js-compile-test.rb --no-newline {:newline=>false}

ARGFの利用

  • 定数ARGFには、配列ARGVに含まれる値をファイルパスとみなして、各ファイルの中身をまとめて受け取る仮想ファイル
    • 定数ARGVには、コマンド引数が収められている配列。
  • もし、ARGVが空っぽなら、ARGFは標準入力を指し示す。
  • よって、ARGFが良きに計らいコマンド引数、あるいは標準入力から受け取ってくれるのだ。
$ echo -e "abc\ndef\nghi" > sample.txt
$ cat sample.txt
abc
def
ghi

$ ruby -e 'puts ARGF.gets(nil)' sample.txt
abc
def
ghi

$ cat sample.txt | ruby -e 'puts ARGF.gets(nil)'
abc
def
ghi
  • よって、現状のコマンド引数、あるいは標準入力から受け取るコードの部分は、もっとシンプルに書き換えられる。
現状
  • コマンド引数は、JavaScriptコードとみなされる。
    • 標準入力も、JavaScriptコードとみなされる。
input =  URI.decode(ARGV[0] || STDIN.gets(nil))
改善

ARGF.gets(nil)とすることで...

  • コマンド引数は、ファイルパスとみなされる。
  • 標準入力は、JavaScriptコードとみなされる。
input =  URI.decode(ARGF.gets(nil))
  • さらに、getsはデフォルトでARGFから読み込むことになっているので、ARGFは省略できる。
input =  URI.decode(gets(nil))
  • コマンド引数の解釈が、JavaScriptコードからファイルパスに変化してしまったが、
  • ファイルパスと解釈する方が、コマンドインターフェースとしては一般的だと思う。
    • こちらの方が処理の幅も広がる。

サンプルコード(改善後)

  • 以上の改善をコードに反映して、サンプルコード(悪い例)は以下のようになった。
#!/usr/bin/ruby

require 'optparse'
require 'net/http'
require 'uri'

# デフォルト設定
params = {compilation_level:'WHITESPACE_ONLY',
          output_format:'text',
          output_info:'compiled_code'}
option_hash = {newline:true}

# オプション解析
OptionParser.new do |opt|
  opt.banner = 'Usage: js-compile.rb [options] [FILE_PATH]'
  opt.separator('')
  opt.on('-l','--compilation_level=STR', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'], 
                                          'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| params[:compilation_level] = v}
  opt.on('--output_format=STR', ['text', 'xml', 'json'], 'text | xml | json (Default:text)') {|v| params[:output_format] = v}
  opt.on('--pretty_print', 'Add new line and indent for readable code.') {|v| params[:formatting] = 'pretty_print'}
  opt.on('--[no-]newline', 'With new line, or without new line.(Default:--newline)') {|v| option_hash[:newline] = v}
  opt.separator('')
  opt.on('Example:', 
         '    cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print', 
         '    cat FILE_PATH | js-compile.rb -lW --pretty_print', 
         '    cat FILE_PATH | js-compile.rb --pretty_print', 
         '    # The above commands output same compiled codes.', 
         '', 
         '    js-compile.rb FILE_PATH          # Argument receive file path.', 
         '    cat FILE_PATH | js-compile.rb    # STDIN receive JavaScript code.')
  
  opt.parse!(ARGV)
end
input = params[:js_code] = URI.decode(gets(nil))

# コンパイル
url = URI('http://closure-compiler.appspot.com/compile')
res = Net::HTTP.post_form(url, params)
output = option_hash[:newline] ? res.body : res.body.gsub(/\n/, '')

# 出力
puts output
STDERR.puts "", "Before: #{input.length} Byte", "After : #{output.length} Byte", "Rate  : #{output.length * 100 / input.length}%"
  • ヘルプオプション-hあるいは--helpを指定すると、以下のように出力される。
$ js-compile.rb -h
Usage: js-compile.rb [options] [FILE_PATH]

    -l, --compilation_level=STR      WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)
        --output_format=STR          text | xml | json (Default:text)
        --pretty_print               Add new line and indent for readable code.
        --[no-]newline               With new line, or without new line.(Default:--newline)

Example:
    cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print
    cat FILE_PATH | js-compile.rb -lW --pretty_print
    cat FILE_PATH | js-compile.rb --pretty_print
    # The above commands output same compiled codes.

    js-compile.rb FILE_PATH          # Argument receive file path.
    cat FILE_PATH | js-compile.rb    # STDIN receive JavaScript code.

完成!


複数ファイル対応

  • コマンド引数に複数のファイルパスを指定できるようにしてみた。
  • 複数ファイルを一つのJavaScriptコードにまとめる仕様である。
#!/usr/bin/ruby

require 'optparse'
require 'net/http'
require 'uri'

# デフォルト設定
params = {compilation_level:'WHITESPACE_ONLY',
          output_format:'text',
          output_info:'compiled_code'}
option_hash = {newline:true}

# オプション解析
OptionParser.new do |opt|
  opt.banner = 'Usage: js-compile.rb [options] [FILE_PATH...]'
  opt.separator('')
  opt.on('-l','--compilation_level=STR', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'], 
                                          'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| params[:compilation_level] = v}
  opt.on('--output_format=STR', ['text', 'xml', 'json'], 'text | xml | json (Default:text)') {|v| params[:output_format] = v}
  opt.on('--pretty_print', 'Add new line and indent for readable code.') {|v| params[:formatting] = 'pretty_print'}
  opt.on('--[no-]newline', 'With new line, or without new line.(Default:--newline)') {|v| option_hash[:newline] = v}
  opt.separator('')
  opt.on('Example:', 
         '    cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print', 
         '    cat FILE_PATH | js-compile.rb -lW --pretty_print', 
         '    cat FILE_PATH | js-compile.rb --pretty_print', 
         '    # The above commands output same compiled codes.', 
         '', 
         '    js-compile.rb FILE_PATH          # Argument receive file path.', 
         '    cat FILE_PATH | js-compile.rb    # STDIN receive JavaScript code.')
  
  opt.parse!(ARGV)
end

while gets(nil)
  input = params[:js_code] = URI.decode($_)
  
  # コンパイル
  url = URI('http://closure-compiler.appspot.com/compile')
  res = Net::HTTP.post_form(url, params)
  output = option_hash[:newline] ? res.body : res.body.gsub(/\n/, '')

  # 出力
  print output
  STDERR.puts "", "Before: #{input.length} Byte", "After : #{output.length} Byte", "Rate  : #{output.length * 100 / input.length}%"
end
  • 差分


$ colordiff -u <(pbpaste) /usr/local/bin/js-compile.rb
--- /dev/fd/63 2014-08-21 11:43:46.000000000 +0900
+++ /usr/local/bin/js-compile.rb 2014-08-21 11:42:13.000000000 +0900
@@ -12,7 +12,7 @@

# オプション解析
OptionParser.new do |opt|
- opt.banner = 'Usage: js-compile.rb [options] [FILE_PATH]'
+ opt.banner = 'Usage: js-compile.rb [options] [FILE_PATH...]'
opt.separator('')
opt.on('-l','--compilation_level=STR', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'],
'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| params[:compilation_level] = v}
@@ -31,13 +31,15 @@

opt.parse!(ARGV)
end
-input = params[:js_code] = URI.decode(gets(nil))

+while gets(nil)
+input = params[:js_code] = URI.decode($_)

# コンパイル
url = URI('http://closure-compiler.appspot.com/compile')
res = Net::HTTP.post_form(url, params)
output = option_hash[:newline] ? res.body : res.body.gsub(/\n/, '')

# 出力
-puts output
+print output
STDERR.puts "", "Before: #{input.length} Byte", "After : #{output.length} Byte", "Rate : #{output.length * 100 / input.length}%"
+end


--no-newline不要

  • よく考えたら、pretty_print以外は余分な改行は不要な訳なので、
  • pretty_printの有無によって、改行の出力をコントロールすればいい。
#!/usr/bin/ruby

require 'optparse'
require 'net/http'
require 'uri'

# デフォルト設定
params = {compilation_level:'WHITESPACE_ONLY',
          output_format:'text',
          output_info:'compiled_code'}

# オプション解析
OptionParser.new do |opt|
  opt.banner = 'Usage: js-compile.rb [options] [FILE_PATH...]'
  opt.separator('')
  opt.on('-l','--compilation_level=STR', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'], 
                                          'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| params[:compilation_level] = v}
  opt.on('--output_format=STR', ['text', 'xml', 'json'], 'text | xml | json (Default:text)') {|v| params[:output_format] = v}
  opt.on('--pretty_print', 'Add new line and indent for readable code.') {|v| params[:formatting] = 'pretty_print'}
  opt.separator('')
  opt.on('Example:', 
         '    cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print', 
         '    cat FILE_PATH | js-compile.rb -lW --pretty_print', 
         '    cat FILE_PATH | js-compile.rb --pretty_print', 
         '    # The above commands output same compiled codes.', 
         '', 
         '    js-compile.rb FILE_PATH          # Argument receive file path.', 
         '    cat FILE_PATH | js-compile.rb    # STDIN receive JavaScript code.')
  
  opt.parse!(ARGV)
end

while gets(nil)
  input = params[:js_code] = URI.decode($_)
  
  # コンパイル
  url = URI('http://closure-compiler.appspot.com/compile')
  res = Net::HTTP.post_form(url, params)
  output = params[:formatting] == 'pretty_print' ? res.body : res.body.gsub(/\n/, '')

  # 出力
  print output
  STDERR.puts "", "Before: #{input.length} Byte", "After : #{output.length} Byte", "Rate  : #{output.length * 100 / input.length}%"
end
  • 差分


$ colordiff -u <(pbpaste) /usr/local/bin/js-compile.rb
--- /dev/fd/63 2014-08-22 08:51:53.000000000 +0900
+++ /usr/local/bin/js-compile.rb 2014-08-22 08:48:33.000000000 +0900
@@ -8,7 +8,6 @@
params = {compilation_level:'WHITESPACE_ONLY',
output_format:'text',
output_info:'compiled_code'}
-option_hash = {newline:true}

# オプション解析
OptionParser.new do |opt|
@@ -18,7 +17,6 @@
'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| params[:compilation_level] = v}
opt.on('--output_format=STR', ['text', 'xml', 'json'], 'text | xml | json (Default:text)') {|v| params[:output_format] = v}
opt.on('--pretty_print', 'Add new line and indent for readable code.') {|v| params[:formatting] = 'pretty_print'}
- opt.on('--[no-]newline', 'With new line, or without new line.(Default:--newline)') {|v| option_hash[:newline] = v}
opt.separator('')
opt.on('Example:',
' cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print',
@@ -38,7 +36,7 @@
# コンパイル
url = URI('http://closure-compiler.appspot.com/compile')
res = Net::HTTP.post_form(url, params)
- output = option_hash[:newline] ? res.body : res.body.gsub(/\n/, '')
+ output = params[:formatting] == 'pretty_print' ? res.body : res.body.gsub(/\n/, '')

# 出力
print output


エラー処理追加

  • オプションエラー発生時に、トレース表示しないように修正した。
#!/usr/bin/ruby

require 'optparse'
require 'net/http'
require 'uri'

# デフォルト設定
params = {compilation_level:'WHITESPACE_ONLY',
          output_format:'text',
          output_info:'compiled_code'}

# オプション解析
OptionParser.new do |opt|
  opt.banner = 'Usage: js-compile.rb [options] [FILE_PATH...]'
  opt.separator('')
  opt.on('-l','--compilation_level=STR', ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'], 
                                          'WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS (Default:WHITESPACE_ONLY)') {|v| params[:compilation_level] = v}
  opt.on('--output_format=STR', ['text', 'xml', 'json'], 'text | xml | json (Default:text)') {|v| params[:output_format] = v}
  opt.on('--pretty_print', 'Add new line and indent for readable code.') {|v| params[:formatting] = 'pretty_print'}
  opt.separator('')
  opt.on('Example:', 
         '    cat FILE_PATH | js-compile.rb --compilation_level=WHITESPACE_ONLY --pretty_print', 
         '    cat FILE_PATH | js-compile.rb -lW --pretty_print', 
         '    cat FILE_PATH | js-compile.rb --pretty_print', 
         '    # The above commands output same compiled codes.', 
         '', 
         '    js-compile.rb FILE_PATH          # Argument receive file path.', 
         '    cat FILE_PATH | js-compile.rb    # STDIN receive JavaScript code.')
  
  begin
    opt.parse!(ARGV)
  rescue => e
    puts e
    exit
  end
end

while gets(nil)
  input = params[:js_code] = URI.decode($_)
  
  # コンパイル
  url = URI('http://closure-compiler.appspot.com/compile')
  res = Net::HTTP.post_form(url, params)
  output = params[:formatting] == 'pretty_print' ? res.body : res.body.gsub(/\n/, '')

  # 出力
  print output
  STDERR.puts "", "Before: #{input.length} Byte", "After : #{output.length} Byte", "Rate  : #{output.length * 100 / input.length}%"
end
  • 差分


$ colordiff -u <(pbpaste) /usr/local/bin/js-compile.rb
--- /dev/fd/63 2014-08-29 10:06:09.000000000 +0900
+++ /usr/local/bin/js-compile.rb 2014-08-29 10:01:14.000000000 +0900
@@ -27,7 +27,12 @@
' js-compile.rb FILE_PATH # Argument receive file path.',
' cat FILE_PATH | js-compile.rb # STDIN receive JavaScript code.')

- opt.parse!(ARGV)
+ begin
+ opt.parse!(ARGV)
+ rescue => e
+ puts e
+ exit
+ end
end

while gets(nil)