关于vscode插件:vscode插件开发

23次阅读

共计 9380 个字符,预计需要花费 24 分钟才能阅读完成。

vscode 插件开发

当时阐明

  • 该插件提供以下能力

    1. 在编辑器中选中的内容下一行增加 console.log(‘content’, content)

      命令行操作: Insert Log
      快捷键: 
          win: ctrl+w
          mac: cmd+shift+w
    2. 删除以后文件中所有的 console

      命令行操作: Del all Logs
      快捷键:
          win: ctrl+r
          mac: cmd+shift+r
    3. 删除以后文件所有正文

      命令行操作: Remove all comments
      快捷键:
          win: ctrl+t
          mac: cmd+shift+t
  • 该文档记录一下 从插件代码初始化, 到插件工程目录阐明, 到 package.json 字段阐明, 到 extension.ts 文件阐明, 到性能实现, 到 azure devops 插件市场账号申请, 到插件公布的过程

工程初始化

// 当时全局装置 yo(脚手架工具, 生成模板) generator-code(vscode 拓展生成器, 配合 yo 应用构建我的项目)
npm install yo generator-code -g
yo code   // 找个目录初始化我的项目

? What type of extension do you want to create(您想要创立什么类型的扩大?)? New Extension (TavaScript)
? What’s the name of your extension(你的分机名是什么,也就是我的项目名)? auto-log
? What’s the identifier of your extension(你的扩大的标识符是什么)? auto-log
? What’s the description of your extension(什么是您的扩大的形容)? auto-log
? Initialize a git repository(初始化一个 git 仓库)? Yes
? bundel the source code with webpack (是否用 webpack 打包源码)?No
? Which package manager to use(应用哪个包管理器)? npm

初始化工程目录阐明

初始化 package.json 字段阐明(后续新增的字段, 后续阐明)

{
    "name": "auto-log",// 插件工程名称
    "displayName": "auto-log",    // 插件市场显示的名字
    "description": "auto-log",    // 插件形容
    "version": "0.0.1",    // 插件版本号
    "engines": {    // 示意插件最低反对的 vscode 版本
        "vscode": "^1.73.0"
    },
    "categories": [        // 插件利用市场分类
        "Other"
    ],
    "activationEvents": [        // 插件的被动激活事件,可配 * 来放弃在后盾继续运行
        "onCommand:auto-log.helloWorld"
    ],
    "main": "./out/extension.js",        // 插件性能的主入口文件
    "contributes": {    // 奉献点,整个插件最重要最多的配置项
        "commands": [
            {
                "command": "auto-log.helloWorld",
                "title": "Hello World"
            }
        ]
    },
    "scripts": {        // 执行命令
        "vscode:prepublish": "npm run compile",
        "compile": "tsc -p ./",
        "watch": "tsc -watch -p ./",
        "pretest": "npm run compile && npm run lint",
        "lint": "eslint src --ext ts",
        "test": "node ./out/test/runTest.js"
    },
    "devDependencies": {        // 依赖
        "@types/vscode": "^1.73.0",
        "@types/glob": "^7.2.0",
        "@types/mocha": "^9.1.1",
        "@types/node": "16.x",
        "@typescript-eslint/eslint-plugin": "^5.27.0",
        "@typescript-eslint/parser": "^5.27.0",
        "eslint": "^8.16.0",
        "glob": "^8.0.3",
        "mocha": "^10.0.0",
        "typescript": "^4.7.2",
        "@vscode/test-electron": "^2.1.3"
    }
}

在这 package.json 文件中,重点关注的次要有三局部内容:activationEvents、main 以及 contributes,其是整个文件中的重中之重。

1、main
指明了该插件的主入口在哪,只有找到主入口整个我的项目能力失常的运行

2、activationEvents
指明该插件在何种状况下才会被激活,因为只有激活后插件能力被失常应用,官网曾经指明了激活的机会 (opens new window),这样咱们就能够按需设置对应机会。(具体每个机会用的时候具体查看即可)

onLanguage 关上解析为特定语言文件时被激活,例如 ”onLanguage:python”
onCommand 在调用命令时被激活
onDebug 在启动调试话之前被激活
onDebugInitialConfigurations
onDebugResolve
workspaceContains 每当关上文件夹并且该文件夹蕴含至多一个与 glob 模式匹配的文件时
onFileSystem 每当读取来自特定计划的文件或文件夹时
onView 每当在 VS Code 侧栏中开展指定 id 的视图
onUri 每当关上该扩大的零碎范畴的 Uri 时
onWebviewPanel
onCustomEditor
onAuthenticationRequest
只有一启动 vscode,插件就会被激活
onStartupFinished
3、contributes
通过扩大注册 contributes 用来扩大 Visual Studio Code 中的各项技能,其有多个配置,如下所示:

breakpoints 断点
colors 主题色彩
commands 命令
configuration 配置
configurationDefaults 默认的特定于语言的编辑器配置
customEditors 自定义编辑器
debuggers
grammars
iconThemes
jsonValidation
keybindings 快捷键绑定
languages
menus 菜单管制
problemMatchers
problemPatterns
productIconThemes
resourceLabelFormatters
snippets 特定语言的片段
submenus
taskDefinitions
themes 色彩主题
typescriptServerPlugins
views
viewsContainers
viewsWelcome
walkthroughs

extension.ts 文件阐明

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
// 依赖导入
import * as vscode from 'vscode';

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed

// 总的来说该文件须要导出两个办法 activate 和 deactivate    
// 其中 activate 是插件被激活时执行的函数 
// deactivate 是插件被销毁时调用的办法,比方开释内存等    
export function activate(context: vscode.ExtensionContext) {// Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension"auto-log"is now active!');

    // The command has been defined in the package.json file
    // Now provide the implementation of the command with registerCommand
    // The commandId parameter must match the command field in package.json
    let disposable = vscode.commands.registerCommand('auto-log.helloWorld', () => {
        // The code you place here will be executed every time your command is executed
        // Display a message box to the user
        vscode.window.showInformationMessage('Hello World from auto-log!');
    });

    context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
export function deactivate() {}

性能实现

package.json

{
    "name": "auto-log",
    "displayName": "auto-log",
    "description": "auto-log",
    "version": "0.0.2",
    "publisher": "jianting-wu",
    "engines": {"vscode": "^1.73.0"},
    "categories": ["Other"],
    "activationEvents": [ // 注册命令
        "onCommand:auto-log.insert",
        "onCommand:auto-log.del",
        "onCommand:auto-log.remove-comments"
    ],
    "main": "./out/extension.js",
    "contributes": {
        "commands": [
            {
                "command": "auto-log.insert",
                "title": "Insert Log"    // cmd+shift+p 命令行中输出的命令, 也是右键显示的命令
            },
            {
                "command": "auto-log.del",
                "title": "Del all Logs"
            },
            {
                "command": "auto-log.remove-comments",
                "title": "Remove all comments"
            }
        ],
        "keybindings": [    // 绑定快捷键
            {
                "command": "auto-log.insert",
                "key": "ctrl+w",
                "mac": "cmd+shift+w",
                "when": "editorTextFocus"
            },
            {
                "command": "auto-log.del",
                "key": "ctrl+r",
                "mac": "cmd+shift+r",
                "when": "editorTextFocus"
            },
            {
                "command": "auto-log.remove-comments",
                "key": "ctrl+t",
                "mac": "cmd+shift+t",
                "when": "editorFocus"
            }
        ],
        "menus": {
            "editor/context": [        // 配置右键显示
                {
                    "when": "editorTextFocus",
                    "command": "auto-log.insert",
                    "group": "navigation"
                },
                {
                    "when": "editorTextFocus",
                    "command": "auto-log.del",
                    "group": "navigation"
                },
                {
                    "when": "editorFocus",
                    "command": "auto-log.remove-comments",
                    "group": "navigation"
                }
            ]
        }
    },
    "scripts": {
        "vscode:prepublish": "npm run compile",
        "compile": "tsc -p ./",
        "watch": "tsc -watch -p ./",
        "pretest": "npm run compile && npm run lint",
        "lint": "eslint src --ext ts",
        "test": "node ./out/test/runTest.js"
    },
    "devDependencies": {
        "@types/vscode": "^1.73.0",
        "@types/glob": "^7.2.0",
        "@types/mocha": "^9.1.1",
        "@types/node": "16.x",
        "@typescript-eslint/eslint-plugin": "^5.27.0",
        "@typescript-eslint/parser": "^5.27.0",
        "eslint": "^8.16.0",
        "glob": "^8.0.3",
        "mocha": "^10.0.0",
        "typescript": "^4.7.2",
        "@vscode/test-electron": "^2.1.3"
    },
    "repository": {
        "type": "git",
        "url": "https://github.com/ulahala/auto-log.git"
    }
}

src/extension.ts

import * as vscode from 'vscode';
import insert from './insert';
import del from './del';
import remove from './remove';

const commandList = [{command: 'auto-log.insert', handler: insert},
    {command: 'auto-log.del',handler: del},
    {command: 'auto-log.remove-comments',handler: remove}
];

export function activate(context: vscode.ExtensionContext) {console.log('activated inter');

    commandList.forEach(({command, handler}) => {context.subscriptions.push(vscode.commands.registerCommand(command, handler));
    });

}

export function deactivate() {}

src/insert.ts

import * as vscode from 'vscode';

function insertText(str: string) {
    const editor = vscode.window.activeTextEditor;

    if(!editor) {return vscode.window.showErrorMessage('Can\'t insert log becase no document is opened');};

    const selection = editor.selection;

    const lineOfSelectionVar = selection.active.line;

    editor.edit(editBuilder => {
        // todo: 插入地位和选中行 头部对齐
        editBuilder.insert(new vscode.Position(lineOfSelectionVar + 1, 0), str);
    });
}

export default () => {
    const editor = vscode.window.activeTextEditor;

    if(!editor) {return;}

    const selection = editor.selection;

    const text = editor.document.getText(selection);

    const logToInsert = `console.log('${text}', ${text});\n`;

    text ? insertText(logToInsert) : insertText('console.log();\n');
};

src/del.ts

import * as vscode from 'vscode';

function getAllLogs() {
    const editor = vscode.window.activeTextEditor;

    if(!editor) {return [];};

    const document = editor.document;

    const documentText = document.getText();

    const allLogs = [];

    const logRegex = /console.(log|debug|info|warn|error|assert|dir|dirxml|trace|group|groupEnd|time|timeEnd|profile|profileEnd|count)\((.*)\);?/g;

    let match;
    while(match = logRegex.exec(documentText)) {let matchRange = new vscode.Range(document.positionAt(match.index), document.positionAt(match.index + match[0].length));

        if(!matchRange.isEmpty) {allLogs.push(matchRange);};
    }

    return allLogs;
}


export default () => {
    const editor = vscode.window.activeTextEditor;

    if(!editor) {return;};

    const workspaceEdit = new vscode.WorkspaceEdit();

    const document = editor.document;

    const allLogs = getAllLogs();

    allLogs.forEach(log => {workspaceEdit.delete(document.uri, log);
    });

    vscode.workspace.applyEdit(workspaceEdit).then(() => {vscode.window.showInformationMessage(`${allLogs.length} console deleted`);
    });

};

src/remove.ts

import * as vscode from 'vscode';


export default () => {
    const editor = vscode.window.activeTextEditor;

    if(!editor) {return;}

    editor.edit(editBuilder => {let text= editor.document.getText();

        text = text.replace(/((\/\*([\w\W]+?)\*\/)|(\/\/(.(?!"\)))+)|(^\s*(?=\r?$)\n))/gm,'')
                    .replace(/(^\s*(?=\r?$)\n)/gm, '')
                    .replace(/\\n\\n\?/gm, '');

        const end = new vscode.Position(editor.document.lineCount + 1, 0);

        editBuilder.replace(new vscode.Range(new vscode.Position(0, 0), end), text);

        vscode.commands.executeCommand('editor.action.formatDocument');

    });
};

azure devops 插件市场账号申请

简略阐明一下:
Visual Studio Code 的利用市场基于微软本人的 Azure DevOps,插件的身份验证、托管和治理都是在这里。

  • 要公布到利用市场首先得有利用市场的 publisher 账号;
  • 而要有公布账号首先得有 Azure DevOps 组织;
  • 而创立组织之前,首先得创立 Azure 账号;
  • 创立 Azure 账号首先得有 Microsoft 账号;

而且

  • 一个 Microsoft 账号能够创立多个 Azure 组织;
  • 一个组织能够创立多个 publisher 账号;
  • 同时一个组织能够创立多个 PAT(Personal Access Token,集体拜访令牌);
  1. 申请 Microsoft 账号
    登录 Microsoft , 没有的话注册一个
  2. 创立 Azure DevOps 组织

https://aka.ms/SignupAzureDevOps

点击 continue 创立组织

  1. 创立令牌

进入组织的主页后,点击右上角的 Security,点击创立新的集体拜访令牌,这里特地要留神 Organization 要抉择 all accessible organizations,Scopes 要抉择 Full access,否则前面发布会失败。

点击 Create 创立 token, token 要本人存一下, 在公布的时候要用的, 没存的话公布的时候得从新生成

  1. 创立公布账号

拜访 https://aka.ms/vscode-create-publisher

把 name 和 id 这俩必填的填上就行 这个 name 要和你插件的 package.json 中的 ‘publisher’ 字段保持一致

点击下方 Create 创立公布账号, 这块如果你用的 google 浏览器会有个 无奈加载 recaptcha 的报错, 这是 google 的人机验证, 头铁的多试几次, 头肿了了用火狐搞, 解决办法的话查一下 无奈加载 recaptcha 不细讲了, 反正我头铁过来了

到这了账号的问题根本搞完了, 接下来就是搞公布的事了

  1. 公布到利用市场

先全局装置 vsce, 这个是 vscode 插件的打包工具

npm install vsce -g

而后本地创立一个发布者

vsce create-publisher jianting-wu 
// 这个名字要和创立公布账号的那个 name 统一, 和 package.json 中的 'publisher' 字段统一

而后在我的项目根目录下执行

vsce publish

第一次执行会让你输出下面生成的 token, 还遇到提醒 package.json 中没有 repository 字段, 根目录下没有 LICENSE… 爱补就补上

而后等个几分钟, 在利用市场上就能看到你公布的利用了

完事, 先到这 …

正文完
 0