mcliを使ってクロスプラットフォーム向けCLIツールを開発

Haxeはクロスプラットフォームをターゲットにコードを出力できるので、CLIツールを作るときも１ソースで複数のプラットフォームで動作するツールを作成することが出来ます。

CLIツールを作成するのに[mcli](https://github.com/waneck/mcli)というライブラリがあり、このライブラリを利用することで簡単にCLIツールが作成出来ます。
[mcli](https://github.com/waneck/mcli)はHaxeのコンパイルターゲット全てに対応しているわけではなく、`C#`,`C++`,`Java`,`PHP`,`Python3`,`neko`で動作するCLIツールを作成出来ます。

# インストール

haxelibを利用してインストール出来ます。

```
haxelib install mcli
```

> Haxeでは`C#`,`C++`,`Java`へのコンパイルを行うためには別途`hxcs`,`hxcpp`,`hxjava`といったライブラリをhaxelibからインストールする必要があります。
> 
> （これらのライブラリがインストールされていると、Haxeが出力した`C#`,`C++`,`Java`のコードをそのままコンパイルしてくれる。）

# 使い方

以下にmcliの使い方をサンプルコードを交えて説明します。
サンプルコードのコンパイルには以下のhxmlファイルを利用したものとします。

```hxml
-cp ./
-main Cli
-lib mcli

--each

-python bin/python/cli.py

--next

-php bin/php

--next

-neko bin/neko/cli.n

--next

-java bin/java
```

## 基本

1. CLIツールのベースになるクラスに`mcli.CommandLine`を継承させます。
2. `mcli.Dispatch`クラスに`Sys.args()`を渡してインスタンスを生成します。
3. `dispatch`メソッドにCommandLineを継承したインスタンスオブジェクトを渡して呼び出すことでCLIが起動します。

```hx
import mcli.*;

class Cli extends CommandLine {

    public static function main() {
        new Dispatch( Sys.args() ).dispatch( new Cli() );
    }

    public function new() {
        super();
    }

}
```

## Helpの出力

`CommandLine`クラスを継承したクラスに適当なメソッドを定義し、`showUsage`を呼び出すことでCLIツールのHelpを出力させることが出来ます。

```hx
import mcli.*;

class Cli extends CommandLine {

    public static function main() {
        new Dispatch( Sys.args() ).dispatch( new Cli() );
    }

    public function new() {
        super();
    }

    public function help() {
        Sys.println( showUsage() );
    }

    public function foo() {}

    public function bar(param) {}

}
```

上記のコードを実行すると以下の様に出力されます。

```
$ python3 bin/python/cli.py --help
  --help
  --foo
  --bar <param>
```

### Helpのオプションに説明を出力する

`CommandLine`クラスを継承したクラスに定義したメソッドにDocコメントをつけることで各オプションに説明を出力することが出来ます。


```hx
import mcli.*;

class Cli extends CommandLine {

    public static function main() {
        new Dispatch( Sys.args() ).dispatch( new Cli() );
    }

    public function new() {
        super();
    }

    /**
      show help.
     */
    public function help() {
        Sys.println( showUsage() );
    }

    /**
      foo.
     */
    public function foo() {}

    /**
      bar.
     */
    public function bar(param) {}

}
```

上記のコードを実行すると以下の様に出力されます。

```
$ php bin/php/index.php --help
  --help           show help.
  --foo            foo.
  --bar <param>    bar.
```

### CLIツールの説明を出力する

`CommandLine`クラスを継承したクラスにDocコメントを書くことでCLIツールの説明を出力することが出来ます。

```hx
import mcli.*;

/**
  ==============================
  mcli command line tool sample.
  ==============================
 */
class Cli extends CommandLine {

    public static function main() {
        new Dispatch( Sys.args() ).dispatch( new Cli() );
    }

    public function new() {
        super();
    }

    /**
      show help.
     */
    public function help() {
        Sys.println( showUsage() );
    }

    /**
      foo.
     */
    public function foo() {}

    /**
      bar.
     */
    public function bar(param) {}

}
```

上記のコードを実行すると以下の様に出力されます。

```
$ neko bin/neko/cli.n --help
==============================
mcli command line tool sample.
==============================

  --help           show help.
  --foo            foo.
  --bar <param>    bar.
```

## CLIオプションのアライアスを定義する

`CommandLine`クラスを継承したクラスに定義したメソッドにDocコメント内に`@alias`アノテーションを記述することで、 オプションのaliasを定義することが出来ます。

```hx
import mcli.*;

/**
  ==============================
  mcli command line tool sample.
  ==============================
 */
class Cli extends CommandLine {

    public static function main() {
        new Dispatch( Sys.args() ).dispatch( new Cli() );
    }

    public function new() {
        super();
    }

    /**
      show help.
      @alias h
     */
    public function help() {
        Sys.println( showUsage() );
    }

    /**
      foo.
      @alias f
     */
    public function foo() {}

    /**
      bar.
      @alias b
     */
    public function bar(param) {}

}
```

上記のコードを実行すると以下の様に出力されます。
aliasに定義したオプションでhelpが実行出来ていることが分かります。

```
$ java -jar bin/java/Cli.jar -h
==============================
mcli command line tool sample.
==============================

  -h, --help           show help.
  -f, --foo            foo.
  -b, --bar <param>    bar.
```

# まとめ

mcliを利用すると簡単にCLIツールが作成でき、そのツールは様々な言語で動作させることが出来ます（つまり様々な環境で動作させることが出来る）。

windows、mac、linuxといった利用しているOSがバラバラなチームに提供するCLIツールを作成する場合には、Haxeとmcliといった選択をしてみると幸せになれるかもしれませんね。