uncrustify + husky + lint-stagedでObjCコードをコミット時に自動整形する

# はじめに

前回の記事「[Uncrustifyを使ってObjCコードを整形する](https://qiita.com/hituziando/items/2322438112424c2111e2)」ではUncrustifyの基本的な使い方について触れました。

本稿では、**コード整形を自動で実行する仕組みづくり**を目的にしています。具体的には、 `git commit` する際に、gitのステージに上がっているソースファイルに対してコード整形を実行し、整形後のソースファイルがコミットされるようにします。

:::note info
コード整形を自動化することで、常に 改行やインデントなどを定めたルール(コーディング規約)を適用し、ソースコードの品質を保つことができます。
:::

【参考】Swift版は[こちら](https://qiita.com/hituziando/items/c9afa14898008a224866)

https://qiita.com/hituziando/items/c9afa14898008a224866

# 実行環境

macOSのバージョン

```shell
sw_vers
ProductName:		macOS
ProductVersion:		13.1
BuildVersion:		22C65
```

# 自動コード整形環境の構築
## 3つのツール

自動コード整形環境は、以下の3つのツールを組み合わせて構築します。

1. **[uncrustify](https://github.com/uncrustify/uncrustify)** ... コード整形ツール

2. **[husky](https://typicode.github.io/husky/#/)** ... 任意のコマンドを `git commit` 時などに実行するツール

3. **[lint-staged](https://github.com/okonet/lint-staged)** ... 任意のコマンドをgitのステージに上がっているファイルに対して実行するツール

## uncrustifyの設定

「[Uncrustifyを使ってObjCコードを整形する](https://qiita.com/hituziando/items/2322438112424c2111e2)」を参考に `uncrustify` コマンドが使えるようにしてください。
また、コード整形ルールを定義したコンフィグファイルを作成してください。本稿ではuncrustify-objc.cfgというファイル名でプロジェクトのルートディレクトリに保存しています。

## node + npmのインストール

huskyおよびlint-stagedはどちらもnpmで配布されているパッケージです。そのため、まずは `node` と `npm` コマンドをインストールします。既にインストールされている方は読み飛ばしてください。

本稿では、Node.jsのバージョン管理ツール [volta](https://volta.sh/) を使います。

```shell
volta install node@18.14.2
node --version
volta install npm@9.5.1
npm --version
```

## husky + lint-stagedのインストール

:::note warn
これ以降のコマンドはプロジェクトのルートディレクトリで実行してください。
:::

```shell
npm init
```

対話形式でいろいろ入力を求められますが、returnキー連打で構いません。すべて入力するとpackage.jsonが生成されます。package.jsonの不要な項目は削除してしまっても構いません。

```package.json
{
  "name": "your project name",
  "private": true,
  "scripts": {
  }
}
```

huskyとlint-stagedをインストールします。

```shell
npm install -D husky lint-staged
```

## huskyの設定

package.jsonに下記の `"prepare"` を追記します。

```package.json
{
  "name": "your project name",
  "private": true,
  "scripts": {
    "prepare": "npx husky install && npx husky add .husky/pre-commit \"npx --no-install lint-staged\""
  },
  "devDependencies": {
    "husky": "^8.0.3",
    "lint-staged": "^13.1.2"
  }
}
```

以下のコマンドを実行します。

```shell
npm run prepare
```

コマンドが成功すると `.husky` ディレクトリが生成されます。
本稿の設定では、コミット前(pre-commit)に `npx --no-install lint-staged` コマンドが実行されます。

## lint-stagedの設定

package.jsonに下記の `"lint-staged"` を追記します。

```package.json
{
  "name": "your project name",
  "private": true,
  "scripts": {
    "prepare": "npx husky install && npx husky add .husky/pre-commit \"npx --no-install lint-staged\""
  },
  "devDependencies": {
    "husky": "^8.0.3",
    "lint-staged": "^13.1.2"
  },
  "lint-staged": {
    "./**/*.{m,h}": [
      "uncrustify -c uncrustify-objc.cfg --no-backup -l OC"
    ]
  }
}
```

`"./**/*.{m,h}"` はプロジェクトのルートディレクトリ配下にあるすべての.mファイルおよび.hファイルを対象にしています。このパスはあなたのプロジェクトに合わせて調整してください。
gitステージに上げたファイルのうち、このパスの条件に合致するファイルに対して、 `uncrustify` コマンドを実行します。

以上でセットアップは完了です。

ここまでの操作で下記のファイルとディレクトリが生成されているはずです。

```:Your project root directory
- .husky/
- node_modules/
- package-lock.json
- package.json
- uncrustify-objc.cfg
```

# 使い方

gitステージに上げたObjCソースファイルに対して、コミット時にコード整形を自動的に実行します。

```shell
git add [ObjCソースファイル]

git commit -m "コミットメッセージ"
```

コード整形されたソースファイルがコミットに反映されます。


以上でコード整形を自動で実行する仕組みができました。