SublimeText3をPowershellスクリプトと組み合わせてなんでも一発コンパイルできるようにした(い)

###はじめに
　はじめまして、麻菜結(あさなゆい)と申します。私はSublimeTextが好きです。正直日本人にとって若干取りつきにくいと思われる(日本語文献が他の主要エディタに比べ少ない、shift-jisへの対応など)仕様も手がかかる子供のように好きです。皆さんも可愛い子供のようにこのエディタを育ててみましょう。

###環境
OS: Windows10
Sublime_Text3 Version: 3.2.1
Powershell Version: 5.1.18362.145
使いたい言語の環境変数は通してある状態

###概要
1. SublimeのBuildSystemからPowershellスクリプトを呼び出し、そこにコンパイルしたいファイルのフルパスを渡す。
2. 渡されたパスからファイルネームと拡張子を取り出し、拡張子を条件としてコンパイルを選ぶ。
3. コンパイルに成功した場合はコンパイルを完了した旨を、失敗した場合はエラーメッセージを表示する。

###Sublime_Text3のBuildSystem
Tools > Build System > New Build System…

```sublime-build:CompileAll.sublime-bulid
{
    "cmd": ["powershell","-File","C:\\{あなたがPSスクリプトを置いている場所}\\CompileAllLang.ps1","$file"],
    "shell":true,
    "encoding": "cp65001"
}
```
これを見てもらえばわかると思いますが、cmdからPowershellを呼び出す形になります。
~~あと utf-8 を明示していますが、適宜削ってください。~~ Windows10の環境で行うとSublimeのコンソール画面はshift-jisで出力されてるっぽいので`"encoding": "cp932"`の方が文字化けしないかもしれません。後述のjavaの場合でもこうすれば文字化けにはなりませんでした。(2019/10/17追記)

###PSスクリプトのテンプレート
以下のテンプレートの条件文の部分を編集して使用してください。

```Powershell:CompileAllLang.ps1
#引数(ファイルのフルパス)を受け取り、そこから拡張子($ext)とファイル名($file)を取り出しています。
#任意でファイルのフルパスを表示(echo $one)すると便利かもしれません。
Param([string] $one)
echo $one
$ext = [System.IO.Path]::GetExtension($one)
$file = [System.IO.Path]::GetFileNameWithoutExtension($one)

#下の条件文から呼び出され、コンパイル成功時には引数の$msgを表示します。
function Print-Message($msg){
	if($lastexitcode -eq 0){
		echo Finished
		echo $msg
	}
}

if($ext -eq ".xxx"){                 #拡張子を判定
    {Compile} $one                   #コンパイラを呼び出す
    Print-Message("PS> ./${file}")   #成功したときのメッセージを指定する。(実行の仕方とか)
}elseif($ext -eq ".yyy"){
    {Compile} $one
    Print-Message("PS> run ${file}")
}else{                               #もし該当の拡張子が無かった時、Sublimeでこのスクリプトを開く
    cd "C:\Program Files\Sublime Text 3"
    sublime_text.exe "C:\\{あなたがPSスクリプトを置いている場所}\\CompileAllLang.ps1"
}
```

###具体例
　C言語のようにコンパイル→実行のような流れの言語はこの方法に違和感なく適合します。

```Powershell:C言語
if($ext -eq ".c"){
    gcc $one -o $file
    Print-Message("PS> ./${file}")
}
```
　これはkotlinの例です。

```Powershell:kotlin
if($ext -eq ".kt"){
    kotlinc $one -include-runtime -d ($file + ".jar")
    Print-Message("PS> java -jar ${file}.jar")
}
```
　コンパイルの必要ない言語の場合は、実行オプションを確認しましょう。
　たとえばPythonでは `-m compileall`というオプションを使って実行せずコンパイルのみを行います。このオプションは .pyc という拡張子のファイルを生成します。この例では削除していますが、気にならない場合は削除する必要はありません。


```Powershell:Python
if($ext -eq ".py"){
    py -m compileall "${file}.py"
    if ($lastexitcode -eq 0){
        Remove-Item "C:\{コンパイルを実行したディレクトリ}\__pycache__\${file}.cpython-37.pyc"
        Print-Message("PS> py ${file}.py")
    }
}
```
　環境変数を設定していない場合でも .exe に対してなら直接実行することができます。
　これはWindowsに付属しているC＃コンパイラです。

```Powershell:C#
if ($ext -eq ".cs"){
    C:\Windows\Microsoft.NET\Framework\{バージョン番号}\csc.exe $one
    Print-Message("PS> ./${file}")
}
```

　さてJavaなのですが、自分の環境ではいろいろいじってみてもコンパイルエラーのメッセージの日本語の部分が文字化けしてしまいました… 上のC言語のようにできれば幸運ですが、同じ症状の方は下のように書いてみるのを試してみてください
詳細な説明は省きますが、cmdの`/c`オプションで引数をコマンドとして実行しています。
`javac -J-Duser.language=en`でコンパイルメッセージを英語にします。このオプションがPowershell上だとエラーがでたのでcmdでコンパイルしています。Powershell上でも javacの`-J`オプションを実行する方法募集中。

```Powershell:Java
if($ext -eq ".java"){
    cmd.exe /c "javac -J-Duser.language=en ${one}"
    Print-Message("PS> java ${file}")
}
```
　指定のない拡張子で実行するとこのスクリプトがテキストとして開かれてしまうので、開きたくない場合はテンプレートの else 節を削除するか、以下のように拡張子を明示してエスケープしてください。

```Powershell
if($ext -eq ".txt"){
	echo "このファイルはコンパイルしません"
}
```

###おわりに
　ここまで記事を読んでくださってありがとうございます。初めての記事なので読みずらい部分があったら申し訳ありません。賢い皆様ならお気づきかもしれませんが、これはぶっちゃけSublimeText3じゃなくても使える汎用スクリプトです。要はエディターショートカットからPowershellスクリプトを呼び出してそこにファイルのフルパスを渡せる機能があるならなんでも使えるはずです。Sublimeへの愛が足りない？いやいや道具は使いやすく加工するものです。
　お困りのあなたにこの情報が共有されることを願ってこの辺で筆をおきます。次回は何をしようかな。