BlueMonkMN
BlueMonkMN

Reputation: 25601

How to synchronize VS Code's outline to the current position in the editor

I'm working in a language that usually has very large and hard to navigate files, so I would like to readily see what function I'm in at all times, since that's usually the biggest annoyance (paging up ~20 times to find the current function name, then paging back down).

I see how I can write an extension to list all the functions by registering a document symbol provider. Before I go too far down path, though, I want to know if there will be some way to automatically and constantly have some sort of indication in the outline view of which node represents the current position in the code editor. If not, I may just have to create my own tree view instead (will that have this capability?).

Upvotes: 4

Views: 2373

Answers (2)

BlueMonkMN
BlueMonkMN

Reputation: 25601

If you have a reasonably functional outline view, that is to say, one that has the symbols hierarchically arranged by providing range objects for the full scope of each symbol instead of just a position, then you can toggle the "Breadcrumbs" item in the view menu to have a constant view of where you are within the outline's hierarchy. This is exactly what I was after.

To help with this, I had some data stored in a variable called currentBlock, including symbolInformation that was created when I encountered the first line of, for example, a method (taken from a match object returned from a regular expression):

currentBlock.symbolInformation = new vscode.SymbolInformation(
    match[1],
    vscode.SymbolKind.Method,
    className,
    new vscode.Location(document.uri,
        new vscode.Position(lineNum, line.firstNonWhitespaceCharacterIndex)));

Then when I got to the end of the block I would wrap up the remainder of the information incorporating the data stored earlier, and push it onto the SymbolInformation[] result.

private popBlock(document: vscode.TextDocument, lineNum: number, currentBlock: IndentInfo): vscode.SymbolInformation | undefined {
    if (currentBlock.symbolInformation !== undefined) {
        currentBlock.symbolInformation = new vscode.SymbolInformation(
            currentBlock.symbolInformation.name,
            currentBlock.symbolInformation.kind,
            currentBlock.symbolInformation.containerName,
            new vscode.Location(
                currentBlock.symbolInformation.location.uri,
                new vscode.Range(
                    currentBlock.symbolInformation.location.range.start,
                    new vscode.Position(lineNum-1, document.lineAt(lineNum-1).text.length)
                )
            )
        );
        return currentBlock.symbolInformation;
    }
}

Here you can see the breadcrumbs reporting the full context of the current location above the editor pane. It's based on the same information that is used to build the outline.

enter image description here

Upvotes: 1

Mike Lischke
Mike Lischke

Reputation: 53307

Yes, this is possible. Your tree provider needs a way to match a symbol to a tree item, then call TreeView.reveal(). Here's code I use to select an entry in a list of actions, depending on where the caret is in the current source editor:

public update(editor: TextEditor) {
    let position = editor.selection.active;

    let action = Utils.findInListFromPosition(this.actions, position.character, position.line + 1);
    if (action) {
        this.actionTree.reveal(action, { select: true });
        return;
    }
    let predicate = Utils.findInListFromPosition(this.predicates, position.character, position.line + 1);
    if (predicate) {
        this.actionTree.reveal(predicate, { select: true });
        return;
    }
}

This method is called from the selection change event registered in the main extension file:

window.onDidChangeTextEditorSelection((event: TextEditorSelectionChangeEvent) => {
    if (event.textEditor.document.languageId === "antlr" && event.textEditor.document.uri.scheme === "file") {
        ...
        actionsProvider.update(event.textEditor);
    }
});

Upvotes: 1

Related Questions