Visual Studio Code 15.1の統合シェルをMSYS2のbashにする

# 追記

この記事の内容は古くなっています。

https://qiita.com/chirimen/items/04e2e10c86c9ecd1e158

を参照してください。

ただしVS Code 1.60.0ではバグがあるようです

https://teratail.com/questions/357860

# 対象とするVSCodeのバージョン

15.1 or later

# 先行研究

まずもって、この話をググると、msys2のgitを使う話が混ざってきて、それだけでもggrbility(検索可能性)がない。

まあまず引っかかるのは

Visual Studio CodeのIntegrated Terminalでmsys2のzshを使う - 備忘録β版
http://yami-beta.hateblo.jp/entry/2016/06/08/000000

だろう。

すると

>mattnさんによる実行モジュールがあるようなので、そちらを用いると良さそうです。（コメント欄参照）
>[Visual Studio Code で msys2 の bash を使う方法 · GitHub](https://gist.github.com/mattn/000735084394601b225a861af4afd35e)

とか言われて、見に行くと

>go で bash-login.go をビルドした後、出来上がった exe を以下の様に指定する。

え、goでビルド・・・？って思いがあふれる。一回作ればいいって言ったってだるいものはだるい。

他に情報がないかと思って見ていると

Visual Studio Codeの統合シェルをMSYS2のBashにしたら.bash_profileが読み込まれなかった - Qiita
http://qiita.com/catfist/items/ea925fb9e0ba5c0ba9f3

というのが見つかるが、

>ワークスペースを作業ディレクトリとして開いてくれない

とか言っている。しかもその解決のためにVSCodeの拡張を使うとかいう暴挙に出ている。ゼッテー嫌だ。

# Visual Studio Codeの統合シェルをMSYS2のbashにするには

```json:setting.json
{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
    "terminal.integrated.env.windows": {
        "MSYSTEM": "MINGW64",
        "CHERE_INVOKING": "1"
    },
    "terminal.integrated.shellArgs.windows": [
        "--login"
    ],
    "terminal.integrated.cursorStyle": "line"
}
```

を設定に書けば良い。`terminal.integrated.cursorStyle`は好みで。

# 解説
## `terminal.integrated.shell.windows`

bashへのフルパスを指定する。このときmsys2のbashではないなにか(ex. git-bashのbash)を指定してはだめだ。

## `terminal.integrated.env.windows`

環境変数を設定できる。

### `MSYSTEM`

msys2ユーザーならご存知と思うが、`$PATH`が3種類(`/usr/bin`, `/mingw32/bin`,  `/mingw64/bin`)あるのに対応していて、`MSYS`, `MINGW32`, `MINGW64`がある。

`MSYS`はmsys2のパッケージを作るときとか以外はお世話にならない(わけでもない

`MINGW32`はgccの例外モデルがBorlandの特許の関係でSEHではなくdwarfなi686向けの環境である。

`MINGW64`はおそらくもっともよく使う環境だ。

### `CHERE_INVOKING`

bashにログイン時に**作業ディレクトリ**を環境変数`$HOME`のパスにするかを決めるフラグで、`1`に設定すると移動を阻止します。

Visual Studio Codeの統合シェルをMSYS2のBashにしたら.bash_profileが読み込まれなかった - Qiita
http://qiita.com/catfist/items/ea925fb9e0ba5c0ba9f3
で**ワークスペースを作業ディレクトリとして開いてくれないとか言っていたのはこれを設定していないせいだ**。@catfist さんみたいに、わざわざ[VSCodeの拡張](https://marketplace.visualstudio.com/items?itemName=Tyriar.vscode-terminal-here)を使う必要はない。

まあ`msys2_shell.cmd`の中身が奇っ怪すぎるのでわからなくても仕方ない感はある。

参考リンク:

- [Cygwin導入＆ある程度日本語化（Cygwin-JE未使用）｜mizuk6nの【公開備忘録】](https://ameblo.jp/mizuk6n/theme-10002628249.html)

### `MSYS` (opt)

```json
{
    "terminal.integrated.env.windows": {
        "MSYS": "winsymlinks:nativestrict",
    },
}
```

のように、`winsymlinks:nativestrict`を指定するとシンボリックリンクが`.lnk`ファイルじゃなくて本物のシンボリックリンクになる。

### `MSYS2_PATH_TYPE` (opt)

`MSYS2_PATH_TYPE`は環境変数`PATH`をどうするか決めるものだ。

`/etc/profile`を覗くと

```bash
MSYS2_PATH="/usr/local/bin:/usr/bin:/bin"
MANPATH='/usr/local/man:/usr/share/man:/usr/man:/share/man'
INFOPATH='/usr/local/info:/usr/share/info:/usr/info:/share/info'

case "${MSYS2_PATH_TYPE:-minimal}" in
  strict)
    # Do not inherit any path configuration, and allow for full customization
    # of external path. This is supposed to be used in special cases such as
    # debugging without need to change this file, but not daily usage.
    unset ORIGINAL_PATH
    ;;
  inherit)
    # Inherit previous path. Note that this will make all of the Windows path
    # available in current shell, with possible interference in project builds.
    ORIGINAL_PATH="${ORIGINAL_PATH:-${PATH}}"
    ;;
  *)
    # Do not inherit any path configuration but configure a default Windows path
    # suitable for normal usage with minimal external interference.
    WIN_ROOT="$(PATH=${MSYS2_PATH} exec cygpath -Wu)"
    ORIGINAL_PATH="${WIN_ROOT}/System32:${WIN_ROOT}:${WIN_ROOT}/System32/Wbem:${WIN_ROOT}/System32/WindowsPowerShell/v1.0/"
esac
```

のように書かれている。通常は指定しなくていいが、`strict`モードと`inherit`モードがあることくらい頭に入れておいてもいいかもしれない。

## `terminal.integrated.shellArgs.windows`

`--login`を渡している。`-l`でも同じだ。

ここでbashのmanを読んでみよう。

```man
BASH(1)                                                      General Commands Manual                                                     BASH(1)

NAME
       bash - GNU Bourne-Again SHell
OPTIONS
       -l        Make bash act as if it had been invoked as a login shell (see INVOCATION below).

       --login
              Equivalent to -l.

       --noprofile
              Do  not  read  either  the  system-wide  startup  file  /etc/profile  or any of the personal initialization files ~/.bash_profile,
              ~/.bash_login, or ~/.profile.  By default, bash reads these files when it is invoked as a login shell (see INVOCATION below).
```

まあ`see INVOCATION below`とか言っているが自分で読んでくれ。要約すると、`-l`または`--login`をつけないと`~/.bash_profile`は読み込まないぞ、となる。

詳しくはログインシェルとインタラクティブシェルのお話なので

- [ログインシェルとインタラクティブシェルと~/.bashrc達の関係 - Qiita](http://qiita.com/incep/items/7e5760de0c2c748296aa)
- [bashのログインシェルとインタラクティブシェル | kanonjiのブログ](http://kanonji.info/blog/2013/06/20/bash%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%A8%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96%E3%82%B7%E3%82%A7%E3%83%AB/)

を参照のこと。

## `terminal.integrated.cursorStyle` (opt)

**なくても動く**

ターミナルのカーソルの形状を選べる。規定は`"block"`だ。私は線状のほうが好きなので`"line"`にした。

# 最後に

![image.png](https://qiita-image-store.s3.amazonaws.com/0/94177/46ef93e1-d3cc-c6d9-8ee0-f3f440b4eaa6.png)


やったぜ。

# 追記: ビルドタスクを使うときの注意

ビルドタスクをふつうの設定で動かそうとすると、パス区切り文字の問題から動きません。そこで`tasks.json`の構成ごとに

```json
            "windows": {
                "options": {
                    "shell": {
                        "executable": "cmd.exe",
                        "args": ["/d", "/c"]
                    }
                },
            }
```

のような内容を追記することで、タスクを動かすときだけシェルを切り替えられ、うまくいきます。

https://github.com/microsoft/vscode/issues/35593#issuecomment-488728912

ちなみに`lanch.json`、つまりデバッグ実行の方はなんかうまく行った試しがありません。