Flutterの"Wrap with..."のjsonを共有（VSCode）

Flutterでコーディングする際に、`⌘ + .`で`wrap with...`のショートカットを表示させるのは定番になっていると思います。
しかし、デフォルトの場合その選択肢は以下のようになっていると思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735195/1d0c46ed-9e8b-d004-767f-05bc80313a64.png" width="350" >

`Wrap with Center`のように選べるウィジェットがあればそれを指定すればいいのですが、ない場合は`Wrap with widget...`を選択して自分でクラス名などを記載していきます。

今回は、`Wrap with widget...`を選択する機会を減らすための設定についてお伝えします。

## チームでプラグインを共有

今回はFlutter Plusというプラグインを用います。
チーム開発をしている方は特にプラグインを共有するようにしておくとスムーズだと思います。
`.vscode/extensions.json`に以下のように設定しましょう

```json
{
    "recommendations": [
        "plugfox.flutter-plus",
    ]
}
```

## ショートカットで出すウィジェットの定義

プラグインの設定になるため、`.vscode/settings.json`に記載していきます

### 基本的な書き方

```js
{
  "flutter-plus.wraps": [
    {
      "name": "Container", // Widget名
      "body": [ // この中に自動でWrapしたいフォーマットを指定
        "Container(",
        "  child: ${widget},", // ${widget}でラップ対象ウィジェットを定義できます
        ")"
      ]
    },
  ]
}
```

## 定番ウィジェット一覧

```json
{
  "flutter-plus.wraps": [
    {
      "name": "Align",
      "body": [
        "Align(",
        "  alignment: Alignment.center,",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "ClipRRect",
      "body": [
        "ClipRRect(",
        "  borderRadius: BorderRadius.circular(16),",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "Container",
      "body": [
        "Container(",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "CustomScrollView",
      "body": [
        "CustomScrollView(",
        "  slivers: [",
        "    ${widget}",
        "  ],",
        ")"
      ]
    },
    {
      "name": "FutureBuilder",
      "body": [
        "FutureBuilder(",
        "  future: ${1:future},",
        "  builder: (context, snapshot) {",
        "    if (snapshot.connectionState == ConnectionState.waiting) {",
        "      return Center(child: CircularProgressIndicator());",
        "    }",
        "    return ${widget};",
        "  },",
        ")"
      ]
    },
    {
      "name": "GestureDetector",
      "body": [
        "GestureDetector(",
        "  onTap: () {",
        "    ${0}",
        "  },",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "InkWell",
      "body": [
        "InkWell(",
        "  onTap: () {",
        "    ${0}",
        "  },",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "IntrinsicHeight",
      "body": [
        "IntrinsicHeight(",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "IntrinsicWidth",
      "body": [
        "IntrinsicWidth(",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "ListView",
      "body": [
        "ListView.builder(",
        "  itemCount: ${1:count},",
        "  itemBuilder: (context, index) {",
        "    return ${widget};",
        "  },",
        ")"
      ]
    },
    {
      "name": "ListView.builder",
      "body": [
        "ListView.builder(",
        "  itemCount: ${1:count},",
        "  itemBuilder: (context, index) {",
        "    return ${widget};",
        "  },",
        ")"
      ]
    },
    {
      "name": "Positioned",
      "body": [
        "Positioned(",
        "  top: 0,",
        "  left: 0,",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "Scaffold",
      "body": [
        "Scaffold(",
        "  body: ${widget},",
        ")"
      ]
    },
    {
      "name": "SingleChildScrollView",
      "body": [
        "SingleChildScrollView(",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "SliverAppBar",
      "body": [
        "SliverAppBar(",
        "  title: Text('${1:title}'),",
        "  pinned: true,",
        "  expandedHeight: 200,",
        "  flexibleSpace: FlexibleSpaceBar(",
        "    background: ${widget},",
        "  ),",
        ")"
      ]
    },
    {
      "name": "SliverFillRemaining",
      "body": [
        "SliverFillRemaining(",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "SliverFillViewport",
      "body": [
        "SliverFillViewport(",
        "  delegate: SliverChildListDelegate([",
        "    ${widget}",
        "  ]),",
        ")"
      ]
    },
    {
      "name": "SliverGrid",
      "body": [
        "SliverGrid(",
        "  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(",
        "    crossAxisCount: 2,",
        "  ),",
        "  delegate: SliverChildListDelegate([",
        "    ${widget}",
        "  ]),",
        ")"
      ]
    },
    {
      "name": "SliverGrid.builder",
      "body": [
        "SliverGrid.builder(",
        "  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(",
        "    crossAxisCount: 2,",
        "  ),",
        "  itemCount: ${1:count},",
        "  itemBuilder: (context, index) {",
        "    return ${widget};",
        "  },",
        ")"
      ]
    },
    {
      "name": "SliverList",
      "body": [
        "SliverList(",
        "  delegate: SliverChildListDelegate([",
        "    ${widget}",
        "  ]),",
        ")"
      ]
    },
    {
      "name": "SliverList.builder",
      "body": [
        "SliverList.builder(",
        "  itemCount: ${1:count},",
        "  itemBuilder: (context, index) {",
        "    return ${widget};",
        "  },",
        ")"
      ]
    },
    {
      "name": "SliverPadding",
      "body": [
        "SliverPadding(",
        "  padding: EdgeInsets.all(16),",
        "  sliver: ${widget},",
        ")"
      ]
    },
    {
      "name": "SliverToBoxAdapter",
      "body": [
        "SliverToBoxAdapter(",
        "  child: ${widget},",
        ")"
      ]
    },
    {
      "name": "Stack",
      "body": [
        "Stack(",
        "alignment: Alignment.center,",
        "  children: [",
        "    ${widget}",
        "  ],",
        ")"
      ]
    },
    {
      "name": "Wrap",
      "body": [
        "Wrap(",
        "  children: [",
        "    ${widget}",
        "  ],",
        ")"
      ]
    }
  ]
}
```

以上です！
意外と設定しておくと便利ですね。

また、ある程度共通パーツが充実したプロジェクトの場合共通ウィジェットを定義しておくことでよりコーディングが楽になると思います！