はじめに
「VSCodeでいちいちコマンドをコピペしてターミナルで実行するのめんどくさい…」
そんな悩みを持つ開発者は多いはずです。実際、検索数から見ても:
■検索ワード(月間検索数)
- 1000~1万: "vscode ターミナル"
- 100~1000: "vscode コマンド プロンプト", "vscode powershell", "vscode gitbash"
- 10~100: "vscode ターミナル 実行", "vscode cmd"ターミナル実行の効率化は、多くの開発者が求めている機能です。
本記事では、カーソル行または選択テキストをショートカットキー一発でターミナル実行できるTypeScriptマクロの実装方法を完全解説します。
この記事で分かること
- ターミナル実行マクロの実装方法
- cmd/PowerShell/Git Bashの使い分け
- 単一行・複数行コマンドの実行方法
- キーバインド設定のベストプラクティス
- 実践的な使用例とワークフロー
- トラブルシューティング
こんな人におすすめ
- コマンドをメモ帳に保存している人
- コマンド実行のたびにコピペしている人
- よく使うコマンドをすぐ実行したい人
- 複数のターミナル(cmd/PS/GitBash)を使い分けたい人
解決できる課題
従来の問題点
1. コピペの手間
1. コマンドを選択
2. Ctrl+Cでコピー
3. ターミナルをクリック
4. Ctrl+Vで貼り付け
5. Enter押下2. コマンド管理の煩雑さ
- よく使うコマンドをどこに保存?
- 過去のコマンド履歴を探すのが大変
- プロジェクトごとのコマンド集が散在
3. ターミナル切り替えの手間
- cmd、PowerShell、Git Bashを使い分け
- それぞれでコマンド入力が必要
この機能で実現できること
ショートカットキー一発で実行!
Before:
選択 → コピー → ターミナル切替 → 貼り付け → Enter(5ステップ)
After:
Ctrl+Shift+1(1ステップ)複数コマンドも順次実行
# 3行を選択してCtrl+Shift+1
cd /d C:\projects
npm install
npm run dev
# → 自動で順次実行!機能仕様
基本機能
| 機能 | 説明 |
|---|---|
| 単一行実行 | カーソル行を実行 |
| 複数行実行 | 選択範囲を行ごとに順次実行 |
| 空行スキップ | 空行は自動で除外 |
| ターミナル管理 | 専用ターミナルを自動作成・再利用 |
| エディタ自動復帰 | 単一行・複数行ともに実行後エディタにフォーカスを戻す。単一行は次の行の先頭へ移動。複数行は行頭なら選択解除のみ、行中なら選択範囲の次の行へ移動 |
ショートカットキー
| キー | 機能 | ターミナル |
|---|---|---|
| Ctrl+Shift+1 | CMD実行 | コマンドプロンプト |
| Ctrl+Shift+2 | PS実行 | PowerShell |
| Ctrl+Shift+3 | Bash実行 | Git Bash |
動作フロー
1. テキスト未選択の場合(1行コマンド)
↓
カーソル行の文字列全体を取得
↓
ターミナルで実行
↓
エディタにフォーカスを戻す
↓
カーソルを次の行の先頭に移動
2. テキスト選択の場合(複数行コマンド)
↓
選択範囲を行ごとに分割
↓
空行を除外
↓
各行を順次実行(100ms待機)
↓
エディタにフォーカスを戻す
↓
[カーソルが行頭(char=0)の場合] 選択解除のみ(カーソル移動なし)
[カーソルが行中の場合] 選択範囲の次の行の先頭に移動TypeScript実装コード
ファイル構成
src/
├── extension.ts # コマンド登録
└── macros/
└── runInTerminal.ts # ターミナル実行機能runInTerminal.ts(完全版)
import * as vscode from 'vscode';
/**
* ターミナルのタイプ
*/
export enum TerminalType {
CMD = 'cmd',
PowerShell = 'powershell',
GitBash = 'gitbash'
}
/**
* コマンドプロンプトで実行
*/
export async function runInCmd() {
await runInTerminal(TerminalType.CMD);
}
/**
* PowerShellで実行
*/
export async function runInPowerShell() {
await runInTerminal(TerminalType.PowerShell);
}
/**
* Git Bashで実行
*/
export async function runInGitBash() {
await runInTerminal(TerminalType.GitBash);
}
/**
* 指定されたターミナルでコマンド実行
*/
async function runInTerminal(terminalType: TerminalType) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showWarningMessage('アクティブなエディタがありません');
return;
}
// コマンド取得
const commands = getCommandsToExecute(editor);
if (commands.length === 0) {
vscode.window.showWarningMessage('実行するコマンドがありません');
return;
}
// 現在の行位置・選択範囲を記憶
const currentLine = editor.selection.active.line;
const currentChar = editor.selection.active.character;
const selectionEndLine = editor.selection.end.line;
const isSingleCommand = commands.length === 1;
// ターミナル取得または作成
const terminal = getOrCreateTerminal(terminalType);
terminal.show();
// コマンド実行(複数行の場合は順次実行)
for (const command of commands) {
const trimmedCommand = command.trim();
if (trimmedCommand) {
terminal.sendText(trimmedCommand, true);
// 複数コマンド実行時は少し待機
if (commands.length > 1) {
await sleep(100);
}
}
}
// エディタをアクティブにする
await vscode.commands.executeCommand('workbench.action.focusActiveEditorGroup');
if (isSingleCommand) {
// 1行コマンド: 次の行の先頭にカーソルを移動
const nextLine = currentLine + 1;
if (nextLine < editor.document.lineCount) {
const newPosition = new vscode.Position(nextLine, 0);
editor.selection = new vscode.Selection(newPosition, newPosition);
editor.revealRange(new vscode.Range(newPosition, newPosition));
}
} else {
// 複数行コマンド: カーソルが行の先頭(char 0)でなければ選択範囲の次の行に移動
if (currentChar > 0) {
const nextLine = selectionEndLine + 1;
if (nextLine < editor.document.lineCount) {
const newPosition = new vscode.Position(nextLine, 0);
editor.selection = new vscode.Selection(newPosition, newPosition);
editor.revealRange(new vscode.Range(newPosition, newPosition));
}
} else {
// カーソルが行頭にある場合は移動せず、選択状態のみ解除
const currentPosition = new vscode.Position(currentLine, currentChar);
editor.selection = new vscode.Selection(currentPosition, currentPosition);
}
}
// 実行完了メッセージ
const terminalName = getTerminalDisplayName(terminalType);
const message = commands.length === 1
? `${terminalName}でコマンドを実行しました`
: `${terminalName}で${commands.length}個のコマンドを実行しました`;
vscode.window.showInformationMessage(message);
}
/**
* 実行するコマンドを取得
*/
function getCommandsToExecute(editor: vscode.TextEditor): string[] {
const selection = editor.selection;
const document = editor.document;
// テキストが選択されている場合
if (!selection.isEmpty) {
const selectedText = document.getText(selection);
// 複数行の場合は行ごとに分割
const lines = selectedText.split(/\r?\n/);
// 空行を除外してコマンドリストを作成
return lines
.map(line => line.trim())
.filter(line => line.length > 0);
}
// テキスト未選択の場合は現在行を取得
const currentLine = document.lineAt(selection.active.line);
const lineText = currentLine.text.trim();
return lineText.length > 0 ? [lineText] : [];
}
/**
* ターミナルを取得または作成
*/
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);
}
/**
* Git Bash のパスを解決する
* 優先順位: VSCode設定 → 既定パス1 → 既定パス2
*/
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;
}
/**
* 新しいターミナルを作成
*/
function createTerminal(terminalType: TerminalType): vscode.Terminal {
const name = getTerminalName(terminalType);
let shellPath: string | undefined;
let shellArgs: string[] | undefined;
switch (terminalType) {
case TerminalType.CMD:
shellPath = 'cmd.exe';
break;
case TerminalType.PowerShell:
shellPath = 'powershell.exe';
break;
case TerminalType.GitBash:
shellPath = resolveGitBashPath(); // VSCode設定 → Program Files の順で解決
shellArgs = ['--login', '-i'];
break;
}
return vscode.window.createTerminal({
name: name,
shellPath: shellPath,
shellArgs: shellArgs
});
}
/**
* ターミナル名を取得
*/
function getTerminalName(terminalType: TerminalType): string {
switch (terminalType) {
case TerminalType.CMD:
return 'My Macros - CMD';
case TerminalType.PowerShell:
return 'My Macros - PowerShell';
case TerminalType.GitBash:
return 'My Macros - Git Bash';
}
}
/**
* ターミナル表示名を取得
*/
function getTerminalDisplayName(terminalType: TerminalType): string {
switch (terminalType) {
case TerminalType.CMD:
return 'コマンドプロンプト';
case TerminalType.PowerShell:
return 'PowerShell';
case TerminalType.GitBash:
return 'Git Bash';
}
}
/**
* 待機用ヘルパー関数
*/
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}extension.ts(コマンド登録)
import * as vscode from 'vscode';
import { runInCmd, runInPowerShell, runInGitBash } from './macros/runInTerminal';
export function activate(context: vscode.ExtensionContext) {
console.log('my-macros extension is now active');
// コマンド登録
const commands = [
// ターミナル実行
vscode.commands.registerCommand('myMacros.runInCmd', runInCmd),
vscode.commands.registerCommand('myMacros.runInPowerShell', runInPowerShell),
vscode.commands.registerCommand('myMacros.runInGitBash', runInGitBash),
];
commands.forEach(command => context.subscriptions.push(command));
}
export function deactivate() {}package.json(設定ファイル)
{
"name": "my-macros",
"displayName": "My Macros",
"version": "0.0.2",
"contributes": {
"commands": [
{
"command": "myMacros.runInCmd",
"title": "Run in Command Prompt",
"category": "My Macros"
},
{
"command": "myMacros.runInPowerShell",
"title": "Run in PowerShell",
"category": "My Macros"
},
{
"command": "myMacros.runInGitBash",
"title": "Run in Git Bash",
"category": "My Macros"
}
],
"keybindings": [
{
"command": "myMacros.runInCmd",
"key": "ctrl+shift+1",
"when": "editorTextFocus"
},
{
"command": "myMacros.runInPowerShell",
"key": "ctrl+shift+2",
"when": "editorTextFocus"
},
{
"command": "myMacros.runInGitBash",
"key": "ctrl+shift+3",
"when": "editorTextFocus"
}
]
}
}コードの詳細解説
1. Enum定義
export enum TerminalType {
CMD = 'cmd',
PowerShell = 'powershell',
GitBash = 'gitbash'
}ポイント:
- 型安全にターミナルタイプを管理
- 文字列のタイポを防止
- IntelliSenseが効く
2. コマンド取得ロジック
function getCommandsToExecute(editor: vscode.TextEditor): string[] {
const selection = editor.selection;
// 選択されている場合
if (!selection.isEmpty) {
const selectedText = document.getText(selection);
const lines = selectedText.split(/\r?\n/);
return lines
.map(line => line.trim())
.filter(line => line.length > 0);
}
// 未選択の場合は現在行
const currentLine = document.lineAt(selection.active.line);
return currentLine.text.trim().length > 0 ? [currentLine.text.trim()] : [];
}機能:
- 選択範囲の検知
- 行単位で分割
- 空行の自動除外
- trim()でホワイトスペース除去
3. ターミナル管理
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);
}メリット:
- ターミナルの再利用
- メモリ効率の向上
- ターミナルの乱立防止
4. 複数コマンドの順次実行
for (const command of commands) {
terminal.sendText(command, true);
if (commands.length > 1) {
await sleep(100); // 100ms待機
}
}100ms待機の理由:
- コマンドの確実な実行
- 先行コマンドの完了待ち
- ターミナルの処理負荷軽減
5. エディタ自動復帰とカーソル制御
// エディタをアクティブにする(単一行・複数行ともに)
await vscode.commands.executeCommand('workbench.action.focusActiveEditorGroup');
if (isSingleCommand) {
// 1行コマンド: 次の行の先頭にカーソルを移動
const nextLine = currentLine + 1;
if (nextLine < editor.document.lineCount) {
const newPosition = new vscode.Position(nextLine, 0);
editor.selection = new vscode.Selection(newPosition, newPosition);
editor.revealRange(new vscode.Range(newPosition, newPosition));
}
} else {
// 複数行コマンド: 行頭(char 0)かどうかでカーソル制御を分岐
if (currentChar > 0) {
// 行中の場合は選択範囲の次の行へ移動
const nextLine = selectionEndLine + 1;
if (nextLine < editor.document.lineCount) {
const newPosition = new vscode.Position(nextLine, 0);
editor.selection = new vscode.Selection(newPosition, newPosition);
editor.revealRange(new vscode.Range(newPosition, newPosition));
}
} else {
// 行頭の場合は選択解除のみ(カーソル移動なし)
const currentPosition = new vscode.Position(currentLine, currentChar);
editor.selection = new vscode.Selection(currentPosition, currentPosition);
}
}機能のポイント:
- 単一行・複数行ともに実行後エディタに自動復帰
- 単一行: 次の行の先頭にカーソルが移動(連続実行に最適)
- 複数行(行頭から選択開始の場合): 選択解除のみ(カーソル移動なし)
- 複数行(行中から選択開始の場合): 選択範囲の次の行へ移動
メリット:
- コマンドを順番に実行する際、エディタとターミナルの切り替えが不要
- カーソルが自動で次の行に移動するため、テンポよく連続実行できる
- 複数行実行後も即座に次の操作に移れる
使い方
基本的な使い方
1. 単一コマンドの実行
# test_commands.txt
npm run dev1. カーソルを行に配置
2. Ctrl+Shift+2(PowerShellで実行)
3. → PowerShellが開いて自動実行!
4. → 自動的にエディタにフォーカスが戻り、カーソルが次の行へ移動新機能のメリット:
- コマンドを連続実行する際、エディタとターミナルの切り替え不要
- カーソルが自動で次の行に移動するため、テンポよく実行できる
- 1行ずつ確認しながら実行するワークフローに最適
2. 複数コマンドの実行
# deploy.txt
cd /d C:\projects\my-app
git pull origin main
npm install
npm run build
npm run deploy1. 全行を選択(Ctrl+A)
2. Ctrl+Shift+1(CMDで実行)
3. → 5つのコマンドが順次実行!
4. → 実行後、エディタにフォーカスが自動復帰動作の違い:
- 1行コマンド: 実行後、エディタに自動復帰してカーソルが次の行へ
- 複数行(行頭から選択): 実行後、エディタに自動復帰して選択解除のみ(カーソル移動なし)
- 複数行(行中から選択): 実行後、エディタに自動復帰して選択範囲の次の行へ移動
実践的な活用例
開発環境セットアップ
# setup_dev.txt
cd /d C:\projects
git clone https://github.com/user/repo.git
cd repo
npm install
code .選択 → Ctrl+Shift+1で一括セットアップ!定型作業の自動化
# daily_tasks.txt
cd /d C:\projects\app
git fetch origin
git status
npm run test毎朝Ctrl+Shift+1で健全性チェック!Docker操作
# docker_commands.txt
docker-compose down
docker-compose build
docker-compose up -d
docker-compose logs -fCtrl+Shift+2で一括操作!キーバインドのカスタマイズ
keybindings.json での変更
// ショートカットキーを変更
[
{
"key": "ctrl+alt+1",
"command": "myMacros.runInCmd",
"when": "editorTextFocus"
},
{
"key": "ctrl+alt+2",
"command": "myMacros.runInPowerShell",
"when": "editorTextFocus"
},
{
"key": "ctrl+alt+3",
"command": "myMacros.runInGitBash",
"when": "editorTextFocus"
}
]コンテキストによる制限
// Markdownファイルでのみ有効
{
"key": "ctrl+shift+1",
"command": "myMacros.runInCmd",
"when": "editorTextFocus && resourceExtname == '.md'"
}// 特定のワークスペースでのみ有効
{
"key": "ctrl+shift+1",
"command": "myMacros.runInCmd",
"when": "editorTextFocus && workspaceFolderCount > 0"
}メリット・デメリット
メリット
1. 圧倒的な時短効果
- コピペ操作の削減: 5ステップ → 1ステップ
- よく使うコマンドを即実行
- 複数コマンドも一括処理
- 1行コマンド実行後の自動エディタ復帰で連続実行がスムーズ
2. コマンド集の一元管理
.txtまたは.mdで管理- プロジェクトごとにファイル作成
- Gitで履歴管理
3. ターミナルの使い分けが簡単
- cmd/PS/Bashを自在に切替
- ターミナル固有のコマンドも対応
- ターミナルの再利用で効率化
4. 学習コストが低い
- 直感的な操作
- 既存のメモをそのまま活用
- エディタ感覚で編集可能
デメリット
1. 初期セットアップが必要
- TypeScript環境の構築
- 拡張機能のインストール
2. 対話的なコマンドは非対応
npm initなどの入力待ちコマンドsshでのパスワード入力
3. エラーハンドリングが弱い
- コマンド失敗時も次へ進む
- 自動リトライ機能なし
総評
デメリットを大きく上回る効率化が可能
特に、頻繁にコマンド実行する開発者には必須の機能です。
応用テクニック
1. プロジェクト別コマンド集
project-commands/
├── backend/
│ ├── dev.txt
│ ├── test.txt
│ └── deploy.txt
└── frontend/
├── dev.txt
├── build.txt
└── deploy.txt使い方:
1. dev.txtを開く
2. Ctrl+A → Ctrl+Shift+2
3. → 開発環境が起動!2. エイリアス定義ファイル
# aliases.txt(Git Bash用)
alias ll='ls -la'
alias gs='git status'
alias gp='git pull'
alias gb='git branch'起動時にCtrl+Shift+3で一括登録!3. 環境変数設定
# env_setup.ps1(PowerShell用)
$env:NODE_ENV="development"
$env:API_KEY="your-api-key"
$env:DEBUG="true"Ctrl+Shift+2で環境変数を一括設定!4. ドキュメント化
# コマンド集
## 開発環境起動
cd /d C:\projects
npm run dev
## ビルド
npm run build
## デプロイ
npm run deployMarkdownで管理 + 実行可能!トラブルシューティング
Git Bashが起動しない
エラー:
Failed to launch terminal解決策:VSCode設定でパスを指定する
Git Bashが C:\Program Files\Git 以外の場所(AppData\Local 等)にインストールされている場合は、VSCode設定でパスを指定してください。
Ctrl+, → 検索欄に「myMacros.gitBash」と入力
→ Git Bash Path 欄に bash.exe のフルパスを入力設定例:
C:\Users\ユーザー名\AppData\Local\Programs\Git\bin\bash.exeパスの探索順序:
myMacros.gitBashPath設定値(指定がある場合のみ)C:\Program Files\Git\bin\bash.exeC:\Program Files (x86)\Git\bin\bash.exe
コマンドが実行されない
原因1: 空行が含まれる
→ trim() と filter() で除外済み
原因2: ターミナルが閉じている
→ 自動で再作成されるはずだが、手動で閉じた場合は再実行
原因3: パスに空白が含まれる
# NG
cd C:\Program Files\app
# OK
cd "C:\Program Files\app"複数コマンドが途中で止まる
原因: コマンド実行時間が長い
解決策: 待機時間を調整
// 100ms → 500msに変更
if (commands.length > 1) {
await sleep(500);
}キーバインドが効かない
確認ポイント:
- when条件の確認
"when": "editorTextFocus"
// エディタにフォーカスがあるか?- 競合の確認
Ctrl+Shift+P → "Preferences: Open Keyboard Shortcuts"
→ Ctrl+Shift+1で検索- 拡張機能の有効化確認
Ctrl+Shift+P → "Extensions: Show Installed Extensions"
→ My Macros が有効か確認パフォーマンス最適化
ターミナルの再利用
// ターミナル名で識別して再利用
function getOrCreateTerminal(terminalType: TerminalType): vscode.Terminal {
const terminalName = getTerminalName(terminalType);
const existingTerminal = vscode.window.terminals.find(
t => t.name === terminalName
);
return existingTerminal || createTerminal(terminalType);
}メリット:
- 新規作成のオーバーヘッド削減
- 環境変数の保持
- 作業ディレクトリの維持
非同期処理の最適化
// 並列実行は避ける(コマンドの依存関係のため)
for (const command of commands) {
await terminal.sendText(command, true);
// 順次実行を保証
}まとめ
VSCodeでショートカット一発でターミナル実行できるTypeScriptマクロを実装しました。
得られる効果:
- コマンド実行が5ステップ → 1ステップに
- よく使うコマンドを即座に実行
- 複数コマンドの一括実行
- cmd/PowerShell/Git Bashの使い分けが簡単
こんな人に最適:
- 頻繁にコマンド実行する開発者
- コマンドをメモ帳管理している人
- 作業を効率化したい人
- 複数のターミナルを使い分ける人
次のステップ:
- 環境構築(TypeScript + VSCode拡張)
- コード実装(この記事のコードをコピー)
- パッケージ化してインストール
- よく使うコマンド集を作成
- ショートカットで爆速実行!
ぜひ実装して、開発効率を劇的に向上させてください!
関連記事
TypeScript拡張機能の開発環境構築

サクラエディタからVSCodeへのマクロ移行

タグ: #VSCode #TypeScript #マクロ #ターミナル #コマンド実行 #生産性向上 #自動化
コメント