乐趣区

FEBASEvscode使用原理插件开发笔记

使用

命令行使用

  • 帮助:code --help
  • 使用已经打开的窗口来打开文件:code -r
  • 打开文件并滚动到特定行:code -r -g package.json:128
  • 比较两个文件:code -r -d a.txt b.txt
  • 接受管道符数据:ls | code -

图形界面、快捷键使用

  • 光标移动至

    • 单词开头 / 末尾 Ctrl + Left/Right,
    • 代码块开头 / 末尾 Cmd + Shift + \
    • 文档首行 / 末行 Ctrl + Home/End
  • 文本

    • 全选 / 剪切 / 复制 / 黏贴 / 保存 Ctrl A/X/C/V/S
    • 文本选择 = Shift + 上述光标操作
    • 格式化 Alt + Shift + F
    • 格式化部分:选中,Ctrl + K + Ctrl + F
    • 删除 Ctrl + Shift + K
    • 剪切 / 复制 / 黏贴 Ctrl + X/C/V
    • 在当前行的下 (上) 面新开始一行 Ctrl (+ Shift) + Enter
    • 上 / 下移动 Alt + 上 / 下
  • 文档

    • 查找 / 替换 / 符号跳转 Ctrl + F/H/T
    • 转到行 Ctrl + G
    • 转到文件 Ctrl + P
    • 转到符号 Ctrl + Shift + O
    • 打开命令面板 Ctrl + Shift + P
  • 窗体

    • 关闭Ctrl + W
    • 打开关闭侧边栏 Ctrl + B
    • 侧边栏位置 命令面板toggle side bar pos
    • markdown 预览 Ctrl + K V
    • 1/2/ 3 列 Ctrl + 1/2/3
    • 行列切换 Shift + Alt + 0
    • 2×2 布局 命令面板2x2
    • Tab 切换 Ctrl + Pagedown/Pageup
    • 缩放 Ctrl + /-(reset zoom 恢复)
  • 自定义快捷键 Ctrl + K + Ctrl + S
  • 鼠标操作

    • 选中单词 双击
    • 选中行 三击 / 单击行号
    • 多光标:Alt + 单击
    • 代码跳转:Ctrl + 单击
  • 编码

    • 代码补全 Ctrl + 空格
    • 代码折叠 / 展开 Ctrl + Shift + [/]
    • 参数预览 Ctrl + Shift + Space
    • 自动修复建议 Ctrl + .
    • 打开终端 Ctrl + Shift + `
    • 隐藏 / 显示面板 Ctrl + J
    • 转到上次编辑位置 命令面板go to last edit
    • 调出最近打开的工作区 Ctrl + R
  • 用户设置

    • 面包屑:breadcrumbs
    • 小地图:minimap
    • 自动格式化:formatOnSave、formatOnType
    • 自动保存:autoSave
    • 默认语言:default language
  • 其他用户设置

    • editor cursor,光标渲染和多光标
    • editor find,编辑器内搜索
    • editor font,字体

      • 连字字体

        "editor.fontFamily": "Fira Code",
        "editor.fontLigatures": true
    • editor format,代码格式化
    • editor suggest,自动补全、建议窗口

emment

https://docs.emmet.io/abbrevi…

编辑执行任务 tasks

命令面板输入conf task

shell

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo Hello"
        }
    ]
}
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo",
            "args": [
                {
                    "value": "Hello World",
                    "quoting": "escape"
                }
            ]
        }
    ]
}

process

{
 "version": "2.0.0",
 "tasks": [
  {
   "label": "chrome",
   "type": "process",
   "command": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","windows": {"command": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
      },
      "linux": {"command": "/usr/bin/google-chrome"}
  }
 ]
}

group

{
 "version": "2.0.0",
 "tasks": [
  {
   "label": "test shell",
   "type": "shell",
   "command": "./scripts/test.sh",
   "windows": {"command": ".\\scripts\\test.cmd"},
   "group": "test",
   "presentation": {
    "reveal": "always",
    "panel": "new"
   },
   "options": {"cwd": "","env": {},"shell": {"executable":"bash"}
   }
  }
 ]
}

安装 quick task 插件便于可视化

自定义问题分析器

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "echo",
            "args": [
                {
                    "value": "index.js:5:3: warning: unused variable",
                    "quoting": "escape"
                }
            ],
            "problemMatcher": {
                "owner": "echo",
                "fileLocation": ["relative", "${workspaceFolder}"],
                "pattern": {"regexp": "^(.*):(\\d +):(\\d +):\\s + (warning|error):\\s + (.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            }
        }
    ]
}

多任务

{
 "taskName": "compile",
 "dependsOn": [
  "frontend",
  "backend"
 ],
 "group": {
  "kind": "build",
  "isDefault": true
 }
}

更多资料

https://code.visualstudio.com…

调试

VS Code 为插件作者提供了一套统一的接口,叫做 Debug Adapter Protocol(DAP),插件最终实现调试功能。

自带 node 调试插件 Node Debug
需安装 chrome 调试插件Debugger for Chrome

vscode 架构

Visual Studio Code / Egret Wing 技术架构

基于 Electron(Chromium + node)electron 应用结构

vscode 源码结构
VSCode 源码阅读

vscode 插件架构

  • 3 个主要进程:

    • 第一次被启动时会创建一个主进程(main process)
    • 每个窗口都会创建一个渲染进程(Renderer Process)
    • 每个窗口都会创建一个执行插件宿主进程(Extension Host)

还有两种特殊的进程:

- 调试进程(Debug Adapter),渲染进程会通过 VS Code Debug Protocol 跟 Debug Adapter 进程通讯。- 语言支持(Language Server)

开发插件

VSCode 插件开发急速入门

准备工作

确保安装了 Node.js 和 Git
然后安装 Yeoman 和 VS Code Extension Generator 和 VSCE:

npm install -g yo@latest generator-code vsce

注册账号 https://aka.ms/SignupAzureDevOps
登录后 User settings 选择 Security, 添加 token, 注意备份, 之后要用

yo code myextension创建一个 VS Code 的插件模板, 选择类型
cd myextension && code . 开始编辑

重要文件

- package.json 记录了 node 应用和插件的信息
- extension.js 当前插件的全部代码
- .vscode 官方提供的调试配置、任务配置等

编写 js/ts 代码插件(New Extension)

extension.js

const vscode = require('vscode');
// 激活扩展程序时会调用此方法
// 您的扩展程序在第一次执行命令时被激活 
function activate(context) {
    // 使用控制台输出诊断信息(console.log)和错误(console.error)// 此代码行仅在激活扩展程序时执行一次 
    console.log('Congratulations, your extension"mdf"is now active!');
    // 该命令已在 package.json 文件中定义
    // 现在使用 registerCommand 提供命令的实现
    //commandId 参数必须与 package.json 中的命令字段匹配 
    let disposable = vscode.commands.registerCommand('extension.helloWorld', function () {
        // 每次执行命令时,都会执行此处放置的代码
        vscode.window.showInformationMessage('Hello World!');// 向用户显示消息框 
    });
    context.subscriptions.push(disposable);
}
exports.activate = activate;
// 停用扩展程序时会调用此方法 
function deactivate() {}
module.exports = {
    activate,
    deactivate
}

package.json

  • engines 指定了运行这个插件需要的 VS Code 版本

    "vscode": "^1.29.0"
  • activationEvents 指定了什么情况下这个插件应该被加载并且激活

    "activationEvents": ["onCommand:extension.sayHello"]
  • contributes VS Code 会把这个 command 命令注册到命令面板中

    "contributes": {
        "commands": [
            {
                "command": "extension.sayHello",
                "title": "Hello World"
            }
        ]
    },

调试 F5(会再开一个 vscode, 请确保电脑内存充足)
查询 API vscode.languages定义文件 vscode.d.ts

编写快捷键插件 (Keymap)

只需编写package.json

"contributes": {
    "commands": [
        {
            "command": "extension.sayHello",
            "title": "Hello World"
        }
    ],
   "keybindings": [
        {
            "key": "ctrl + t",
            "command": "extension.sayHello",
            "when": "editorTextFocus"
        }
    ]
},

示例:Notepad + + 源码
注意事项:"activationEvents": ["*"]永远激活插件可能影响性能,慎用。

编写代码片段 (Code Snippets)

只需编写 snippets/snippets.json(若不分享插件则本地命令面板输入 snippets 即可编写)
snippets.json

{
    "Print to console": {
        "prefix": "log",
        "body": ["console.log(${1:i});",
            "console.log(${1:i} + 1); // ${1:i} + 1",
            "$2"
        ],
        "description": "Log output to console"
    }
}

package.json

"contributes": {
    "snippets": [
        {
            "language": "javascript",
            "path": "./snippets/snippets.json"
        }
    ]
}

snippet- 官网资料

编写主题插件(New Color Theme)

编写 themes/mytheme-color-theme.json
以及package.json

"contributes": {
    "themes": [
        {
            "label": "mytheme",
            "uiTheme": "vs-dark",
            "path": "./themes/mytheme-color-theme.json"
        }
    ]
}

编写语言支持(New Language Support)

  • tmLanguage: 语言语法定义文件(正则搜索代码并标注类型)参考文档
  • Language id: 语言唯一标识
  • Language name: 语言名字
  • File extensions 文件后缀

package.json

  • configurations:./ language-configuration.json 语言的配置信息所在文件的相对地址
  • language-configuration.json 语言相关信息的模板
{
    "comments": {
        "lineComment": "//",// 单行注释
        "blockComment": ["/*", "*/"]// 多行注释
    },
    "brackets": [// 支持的括号类型
        ["{", "}"],
        ["[", "]"],
        ["(", ")"]
    ],
    "autoClosingPairs": [// 键入时自动关闭的符号
        ["{", "}"],
        ["[", "]"],
        ["(", ")"],
        ["\"", "\""],
        ["'","'"]
    ],
    "surroundingPairs": [// 可用于包围选区的符号 
        ["{", "}"],
        ["[", "]"],
        ["(", ")"],
        ["\"", "\""],
        ["'","'"]
    ],"folding": {// 可被折叠的代码段的开头和结尾
        "markers": {
            "start": "^\\s*//#region",
            "end": "^\\s*//#endregion"
        }
    },
    "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\ + \\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s] + )",// 一个单词
    "indentationRules": {// 如何根据一行的内容来控制缩进
        "increaseIndentPattern": "^\\s*((begin|class|(private|protected)\\s + def|def|else|elsif|ensure|for|if|module|rescue|unless|until|when|while|case)|([^#]*\\sdo\\b)|([^#]*=\\s*(case|if|unless)))\\b([^#\\{;]|(\"|'|\/).*\\4)*(#.*)?$",
        "decreaseIndentPattern": "^\\s*(}\\]]?\\s*(#|$)|\\.[a-zA-Z_]\\w*\\b)|(end|rescue|ensure|else|elsif|when)\\b)"
    }
}

插件发布

插件市场
使用 vsce 工具命令创建发布账号 vsce create-publisher your-publisher-name
登录账号 vsce login your-publisher-name
发布 vsce publish
发布 - 官方文档

官方 demo

https://github.com/Microsoft/…

其他教程

VSCode 插件开发全攻略

API 使用

工作台 API

  1. Information、Warning、Error 消息
vscode.window.showInformationMessage('Hello World', 'Yes', 'No').then(value => {value=='Yes'&&vscode.window.showWarningMessage('User press' + value);
    value=='No'&&vscode.window.showErrorMessage('User press' + value);
})
  1. QuickPick

给用户提供了一系列选项,然后根据用户选择的选项进行下一步的操作。

vscode.window.showQuickPick(['first', 'second', 'third']).then(value => {vscode.window.showInformationMessage('User choose' + value);
})
vscode.commands.registerCommand('extension.sayHello', () => {
    vscode.window.showQuickPick([{
        label: 'first',
        description: 'first item',
        detail: 'first item details'
    }, {
        label: 'second',
        description: 'second item',
        detail: 'second item details'
    }]).then(value => {vscode.window.showInformationMessage('User choose' + value.label);
    })
});

面板(Panel) API

  1. 问题面板
let collection = vscode.languages.createDiagnosticCollection('myextension');
    let uri = vscode.window.activeTextEditor.document.uri;
    collection.set(uri, [
        {range: new vscode.Range(0, 0, 0, 1),
            message: 'We found an error'
        }
    ]);
  1. 输出面板
let channel =vscode.window.createOutputChannel('MyExtension');
channel.appendLine('Hello World');

调试面板
终端面板

视图(TreeView) API

vscode.window.registerTreeDataProvider('myextension', {getChildren: (element) => {if (element) {return null;}

        return ['first', 'second', 'third'];
    },
    getTreeItem: (element) => {
        return {
            label: element,
            tooltip: 'my' + element + 'item'
        }
    }
})

package.json 的 contributes

"contributes": {
        "views": {
   "explorer": [
    {
     "id": "myextension",
     "name": "My Extension"
                }
            ]
        }
    }

WebView API 来生成任意的编辑器内容
FileSystemProvider 或者 TextDocumentContentProvider 来为 VS Code 提供类似于本地文件的文本内容

装饰器(Decorations) API

let decorationType = vscode.window.createTextEditorDecorationType({
    backgroundColor: '#fff',
    border: '1px solid red;',
    fontStyle: 'italic',
    letterSpacing: '3px'
});
let editor = vscode.window.activeTextEditor;
editor.setDecorations(decorationType, [new vscode.Range(0, 0, 0, 1)]);

createTextEditorDecorationType(DecorationRenderOptions)

DecorationRenderOptions={
    // 颜色和背景相关
    backgroundColor?: string | ThemeColor;
    color?: string | ThemeColor;
    overviewRulerColor?: string | ThemeColor;
    // 边框
    border?: string;
    borderColor?: string | ThemeColor;
    borderRadius?: string;
    borderSpacing?: string;
    borderStyle?: string;
    borderWidth?: string;
    // 轮廓
    outline?: string;
    outlineColor?: string | ThemeColor;
    outlineStyle?: string;
    outlineWidth?: string;
    // 字体
    fontStyle?: string;
    fontWeight?: string;
    opacity?: string;
    letterSpacing?: string;
    // 其他
    gutterIconPath?: string | Uri;
    gutterIconSize?: string;
    before?: ThemableDecorationAttachmentRenderOptions;
    after?: ThemableDecorationAttachmentRenderOptions;
}

ThemeColor

new vscode.ThemeColor('editorWarning.foreground') 

插件参考:Rainbow Brackets 和 Indent Rainbow

插件 API 设计模式

发布流程:

  • 提议(Proposal),API 在 vscode.proposed.d.ts 文件中,
  • 维护团队 review,要点:

    • 插件 API 不会将 UI 直接暴露给插件。插件提供内容,VS Code 负责渲染。增量更新,尽可能地减少 VS Code 重新渲染
    • 长时间运行的任务应该支持 Promise,并可以取消
    • 插件 API 能够正确地处理对象的生命周期。VS Code 使用了 Dispose 模式,运行 dispose 可以将这个对象销毁。
  • 稳定版本(Stable),API 则是在 vscode.d.ts 里

Node.js 模块使用:

  • 使用模块要克制
  • treeshaking
  • Native Module:不用担心 Electron 升级的问题;不同的平台要分别编译
  • Web Assembly:无法访问系统 API

参考

极客时间 - 玩转 vscode

your-first-extension

退出移动版