vscode开发
# 安装code命令

打开VSC快捷键`⇧⌘P`打开命令行找到`shell command`选择`Shell Command: Install 'code' command in PATH command`安装

<img width="719" alt="屏幕快照 2019-04-29 下午5 31 59" src="https://user-images.githubusercontent.com/17243165/56887644-afe96480-6aa4-11e9-8f0f-61f8e6057280.png">

# 安装脚手架

执行完以下命令后，在VSC按`F5`，此时成功的话会打开一个新的调试窗口(扩展开发主机)
```bash
npm install -g yo generator-code
yo code
# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? HelloWorld
### Press <Enter> to choose default for all options below ###

# ? What's the identifier of your extension? helloworld
# ? What's the description of your extension? LEAVE BLANK
# ? Enable stricter TypeScript checking in 'tsconfig.json'? Yes
# ? Setup linting using 'tslint'? Yes
# ? Initialize a git repository? Yes
# ? Which package manager to use? npm
code ./helloworld
```

# Hello World

快捷键`⇧⌘P`打开命令行，执行`Hello World`

<img width="739" alt="屏幕快照 2019-04-29 下午5 29 23" src="https://user-images.githubusercontent.com/17243165/56887719-df986c80-6aa4-11e9-9741-dd28cbaab787.png">

# 添加右键菜单和快捷键

打开`package.json`，按照下述方式添加：

`extension.sayHello`对应的是`extension.js`里面的方法
```js
{
    "contributes": {
        "commands": [
            {
                "command": "extension.sayHello",
                "title": "Hello World"
            }
        ],
        // 快捷键绑定
        "keybindings": [
            {
                "command": "extension.sayHello",
                "key": "ctrl+f10",
                "mac": "cmd+f10",
                "when": "editorTextFocus"
            }
        ],
        // 设置菜单
        "menus": {
            "editor/context": [
                {
                    "when": "editorFocus",
                    "command": "extension.sayHello",
                    "group": "navigation"
                }
            ]
        }
    }
}
```

# setting.json
`Code`->`首选项设置`->`设置`->`文本编辑器`->`文件`->`Associations `
```json
{
    "git.ignoreMissingGitWarning": true,
    "explorer.confirmDelete": false,
    "javascript.updateImportsOnFileMove.enabled": "never",
    "files.associations": {
        "*.cjson": "jsonc",
        "*.wxss": "css",
        "*.wxs": "javascript",
        "*.omi": "html"
    }
}
```

# 打包 发布

无论是本地打包还是发布到应用市场都需要借助`vsce`这个工具
```bash
npm i vsce -g
```
打包成`vsix`文件
```bash
vsce package
```
登录[marketplacejian](https://marketplace.visualstudio.com/manage/publishers/wscats)上传

# 监听命令

```js
var vscode = require('vscode');
function activate(context) {
    // when you click ctrl+s, fn will action
    vscode.workspace.onDidSaveTextDocument(function (document) {
        console.log(document)
    });
}
exports.activate = activate;
```

# Webview

读取html需要`vscode-resource`配合
```js
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';

/**
 * 从某个HTML文件读取能被Webview加载的HTML内容
 * @param {*} context 上下文
 * @param {*} templatePath 相对于插件根目录的html文件相对路径
 */
function getWebViewContent(context: vscode.ExtensionContext, templatePath: string) {
	const resourcePath = path.join(context.extensionPath, templatePath);
	const dirPath = path.dirname(resourcePath);
	let html = fs.readFileSync(resourcePath, 'utf-8');
	// vscode不支持直接加载本地资源，需要替换成其专有路径格式，这里只是简单的将样式和JS的路径替换
	html = html.replace(/(<link.+?href="|<script.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => {
		return $1 + vscode.Uri.file(path.resolve(dirPath, $2)).with({ scheme: 'vscode-resource' }).toString() + '"';
	});
	return html;
}

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {

	// Use the console to output diagnostic information (console.log) and errors (console.error)
	// This line of code will only be executed once when your extension is activated
	console.log('Congratulations, your extension "qf" is now active!');

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with registerCommand
	// The commandId parameter must match the command field in package.json

	// 欢迎提示
	let disposable = vscode.commands.registerCommand('extension.qf', function () {
		// vscode.window.showInformationMessage('Hello World');
		const panel = vscode.window.createWebviewPanel(
			'testWelcome', // viewType
			"Welcome to Eno Snippets", // 视图标题
			vscode.ViewColumn.One, // 显示在编辑器的哪个部位
			{
				enableScripts: true, // 启用JS，默认禁用
				retainContextWhenHidden: true, // webview被隐藏时保持状态，避免被重置
			}
		);
		panel.webview.html = getWebViewContent(context, 'src/html/index.html');
	});
	context.subscriptions.push(disposable);
	// 如果设置里面开启了欢迎页显示，启动欢迎页
	const key = 'vscodePluginDemo.showTip';
	if (vscode.workspace.getConfiguration().get(key)) {
		vscode.commands.executeCommand('extension.qf');
	}
}

// this method is called when your extension is deactivated
export function deactivate() { }
```

# 配置参数

`package.json`配置文件如下：
```js
"configuration": {
  "title": "Px to rem configuration",
  "properties": {
    "px-to-rem.px-per-rem": {
      "type": "integer",
      "default": 16,
      "description": "Number of pixels per 1rem."
    },
    "px-to-rem.only-change-first-ocurrence": {
      "type": "boolean",
      "default": false,
      "description": "Set value to only change first occurence of px/rem per selection."
    },
    "px-to-rem.notify-if-no-changes": {
      "type": "boolean",
      "default": true,
      "description": "Show a warning if no conversion could be made."
    },
    "px-to-rem.number-of-decimals-digits": {
      "type": "integer",
      "default": 4,
      "description": "Maximum number of decimals digits a px or rem can have."
    }
  }
}
```

在代码中获取默认的配置参数
```
const config = vscode.workspace.getConfiguration("px-to-rem");
```


# FileSystemWatcher

用于监听文件是否发生了变化，可以监听到新建、更新、删除这 3 种事件,也可以选择忽略其中某个类型事件。创建`watcher`是利用`vscode.workspace.createFileSystemWatcher：
function createFileSystemWatcher(globPattern: GlobPattern, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean): FileSystemWatcher;`

例如监听所有js文件的变动：

```js
const watcher = vscode.workspace.createFileSystemWatcher('*.js', false, false, false);
watcher.onDidChange(e => { // 文件发生更新
  console.log('js changed,' e.fsPath);
});
watcher.onDidCreate(e => { // 新建了js文件
  console.log('js created,' e.fsPath);
});
watcher.onDidDelete(e => { // 删除了js文件
  console.log('js deleted,' e.fsPath);
});
```

# 设置并持久保存token

https://gitee.com/g8up/vscode-gitee/blob/dev/src/tokens.ts

```js
import { Memento } from 'vscode';

interface Tokens {
  [host: string]: {
    token: string;
  };
}

export function setToken(memento: Memento, provider: string, token: string): void {
  if (token) {
    const tokens = getToken(memento);
    tokens[provider] = {
      token,
    };
    memento.update('tokens', tokens);
  }
};

export function getToken(memento: Memento): Tokens {
  return memento.get<Tokens>('tokens', {});
}

export function removeToken(memento: Memento, provider: string): void {
  const tokens: Tokens | undefined = memento.get('tokens');
  if (tokens) {
    delete tokens[provider];
    memento.update('tokens', tokens);
  }
}
```