Kinx ライブラリ - Getopt

# Kinx ライブラリ - Getopt

## はじめに

**「見た目は JavaScript、頭脳(中身)は Ruby、（安定感は AC/DC）」** でお届けしているスクリプト言語 [Kinx](https://github.com/Kray-G/kinx)。言語はライブラリが命。ということでライブラリの使い方編。 

今回は Getopt です。SpecTest で内部的に実装して使っていたのですが、標準ライブラリのほうに移動させました。

* 参考
    * 最初の動機 ... [スクリプト言語 KINX（ご紹介）](https://qiita.com/Kray-G/items/ca08b6fb40d15dd0ec76)
        * 個別記事へのリンクは全てここに集約してあります。
    * リポジトリ ... [https://github.com/Kray-G/kinx](https://github.com/Kray-G/kinx)
        * Pull Request 等お待ちしております。 

ロングオプションにも対応しました(~~まだリリースしてませんが...~~ リリースしました)。

## Getopt - `System.getopt`

### 使い方

以下のように、while 文の条件式の場所にオプションの配列とオプション文字列、ロングオプション・オブジェクトを指定する。ロングオプション・オブジェクトは省略可能。

```javascript
var opt, add, check;
while (opt = System.getopt($$, "a:df", { add: 'a', delete: 'd', help: null, "do-check": '=' })) {
    switch (opt.type) {
    case 'a':               // '--add' でも 'a' が返る。
        add = opt.arg;      // ':' 指定は引数があることを示す。
        System.println('-a with "%{add}"');
        break;
    case 'd':               // '--delete' でも 'd' が返る。
        System.println('-d');
        break;
    case 'f':               // '-f' で返る。
        System.println('-f');
        break;
    case 'help':            // '--help' で返る。
        System.println('--help');
        break;
    case 'do-check':        // '--do-check' で返る。
        check = opt.arg;    // '=' 指定は引数があることを示す。
        System.println('--do-check with "%{check}"');
        break;
    case '-':               // オプションではなかった場合、ここに来る。
        list.push(opt.arg);
        break;
    }
}

// オプション以外の表示
System.println("Program options: ", list);
```

#### オプション文字列の詳細

* 引数有りを指定した場合、引数を指定しなかった時には ArgumentException 例外が送出される。
* 引数が無いオプションの場合、同じオプション内に次のオプションを指定できる。例えば、`-d -f` は `-df` と書いても良い。
* 引数があるオプションの場合、次に文字が続いていれば引数とみなされる。例えば、`-a ARG` は `-aARG` と書いてよい。
* 上記 2 つを組み合わせると、`-d -a ARG` は `-da ARG` とも `-daARG` とも書くことができる。

#### ロングオプションの詳細

* ロングオプションでオプション文字を指定した場合、引数の有無もオプション文字の指定に従う。
* 引数有りを指定した場合、引数を指定しなかった時には ArgumentException 例外が送出される。
* ロングオプションの場合は `--long-option=argument` の形式で引数を指定する。また、ロングオプションの場合は空文字列の引数が許容される。

### サンプルの実行

先ほどのサンプルを動作させると次のようになる。

```
$ ./kinx examples/option.kx -d -a arg
-d
-a with "arg"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx -da arg
-d
-a with "arg"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx -daarg
-d
-a with "arg"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx --help something
--help
Program options: ["examples/option.kx", "something"]

$ ./kinx examples/option.kx --do-check=
--do-check with ""
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx --do-check=abc
--do-check with "abc"
Program options: ["examples/option.kx"]

$ ./kinx examples/option.kx -a
Uncaught exception: No one catch the exception.
ArgumentException: Needs an argument for -a
Stack Trace Information:
        at <main-block>(examples/option.kx:2)

$ ./kinx examples/option.kx --unknown
Uncaught exception: No one catch the exception.
ArgumentException: Unknown option: --unknown
Stack Trace Information:
        at <main-block>(examples/option.kx:2)
```

## おわりに

オプション解析の方法も色々あって、`getopt` も歴史が古いですが今でも現役ですね。**Most fitting in C programmers** の観点では `getopt` は使いやすいんじゃないかな、と思います。

ヘルプを表示できるという意味では、`boost::program_options` も捨てがたい。まずは最低限のことができるという意味で `System.getopt` のサポートです。今後もっと便利なものが出てくるかもしれない（どこから？）。

ではまた、次回。