前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >编写你的第一款VSCode插件

编写你的第一款VSCode插件

作者头像
腾讯IVWEB团队
发布2020-06-24 11:06:07
2.6K0
发布2020-06-24 11:06:07
举报
文章被收录于专栏:腾讯IVWEB团队的专栏

锋利的VSCode

工欲善其事,必先利其器。对于一名程序猿来说,好的编辑器能够大大提高写代码的效率。VSCode作为微软主推的开源跨平台编辑器,是前端开发的利器,它拥有各种丰富的插件,更是使得其如虎添翼。

但是插件市场上的插件都是面向大家普适的需求。如何去定制一款专属于自己的插件,在特殊场景下提高开发效率,减少时间成本?希望下面的内容能够有一些帮助。

HelloWolrd

首先,你需要安装Node.js以及NPM,这里推荐使用NVM进行安装。方便以后Node的版本切换。

NVM地址戳我⬅️

接下来使用NPM安装Yeoman和 VSCode Extention Generator

代码语言:javascript
复制
npm install -g yo generator-code

Yeoman 是一个代码生成器,能帮你创建一个新插件的骨架模版。官网链接戳我⬅️ generator-code 是VSCode团队编写的VSCode插件模版。

运行以下命令:

代码语言:javascript
复制
yo code

企业微信20190602113223.png

选择你想创建脚手架类型(建议选择TypeScript,原因稍后再说),输入其他项目信息。等待安装……

你的第一个VSCode插件已经完成了!来看看效果:

代码语言:javascript
复制
cd hello-code
code .

如果提示没有code命令,你需要在~/.zshrc中加入以下内容:

代码语言:javascript
复制
code () {
if [[ $# = 0 ]]
then
    open -a "Visual Studio Code"
else
    [[ $1 = /* ]] && F="$1" || F="$PWD/${1#./}"
    open -a "Visual Studio Code" --args "$F"
fi
}

source ~/.zshrc使之生效。

打开项目之后,点击F5或者Debug按钮。会弹出来一个新的VSCode窗口。

这个新的VS Code实例会运行在特殊环境中(Extension Development Host),专门用于插件的调试。

small-window.png

在新窗口的命令面板(⇧⌘P)中输入Hello World命令。右下角就会出现Hello World的弹窗哦。

恭喜你,已经运行起了你的第一个VSCode插件。

插件的目录结构

下面,我们将要打造专属于自己的VSCode插件。首先来了解一下VSCode插件的目录结构:

代码语言:javascript
复制
.
├── .gitignore
├── .vscode                     // VS Code 文件
│   ├── launch.json
│   ├── settings.json
│   └── tasks.json
├── .vscodeignore               // 发布插件时忽略的文件
├── README.md
├── src
│   └── extension.ts            // 插件的入口(源文件)
├── test                        // 测试文件夹
│   ├── extension.test.ts       // extension.test.js, 如果是 JavaScript 插件的话
│   └── index.ts                // index.js, 如果是 JavaScript 插件的话
├── node_modules
│   ├── vscode                  // 包含了vscode插件开发时的类型定义文件
│   └── typescript              // typescript的编译器 (TypeScript only)
├── out                         // 编译出口 (TypeScript only)
│   ├── extension.js            // 插件入口
│   ├── extension.js.map
│   └── test
│       ├── extension.test.js
│       ├── extension.test.js.map
│       ├── index.js
│       └── index.js.map
├── package.json                // 插件清单
├── tsconfig.json               // jsconfig.json, 如果是 JavaScript 插件的话
└── vsc-extension-quickstart.md // 快速上手插件开发

插件的入口就在package.json当中。其中最重要的部分如下:

代码语言:javascript
复制
  "contributes": {
        "commands": [{
            "command": "extension.sayHello",
            "title": "Hello World"
        }]
    }

它为命令面板定义了一个叫做Hello world的入口,会调用'extension.sayHello'。

在src/extension.ts文件下,存放着这个sayHello函数的定义。

所以我们转到src/extension.ts文件下。

代码语言:javascript
复制
import * as vscode from 'vscode';

// vscode在开启时调用activate函数
export function activate(context: vscode.ExtensionContext) {

    // 用console输出诊断信息(console.log)和错误(console.error)
    // 下面的代码只会执行一次
    console.log('Congratulations, your extension "my-first-extension" is now active!');

    // 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法
    // registerCommand中的参数必须与package.json中的command保持一致,用于在VSCode环境中注册这个命令函数
    let disposable = vscode.commands.registerCommand('extension.sayHello', () => {
        // 把你的代码写在这里,每次命令执行时都会调用这里的代码
        vscode.window.showInformationMessage('Hello World!');
    });

    context.subscriptions.push(disposable);
}

开始定制自己的插件

在维护旧代码时,经常会有这样的状况:

企业微信20190603072948.png

由于开启了ESLint的Strings must use singlequote规则,JS代码中必须使用单引号。作为一名代码洁癖症患者,满屏飘红坚决不能忍。我们可以考虑使用VSCode的全局替换功能,把js文件中的双引号替换成单引号。

但是,React项目中,JSX语法中className却又要使用双引号。这样我们又得去一个个修改JSX得引号。

很麻烦对吧?如何写一款插件来帮我们解决这个问题呢?

在启动模版上面改动,只需要几行代码:

代码语言:javascript
复制
	let disposable = vscode.commands.registerCommand('extension.replaceQuotationMarks', () => {
		// 获取当前激活的编辑页面
        let editor = vscode.window.activeTextEditor;
		if (!editor) {
			return; // 没有打开编辑器
		}
        // 获取选中对象
		let selection = editor.selection;
        // 获取选中的文本
		let text = editor.document.getText(selection);
        // 替换文本,注意引号需要转义,并且需要开启RegExp的全局搜索标志,不然只会替换第一个引号
		let replacedText = text.replace(/\"/g, '\'');
		editor.edit( editBuilder => {
            // 替换内容,替换的位置可以有选中的对象获取
			editBuilder.replace(selection, replacedText);
		});
		// 给用户一个消息提示框
		vscode.window.showInformationMessage("Replace Done!");
	});

VSCode 提供了一系列的API,可以对文本内容进行操作和更改。详细的文档可以查看这里:https://code.visualstudio.com/api/references/vscode-api

vscode-doc.png

可以看到,VSCode 的文档十分完善,由于VSCode使用TypeScript,这些API都标注了传入和返回值的类型,并且通过超链接进行关联。使用TypeScript编写插件时,也会有详尽的代码提示。这也是为什么推荐使用TypeScript编写插件。

编写完成,我们来测试一下效果:用鼠标选中需要替换的内容,呼出命令面板,输入Replace命令。替换瞬间完成。

但这样感觉还是很麻烦,下面有几个优化方案:

自定义快捷键

VSCode支持插件自定义快捷键,并且只需要在package.json中进行简单的配置:

代码语言:javascript
复制
"contributes": {
	"keybindings": [{
		// 指定快捷键执行的操作
		"command": "extension.replaceQuotationMarks",
		// windows下快捷键
		"key": "f2",
		// mac下快捷键
		"mac": "f2",
		// 快捷键何时生效
		"when": "editorTextFocus"
	}]
}

选中后按下f2,插件将会立即被执行!

使用正则自动替换

代码语言:javascript
复制
export function activate(context: vscode.ExtensionContext) {
	let disposable = vscode.commands.registerCommand('extension.replaceQuotationMarks', () => {
		let editor = vscode.window.activeTextEditor;
		if (!editor) {
			return; // 没有打开的编辑器
		}
		let text = editor.document.getText();
		let replacedText = text.replace(/\"/g, '\'');
		replacedText = replacedText.replace(/className\s*=\s*\'(.+)\'/g, 'className=\"$1\"');
		const fullRange = new vscode.Range(
			editor.document.positionAt(0),
			editor.document.positionAt(text.length - 1)
		);
		editor.edit( editBuilder => {
			editBuilder.replace(fullRange , replacedText);
		});
		// 给用户一个消息提示框
		vscode.window.showInformationMessage("Replace Done!");
	});
	context.subscriptions.push(disposable);
    // 立即执行!
	vscode.commands.executeCommand('extension.replaceQuotationMarks');
}

在package.json中配置打开javascript文件,并且该文件存在react内容时,自动执行该插件。

代码语言:javascript
复制
	"activationEvents": [
		"onLanguage:javascriptreact"
	],

在本地安装插件

到目前为止,你的插件都还跑在插件开发模式中,要想让你的插件在正常的VS Code中运行起来将你的插件复制到.vscode/extensions目录下。

一些思路?

这里已我个人的场景为例,来探索VSCode插件有哪些潜在的新玩法~

我平时在写博客文章时,习惯先用VSCode在本地写好,再去博客上面发布,所以,发布一篇博客,需要这么几步:

  1. 打开VSCode,新建markdown文档。
  2. 写作✏️
  3. 将所有的图片上传至图床
  4. 替换本地博客的文档的图片路径为图床路径
  5. 打开浏览器
  6. 打开我的博客地址
  7. 复制、粘贴内容
  8. 点击发布

太繁琐了,简直影响写博客的热情有木有!!!

那么,就编写一款插件,在VSCode中实现一键发布文章。

主要的思路如下:

  1. 先用VSCode的API获取所有文本内容
  2. 使用正则表达式筛选图片,并上传图片到图床
  3. 使用图床的图片地址替换本地的地址
  4. 使用博客的API发布

在这里强烈安利Ghost博客,使用Node打造的Ghost博客,相较于年迈的Wordpress,拥有着更好看的主题,更小的内存占用(使用SQlite),还提供官方的API可供调用。

整体代码如下:

代码语言:javascript
复制
class Publisher {
	// 文本替换,将replace变为async
	private asyncReplace(str: string, re: RegExp, replacer: Function) {
		return Promise.resolve().then(() => {
			const fns: any[] = [];
			str.replace(re, (m, ...args) => {
				fns.push(replacer(m, ...args));
				return m;
			});
			return Promise.all(fns).then(replacements => {
				return str.replace(re, () => replacements.shift());
			});
		});
	}
	// 发布图片到图床,这里使用sm.ms图床
	private async sendImage(path: string): Promise<string> {
		const form = new formdata();
		if (!fs.existsSync(path)) {
			return '替换错误,请检查该文件是否存在';
		}
		const stream = fs.createReadStream(path);
		form.append('smfile', stream);
		const result = await fetch('https://sm.ms/api/upload', {
			method: 'POST',
			body: form
		})
			.then(
				(res: any) => res.json()
			)
			.then(
				(json: any) => {
					vscode.window.showInformationMessage(`${json.data.url}: ok`);
					return json.data.url;
				});
		return result;
	}
	public publish() {
		const editor = vscode.window.activeTextEditor;
		if (!editor) {
			return;
		}
		vscode.window.showInformationMessage(`上传开始……`);
		const currentlyOpenTabfilePath = editor.document.fileName;
		const dirName = path.dirname(currentlyOpenTabfilePath);
		const fileName =  path.basename(currentlyOpenTabfilePath, '.md');
		let text = editor.document.getText();
		// 筛选图片地址的正则表达式
		const imageReg = /!\[.*?\]\((.*?\.(png|jpg|webp|gif))\)/g;
		this.asyncReplace(text, imageReg, async (_: any, fileName: string) => {
			const imagePath = path.join(dirName, fileName);
			const result = await this.sendImage(imagePath);
			return `![](${result})`;
		}).then(text => {
			// 发布博客使用Ghost博客提供的API
			const api = new GhostAdminAPI({
				url: 'youblogurl',
				key: 'yourkey',
				version: 'v2'
			});
			const html = md.render(text);
			console.log(html);
			api.posts.add(
					{ title: fileName, html ,status: "published"},
					{ source: 'html' } // Tell the API to use HTML as the content source, 
				)
				.then((res:any) => vscode.window.showInformationMessage('文章发布成功!!!'));
		});
	}
}

最后让我们来看下效果如何:

publisher.png

文章发布成功!

短短100来行代码,我们就实现了这个功能。赶快来尝试开发专属于你自己的VSCode插件吧!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 锋利的VSCode
  • HelloWolrd
  • 插件的目录结构
  • 开始定制自己的插件
    • 自定义快捷键
      • 使用正则自动替换
      • 在本地安装插件
      • 一些思路?
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档