파일이 열렸을 때, 닫혔을 때, 활성화 되었을 때 exporer의 tabs에 파일이 추가 될 수 있는 부분을 구현해보았습니다.

 

사용 API

현재 열려있는 파일의 정보를 가져오는 방법

https://code.visualstudio.com/api/references/vscode-api#TextDocument

 

VS Code API

Visual Studio Code extensions (plug-in) API Reference.

code.visualstudio.com

vscode.workspace.textDocuments

 

 

절대 경로를 작업 공간 내의 상대 경로로 변환

vscode.workspace.asRelativePath("
d:\code\extendtions\TabAndGroup\src\TabProvider.ts")

//반환
//TabProvider.ts

 

 

트리 뷰에서 사용되는 항목을 생성하는 코드

https://code.visualstudio.com/api/extension-guides/tree-view

https://vshaxe.github.io/vscode-extern/vscode/TreeItem.html

첫번 째 매개변수 : 트리 아이템에 표시될 텍스트

두번 째 매개변수 : 이 항목이 접히거나 펼쳐질 수 있는지 여부를 정의, None은 해당 항목이 자식 요소 없이 고정된 상태로 표시

new vscode.TreeItem("TabProvider.ts", vscode.TreeItemCollapsibleState.None)

 

 

구현 기능 명세

  1. 파일이 열리는 경우, 닫히는 경우, 활성화 되는 경우 tabs에 파일 이름이 들어간다.
  2. tabs에서 파일을 누르면 파일이 열린다.
  3. git 관련된 파일은 Tabs에 포함되면 안된다.

 

구현

TabProvider.ts

//📃TabProvider.ts
import * as vscode from "vscode";

export class TabProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
    private _onDidChangeTreeData: vscode.EventEmitter<
        vscode.TreeItem | undefined | void
    > = new vscode.EventEmitter<vscode.TreeItem | undefined | void>();
    readonly onDidChangeTreeData: vscode.Event<
        vscode.TreeItem | undefined | void
    > = this._onDidChangeTreeData.event;

    // 트리 항목 반환(탭 목록)
    getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
        return element;
    }

    // 열린 파일 목록을 자식 요소로 제공
    getChildren(
        element?: vscode.TreeItem
    ): vscode.ProviderResult<vscode.TreeItem[]> {
        if (!element) {
            // 현재 열린 파일 목록을 가져옴
            const openFiles = [...vscode.workspace.textDocuments];

            console.log(openFiles);

            // Git 관련 파일 필터링
            const filteredFiles = this.getFilterFiles(openFiles);

            // 각 파일을 TreeItem으로 변환
            const treeItem = this.createTreeItems(filteredFiles);
            return Promise.resolve(treeItem);
        }

        return [];
    }

    //필터 목록 파일을 제외하고 파일 목록 반환
    private getFilterFiles(
        files: vscode.TextDocument[]
    ): vscode.TextDocument[] {
        return files.filter((doc) => {
            const filePath = doc.uri.fsPath.toLowerCase();

            //1. git 관련 파일 필터
            const gitPatterns = [
                "/.git/",
                ".git/",
                "\\.git\\",
                "/git/",
                "\\git\\",
                "git\\",
                ".git",
            ];

            return !gitPatterns.some((pattern) => filePath.includes(pattern));
        });
    }

    private createTreeItems(files: vscode.TextDocument[]): vscode.TreeItem[] {
        return files.map((doc) => {
            const label = vscode.workspace.asRelativePath(doc.uri.fsPath);
            const item = new vscode.TreeItem(
                label,
                vscode.TreeItemCollapsibleState.None
            );

            // 파일 경로와 명령어 설정을 메서드로 분리
            this.openSelectFile(item, doc.uri);

            return item;
        });
    }

    //파일 클릭 시 파일 열기
    private openSelectFile(item: vscode.TreeItem, uri: vscode.Uri) {
        item.resourceUri = uri;
        item.command = {
            // 파일 클릭 시 해당 파일로 이동
            command: "vscode.open",
            title: "Open File",
            arguments: [uri],
        };
    }

    // 트리 뷰 새로고침
    refresh(): void {
        this._onDidChangeTreeData.fire();
    }
}

 

 

extension.ts

onDidChangeActiveTextEditor(), onDidOpenTextDocument(), onDidCloseTextDocument() 를 통해 파일이 활성화, 열림, 닫힘 시 트리뷰를 새로고침 합니다.

//📃extension.ts
import * as vscode from "vscode";
import { TabProvider } from "./TabProvider";
import { BookmarkProvider } from "./BookmarkProvider";

export function activate(context: vscode.ExtensionContext) {
    console.log("🎈🎈🎈🎈 확장 기능 활성화됨!");

    const openFiles = vscode.workspace.textDocuments;
    console.log("🎀2 현재 열린 파일 목록", openFiles);

    // TabProvider 등록
    const tabProvider = new TabProvider();
    //views에 들어갈 id는 tab-view
    vscode.window.registerTreeDataProvider("tab-view", tabProvider);

    // BookmarkProvider 등록
    const bookmarkProvider = new BookmarkProvider();
    //views에 들어갈 id는 bookmark-view
    vscode.window.registerTreeDataProvider("bookmark-view", bookmarkProvider);

    // 이미 열린 파일들을 트리 뷰에 추가

    tabProvider.refresh();

    // 파일 변경될 때 새로고침
    vscode.window.onDidChangeActiveTextEditor(() => {
        tabProvider.refresh();
    });

    // 파일 열때 때 새로고침
    vscode.workspace.onDidOpenTextDocument(() => {
        tabProvider.refresh();
    });

    // 파일 닫을 때 새로고침
    vscode.workspace.onDidCloseTextDocument(() => {
        tabProvider.refresh();
    });

    // 명령어를 통해 트리 뷰 새로고침
    const refreshCommand = vscode.commands.registerCommand(
        "tabView.refresh",
        () => {
            tabProvider.refresh();
        }
    );

    context.subscriptions.push(refreshCommand);
}

export function deactivate() {}

 

 

package.json

"tabView.refresh"라는 명령어를 정의하고, 이 명령어를 실행할 때 '열린 파일 목록 새로고침' 기능을 하도록 만듭니다.

"commands": [
            {
                "command": "tabView.refresh",
                "title": "Refresh Open Files"
            }
        ]

 

 

전체 package.json

{
    "name": "vscode-tabgroup-and-bookmark",
    "displayName": "grop tab",
    "description": "",
    "version": "0.0.1",
    "engines": {
        "vscode": "^1.94.0"
    },
    "categories": [
        "Other"
    ],
    "activationEvents": [
        "*"
    ],
    "main": "./out/extension.js",
    "contributes": {
        "viewsContainers": {
            "activitybar": [
                {
                    "id": "vscode-tabgroup-and-bookmark",
                    "title": "Package Explorer",
                    "icon": "images/my-icon.svg"
                }
            ]
        },
        "views": {
            "vscode-tabgroup-and-bookmark": [
                {
                    "id": "tab-view",
                    "name": "Tabs",
                    "type": "tree"
                },
                {
                    "id": "bookmark-view",
                    "name": "Bookmarks",
                    "type": "tree"
                }
            ]
        },
        "commands": [
            {
                "command": "tabView.refresh",
                "title": "Refresh Open Files"
            }
        ]
    },
    "scripts": {
        "vscode:prepublish": "npm run compile",
        "compile": "tsc -p ./",
        "watch": "tsc -watch -p ./",
        "pretest": "npm run compile && npm run lint",
        "lint": "eslint src",
        "test": "vscode-test"
    },
    "devDependencies": {
        "@types/vscode": "^1.94.0",
        "@types/mocha": "^10.0.8",
        "@types/node": "20.x",
        "@typescript-eslint/eslint-plugin": "^8.7.0",
        "@typescript-eslint/parser": "^8.7.0",
        "eslint": "^9.11.1",
        "typescript": "^5.6.2",
        "@vscode/test-cli": "^0.0.10",
        "@vscode/test-electron": "^2.4.1"
    }
}

 

 

git 폴더 같은 쓸모없는 목록이 있어서 이를 필터링 해주는 코드가 존재합니다.

 

동작

 

 

개선이 필요한 부분

  1. 이미 기존에 열려있는 파일은 tabs 목록에 들어가지 않는다
  2. 파일을 열고 아이콘을 눌러서 tabs 목록을 보니까 뭔가 불편하다.
    1. unsaved file? 여기에서도 보일 수 있게 추가되면 좋을 것 같다.
  3. git 부분만 필터링 하지 않고 추가적인 필터링이 더 필요할 것 같다.
    1. 필터링 할 수 있는 부분을 좀 확장성 있게 수정이 필요할 것 같다.
vscode extension 열린 파일 view tree에 추가하기