What is it, naokirin?

Clojureでコマンドラインオプションを処理してみよう

Clojureコマンドラインのオプションを処理するための便利なマクロがあります。

それがclojure.contrib.command-lineです。

早速ですが使い方を見てみます。

(ns sample.core
  (:use [clojure.contrib.command-line :only (with-command-line)])
  (:use [clojure.contrib.str-utils :only (str-join)]))

(defn -main [& args]
  (with-command-line args
    "print text or reversing text"
    [[print p "print text" nil]
     [rev r "print reversing text" nil]
     [appname? a? "print appname" false]
     remaining]
    (cond
      (appname? (println "sample application"))
      (not (nil? print)) (println print)
      (not (nil? reverse)) (println (str-join "" (reverse rev)))
      :else (println "exec with no option"))))

上記のコードをビルドして"sample.jar"というスタンドアロンjarを作成したとします。

その時にコマンドラインに渡すオプションでどのように動作するか見てみます。

>java -jar sample.jar --print "text"
text

>java -jar sample.jar -p "text"
text

>java -jar sample.jar -r "text"
txet

>java -jar sample.jar -a
"sample application"

>java -jar sample.jar
"exec with no option"

もう少し詳細な部分を見ていきます。
そのためにもう少し重要な部分のみに絞ったコードに書き換えます。

  (with-command-line args
    "説明"
    [[value v "値をもらうオプション" nil]
     [flag? f? "フラグのオプション"]
     remaining]
    (cond
      (not (nil? value)) value)
      flag? "flag"
      :else "")

with-command-lineでは、第1引数にコマンドライン引数を受け取ります。

第2引数でそのコマンドラインオプションの処理の説明を書きます。

第3引数でオプションとその説明、および必要ならばデフォルト値をシーケンスで書きます。

第4引数で、そのオプションに対しての処理を行います。
ここでこの処理を行う際に、第3引数で定義したオプションの名前が使えることになります。

"オプション名?"と書いた時は真偽値になります。
?をつけずにオプション名を書いた時は、直後に受け取った文字列が束縛されます。

実は--helpなどのヘルプのオプションも勝手に作られているので、かなり便利なマクロになっています。