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

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

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

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
(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)))))
(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)))))
(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!

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