SMCのステートマシン作業環境【VisualStudio/IntelliJ】

<!-- 
Note　タグの表記ゆれがすごい
StateMachine
状態マシン図
ステートマシン

1. SMCのステートマシン作業環境【VisualStudio/IntelliJ】　←今ココ
2. SMCのC#サンプルコード読んでみた
 3. https://qiita.com/lilacs/items/c204f56c2604ac71f626

-->



# はじめに
状態遷移を記述できるステートマシンは、ゲームキャラの状態遷移やUIの受付状態など、適用範囲が広く便利（らしい）です。SMC（State Map Compiler）を使用すると、状態遷移記述に特化した独自言語を使用して状態遷移を記述してから特定の言語（C#など）での実装を生成できます。Dotファイルも生成できるので、ステートマシン図（画像）も作成できます。
↓の記事に詳しいです。

>要約：知らないと損するアプリ開発におけるStateMachineの活用法
>https://qiita.com/mokemokechicken/items/9a4f7dea5a0fe37bd26f

ステートマシンの記述方法には、プログラムに自作で組み込む方法と、ツール（SMC）を使用する方法が考えられると思います。

- 自作
 - メリット：環境構築不要。
 - いくつかC#実装例を見た中では、↓の実装が簡潔でいい感じでした。
 - https://stackoverflow.com/questions/5923767/simple-state-machine-example-in-c
- SMCを使用
 - メリット：ソースコードとステートマシン図を単一ファイル（独自言語）で一元管理できる
 - 公式サイト：http://smc.sourceforge.net/

SMCが便利そうだったので、IDE（VisualStudioとIntelliJ）でSMCを利用する作業環境を考えてみました。

# 環境

- Windows10 Pro 64bit
- VisualStudio 2015
- IntelliJ Ultimate 2018.1

#SMC概要（コマンドラインからの利用）

## インストール関連

- Java1.7をインストール
 - Smc.jarの実行に必要
 - Java1.8は動作しないようだ（2018/8/22 Smcバージョン6.6.0）
- SMCをインストール
 - ↓からダウンロード、解凍して好きなフォルダに置く
 - https://sourceforge.net/projects/smc/files/
- Graphvizをインストール
 - ↓からダウンロード（私の場合は2.38 Stable Releaseの「graphviz-2.38.zip」@2018/8/14）。
 - https://graphviz.gitlab.io/_pages/Download/Download_windows.html
 - dotファイルをpng画像化するのに必要
 - 余談：dotファイルの編集・コードハイライト・プレビューならVS Codeがオススメ
 - https://qiita.com/lilacs/items/fe8b3223f2a193c0fa2e

## SMC使い方
### smファイルのコンパイル
smファイル（独自言語）のあるフォルダで以下のコマンドを実行します。ソースコードとステートマシン図を同時に出力できないので、オプションを変えて2つのコマンドを実行します。

```terminal:C#ソースコードとグラフ画像生成用Dotファイルを出力するコンパイルコマンド
java -jar （Smc.jarへの絶対パス） -csharp （コンパイル対象のsmファイル）
java -jar （Smc.jarへの絶対パス） -graph test.sm
```

<!--
:（例）java -jar /path/to/smc/bin/Smc.jar -csharp test.sm
-->

### Dot画像出力
Graphvizでdotファイルからpng画像を出力します。

```terminal:png画像出力
dot -Tpng -o test_sm.png test_sm.dot
```


# IDEからSMCを使用する作業環境の作成
　IDEの外部ツール呼び出し機能をつかってSMCコンパイルできるようにします。

## 準備（コンパイル・画像生成bat作成）
以下のコンパイル用batファイルをsmcインストールディレクトリに作成します。

```terminal:smc_cs.bat
:
:ソースコード生成とグラフ生成
:
"（Java1.7インストールディレクトリ）\bin\java.exe" -jar "（SMCインストールディレクトリ）\smc\bin\Smc.jar" -csharp %1
"（Java1.7インストールディレクトリ）\bin\java.exe" -jar "（SMCインストールディレクトリ）\smc\bin\Smc.jar" -graph %1
dot -Tpng -o %~n1_sm.png "%~p1\%~n1_sm.dot"
```

<!--
:（例）"C:\Program Files\Java\jdk1.7.0_80\bin\java.exe" -jar "C:\path\to\smc\bin\Smc.jar" -csharp %1
-->

引数で与えたsmファイルに対して以下のことを実行するバッチファイルです

- smファイルをコンパイルしてc#コードを出力(SMC)
- smファイルをコンパイルしてdotファイルを出力(SMC)
- dotファイルからグラフのpng画像を出力（Graphviz）

※　「java」コマンドではなく、「java1.7のjava.exeへの絶対パス」を記述しているのは、「java」コマンドは、環境変数設定によってはjava1.7以外が起動してしまうことがあるため。（Smc.jarの実行はjava1.8だと失敗する）

## VisualStudio からSMC利用（C#）

### VisualStudio　への設定手順

1. 外部ツールにSMCの設定を追加
 2. Tools > External Tools... > Add ボタン
 3.  下図のように設定する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186338/242d7a58-6454-74fa-0554-f0d9b70720eb.png)

### 使い方（外部ツール呼び出し）

1. Solution Explorerでコンパイルしたいsmファイルを選択
2. 作成した外部ツールを実行
 1. Tools > smc(C#)（作成した設定名）

## IntelliJからSMC利用（java,javascript,pythonなど）
IntelliJにはsmファイル用のコードハイライトプラグインがあるので、それも導入すると便利です。
（ただし、エディタの挙動がバギーな気がする　2018/9/5）

<!--
「External Tool」機能からSmc.jarを呼び出すように設定する
>External Tool　設定の参考
>https://confluence.jetbrains.com/display/PhpStorm/Running+External+Tools+in+PhpStorm
-->

### IntelliJ　への設定手順
1. （任意）コードハイライトのプラグイン「SmcPlugin」をインストール
 1. File > Setting > Plugins > Search In Repositories > SmcPluginを検索 > Install > （IntelliJ再起動）
2. 外部ツールにSMCの設定を追加
 1. File > Settings > Tools > External Tools > ＋アイコンから設定追加
 - 下図のように設定する
 - Argumentsの、ファイル絶対パスを表すマクロ「$FilePath」を「"」で囲んでいるのは、パスに半角スペースが含まれていた場合にうまく動作しないため。

<!--
3. 必要に応じてショートカットキー設定　　　TODO
-->

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186338/3358e39e-4549-1140-aac2-19cc69d6ef86.png)

### 使い方（外部ツール呼び出し）
1. Project ビューでコンパイルしたいsmファイルを選択して、作成した外部ツールを実行
 1. Tools > External Tools > smc(C#)（作成した設定名）

# おまけ
##コンパイル時の言語ごと引数対応

以下公式サイトから抜粋
> SmcManual
> http://smc.sourceforge.net/SmcManual.htm

|Target Language|Command Line Option|Base File Name|File Name Suffix|Complete File Name|
|---|---|---|---|---|
|C|-c|AppClass_sm|.h, .c|AppClass_sm.h |AppClass_sm.c|
|C++|-c++|AppClass_sm|.h, .cpp|AppClass_sm.h|AppClass_sm.cpp|
|C#|-csharp|AppClass_sm|.cs|AppClass_sm.cs|
|Graphviz|-graph|AppClass_sm|.dot|AppClass_sm.dot|
|Groovy|-groovy|AppClassContext|.groovy|AppClassContext.groovy|
|Java|-java, -java7|AppClassContext|.java|AppClassContext.java|
|Lua|-lua|AppClass_sm|.lua|AppClass_sm.lua|
|Objective-C|-objc|AppClass_sm|.h, .m|AppClass_sm.h|AppClass_sm.m|
|Perl|-perl|AppClass_sm|.pm|AppClass_sm.pm|
|Php|-php|AppClass_sm|.php|AppClass_sm.php|
|Python|-python|AppClass_sm|.py|AppClass_sm.py|
|Ruby|-ruby|AppClass_sm|.rb|AppClass_sm.rb|
|Scala|-scala|AppClassContext|.scala|AppClassContext.scala|
|HTML table|-table|AppClass_sm|.html|AppClass_sm.table|
|Tcl|-tcl|AppClass_sm|.tcl|AppClass_sm.tcl|
|Visual BASIC .Net|-vb|AppClass_sm|.vb|AppClass_sm.vb|

## IntelliJのRunからSMC実行する方法
※smファイルを追加するたびに「Run Configuration」を記述する必要があるため、この方法はお蔵入りです。一応、こういう方法もあるということで書いておきます。

1. コードハイライトのプラグイン「SmcPlugin」をインストール
1. JRE1.7（or JDK1.7)をSDKへ追加　2018/8/22
 - やり方：http://d.hatena.ne.jp/absj31/20120801/1344102946
2. Run Configurationに設定追加
 - JAR Application項目に、下図のように設定追加する
 - JREはjava1.7を指定のこと

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186338/bf2f3c6e-b94a-cefe-6c7c-5630e6ee4777.png)


<!--
?　参考ページ

> SMC(The State Machine Compiler)を試す その1Add
> http://d.hatena.ne.jp/newonone/20120324/1332587914

? 例　Unityでステートマシン    TODO
? StateパターンとStateMachineの違い
遷移を定義するか否か（≒特定の状態間の遷移のみを許可するか否か）？要確認

-->