VSCodeのターミナル/プロファイルの設定の詳細

## Abstract

VSCodeの利便性を支える要素の一つは間違えなくターミナルではないかと思います。
本記事では最新のターミナルの設定方法を紹介し、その設定の詳細に触れていこうと思います。

## Version

VScode: 1.64.2
April 2021 (version 1.56)の更新以降についての話です。
またWindowsで基本的に記述しています。適宜読み替えてください。

<details><summary>従来の設定方法</summary>
## 従来の設定方法

Version 1.56以前の話です。読み飛ばしても大丈夫です。
VSCodeのアップデート(since 1.56)に伴い、これまでのターミナルの一部設定項目がdeprecatedとなりました。
→ 1.80.0で削除されました！
これまでshellの指定及びその起動オプションは以下のような設定でした。

```settings.json
{
    "terminal.integrated.shell.windows": "C:\\WINDOWS\\system32\\cmd.exe",
    "terminal.integrated.shellArgs.windows": [
        "/k",
        "chcp",
        "65001"
    ]
}
```

※文字コードをutf-8でコマンドプロンプトを起動するという設定です。
アップデートされたVSCodeで見てみると、警告が出ていますね。

> This is deprecated, use `#terminal.integrated.defaultProfile.windows#` instead(2)

ということで、新しい設定に移行していきましょう。

</details>

## プロファイル設定方法

### 結論

`terminal.integrated.defaultProfile.*`, `terminal.integrated.profiles.*`を使って設定します。`*`にはwindows, linux, macのように、お使いのOSが入ります。以下windowsで説明を行いますので、適宜読み替えてください。

ターミナルをprofileという単位で管理するシステムになったようです。profileは
- どのターミナルを使うか
- その起動オプション
- 環境変数の設定

などをまとめたものです。
profileは`terminal.integrated.profiles.windows`に追記していきます。

```jsonc:settings.json
"terminal.integrated.profiles.windows": {
    "名前": {
        "path": "ターミナルやシェルのパス(エイリアス可)",
        // "sourse": "PowerShell" または "Git Bash",  // windows限定。
        "args": [
            // 起動オプション。これまでterminal.integrated.shellArgs.windowsなどで設定したいたもの。
        ],
        "overrideName": true,  // タブに表示される名前に関する設定。trueに設定を推奨。詳しくは後述。
        "env": {
            "環境変数名": "値"
            // "JAVA_HOME": "C:\\Program Files\\Java\\jdk-13.0.1" など
        },
        "icon": "terminal-cmd",  // アイコンID。色々ある。後述。
		"color": "terminal.ansiRed"  // アイコンの色を設定する。後述。
    }
}
```

#### path, sourceについて

公式によると

> A source is available only on Windows and can be used to let VS Code detect the install of either PowerShell or Git Bash. Alternatively, a path pointing directly to the shell executable can be used.

要約すると

- sourceはwindows限定で、インストールされているpowershell, git bashのどちらかを指定できるもの
- pathはシェルのパスを指定するもの。どのOSでも使える
    - 恐らく既定のターミナルでパスが通っていれば、zsh, bashとかでオッケー

windowsでコマンドプロンプトを使いたい場合はpathで指定します。
~~sourceにコマンドプロンプトを選択肢に入れてない辺り、コマンドプロンプトよりもpowershell推しなのでしょう。~~

```jsonc:settings.json
{
   ...
        "path": [
    		"${env:windir}\\Sysnative\\cmd.exe",
    		"${env:windir}\\System32\\cmd.exe"
    	],
    ...
}
```

え？配列？って思うかもしれませんが、設定の説明には(setting.json上でpathの上にポインターを置くとホバーするアレ)

>A single path to a shell executable or an array of paths that will be used as fallbacks when one fails.

と書いてあります。つまりpathは通常文字列ですが、上記のように配列で指定も可能で、その場合上から順番に試して起動に成功したものでターミナルを起動するようです。

##### Git Bash の設定について

(2023/12/01追記)

プロファイルが`"Git Bash"`という名前の場合、**sourceしか参照しない**という挙動があるそうです。 どうやら既定のプロファイルと見做され、pathプロパティを無視するようです。
`"sourse": "Git Bash"`で正常に動作するGit Bashのインストール位置は、12/01現在は下記のようです:
```javascript
// https://github.com/microsoft/vscode/blob/e55863c5c1fc4515bd99e9cd4fb415788000a8b1/src/vs/platform/terminal/node/terminalProfiles.ts#L210C4-L216C94
[
    `${process.env['ProgramW6432']}\\Git\\bin\\bash.exe`,
	`${process.env['ProgramW6432']}\\Git\\usr\\bin\\bash.exe`,
	`${process.env['ProgramFiles']}\\Git\\bin\\bash.exe`,
	`${process.env['ProgramFiles']}\\Git\\usr\\bin\\bash.exe`,
	`${process.env['LocalAppData']}\\Programs\\Git\\bin\\bash.exe`,
	`${process.env['UserProfile']}\\scoop\\apps\\git-with-openssh\\current\\bin\\bash.exe`,
	`${process.env['AllUsersProfile']}\\scoop\\apps\\git-with-openssh\\current\\bin\\bash.exe`
 ]
```

**Gitを上記の場所にインストールしていない場合**は下記の手順が必要になります。
1. プロファイルの名前を Git Bash 以外にする。例: `GitBash`など
1. "path"プロパティにbashのパスを書く

@Akihiro_Nakayama さん、情報提供ありがとうございました。


#### args

`args`では起動オプションを設定することができます。[envについて](#envについて)でも使える特殊変数として、[Variables Reference](https://code.visualstudio.com/docs/editor/variables-reference)で紹介されています。[#Tips](#Tips)参照。

とはいえこの設定、コマンドプロンプトとかならともかく、.bashrcとかを設定できるbashやprofile.ps1を設定できるpowershellなどではあまり使わない気もしますよね。でも私が個人的に愛用している[Pipenv](https://github.com/pypa/pipenv)の仮想環境を自動的にactivateするとかに使えて便利です。powershellでは`-Command`というオプション引数で、起動するときに実行するコマンドを渡すことができます。なので仮想環境に入る`pipenv shell`を渡すと仮想環境に入った状態でシェルを起動してくれます。

```jsonc:settings.json
    ...
		"pipenv": {
			"source": "PowerShell",
			"args": [
				"-Command",
				"pipenv",
				"shell"
			],
			"overrideName": true
		},
    ...
```

↓ 仮想環境に入って起動してくれる。

![1646273542243.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/05f4e42f-0f41-4254-c971-40f7af8f39af.png)

#### overrideNameについて

公式によると

>overrideName: A boolean indicating whether or not to replace the dynamic terminal title that detects what program is running with the static profile name.

つまり： **`true`じゃないと、ターミナルの一覧(tabs)にプロファイル名が反映されない。** 
`false`の場合表示がcmdとかpowershellとか、使っているシェルの名前になるので、何か特別な設定をしているプロファイルなどは特に **`true`にしておく方が良いでしょう。恐らくデフォルト値は`false`なので。**

#### iconについて

選択できるiconはterminalっぽいものに限れば以下のようです。
![terminal-icons.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/798d6ca5-dd06-5755-d100-1c079d84c551.jpeg)
その他、コマンドパレットから`terminal: change icon...`を選択することで、多数のアイコンから選択できるようです。addとかはあくまでアイコンです。画像追加ではないです。
![icons.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/cb683a05-7339-cd77-e5d5-835332d27943.jpeg)
ちなみに[codicon](https://microsoft.github.io/vscode-codicons/dist/codicon.html)に一覧表があります。使いたいアイコンをクリックするとIDがコピーされますので、それを`"icon": "vm"`みたいに設定すればよいです。
独自のアイコンは使えたりするのか・・・調査を進めていきたいです。

#### colorについて

アイコンの色を設定できるようです。文字の色とかではないっぽいです。
[公式](https://code.visualstudio.com/docs/editor/integrated-terminal#_terminal-profiles)では

>`color`: A theme color ID to style the icon

と書いてあるのですが、具体的な一覧のリンクとかは見当たらず。
実際に`setting.json`を開いて設定してみると、2022/03/03現在では`"terminal.ansiBlack", "terminal.ansiRed", "terminal.ansiGreen", "terminal.ansiYellow", "terminal.ansiBlue", "terminal.ansiMagenta", "terminal.ansiCyan", "terminal.ansiWhite"`のいずれかが選べるようです。

ということで選択可能な`color`をすべて表示させてみました。`color`だけ変えたprofileを用意して...

```jsonc:settings.json
{
    "terminal.integrated.profiles.windows": {
        "default-PowerShell": {
            "source": "PowerShell",
            "icon": "terminal-powershell",
            "overrideName": true
        },
        "ansiBlack": {
            "source": "PowerShell",
            "icon": "terminal-powershell",
            "color": "terminal.ansiBlack",
            "overrideName": true
        },
        ...
    },
    ...
}
```

テーマによっても色の見え方が変わりそうなので、lightテーマとdarkテーマ, 個人的に愛用しているdraculaテーマ([Dracula Official](https://marketplace.visualstudio.com/items?itemName=dracula-theme.theme-dracula))で確認してみました。
(左から)順にLight+ (default light), Dark+ (default dark), Dracula soft です。なおいずれも一番上のターミナルが`color`を設定していないprofileです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/83770588-7b3f-1418-7e87-4760c43dbdc7.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/cced7483-a1c7-c9e0-43a1-524404b3d402.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483769/725650e9-d36d-189a-5456-7dbc9235852a.png)

`color`未設定の場合は`"color": "terminal.ansiWhite"`の場合と一緒ではないっぽいですね。
後、Blackはダークテーマだとほぼ見えないので、その辺を考慮して設定したいですね。

:::note
未指定の動作は、`"color": null`という設定っぽいですが、明示的に`"color": null`とすると「その値は選べんよ？」と怒られます。でも動作します。草。
(ソースコード見てないですけど)拡張機能ではsetting.jsonから設定値を取得する時、デフォルトの値を設定していないor存在しない設定値を取得すると`null`を返す仕様なので、「`color`の設定値が`null`ということは、設定がされていない→内部的にデフォルトの動作をする」といったロジックが組まれているのでしょう。
:::


#### envについて

そのターミナル上に限り、環境変数を書き換えたり、消去・追加するようです。
例えば

```jsonc:settings.json
"env": {
    "JAVA_HOME": "C:\\Program Files\\Java\\jdk-13.0.1"
    "PATH": null
}
```

のように記述した場合、そのターミナルを開いてみると

```
C:\root>set JAVA_HOME
JAVA_HOME=C:\Program Files\Java\jdk-13.0.1

C:\root>set PATH
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
```

となり、JAVA_HOMEが上書き/PATHが全く通っていない環境ができます。
※nullはその環境変数の値を削除に相当します。

また全プロファイルに対して適用したい場合は`terminal.integrated.env.windows`を用います。(Linuxは`terminal.integrated.env.linux`)
全く同じ記法で設定することができます。使用タイミングはVSCode使ってる時だけ反映させたい環境変数とか、様々なOSで何か共通の環境変数を持ちたい時でしょうか。

### 既定のターミナルを設定する

`"terminal.integrated.defaultProfile.windows": "名前",`
をsetting.jsonに追記します。ここで`名前`は`"terminal.integrated.profiles.windows"`で作成・設定したprofileの名前のことです。
或いはctrl+shift+pでコマンドパレット→ `terminal: select default profile`
からご自身が最も使うであろうターミナルを選択してください。

**これにて設定終了です。お疲れ様でした。**

以下は私の設定例です。参考になれば幸いです。

```jsonc:settings.json
{
	"terminal.integrated.defaultProfile.windows": "PowerShell",
	"terminal.integrated.profiles.windows": {
		"PowerShell": {
			"path": "pwsh",
			"icon": "terminal-powershell",
			"color": "terminal.ansiCyan"
		},
        // Pipenvの仮想環境に入ってターミナルを起動
		"pipenv": {
			"path": "pwsh",
			"args": [
				"-Command",
				"pipenv",
				"shell"
			],
			"icon": "vm",
			"overrideName": true,
			"color": "terminal.ansiGreen"
		},
		"pipenv in project": {
			// .venvをプロジェクト内に作成する
			"path": "pwsh",
			"args": [
				"-Command",
				"pipenv",
				"shell"
			],
			"icon": "vm",
			"overrideName": true,
			"color": "terminal.ansiGreen",
			"env": {
				"PIPENV_VENV_IN_PROJECT": "true"
			}
		},
		// Git Bash無効
		"Git Bash": null
	},
	"terminal.integrated.defaultProfile.linux": "bash",
	"terminal.integrated.profiles.linux": {
		"bash": {
			"path": "bash",
			"icon": "terminal-bash"
		},
		"Pipenv": {
			"path": "bash",
			"icon": "terminal-bash",
			"args": [
				"-c",
				"pipenv shell"
			]
		},
		"Pipenv in project": {
			"path": "bash",
			"args": [
				"-c",
				"pipenv shell"
			],
			"icon": "vm",
			"overrideName": true,
			"color": "terminal.ansiGreen",
			"env": {
				"PIPENV_VENV_IN_PROJECT": "true"
			}
		}
	},
}
```

## Tips

### 既定のプロファイルを非表示にする

"Git Bash"などの、初めから定義されているプロファイルを非表示にするには、`null`を設定すれば良いみたいです。

```jsonc:settings.json
{
  "terminal.integrated.profiles.windows": {
    "Git Bash": null
  }
}
```

### resolving variables

[公式](https://code.visualstudio.com/docs/editor/integrated-terminal#_terminal-profiles)では

>Tip: Path, args, and env all support resolving variables

という記述があります。適当に解釈すると「`Path`, `args`, `env`といったパス関係の設定の中では、resolving variablesを使えるよ。」という記述です。ここでresolving variablesとは何ぞやというと、`${hoge}`といった形で表される、特殊変数たちのことです。詳細は[Variables Reference](https://code.visualstudio.com/docs/editor/variables-reference)で説明されています。最も基本的な特殊変数は以下の表(公式にも載っている)で、現在のディレクトリが`/home/your-username/your-project`の時の例です。

| 変数                         | 値                                             |
| ---------------------------- | ------------------------------------------------ |
| `${workspaceFolder}`         | /home/your-username/your-project                 |
| `${workspaceFolderBasename}` | your-project                                     |
| `${file}`                    | /home/your-username/your-project/folder/file.ext |
| `${fileWorkspaceFolder}`     | /home/your-username/your-project                 |
| `${relativeFile}`            | folder/file.ext                                  |
| `${relativeFileDirname}`     | folder                                           |
| `${fileBasename}`            | file.ext                                         |
| `${fileBasenameNoExtension}` | file                                             |
| `${fileDirname}`             | /home/your-username/your-project/folder          |
| `${fileExtname}`             | .ext                                             |
| `${lineNumber}`              | line number of the cursor                        |
| `${selectedText}`            | text selected in your code editor                |
| `${execPath}`                | location of Code.exe                             |
| `${pathSeparator}`           | / on macOS or linux, \ on Windows                |

他には、`${env:APPDATA}`などで環境変数も使用することができます。また`${config:editor.fontSize}`などの設定の変数も使えるようです。もっと詳しく知りたい人は[Variables Reference](https://code.visualstudio.com/docs/editor/variables-reference)を読んでください。ユーザーの入力とかも扱えるっぽいことが書いてます。


### デバッグの際のターミナルを設定する

>By default, the task/debug features will use the default profile. To override that, use the terminal.integrated.automationShell.<platform> setting

デバッグする際には、デフォルトで設定したプロファイルを使用します。
しかし何らかの理由で特定のプロファイルに差し替えたい時は`terminal.integrated.automationShell.windows`を使用します。
設定例が以下のように公式では紹介されていました。

```jsonc:settings.json
{
    "terminal.integrated.defaultProfile.osx": "fish",
    // Use a fully POSIX-compatible shell and avoid running a complex ~/.config/fish/config.fish
    // for tasks and debug
    "terminal.integrated.automationShell.osx": "/bin/sh"
}
```

### コマンドの出力結果の行に線を入れる

今フォーカスしているコマンドの出力結果に、線が出るようになる機能です。
地味ですが視認性が向上するので脳死で機能を有効化しましょう。

![terminal-command-guide](https://code.visualstudio.com/assets/docs/terminal/shell-integration/terminal-command-guide.png)


```jsonc:settings.json
{
    "terminal.integrated.shellIntegration.showCommandGuide": true,
}
```

### sticky scroll

2023/11月アップデートで、sticky scrollがターミナルにも実装されました。

![image of the sticky scroll function](https://code.visualstudio.com/assets/updates/1_85/terminal-sticky-scroll.png)
(公式ドキュメントより)

「前打ったコマンドなんだっけ」ということがなくなります。嬉しいですね。
設定は簡単で、setting.jsonに追記するだけです:

```jsonc:settings.json
{
	"terminal.integrated.stickyScroll.enabled": true,
 }
```

将来的には既定で`true`になるようですが、現在は Experimental で提供されているため、`false`が既定です。

### PowerShellの補完表示

PowerShell の補完をターミナル上で有効化できるらしい！

![iamge of pwsh IntelliSense](https://code.visualstudio.com/assets/docs/terminal/shell-integration/pwsh-IntelliSense.png)


```jsonc:settings.json
{
    "terminal.integrated.suggest.enabled": true,
}
```

windows, mac のみとのこと (2024/11/21時点)。現状 Experimental で提供されている模様。

## 参考文献等

公式ドキュメント

https://code.visualstudio.com/docs/terminal/profiles

ターミナル関係だとこっちも必読

https://code.visualstudio.com/docs/terminal/shell-integration

### Git Bash関係

https://qiita.com/kmkkiii/items/fa7c6e4de0e7ce2a4b1e#%E8%AA%BF%E6%9F%BB%E5%AF%BE%E5%BF%9C%E5%86%85%E5%AE%B9

- https://github.com/microsoft/vscode/issues/126023#issuecomment-1224948824
- https://github.com/microsoft/vscode/issues/161219#issuecomment-1445416265