🤓

VSCodeでGitUI/Lazygitを使いたい

に公開

VSCodeでGitUI/Lazygitを使いたい

Screenshot

GitUI/Lazygitとは

GitUI, Lazygitは、ターミナル上(TUI: Terminal User Interface) で動作するGitクライアントです。GUIベースのGitクライアントと比べて軽量で高速に動作し、キーボード操作に最適化されています。

VSCodeでもターミナルを開いてGitUIやLazygitを起動することはできますが、起動するたびにターミナルを開いてコマンドを入力したり、パネルを切り替えるのは面倒でした。そこで、GitUI/LazygitをEditorパネル内ですぐに開けるようにする拡張機能(vscode-gitui)を作成してみました。

vscode-gitui リポジトリ

https://github.com/gymynnym/vscode-gitui

使ってみたい方はVSCode MarketplaceGitHub Releasesでインストールしてみてください。

VSCodeVim ユーザー向けのキーバインドも用意しています。詳しくはリポジトリのREADMEを参考にしてください。

開発過程

1. プロジェクト生成

VSCode: Your First Extensionを参考しました。

まず、次のようなコマンドでプロジェクトを生成します。

$ npx --package yo --package generator-code -- yo code

TypeScriptでの拡張機能開発を選択しました。
次はvsceをインストールしてパッケージ化できるようにします。

$ pnpm add -D @vscode/vsce
package.json
{
  "scripts": {
    "package": "vsce package"
  }
}

2. コマンドの登録

この拡張機能では、二つのコマンドを登録します。

  1. vscode-gitui.open : GitUI/LazygitをEditorパネル内で開くコマンド
  2. vscode-gitui.reload : GitUI/LazygitをPATHから再読み込みするコマンド
src/extension.ts
export function activate(context: vscode.ExtensionContext) {
  const disposables = [
    vscode.commands.registerCommand('vscode-gitui.open', () => handleGitClientCommand(openGitClient)),
    vscode.commands.registerCommand('vscode-gitui.reload', () => handleGitClientCommand(reloadGitClient)),
    ...
  ];
  disposables.forEach((disposable) => context.subscriptions.push(disposable));
}

handleGitClientCommandはGitUI/LazygitがPATHに存在するか確認するユーティリティ関数です。詳しくはextension.tsを参照してください。

3. コマンドの実装

3-1. vscode-gitui.open

src/commands/open.ts
async function openGitClient() {
  const workspace = await getCurrentWorkspace();
  const command = resolveGitCommand();
  if (workspace) {
    runCommandInTerminal(command, {
      name: command,
      cwd: workspace,
      location: vscode.TerminalLocation.Editor,
    });
  }
}

async function getCurrentWorkspace(): Promise<string | undefined> {
  const workspaceFolders = vscode.workspace.workspaceFolders;
  if (!workspaceFolders || workspaceFolders.length === 0) {
    throw new Error(ErrorMessage.WORKSPACE_NOT_FOUND);
  }
  if (workspaceFolders.length === 1) {
    return workspaceFolders[0].uri.fsPath;
  }

  const pickedWorkspace = await vscode.window.showWorkspaceFolderPick({
    placeHolder: 'Select a workspace folder to open gitui in',
    ignoreFocusOut: true,
  });
  return pickedWorkspace?.uri.fsPath;
}

export { openGitClient };

openGitClient関数は、現在のワークスペースを取得し、GitUI/LazygitコマンドをEditorパネル内で実行します。
getCurrentWorkspace関すは、ワークスペースを選択するための関数です。ワークスペースが複数ある場合、ユーザーに選択を促します。

3-2. vscode-gitui.reload

src/commands/reload.ts
async function reloadGitClient() {
  const command = resolveGitCommand();
  const exists = await checkCommandExists(command);
  if (exists) {
    vscode.window.showInformationMessage(InfoMessage.COMMAND_FOUND(command));
  } else {
    vscode.window.showErrorMessage(ErrorMessage.COMMAND_NOT_FOUND(command));
  }
}

reloadGitClient関数は、GitUI/LazygitコマンドがPATHに存在するか確認し、結果をメッセージとして表示します。
checkCommandExistsは、コマンドの存在を確認するユーティリティ関数です。

Lazygitサポート: GitHubからIssueが投稿されました!

support-lazygit-issue.png

実は、最初はGitUIのみをサポートする予定でした。しかし、とあるユーザーからLazygitサポートの要望がIssueとして投稿されました。そこで、Lazygitもサポートすることにしました。

コマンド決定のロジック追加

上のコードで使っているresolveGitCommand関数は、ユーザー設定に基づいてGitUIまたはLazygitのコマンドを決定します。

まず、package.jsonにpropertiesを追加して、ユーザーがLazygitを使うかどうかを設定できるようにしました。

package.json
{
  "contributes": {
    "configuration": {
      "title": "vscode-gitui",
      "properties": {
        ...
        "vscode-gitui.useLazygit": {
          "type": "boolean",
          "default": false,
          "description": "Enable if you want to use Lazygit instead of GitUI."
        }
      }
    },
  }
}

あと、resolveGitCommand関数を次のように実装して、利用するGitクライアントを判定して返すようにしました。

src/lib/command.ts
const GITUI_COMMAND = 'gitui';
const LAZYGIT_COMMAND = 'lazygit';

function resolveGitCommand(): string {
  const useLazygit = vscode.workspace.getConfiguration('vscode-gitui').get<boolean>('useLazygit', false);
  return useLazygit ? LAZYGIT_COMMAND : GITUI_COMMAND;
}

まとめ

VSCodeでGitUI/Lazygitを使うための拡張機能を作成しました。初めてのVSCode拡張機能開発でしたが、比較的簡単に作成できました。開発中には、GitHubからのIssueを通じてユーザーと交流できたのも良い経験でした。読者の皆さんも、ぜひ自分のニーズに合わせたVSCode拡張機能を作成してみてください!

Discussion