1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Visual Studio CodeAdvent Calendar 2024

Day 23

左右2画面でファイルを連続表示+同期スクロールするVSCode拡張機能を試しに作った

Last updated at Posted at 2024-12-22

はじめに

VSCodeを用いて開発を行うとき、1行を長くせずに適切な位置で改行するフォーマッターを用いることがあると思います。
その時に私は思いました。
image.png

(ソースは今回作成した拡張機能のものです)

この右の余白もコード表示に使えたら便利なんじゃないかなあと

作るもの

左右にエディタを分割し、左側で現在表示している範囲の続きを右側に表示することで、画面の切り替えの手間なく多くの内容を同時に参照できるようにします。
本記事で示すコードは、左側エディタを「マスター」とし、左側スクロール停止後一定時間(200ms)経過した段階で右側エディタを自動的に同期表示する仕組みを実装しています。

作ってみた

VSCodeの拡張機能作成の勉強がてら作ってみました。

src/extension.ts

import * as vscode from 'vscode';

const DEBOUNCE_MS = 200;

function clampLine(line: number, maxLine: number): number {
    return Math.max(0, Math.min(line, maxLine));
}

function getTopVisibleLine(editor: vscode.TextEditor): number | undefined {
    const vr = editor.visibleRanges[0];
    return vr ? vr.start.line : undefined;
}

function getVisibleLineCount(editor: vscode.TextEditor): number {
    const vr = editor.visibleRanges[0];
    if (!vr) return 0;
    return vr.end.line - vr.start.line + 1;
}

function syncFromLeftToRight(
    leftEditor: vscode.TextEditor,
    rightEditor: vscode.TextEditor
) {
    const topLeftLine = getTopVisibleLine(leftEditor);
    if (topLeftLine === undefined) return;

    const visibleCount = getVisibleLineCount(leftEditor);
    const docRight = rightEditor.document;
    let expectedRightTop = topLeftLine + visibleCount;
    expectedRightTop = clampLine(expectedRightTop, docRight.lineCount - 1);

    rightEditor.revealRange(
        new vscode.Range(expectedRightTop, 0, expectedRightTop, 0),
        vscode.TextEditorRevealType.InCenterIfOutsideViewport
    );
}

export function activate(context: vscode.ExtensionContext) {
    const disposable = vscode.commands.registerCommand(
        'extension.openSyncedSplitView',
        async () => {
            const activeEditor = vscode.window.activeTextEditor;
            if (!activeEditor) {
                vscode.window.showErrorMessage("No active editor");
                return;
            }

            await vscode.commands.executeCommand(
                'workbench.action.splitEditorRight'
            );
            const editors = vscode.window.visibleTextEditors;
            const leftEditor = editors[0];
            const rightEditor = editors[1];

            if (!leftEditor || !rightEditor) {
                vscode.window.showErrorMessage(
                    "Could not open two editors."
                );
                return;
            }

            let debounceTimer: ReturnType<typeof setTimeout> | undefined;

            const handleVisibleRangeChange = (
                event: vscode.TextEditorVisibleRangesChangeEvent
            ) => {
                if (event.textEditor !== leftEditor) {
                    return;
                }

                if (debounceTimer) {
                    clearTimeout(debounceTimer);
                }

                debounceTimer = setTimeout(() => {
                    debounceTimer = undefined;
                    syncFromLeftToRight(leftEditor, rightEditor);
                }, DEBOUNCE_MS);
            };

            context.subscriptions.push(
                vscode.window.onDidChangeTextEditorVisibleRanges(
                    handleVisibleRangeChange
                )
            );
        }
    );

    context.subscriptions.push(disposable);
}

export function deactivate() {}

使ってみた

こんな感じで左エディタをスクロールさせると、右側も同期してスクロールされます。
Animation.gif

実装のポイント

左右分割の実行

コマンド openSyncedSplitView 実行時に workbench.action.splitEditorRight を呼び出し、アクティブなエディタを左右に分割します。

左エディタをトリガーとした同期

onDidChangeTextEditorVisibleRanges イベントハンドラを登録し、左エディタでスクロールイベントが発生したらデバウンス(200ms待機)後に右側を同期します。

可視行数を利用した続き位置の計算

左エディタで表示中の行数を取得し、その分だけ下の行から右側を表示することで「左の続き」を右側で自然に閲覧できるようにしています。

おわりに

拡張機能を自分で簡易的にでも作ることでVSCodeを更に使いやすくすることができると感じました。ほかにも使いやすいアイデアを見つけたらいろいろ試しに作ってみたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?