示例-任务

通常,在VS Code中,用户可以通过task.json定义一个任务。不过在软件开发中,VS Code会自动检测某些任务。本节介绍了插件应该怎样自动检测任务,为最终用户提供任务。

定义任务


想要定义一个系统级别的任务,插件需要通过properties定义任务,在下面叫做Rake的例子中,任务是这样定义的:

?>译者注:rake是ruby实现的任务管理和自动构建工具,详细请参考rake

  1. "taskDefinitions": [
  2. {
  3. "type": "rake",
  4. "required": [
  5. "task"
  6. ],
  7. "properties": {
  8. "task": {
  9. "type": "string",
  10. "description": "The Rake task to customize"
  11. },
  12. "file": {
  13. "type": "string",
  14. "description": "The Rake file that provides the task. Can be omitted."
  15. }
  16. }
  17. }
  18. ]

上面代码里面,我们为rake任务集配置了一个任务定义。任务定义有两个属性taskfiletask是Rake任务的名字,file指向了包含任务的文件。task属性是必须的,file则为可选。如果省略了file属性,则会使用工作区根目录下名为rake的文件。

任务供应器函数


和语言供应器函数相同,任务供应器使插件支持代码补全,一个插件可以只注册一个任务供应器函数然后执行所有可用的任务集合。使用vscode.tasks命名空间达成这一目标:

  1. import * as vscode from 'vscode';
  2. let rakePromise: Thenable<vscode.Task[]> | undefined = undefined;
  3. const taskProvider = vscode.tasks.registerTaskProvider('rake', {
  4. provideTasks: () => {
  5. if (!rakePromise) {
  6. rakePromise = getRakeTasks();
  7. }
  8. return rakePromise;
  9. },
  10. resolveTask(_task: vscode.Task): vscode.Task | undefined {
  11. return undefined;
  12. }
  13. });

目前resolveTask只返回了undefined,而将来VS Code会通过这个方法优化任务的加载。

getRakeTasks的实现做了下面的事情:

  • 使用rake -AT -f Rakefile命令列出rake文件中的所有rake任务
  • 转换为stdio输出
  • 对每个任务创建一个vscode.task实现

因为一个rake任务初始化需要package.json中有对应的任务定义,VS Code会用TypeScript接口定义出结构,像这样:

  1. interface RakeTaskDefinition extends vscode.TaskDefinition {
  2. /**
  3. * The task name
  4. */
  5. task: string;
  6. /**
  7. * The rake file containing the task
  8. */
  9. file?: string;
  10. }

假设我们的输出最终来自于一个叫compile的任务,那么对应的任务创建过程如下所示:

  1. let task = new vscode.Task({ type: 'rake', task: 'compile' }, 'compile', 'rake', new vscode.ShellExecution('rake compile'));

每个输出任务都对应着上述过程,最后通过调用getRakeTasks会返回一个任务数组。

ShellExecution会针对不同的系统在shell中执行rake compile命令(如:在Windows下会在PowerShell中执行,Ubuntu则是bash)。如果某个任务需要直接执行进程(不通过shell生成),则可以使用vscode.ProcessExecutionProcessExecution的优势在于插件可以完全控制传入进程的参数,ShellExecution则会使用shell命令转义(比如:bash中的*展开)。如果ShellExecution是通过单个命令创建的,那么插件需要在命令内部确保引号和转义符的正确使用(比如,如何处理空格)。