vscode扩展开发(四): 插件首选项配置, 编辑器内容操作, 终端操作

1,894 阅读4分钟

插件首选项配置

每一个插件都可以自行添加首选项的配置, 当打开vscode时, 可以根据首选项选择的配置, 执行不同的逻辑, 插件的首选项可以在package.jsoncontributes.configuration中配置, 如下:

// package.json

    "activationEvents": [
        "onCommand:learn-vscode-extends.customConfig"
    ],
    "contributes": {
        "commands": [
            {
                "command": "learn-vscode-extends.customConfig",
                "title": "customConfig"
            }
        ],
        "configuration": { // 首选项配置在这里配置
          "title": "learn-vscode-extends", // 这里大标题对应项目名称即可, 对应的首选项会被分到一组
          "properties": {
            "hello.title": { // 这里是副标题, 也是这个配置项的key
              "type": "string", // 类型为字符串
              "description": "这里是描述, 随便写", // 描述
              "enum": [ // 下拉选项
                "选项一",
                "选项二",
                "选项三"
              ],
              "markdownEnumDescriptions": [ // 每个选择项的说明, 可以是 markdown 格式的文本, 还有 enumDescriptions 则对应普通的文本
                    "`选项一的描述文本`",
                    "*选项二的描述文本*",
                    "**选项三的描述文本**"
                ],
                "default": "选项三", // 默认值
                "scope": "window" // 指定该配置的范围
            },
            "hello.radio": {
                "type": "boolean",
                "default": false,
                "description": "这是一个单选按钮"
            },
            "hello.input": {
                "type": "string",
                "default": "我是默认的内容",
                "description": "这是一个文本输入框"
            },
            "hello.arrayConfig": {
                "type": "array",
                "default": [],
                "scope": "window",
                "description": "数组类型的配置"
            },
            "hello.markdown": {
                "type": "boolean",
                // 可以设置一些设置链接语法, 格式为: `#配置标题#` 如 `#files.autoSave#`
                "markdownDescription": "设置自动保存`#files.autoSave#`, 设置字体大小`#editor.fontSize#`, 支持markdown语法\n- `高亮`**加粗***斜体*\n- 列表1 \n- 列表2"
            }
          }
        }
      },

在代码中操作首选项:

  • vscode.workspace.getConfiguration().get("hello.title"): 获取指定标题的首选项
  • vscode.workspace.getConfiguration().update("hello.title", "选项一", true): 设置指定标题的首选项
// extension.ts

import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
    const { showInformationMessage, showErrorMessage } = vscode.window;
    const disposable = vscode.commands.registerCommand("learn-vscode-extends.customConfig", () => {
        // 通过副标题获取指定的配置
        const config = vscode.workspace.getConfiguration().get("hello.title");
        // 效果同上
        // const config = (vscode.workspace.getConfiguration().get("hello") as any).title;
        switch (config) {
            case "选项一":
                showInformationMessage("匹配选项一");
                break;
            case "选项二":
                showInformationMessage("匹配选项二");
                break;
            case "选项三":
                showInformationMessage("匹配选项三");
                break;
            default:
                showErrorMessage("没有对应首选项");
                break;
        }
        // 代码中更新配置, 最后一个参数, 为 true 表示写入全局配置, 为 false 或不传时则只写入工作区配置
        vscode.workspace.getConfiguration().update("hello.title", "选项一", true);
    })
    context.subscriptions.push(disposable);
}
export function deactivate() { }

F5预览效果如下:

image.png

image.png

编辑器内容操作

如果需要操作编辑器的内容就需要获取编辑器, 可以通过registerTextEditorCommand来注册命令, registerTextEditorCommandregisterCommand不同

registerTextEditorCommand注册的命令, 只有在编辑器被激活时调用才生效, 还有, 这个命令可以接受到textEditor(当前活动的编辑器)和edit(编辑器操作对象)

vscode.window.activeTextEditor也可以获取到当前活动编辑器(如果有的话)

获取当前编辑器的信息

import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
    const disposable = vscode.commands.registerTextEditorCommand("learn-vscode-extends.operateEditor", (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) => {

        const document = textEditor.document;

        // 获取当前编辑器文件的地址
        console.log(document.fileName);

        // 获取编辑器所有的内容
        const text = document.getText();
        console.log(text);

        // 获取当前选中的文本
        const selectText = document.getText(textEditor.selection);
        console.log(selectText);

        // 获取当前编辑器的语言
        console.log(document.languageId);

        // 修改当前活动编辑器的语言
        // vscode.languages.setTextDocumentLanguage(document, "vue");
    });
    context.subscriptions.push(disposable);
}
export function deactivate() { }

替换内容

import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
    const disposable = vscode.commands.registerTextEditorCommand("learn-vscode-extends.operateEditor", (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) => {
        const document = textEditor.document;
        
        // 获取当前编辑器的文本
        const text = document.getText();
        // 将 hello 替换为 HELLO 
        const result = text.replace(/hello/g, "HELLO");
        // 开始位置
        const start = new vscode.Position(0, 0);
        // 结束位置
        const end = new vscode.Position(document.lineCount + 1, 0);
        const range = new vscode.Range(start, end);
        // 重新替换
        edit.replace(range, result);

        // 将指定文本插入到当前编辑器 11行6个字符处
        // edit.insert(new vscode.Position(10, 5), "测试文本");
    });
    context.subscriptions.push(disposable);
}
export function deactivate() { }

打开新的活动编辑器并插入文本

import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
    const disposable = vscode.commands.registerCommand("learn-vscode-extends.operateEditor", () => {
        // 执行内置的命令, 新建一个活动窗口
        vscode.commands.executeCommand("workbench.action.files.newUntitledFile").then(() => {
            // 获取当前的编辑器对象
            const textEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
            if (textEditor) {
                // 编辑模式
                textEditor.edit((editBuilder: vscode.TextEditorEdit) => {
                    const codeStr = "const sayHi = () => console.log(\"hello world\");";
                    // 插入内容
                    editBuilder.insert(new vscode.Position(0, 0), codeStr);
                });
            }
        });
    });
    context.subscriptions.push(disposable);
}
export function deactivate() { }

给指定的文本添加样式

import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
    const disposable = vscode.commands.registerTextEditorCommand("learn-vscode-extends.operateEditor", (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) => {
        const decorationType = vscode.window.createTextEditorDecorationType({
            backgroundColor: "red", // 背景颜色
            textDecoration: "underline", // 下划线
        });
        // 第1行第2个字符到第1行第4个字符
        const r1 = new vscode.Range(0, 1, 0, 5);
        // 第2行第4个字符到第2行第5个字符
        const r2 = new vscode.Range(1, 3, 1, 6);
        textEditor.setDecorations(decorationType, [r1, r2]);
    });
    context.subscriptions.push(disposable);
}
export function deactivate() { }

终端操作

import * as vscode from "vscode";

export function activate(context: vscode.ExtensionContext) {
    const disposable = vscode.commands.registerCommand("learn-vscode-extends.operateTerminal", () => {

        // 创建一个终端
        const terminal: vscode.Terminal = vscode.window.createTerminal({
            name: "myTerminal", // 终端名称
            cwd: __dirname, // 改变路径
            message: "我是插件的消息" // 第一次启动时会打印出来
        });

        // 发送 shell 文本到 stdin 
        terminal.sendText("npm -v");
        // 显示终端 UI
        terminal.show();

        // 隐藏和销毁
        // terminal.hide();
        // terminal.dispose();
    });
    context.subscriptions.push(disposable);
}
export function deactivate() { }

image.png