0x00 前言

在前几天的美国纽约,微软举行了Connect(); //2015大会。通过这次大会,我们可以很高兴的看到微软的确变得更加开放也更加务实了。当然,会上放出了不少新产品和新功能,其中就包括了VS Code的beta版本。而且微软更进一步,已经在github将VS Code的代码开源了。除了这些让人兴奋的消息,我们还应该注意到VS Code提供了对拓展的支持。
所以本文就来聊一聊使用TypeScript开发VS Code拓展的话题吧。

本文所使用的拓展的应用商店页面:

https://marketplace.visualstudio.com/items/JiadongChen.LicenseHeader

github页面:

https://github.com/chenjd/VSCode-StandardHeader

0x01 你好,世界

"万事开头,Hello World"。所以我们就从一个Hello World作为起点,开始一步一步构建自己的VScode的拓展。
在开发vscode的拓展之前,我们先要确保电脑上已经安装了Node.js。之后,我们便可以利用微软所提供的基于Yeoman的模板生成器来生成vscode拓展的模板了。

npm install -g yo generator-code

之后,我们只需要在终端中运行yo code命令,即可以进入创建拓展模板的引导过程。

yo code

在引导过程中将TypeScript选择为开发语言,并且填完一些基本信息之后,我们的第一个vscode拓展便创建完成了。
那么,yo code命令主要为我们做了一些什么事情呢?

  1. 会根据我们在引导中所填的信息,在当前目录生成一个拓展的文件夹,文件夹名即我们在引导中填入的拓展名称。
  2. 该文件夹中主要包括了盛放源文件(extension.ts)的src文件夹、test文件夹以及out文件夹。需要注意的是out文件夹,在编译typescript源文件之前out文件夹是没有创建的,而编译之后会创建out文件夹并且其中的内容是typescript经过编译之后生成的js文件。
  3. 生成了资源配置文件package.json,package.json文件描述了该拓展的信息和它的功能。下文我还会具体说明package.json文件。
  4. 创建了launch.json以及tasks.json和settings.json(位于项目中的.vscode目录下),其中launch.json文件规定了启动一个在拓展开发(Extension Development)模式的VS Code进程,并且规定在VS Code启动之前会先运行tasks.json文件中所定义的task(根据tasks.json中的定义,相当于npm run compile),即先使用TypeScript的编译器将ts文件编译为js文件。这样我们就可以直接编译(因为是typescript)运行并且调试我们的拓展项目了。
  5. 当然,还会根据我们在引导中的选择来决定是否创建一个Git仓库,用来做版本控制。

下面便是我们的拓展项目的完整目录:

.
├── .gitignore //配置不需要加入版本管理的文件
├── .vscode // VS Code的整合
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .vscodeignore //配置不需要加入最终发布到拓展中的文件
├── README.md
├── src // 源文件
│ └── extension.ts // 如果我们使用js来开发拓展,则该文件的后缀为.js
├── test // test文件夹
│ ├── extension.test.ts // 如果我们使用js来开发拓展,则该文件的后缀为.js
│ └── index.ts // 如果我们使用js来开发拓展,则该文件的后缀为.js
├── node_modules
│ ├── vscode // vscode对typescript的语言支持。
│ └── typescript // TypeScript的编译器
├── out // 编译之后的输出文件夹(只有TypeScript需要,JS无需)
│ ├── src
│ | ├── extension.js
│ | └── extension.js.map
│ └── test
│ ├── extension.test.js
│ ├── extension.test.js.map
│ ├── index.js
│ └── index.js.map
├── package.json // 该拓展的资源配置文件
├── tsconfig.json //
├── typings // 类型定义文件夹
│ ├── node.d.ts // 和Node.js关联的类型定义
│ └── vscode-typings.d.ts // 和VS Code关联的类型定义
└── vsc-extension-quickstart.md

此时,我们只需要点击在VS Code的Debug区域的Start按钮即可。

在接下来开启的一个处于拓展开发模式的新的VS Code中,我们只需要在命令面板中输入Hello World便可以激活这个模板拓展,弹出一个Hello World的消息弹窗。

那么,VS Code到底是如何加载并运行拓展的呢?我们又应该如何开发拓展供自己甚至是分享给更多的人更好的使用VS Code呢?

0x02 关于package.json的两三事

作为拓展项目的资源配置文件,package.json不仅仅描述了该拓展的信息还描述了拓展的功能。需要说明的是,当VS Code启动时,拓展的package.json文件便会被读取,并且VS Code还会对package.json文件中的contributes部分的内容做处理。这一点和拓展的源文件extension.ts有所区别。VS Code并不会在启动时便加载拓展的源代码。
下面我们就来看一看我们刚刚生成的这个拓展项目中的package.json文件的内容吧。

{
"name": "Standard-Header",
"displayName": "Standard-Header",
"description": "standard-header",
"version": "0.0.1",
"publisher": "JiadongChen",
"engines": {
"vscode": "^0.10.1"
},
"categories": [
"Other"
],
"activationEvents": [
"onCommand:extension.sayHello"
],
"main": "./out/src/extension",
"contributes": {
"commands": [{
"command": "extension.sayHello",
"title": "Hello World"
}]
},
"scripts": {
"vscode:prepublish": "node ./node_modules/vscode/bin/compile",
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./"
},
"devDependencies": {
"typescript": "^1.6.2",
"vscode": "0.10.x"
}
}

我们可以看到,package.json描述了该拓展的一些基本信息,例如拓展的名称name、拓展的描述信息description以及拓展的版本号version和发布者的信息publisher等等。顺带提一句,直接通过提高版本号的方式就可以使用拓展发布工具来更新已经发布到VS Code应用商店的拓展版本。
除了这些,我们甚至还可以在package.json文件中配置一些拓展在VS Code的应用商店中的展示信息,例如拓展在商店中的种类:categories、拓展的icon图:icon以及拓展在应用市场主页的一些展示信息:galleryBanner等等。

...
"icon": "res/icon.png",
"galleryBanner": {
"color": "#5c2d91",
"theme": "dark"
},
"categories": [
"Other"
],
...

当然,更重要的内容是activationEvents、contributes以及scripts和main这几项内容。其中scripts项的内容是使用TypeScript进行开发时所特有的,主要的作用是用来提供对ts文件进行编译的相关信息。而main项则指向了将ts源文件编译后所生成的js文件。

ActivationEvents

正如上文所说,VS Code默认状况下并不会在启动时立刻执行拓展中的代码。因此,为了使拓展能够被激活,我们需要在package.json文件中定义activationEvents项的内容。例如上例中,activationEvents的定义如下:

...
"activationEvents": [
"onCommand:extension.sayHello"
],
...

意思是当“onCommand:extension.sayHello”事件被触发之后,拓展会被激活。那么在VS Code中,激活事件都有哪些种类呢?下面我们就来归一下类。

根据文件所使用的语言:onLanguage:${language}
当打开的文件是使用onLanguage所规定的语言时,拓展会被激活。
例如:

...
"activationEvents": [
"onLanguage:python"
]
...

根据所输入的命令:onCommand:${command}
当在onCommand中规定的命令被触发时,拓展会被激活。在上文生成的Hello World模板中,我们就可以看到。

...
"activationEvents": [
"onCommand:extension.sayHello"
]
...

根据文件夹:workspaceContains:${toplevelfilename}

"activationEvents": [
"workspaceContains:package.json"
],

无限制:*

...
"activationEvents": [
"*"
]
...

由于没有限制,因此在VS Code一启动时便会激活该拓展。因此,这种不加以条件限制就激活拓展的方式并不是十分推荐的。大家最好谨慎使用。

Contribution

在package.json文件中的contributes项中,同样包含很多种类。如果需要归类的话,可以分为以下几个类型。

  • configuration
  • commands
  • keybindings
  • languages
  • debuggers
  • grammars
  • themes
  • snippets

但是本文限于篇幅,将只关注commands和keybindings这两种。

commands
还以上文中的Hello World为例,我们在commands项中定义了命令的title以及title所对应的具体命令。如下所示:

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

此时一旦安装了该拓展,我们就可以在VS Code中的命令面板(我在Mac上的快捷键是Shift+cmd+p)中找到“Hello World”,输入便会触发extension.sayHello这条命令,而上文中的拓展激活事件项activationEvents中如果定义的内容是"onCommand:extension.sayHello",则激活事件被触发,拓展的代码被激活。

keybindings
当然,和commands对应的,我们还可以通过在package.json中定义keybindings项,通过绑定快捷键的方式触发命令。这样操作起来更加便捷,例如下文中我们自己开发一个插入标准页眉的拓展时,使用的便是绑定快捷键的方式。

"contributes": {
"keybindings": [{
"command": "extension.insertHeader",
"key": "shift+cmd+1",
"when": "editorTextFocus"
}]
},

如果我们在VS Code中安装了定义了快捷键触发的拓展,则打开VS Code的KeyBoard ShortCut就可以看到拓展中定义的快捷键和它对应的命令了。

0x03 VS Code运行拓展的原理

通过上一小节的内容,我们就能很清楚的理解上文中那个模板拓展的运行过程了。

VS Code首先会检测到拓展并且读取拓展的package.json文件的内容并将package.json文件中的contributes项应用到VS Code中。这样,我们就可以根据contributes项中的内容,或者是在命令面板中输入contributes项中定义的commands,或者是使用contributes项中所定义的快捷键keybindings来触发extension.sayHello命令。
一旦extension.sayHello触发,VS Code会创建一个叫做onCommand:extension.sayHello的激活事件。
与此同时,所有在自己的package.json文件中将activationEvents设置为onCommand:extension.sayHello的拓展会被激活。并且会根据package.json文件中main项的内容,将./out/src/extension.js文件加载到JavaScript VM中。接下来,VS Code会调用在extension.js文件中的active函数,在active函数中,我们需要提供“extension.sayHello”这个函数的具体实现并执行。
好了,了解了VS Code拓展的基本知识之后我们就可以开始着手开发自己的拓展了,这个拓展的目的是向源文件添加License页眉。

0x04 一个插入License页眉的拓展

既然要打造自己的VS Code,那么自己喜欢的一些操作习惯自然希望能够用在VS Code上。而插入页眉便是这样一个简单的小功能。

我们首先来看一看在上文中那个Hello World模板拓展的源文件即extension.ts文件的基本内容。

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {

    var disposable = vscode.commands.registerCommand('extension.sayHello', () => {
    ...
     vscode.window.showInformationMessage('Hello World!');
...

});
}

首先,我们自然要引入vscode命名空间下的API,以获得控制VS Code的能力。

其次,我们注意到了拓展的源文件需要export一个叫做activate的函数,当拓展的package.json文件中activationEvents所定义的事件被触发时,VS Code会调用activate函数。

最后,我们可以看到我们使用vscode的API注册了一个叫做“extension.sayHello”的命令,并且提供了它的具体实现,按照模板中的逻辑,“extension.sayHello”命令的逻辑是在窗口中显示一个内容为“Hello World”的信息消息。具体的效果在本文一开始的部分各位已经看到了。

那么接下来就十分简单了,我们首先新建一个叫做HeaderGenerator的类,用来执行插入页眉的任务。

class HeaderGenerator {
private _disposable: Disposable;
public insertHeader() { // Get the current text editor
let editor = window.activeTextEditor;
if (!editor) {
return;
} // Define header content
var header = "License Header"; // Get the document
var doc = editor.document; // Insert header
editor.edit((eb) => {
eb.insert(doc.positionAt(0), header);
});
} dispose() {
this._disposable.dispose();
}
}

插入页眉的具体执行是当前窗口的editor(TextEditor类)的edit方法,通过利用TextEditorEdit类的insert方法实现对当前的文档doc(TextDocument类)插入新的内容。

之后,我们只需在extension.ts文件中的activate函数中实现调用HeaderGenerator类的insertHeader方法即可。

import * as vscode from 'vscode';
import {window, commands, Disposable, ExtensionContext, TextDocument} from 'vscode'; export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "standard-header" is now active!');
let headerGen = new HeaderGenerator();
var disposable = vscode.commands.registerCommand('extension.insertHeader', () => {
headerGen.insertHeader();
});
context.subscriptions.push(headerGen);
context.subscriptions.push(disposable);
}

当然,为了增加快捷键“shift+cmd+1”的支持,我们还需要在package.json中修改contributes的内容:

"contributes": {
"keybindings": [{
"command": "extension.insertHeader",
"key": "shift+cmd+1",
"when": "editorTextFocus"
}]
},

之后,让我们先进入拓展开发模式看一下效果。使用快捷键shift+cmd+1,我们可以看到在VS Code的窗口中插入了页眉(截图中的页眉内容我已经换成了MIT协议)。

好了,到此我们的小小的在源文件中插入页眉的拓展就完成了,下面就让我们来使用安装、甚至是发布到VS Code的应用商店让大家一起分享我们的劳动成果吧。

0x05 本地安装或在应用商店发布

为了不必再每次都要进入拓展开发模式才能“使用”我们的拓展,我们就必须让自己的VS Code安装这个拓展。

事实上在本地安装供自己的拓展是十分简单并且方便的事情。VS Code会在.vscode/extensions文件夹中获取本地的拓展。而.vscode/extensions文件夹所在的位置我们可以总结如下:

  • Windows %USERPROFILE%\.vscode\extensions
  • Mac $HOME/.vscode/extensions
  • Linux $HOME/.vscode/extensions

我们只需拷贝一份我们的拓展到.vscode/extensions文件夹中,VS Code在启动时便能够检查到该拓展了。

当然,除了自己使用自己开发的拓展之外,我们还可以将拓展发布到VS Code的应用商店。此时我们就要借助一个拓展发布工具——vsce了。

首先是安装vsce:

npm install -g vsce

之后我们还需要到Visual Studio Team Services注册并登陆,以获取Personal Access Token。

一旦获取了Personal Access Token,我们就可以使用vsce创建一个发布者账号了。

vsce create-publisher 

紧接着,登陆并发布:

vsce login
vsce publish

发布成功之后,我们就可以在VS Code的应用商店中看到自己的拓展了。

并且在VS Code的命令面板中,我们也可以使用命令安装:

ext install 

好啦,行文至此,使用TypeScript拓展你自己的VS Code讲的已经差不多了。希望各位多多交流~

使用TypeScript拓展你自己的VS Code!的更多相关文章

  1. 使用TypeScript拓展你自己的VSCode

    转自:http://www.iplaysoft.com/brackets.html使用TypeScript拓展你自己的VSCode! 0x00 前言在前几天的美国纽约,微软举行了Connect(); ...

  2. 使用Visual Studio Code搭建TypeScript开发环境

    使用Visual Studio Code搭建TypeScript开发环境 1.TypeScript是干什么的 ? TypeScript是由微软Anders Hejlsberg(安德斯·海尔斯伯格,也是 ...

  3. [Tool] 使用Visual Studio Code开发TypeScript

    [Tool] 使用Visual Studio Code开发TypeScript 注意 依照本篇操作步骤实作,就可以在「Windows」.「OS X」操作系统上,使用Visual Studio Code ...

  4. Visual Studio Code开发TypeScript

    [Tool] 使用Visual Studio Code开发TypeScript   [Tool] 使用Visual Studio Code开发TypeScript 注意 依照本篇操作步骤实作,就可以在 ...

  5. TypeScript开发环境搭建(Visual studio code)

    使用Visual Studio Code搭建TypeScript开发环境 1.TypeScript是干什么的 ? TypeScript是由微软Anders Hejlsberg(安德斯·海尔斯伯格,也是 ...

  6. Vs Code推荐安装插件

    前言: Visual Studio Code是一个轻量级但功能强大的源代码编辑器,轻量级指的是下载下来的Vs Code其实就是一个简单的编辑器,强大指的是支持多种语言的环境插件拓展,也正是因为这种支持 ...

  7. TypeScript 2.0候选版(RC)已出,哪些新特性值得我们关注?

    注:本文提及到的代码示例下载地址 - Runnable sample to introduce Typescript 2.0 RC new features 作为一个Javascript的超集, Ty ...

  8. 《TypeScript 中文入门教程》 1、基础数据类型

    转载:https://github.com/MyErpSoft/TypeScript-Handbook/blob/master/pages/zh-CHS/Basic%20Types.md 概述 为了让 ...

  9. TypeScript中的枚举类型

    TypeScript拓展了Javascript原生的标准数据类型集,增加了枚举类型(enmu)和其他语言一 样 它提供我们一种数字类型的值,用来设置由于辨别的名字和方法 enum Students { ...

随机推荐

  1. 一步步开发自己的博客 .NET版(10、前端对话框和消息框的实现)

    关于前端对话框.消息框的优秀插件多不胜数.造轮子是为了更好的使用轮子,并不是说自己造的轮子肯定好.所以,这个博客系统基本上都是自己实现的,包括日志记录.响应式布局.评论功能等等一些本可以使用插件的.好 ...

  2. 水印第三版 ~ 变态水印(这次用Magick.NET来实现,附需求分析和源码)

    技能 汇总:http://www.cnblogs.com/dunitian/p/4822808.html#skill 以前的水印,只是简单走起,用的是原生态的方法.现在各种变态水印,于是就不再用原生态 ...

  3. Carousel 旋转画廊特效的疑难杂症

    疑难杂症 该画廊特效的特点就是前后元素有层级关系. 我想很多人应该看过或者用过这个插件carousel.js,网上也有相关的教程.不知道这个插件的原型是哪个,有知道的朋友可以告诉我. 该插件相对完美, ...

  4. Mac OS 使用 Vagrant 管理虚拟机(VirtualBox)

    Vagrant(官网.github)是一款构建虚拟开发环境的工具,支持 Window,Linux,Mac OS,Vagrant 中的 Boxes 概念类似于 Docker(实质是不同的),你可以把它看 ...

  5. Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配

    (原创:http://www.cnblogs.com/linguanh) 目录: 前序 一,问题描述 二,为何会如此"无情"? 三,目前存在该问题的知名SDK 四,解决方案,1 对 ...

  6. H5项目开发分享——用Canvas合成文字

    以前曾用Canvas合成.裁剪.图片等<用H5中的Canvas等技术制作海报>.这次用Canvas来画文字. 下图中"老王考到驾照后"这几个字是画在Canvas上的,与 ...

  7. 前端制作动画的几种方式(css3,js)

    制作动态的网页是是前端工程师必备的技能,很好的实现动画能够极大的提高用户体验,增强交互效果,那么动画有多少实现方式,一直对此有选择恐惧症的我就总结一下,以便在开发的时候选择最好的实现方式. 1.css ...

  8. dotNet Core开发环境搭建及简要说明

    一.安装 .NET Core SDK 在 Windows 上使用 .NET Core 的最佳途径:使用Visual Studio. 免费下载地址: Visual Studio Community 20 ...

  9. 来自于微信小程序的一封简讯

    9月21晚间,微信向部分公众号发出公众平台-微信应用号(小程序)的内测邀请,向来较为低调的微信在这一晚没人再忽视它了. 来自个人博客:Damonare的个人博客 一夜之间火了的微信应用号你真的知道吗? ...

  10. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...