TabManager - VS Code 插件开发

707 阅读3分钟

插件开发文档

  1. 中文:liiked.github.io/VS-Code-Ext…
  2. 官方:code.visualstudio.com/api

开发流程

1. 初始化开发目录

1.安装Yeoman和generator-code

npm install -g yo generator-code
  • Yeoman 是一个通用的脚手架系统。Yeoman 它自己不能做任何操作。 每个操作都是由 generators 基本插件在 Yeoman 环境所完成的。
  • generator-code 一个Yeoman的基本插件,用来搭建一个VS Code插件开发项目。

2. 初始化项目

yo code
......
? What type of extension do you want to create? New Extension (JavaScript)
? What's the name of your extension? tabManager
? What's the identifier of your extension? TabManager
? What's the description of your extension? TabManager
? Enable JavaScript type checking in 'jsconfig.json'? No
? Initialize a git repository? Yes
? Which package manager to use? yarn
......

3. 项目目录

.
|____jsconfig.json
|____.yarnrc
|____CHANGELOG.md                   // 插件修改日志
|____.vscodeignore
|____README.md                      // 插件文档
|____.gitignore
|____package.json                   // 插件配置
|____.vscode
| |____extensions.json
| |____launch.json
|____vsc-extension-quickstart.md
|____.eslintrc.json
|____extension.js                   // 插件入口

4. 插件入口文件会导出两个函数,activate 和 deactivate,你注册的激活事件被触发之时执行activatedeactivate则提供了插件关闭前执行清理工作的机会。

const vscode = require('vscode');

// 一旦你的插件激活,vscode会立刻调用下述方法
function activate(context) {

    // 用console输出诊断信息(console.log)和错误(console.error)
    // 下面的代码只会在你的插件激活时执行一次
    console.log('Congratulations, your extension "TabManager" is now active!');

    // 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法
    // registerCommand中的参数必须与package.json中的command保持一致
    let disposable = vscode.commands.registerCommand('TabManager.openNewTab', function () {
        // 把你的代码写在这里,每次命令执行时都会调用这里的代码
        // ...
        // 给用户显示一个消息提示
        vscode.window.showInformationMessage('Hello World from tabManager!');
    });

    context.subscriptions.push(disposable);
}

function deactivate() {}

module.exports = {
   activate,
   deactivate
}

2. 插件功能实现

1. 插件配置 package.json

{
  "name": "TabManager",
  "icon": "images/icon.png", // 插件icon
  "displayName": "TabManager",
  "description": "A plugin that functions like a browser TAB bar", // 简单地描述一下你的插件是做什么的。
  "publisher": "xiaonanhai",
  "version": "0.3.1",
  "engines": {
    "vscode": "^1.61.0" // 兼容的VS Code的最小版本
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "onCommand:TabManager.openNewTab" // 执行命令“TabManager.openNewTab”时激活插件
  ],
  "main": "./extension.js", // 插件入口
  "contributes": {
    "commands": [
      {
        "command": "TabManager.openNewTab",
        "title": "openNewTab" // 命令窗口,右键菜单显示的命令名称
      }
    ],
    "menus": {
      "editor/context": [ // 编辑器上下文菜单
        {
          "when": "editorFocus", // 编辑器获取焦点时
          "command": "TabManager.openNewTab",
          "group": "navigation" // 定义了菜单的分组。navigation值不同于普通的group值,一旦设置这个值就会总是显示在菜单的最顶端。
        }
      ]
    }
  },
  "configuration": {
    "title": "tab manager configuration",
    "properties": {
      "TabManager.tabList": {
        "type": "array",
        "default": [],
        "description": "tabList",
        "item": {
          "type": "object",
          "required": [
            "tabName",
            "tabUrl"
          ],
          "properties": {
            "tabName": {
              "type": "string",
              "default": "",
              "description": "tab name"
            },
            "tabUrl": {
              "type": "string",
              "default": "",
              "description": "tab url"
            },
            "params": {
              "default": {},
              "description": "params",
              "type": "object"
            },
            "useBrowser": {
              "default": false,
              "description": "in default browser open url",
              "type": "boolean"
            },
            "useGitParams": {
              "default": false,
              "description": "open git params",
              "type": "boolean"
            },
            "branchKey": {
              "type": "string",
              "default": "",
              "description": "git params key"
            }
          }
        }
      }
    }
  },
  "bugs": {
    "url": "https://github.com/xiaonanhaier/vscode-tab-manager/issues"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/xiaonanhaier/vscode-tab-manager.git"
  },
  "scripts": {
    "lint": "eslint .",
    "pretest": "yarn run lint",
    "test": "node ./test/runTest.js"
  },
  "devDependencies": {
    "@types/vscode": "^1.61.0",
    "@types/glob": "^7.1.4",
    "@types/mocha": "^9.0.0",
    "@types/node": "14.x",
    "eslint": "^7.32.0",
    "glob": "^7.1.7",
    "mocha": "^9.1.1",
    "typescript": "^4.4.3",
    "@vscode/test-electron": "^1.6.2"
  }
}

2. 读取配置文件,显示选择列表

// 打开列表
async function showQuickPickAsync () {
   // 获取配置信息
   // 文档:https://code.visualstudio.com/api/extension-capabilities/common-capabilities#configuration
   const configuration = vscode.workspace.getConfiguration();
   const tabList = configuration.get('TabManager.tabList');
   if (!tabList) return null;

   // 用户选择
   // 文档:https://code.visualstudio.com/api/extension-capabilities/common-capabilities#quick-pick
   const res = await vscode.window.showQuickPick(tabList.map(item => item.tabName), {
      placeHolder: 'select tab',
   });

   // 返回选择的配置内容
   return res ? tabList.find(item => item.tabName === res) : null;
}

3. 获取要打开的

// 组装URL
async function getTabUrlAsync(selectedTab) {
   const {URL} = require('url');
   const {tabUrl, params = {}, useGitParams, branchKey} = selectedTab;
   const urlObj = new URL(tabUrl);
   Object.keys(params).forEach(key => urlObj.searchParams.set(key, params[key]));

   if(useGitParams) {
      const branchK = branchKey || 'branch';
      const branchName = await getGitBranchNameAsync(); // 获取git分支信息
      urlObj.searchParams.set(branchK, branchName);
   }

   return urlObj.toString();
}

4. 打开页面

// 打开页面
async function printDefinitionsForActiveEditor(selectedTab) {
   const url = await getTabUrlAsync(selectedTab);

   // 在默认浏览器打开
   if (selectedTab.useBrowser) {
      return vscode.env.openExternal(vscode.Uri.parse(url))
   }

  // 创建并显示新的webview
   const panel = vscode.window.createWebviewPanel(
      selectedTab.tabName,
      selectedTab.tabName,
      {
         viewColumn: vscode.ViewColumn.Three
      },
      {
         enableScripts: true,
      }
   );
   panel.webview.html = `
      <!DOCTYPE html>
      <html lang="en" style="width:100%;height:100%">
      <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <title>Cat Coding</title>
      </head>
      <body style="width:100%;height:100%">
         <iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms" width="100%" height="100%" src="${url}"/>
      </body>
      </html>
   `
}

3. 打包发布

1. 安装 vsce,一个用于将插件发布到市场上的命令行工具。

npm install -g vsce

2. 注册一个Azure DevOps 账号,获取 Personal Access Token

vsce login name
vsce package --no-yarn // 打包为一个.vsix

3. 如果需要发布到插件市场,还需要到 插件市场 注册一个账号,然后发布即可。

vsce publish

4. 安装

macOS 打开命令面板(Cmd+Shift+P)并键入“shell command”以找到Shell 命令:在 PATH命令中安装“code”命令。

code --install-extension ./TabManager-0.0.1.vsix