vscode插件开发入门:重要文件详解

392 阅读5分钟

package.json 详解

参考: code.visualstudio.com/api/referen…

{
  // 插件名称,应全部小写,不能有空格
    "name": "helloworld",
  // 显示在插件市场的名称,支持中文
    "displayName": "helloworld",
  // 描述
    "description": "",
  // 版本号
    "version": "0.0.1",
  // 关键字,用于应用市场搜索
  "keywords": ["vscode", "plugin", "demo"],
  // 发布者,如果要发布到应用市场的话,这个名字必须与发布者一致
  "publisher": "etest",
  // 表示插件最低支持的vscode版本
    "engines": {
        "vscode": "^1.92.0"
    },
  // 插件应用市场分类,可选值: [Programming Languages, Snippets, Linters, Themes, Debuggers, Formatters, Keymaps, SCM Providers, Other, Extension Packs, Language Packs]
    "categories": [
        "Other"
    ],
  // 设置插件的激活事件, 即在什么情况下插件会被激活;
  // 扩展的激活事件;如: 在命令面板中调用 myExtension.sayHello 命令时插件会被激活
    "activationEvents": ["onCommand:myExtension.sayHello"],
  // 插件的入口文件
    "main": "./dist/extension.js",
  // contributes为插件的贡献点,也是最重要的配置项,定义插件的各种扩展功能
    "contributes": {
    // 命令配置项,即通过Ctrl + Shift + P 输入的命令
        "commands": [
            {
                "command": "vs.helloWorld",
                "title": "Hello World"
            }
        ],
    // 插件的语言配置
    "languages": [
            {
                "id": "typescript",
                "aliases": [
                    "TypeScript",
                    "ts",
                    "typescript"
                ],
        // 设置后缀名
                "extensions": [
                    ".ts"
                ]
            }
        ],
    // 插件语法配置文件, 系统可以通读取对应的语法文件实现语法高亮
        "grammars": [
            {
                "language": "python",
                "scopeName": "source.python",
                "path": "./syntaxes/python.tmLanguage.json"
            }
        ],
    // 代码片段
    "snippets": [
        {
            "language": "javascript",
            "path": "./snippets/javascript.json"
        },
        {
            "language": "html",
            "path": "./snippets/html.json"
        }
    ],
    // 插件配置项,可以在setting.json里面设置的值;可以在插件工程里面读取对应的值
    "configuration": {
            "type": "object",
      // 配置项标题,会显示在vscode的设置页
            "title": "Typescript configuration",
            "properties": {
                "Typescript.encoding": {
                    "type": "string",
                    "default": "utf-8",
                    "description": "default file encoding"
                },
                "Typescript.yourName": {
                    "type": "string",
                    "default": "guest",
                    "description": "你的名字"
                },
                "Typescript.showTip": {
                    "type": "boolean",
                    "default": true,
                    "description": "是否在每次启动时显示欢迎提示!"
                }
            }
        },
    // 自定义菜单配置项
    "menus": {
        "commandPalette": [
          {
              "command": "myExtension.sayHello",
              "when": "editorLangId === markdown"
          }
        ],
        // 编辑器右键菜单
        "editor/context": [
          {
            // 表示只有编辑器具有焦点时才会在菜单中出现
            "when": "editorFocus",
            "command": "extension.sayHello",
            // navigation是一个永远置顶的分组,后面的@6是人工进行组内排序
            "group": "navigation@6"
          },
        ],
        // 编辑器右上角图标,不配置图片就显示文字
        "editor/title": [
          {
            "when": "editorFocus && resourceLangId == javascript",
            "command": "extension.demo.testMenuShow",
            "group": "navigation"
          }
        ],
        // 编辑器标题右键菜单
        "editor/title/context": [
          {
            "when": "resourceLangId == javascript",
            "command": "extension.demo.testMenuShow",
            "group": "navigation"
          }
        ],
              // 资源管理器右键菜单
        "explorer/context": [
          {
            "command": "extension.demo.getCurrentFilePath",
            "group": "navigation"
          },
          {
            "command": "extension.demo.openWebview",
            "group": "navigation"
          }
        ]
    },

    "keybindings": [
            {
        // 快捷键关联的命令
                "command": "paisen.Typescript",
        // Windows平台对应的快捷键
                "key": "ctrl+shift+a",
        // Mac平台对应的快捷键
                "mac": "ctrl+shift+a",
        // 快捷键生效时机
                "when": "editorTextFocus"
            }
        ],
    // 自定义新的activitybar图标,也就是左侧侧边栏大的图标
    "viewsContainers": {
      "activitybar": [
          {
              "id": "running",
              "title": "奔跑",
              "icon": "images/running.svg"
          }
      ]
    },
    // 图标主题
    "iconThemes": [
      {
          "id": "testIconTheme",
          "label": "测试图标主题",
          "path": "./theme/icon-theme.json"
      }
    ]
    },
    "scripts": {
        "vscode:prepublish": "yarn run package",
        "compile": "webpack",
        "watch": "webpack --watch",
        "package": "webpack --mode production --devtool hidden-source-map",
        "compile-tests": "tsc -p . --outDir out",
        "watch-tests": "tsc -p . -w --outDir out",
        "pretest": "yarn run compile-tests && yarn run compile && yarn run lint",
        "lint": "eslint src --ext ts",
        "test": "vscode-test"
    },
    "devDependencies": {
        "@types/vscode": "^1.92.0",
        "@types/mocha": "^10.0.7",
        "@types/node": "20.x",
        "@typescript-eslint/eslint-plugin": "^7.14.1",
        "@typescript-eslint/parser": "^7.11.0",
        "eslint": "^8.57.0",
        "typescript": "^5.4.5",
        "ts-loader": "^9.5.1",
        "webpack": "^5.92.1",
        "webpack-cli": "^5.1.4",
        "@vscode/test-cli": "^0.0.9",
        "@vscode/test-electron": "^2.4.0"
    },
  "repository": {
    "type": "git",
    "url": "https://github.com/***"
  },
  // 主页
  "homepage": "https://github.com/***/master/README.md"
}

activationEvents

插件在 VSCode 中默认是没有被激活的,那什么时候才被激活呢?就是通过 activationEvents 来配置
activationEvents 配置项配置插件的激活数组,目前支持以下 8 种配置: // 参考: code.visualstudio.com/api/referen…

  • onLanguage: 在打开对应语言文件时, 如: 配置了 onLanguage:javascript,那么只要打开了 JS 类型的文件,插件就会被激活
  • onCommand: 在执行对应命令时
  • onDebug: 在 debug 会话开始前
  • onDebugInitialConfigurations: 在初始化 debug 设置前
  • onDebugResolve: 在 debug 设置处理完之前
  • workspaceContains: 在打开一个文件夹后,如果文件夹内包含设置的文件名模式时
  • onFileSystem: 打开的文件或文件夹,是来自于设置的类型或协议时
  • onView: 侧边栏中设置的 id 项目展开时
  • onUri: 在基于 vscode 或 vscode-insiders 协议的 url 打开时
  • onWebviewPanel: 在打开设置的 webview 时
  • *: 在打开 vscode 的时候; 如果配置了'_',只要一启动 vscode,插件就会被激活,为了出色的用户体验,官方不推荐这么做(\是转义了,配置时没有)

contributes

contributes 配置项是整个插件的贡献点,也就是说 contributes 决定了这个插件有哪些功能。contributes 字段可以设置的 key 决定了 vscode 插件具有哪些功能

configuration:通过这个配置项我们可以设置一个属性,这个属性可以在 vscode 的 settings.json 中设置,然后在插件工程中可以读取用户设置的这个值,进行相应的逻辑;主要配置有如下:

参考: code.visualstudio.com/api/referen…

  • commands:命令,通过 Ctrl + Shift + P 面板输入的命令
  • menus:设置菜单选项
  • keybindings:绑定快捷键
  • languages:设置语言支持,包括语言的后缀等
  • grammars:设置描述语言的语法文件的路径等,vscode 可以根据这个语法文件来自动实现语法高亮功能
  • snippets:设置语法片段相关的路径
  • configuration:插件配置项
  • debuggers:调试
  • breakpoints:断点
  • themes:主题
  • jsonValidation:自定义 JSON 校验
  • views:左侧侧边栏视图
  • viewsContainers:自定义 activitybar
    problemMatchers problemPatterns taskDefinitions
  • colors

extension.js 解释

  • extension.js 是插件工程的入口文件,一般包括两个函数 activate 和 deactivate; activate 函数是插件激活时也就是在注册的 Activation Event 发生的时候就会执行; deactivate 中放的是插件关闭时执行的代码; 当触发 package.json 中的 activationEvents 配置项时,extension.js 文件开始执行
  • 在 activate() 函数中通过 return 返回的数据或函数可以作为接口供其他插件使用
  • 在 extension.js 中注册需要的功能,主要使用 vscode.commands.register*相关的 API,来为 package.json 中的 contributes 配置项中的事件绑定方法或者监听器, 如:
  1. registerCompletionItemProvider: 提供代码补齐提示
  2. registerHoverProvider:光标停留在 token 上时触发
  3. registerSignatureHelpProvider: 提供函数签名提示
const vscode = require('vscode');

/**
 * 插件被激活时触发,所有代码总入口
 * @param {*} context 插件上下文信息,实际上也就是当前插件的状态信息
 */
exports.activate = function (context) {
    console.log('恭喜,您的扩展“plugin-demo”已被激活!');
    // 注册命令
    context.subscriptions.push(
        // 给插件订阅extension.sayHello命令
        vscode.commands.registerCommand('extension.sayHello', function () {
            vscode.window.showInformationMessage('Hello World!');
        })
    );

    // return 的内容可以作为这个插件对外的接口
    return {
        hello() {
            return 'hello world';
        },
    };
};

/**
 * 插件被释放时触发
 */
exports.deactivate = function () {
    console.log('您的扩展“plugin-demo”已被释放!');
};
return 给其他插件提供接口

如果需要使用其他插件提供的接口,则可以在 package.json 中将对应插件添加到 extensionDependency 中,然后使用 getExtension 函数中的 export 属性

export function activate(context: vscode.ExtensionContext) {
    let api = {
        hello() {
            return 'hello world';
        },
    };
    return api;
}

// 引入其他插件接口
let helloWorld = extensions.getExtension('helloWorld');
let importedApi = helloWorld.exports;

console.log(importedApi.hello());