nimprettyでNimのソースを綺麗にする


# 概要

nimprettyを使って、Nimのソースを綺麗にしましょう。それ、~~nimbleタスクで~~。

## 追記(2019/10/28)

VSCodeでNim拡張をインストールしている場合ですが、VSコードの設定(settings)で、formatOnSave=Trueにすることで、Nim拡張がNimPrettyを呼び出してソースを綺麗にしてくれるようです。

![Screenshot from 2019-10-28 14-33-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/40abf925-1015-7d21-2bb1-9dd346fd33ee.png)

Nimprettyを実行しているNim拡張の[コード](https://github.com/pragmagic/vscode-nim/blob/master/src/nimFormatting.ts#L22)

## nimprettyってなんぞ？

Nim 0.19.2がリリースされてましたね。リリースノートや、インストール後のbinディレクトリを見ていると、nimprettyというモジュールを見かけました。

@imbsky さんの[記事](https://qiita.com/imbsky/items/9f7a61a143809980b1bf)でnimprettyという単語を初めて見かけ、記事を見たときには「フーン」ぐらいにしか思っていなかったのですが、

「あ、これ、Ｎｉｍのソース綺麗にしてくれるやつだ」

と今更気づき試してみることに。

### windowsだと・・・

windows版だと、*bin*フォルダにnimprettyが入っていなかったので、先の記事と同じくnimフォルダ配下にて、

```shell-session
koch tools
```

と叩くと、binフォルダ配下にnimprettyが出来上がります。

### 早速使ってみる

出来上がったnimpretty を--helpで確認

```shell-session
>nimpretty --help
nimpretty - Nim Pretty Printer Version 0.1
  (c) 2017 Andreas Rumpf
Usage:
  nimpretty [options] file.nim
Options:
  --backup:on|off     create a backup file before overwritting (default: ON)
  --output:file       set the output file (default: overwrite the .nim file)
  --indent:N          set the number of spaces that is used for indentation
  --version           show the version
  --help              show this help
```

--backup:on|off は、バックアップファイルを作るかどうかで、デフォルトはon。
--output:file は、出力先ファイルを変更するため。
--indent:N は、インデントのサイズ

では、さっそくしょうもないnimのソースを作って、nimprettyを試してみます。

```nim:sample.nim
import os,   
   strutils

proc hello_world(        name: string)    :     string = 
    result="hello" &    name
```

```shell-session
nimpretty --indent:2 sample.nim
```


```nim:sample.nim
import os,
   strutils

proc hello_world(name: string): string =
  result = "hello" & name

```

import文の改行はそのままでしたが、余白やコロンの次のスペース、インデントは修正されているのが確認できました。素敵です。

## nimble に pretty タスクを追加する

ファイルを１つ１つnimprettyで指定するのも面倒なので、nimbleファイルに *pretty* タスクを追加してみます。
このタスクは、プロジェクトフォルダ配下の*.nimソースを探してnimprettyを実行します。

nimscript内でwalkDirRecが動かなかったので、util/pretty_files.nimというnimファイルをタスクから実行させます。

```nim:sample.nimble
# util/pretty_files.nimを実行する
task pretty, "ソースの整形" :
  exec "nim c -r --hints:off --verbosity:0 --out:bin/test util/pretty_files"
```

```nim:util/pretty_files.nim
# 再帰的に*.nimを探して、nimprettyの引数にファイル名を渡してフォーマット
import os
import strutils
import osproc

proc pretty_proc(startDir: string) =
  for f in walkDirRec(startDir, yieldFilter = {pcFile}):
    if f.endsWith(".nim"):
      let process = startProcess("nimpretty", startDir, @["--backup:on", f], nil,
          options = {poUsePath, poStdErrToStdOut})
      echo f
      discard process.waitForExit()

when isMainModule:
  let
    cmdArgs = os.commandLineParams()
    target_dir =
      if cmdArgs.len == 1:
        os.expandFilename(cmdArgs[0])
      else:
        os.expandFileName(".")

  echo target_dir
  pretty_proc(target_dir)
else:
  echo "not mainmodule"
```

### prettyタスクの実行

こんな感じで実行します。

```shell-session
>nimble pretty
  Executing task pretty in nimapp_template\nimapp_template.nimble
nimapp_template
nimapp_template\util\get_version.nim
nimapp_template\util\pretty_files.nim
nimapp_template\util\rename_app.nim
nimapp_template\tests\alltest.nim
nimapp_template\tests\test1.nim
nimapp_template\tests\test2.nim
nimapp_template\src\nimapp_template.nim
nimapp_template\src\nimble_config.nim
nimapp_template\src\nimapp_templatepkg\main.nim
nimapp_template\src\nimapp_templatepkg\private\main_impl.nim
```

このタスク実行後は、nim.backupというファイルも大量に生成されます。
これはnimprettyを適用する前のソースが、.backupという拡張子でリネームされています。

## まとめ

nimprettyの使い方を調べてみました。
Nim 0.19.2のリリースノートを見ているとnimprettyのバグフィックスも頻繁に行われているようです。
バグフィックスがたくさん出ていたのでそろそろ枯れてきたのかなと思い、今回試してみようと思いました。

とはいえ、ソースコードが書き換えられるので、不安な方はしっかりユニットテストなどのコード書いて、品質を担保したほうがよいでしょうね。(＞自分)

雑に書いたソースでもnimprettyを使えばそれなりの体裁になるのはかなり魅力的ですね。

### おまけ

拙作のNimのアプリケーションテンプレートにもprettyタスクを追加済みです。

リポジトリ
https://github.com/6in/nimapp_template

テンプレートの使い方
https://github.com/6in/nimapp_template/blob/master/TEMPLATE-README.md