vscode插件开发指南(五)-实战篇-悬停语法提示&webview-完结篇

4,771 阅读3分钟

前言

我们的目标是实现一个基础库的插件,其功能包含以下内容:

  • 语法校验,校验API命令调用的正确性,参数类型的正确性,参数个数的正确性,关键参数和系统打通校验有效性等
  • 语法自动补全,辅助用户编写代码
  • 语法悬停提示,辅助说明语法
  • 其他功能
    • webview查看远程信息

本篇即为悬停语法提示&webview实现篇,我们先看一下最后的效果,是不是很神奇,快来和我一起探讨到底是怎么实现的吧~

悬停提示: 效果

查看更多信息: 效果

完整代码可在我的github中查看。

一、语法悬停提示

1.1 语法说明

registerHoverProvider(selector: DocumentSelector, provider: HoverProvider): Disposable

1.2 实现

如tyc_test下有一个testA方法

// client/src/config/doc.ts
const doc = [
    {
        kind: 'Function',
        body: [
            "testA"
        ],
        detail: "(method) tyc_test.testA( key: string, value: any)",
        documentation: `测试testA自动补全
@param key — 要设置的字段名.
@param value — 要设置的值.`
    }
];

import * as vscode from 'vscode';
import { file } from '../config';

class HoverProvider {
	provideHover(document: vscode.TextDocument, position: vscode.Position) {
		const text = document.getText(new vscode.Range(
			new vscode.Position(0, 0),
			position
		));
		const word = document.getText(document.getWordRangeAtPosition(position));

		if(/tyc_test\.[A-Za-z]+$/g.test(text)) {
			for(let i = 0; i < doc.length; i++ ) {
				const regExp = RegExp(`${doc[i].body[0]}`);
				// 检查当前语法是否有文档,检测关键字
				if(regExp.test(word)){
					const description = doc[i].documentation.replace(/\@/g,function(m,n){
						return `\n${m}`;
					});
					return new vscode.Hover([doc[i].detail,description]);
				}
			}
		};
	}
}

export default function(context: vscode.ExtensionContext) {
	context.subscriptions.push(vscode.languages.registerHoverProvider(file, new HoverProvider()));
};

在插件入口文件引入:

// client/src/extension.ts
import hoverInfo from './provider/hoverInfo';

export function activate(context: vscode.ExtensionContext) {
	// 悬浮提示
	hoverInfo(context);
}

1.3 效果

效果

二、查看更多信息(webview)

2.1 语法说明

createWebviewPanel(viewType: string, title: string, showOptions: ViewColumn | {preserveFocus: boolean, viewColumn: ViewColumn}, options?: WebviewPanelOptions & WebviewOptions): WebviewPanel

2.2 实现

我们的交互设计为当选中任意内容后,右键可以查看其详细信息,我们这里仅示意,展示你选中的内容,实际上你可以根据你的需求,发挥你的想象力,做更多的事情,比如异步获取一些系统的信息展示

首先我们需要注册一个命令,这里我们将命令绑定到了右键菜单上,同时设置了快捷键

"contributes": {
		"commands": [
			{
				"command": "vscode-example-tyc.preview", // 注册一个命令
				"title": "查看更多信息"
			}
		],
		"keybindings": [
			{
				"command": "vscode-example-tyc.preview", // 新增一个快捷键
				"key": "ctrl+l",
				"mac": "cmd+l",
				"when": "editorHasSelection"
			}
		],
		"menus": {
			"editor/context": [
				{
					"when": "editorHasSelection", // 声明一个菜单项
					"command": "vscode-example-tyc.preview",
					"group": "navigation"
				}
			]
		}
	}

创建webview主体逻辑

// client/src/provider/createWebview.ts
import * as vscode from 'vscode';
import { render } from './render/index';

let panel = null;

const preview = vscode.commands.registerCommand('vscode-example-tyc.preview', async function (uri) {

    let editor = vscode.window.activeTextEditor;
    if (!editor) {
        vscode.window.showWarningMessage('请新开一个文件使用');
        return;
    }

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

    if (!text) {
        return;
    };


    if (!panel || panel._store._isDisposed) {
        panel = createWebviewPanel();
    }
    // 设置文档内容
    panel.webview.html = render(text);

});

function createWebviewPanel() {
    let panel = vscode.window.createWebviewPanel(
        'vscode-example-tyc',
        '查看更多信息',
        vscode.ViewColumn.Two, {
            enableScripts: true,
            retainContextWhenHidden: false,
        }
    );
    panel.onDidDispose(async (event) => {
    });
    return panel;
}

export default function(context: vscode.ExtensionContext) {
    context.subscriptions.push(preview);
};

在插件入口文件引入

// client/src/extension.ts
import createWebview from './provider/createWebview';
export function activate(context: vscode.ExtensionContext) {
	// 创建webview
	createWebview(context);
}

2.3 效果

效果

2.4 如何调试webview

按下Ctrl+Shift+P然后执行打开Webview开发工具Open Webview Developer Tools命令

调试界面: 调试界面

2.5 高级内容

Webview出于安全考虑,默认无法直接访问本地资源,如果需要想要加载本地图片、js、css等必须通过特殊的vscode-resource:协议,网页里面所有的静态资源都要转换成这种格式,否则无法被正常加载

如果需要和vscode有交互,需要使用其消息通信API,这里就不赘述了,感兴趣的可以阅读blog.haoji.me/vscode-plug…了解更多

三、系列文章