背景
カーソル行や選択範囲をショートカットキー一発でターミナル実行するVSCodeマクロを作る際、実行のたびに新しいターミナルを作成すると、作業ディレクトリや環境変数がリセットされてしまい不便でした。既存ターミナルの再利用ロジックを紹介します。
1. ターミナル名で既存インスタンスを検索する
function getOrCreateTerminal(terminalType: TerminalType): vscode.Terminal {
const terminalName = getTerminalName(terminalType);
const existingTerminal = vscode.window.terminals.find(
t => t.name === terminalName
);
if (existingTerminal) {
return existingTerminal;
}
return createTerminal(terminalType);
}
vscode.window.terminalsはVSCode上に現在存在する全ターミナルの配列です。固定の名前(My Macros - CMD等)で検索し、見つかればそれを再利用、なければ新規作成します。ユーザーが手動でターミナルを閉じていた場合は自動的に新規作成側に分岐するため、特別なエラーハンドリングは不要です。
2. Git Bashのパスは3段階の優先順位で解決する
function resolveGitBashPath(): string {
const fs = require('fs');
// 1. VSCode設定から取得
const configPath = vscode.workspace.getConfiguration('myMacros').get<string>('gitBashPath', '');
if (configPath && fs.existsSync(configPath)) {
return configPath;
}
// 2. 既定パス(Program Files)
const defaultPath = 'C:\\Program Files\\Git\\bin\\bash.exe';
if (fs.existsSync(defaultPath)) {
return defaultPath;
}
// 3. 代替パス(Program Files (x86))
const altPath = 'C:\\Program Files (x86)\\Git\\bin\\bash.exe';
if (fs.existsSync(altPath)) {
return altPath;
}
return configPath || defaultPath;
}
Git for Windowsのインストール先はProgram Filesが標準ですが、ユーザーがAppData\Local配下にインストールしているケースもあります。「ユーザー設定→標準パス→代替パス」の順にfs.existsSyncで実在確認しながらフォールバックすることで、環境差異を吸収しています。
3. 複数コマンドの実行間に100ms待機を入れる
for (const command of commands) {
const trimmedCommand = command.trim();
if (trimmedCommand) {
terminal.sendText(trimmedCommand, true);
if (commands.length > 1) {
await sleep(100);
}
}
}
terminal.sendText()は非同期の実行完了を待たないため、コマンドを連続で送りすぎると、先行コマンドが終わる前に次のコマンドが送られてしまう場合があります。厳密な完了検知ではなく100msの固定ウェイトという単純な対処ですが、実務上はこれで十分な安定性が得られました。
4. 実行後のカーソル移動は「単一行/複数行」「選択開始位置」で3パターンに分岐
if (isSingleCommand) {
// 単一行: 次の行の先頭へ
} else if (currentChar > 0) {
// 複数行かつ行中から選択: 選択範囲の次の行へ
} else {
// 複数行かつ行頭から選択: 選択解除のみ
}
単一行コマンドは「次のコマンドへ連続実行できるように次行へ」、複数行コマンドは選択開始位置が行頭かどうかで「選択解除だけに留める」か「次のブロックへ移動する」かを分けています。地味な分岐ですが、実際に連続でコマンド集を実行する運用では体感の快適さに直結する部分でした。
まとめ
ターミナルの名前ベース再利用と、実行環境依存のパス解決を「設定→既定→代替」の順で組む設計は、VSCode拡張機能で外部プロセスを扱う際に汎用的に使えるパターンでした。cmd/PowerShell/Git Bashの切り替えとキーバインド設定を含む完全なコードは元記事にまとめています。