Gaucheでコマンドライン引数を処理する

main 手続きでコマンドライン引数を受け取れることを覚えたので、今度は引数(オプション)を処理するやり方を調べてみた。もちろん、Gauche にも用意されている。

 cf. 9.19 gauche.parseopt – コマンドライン引数の解析 – Gauche ユーザリファレンス

この gauche.parseopt というモジュールは、Perl のコマンドライン処理にヒントを得たものらしい。とにかく例を見ながら書いてみた。

(use gauche.parseopt)

(define greeting
  (lambda (name n morning)
    (let ((message (greeting-massage morning)))
      (let loop ((m n) (l '()))
        (if (= m 0)
            l
            (let ((msg (string-append message ", " name "!")))
              (loop (- m 1) (cons msg l))))))))

(define greeting-massage
  (lambda (morning)
    (if morning
        "Good morning"
        "Hello")))

(define show-help
  (lambda (progname)
    (print (string-append "Usage: gosh " progname " [options] NAME"))
    (print "Options:")
    (print " -m --morning Good morning.")
    (print " -t --times=N N times greeting.")
    (print " -h --help Show this message.")
    (exit)))

(define main
  (lambda (args)
    (let-args (cdr args)
      ((morning "m|morning")
       (times "t|times=i" 1)
       (help "h|help" => (cut show-help (car args)))
       . restargs
      )
      (for-each print (greeting (car restargs) times morning)))))

いろいろ書いているけど、キモは33~38行目の let-args だ。ここで、スクリプトの受け付けるオプションを定義している。基本形は (morning "m|morning")。m が短いオプション名で morning が長いオプション名。-m オプションが指定されると #t に変数 morning が束縛される。
オプションは引数をとることもできる。”t|times=i” という書き方は -t(–times)オプションが整数を引数に取ることを指示している。と同時に、1 とあるのはオプションが指定されなかったときのデフォルト値だ。
-h(–help)オプションはコールバック関数を呼び出す。(cut ...)というのは例をまねただけなのでよくわからない(あとで調べてみよう)けど、これでヘルプを表示する show-help 関数を呼び出せるようだ。
で、オプションとして解析されなかった残りのコマンドライン引数は、restargs に束縛される。

それじゃ、うまく動くか試してみよう。

^o^ > gosh greeting.scm --help
Usage: gosh greeting.scm [options] NAME
Options:
  -m --morning       Good morning.
  -t --times=N       N times greeting.
  -h --help          Show this message.

^o^ > gosh greeting.scm Andy
Hello, Andy!

^o^ > gosh greeting.scm --morning Andy
Good morning, Andy!

^o^ > gosh greeting.scm --morning --times 3 Andy
Good morning, Andy!
Good morning, Andy!
Good morning, Andy!

うまくいったようだ。
もっと詳しくはリファレンスマニュアルで。