使用Visual Studio Code执行多个命令/任务

45

我有一个本地文件夹,用作多个小样本和玩具代码的草稿本。我在此目录中存储大量的Python、C++、Shell脚本等。

我正在使用Visual Studio Code(在OS X上),并且正在研究它的任务,以便在不切换到终端的情况下运行/编译代码片段。

例如,我发现以下任务将在当前打开的文件上运行Python。

// A task runner that runs a python program
{
    "version": "0.1.0",
    "command": "/usr/bin/python",
    "args": ["${file}"]
}

无论我当前编辑的文件类型是什么,这个任务都将使用Python作为任务运行程序。

如何实现基于文件类型运行命令的任务(或在多个命令之间进行选择)?例如,如果我正在编辑C++文件,它将运行clang++。

  • 如果我不能基于文件类型执行此操作,是否有其他替代方法?
  • 另一种选择是:是否支持多个命令?

1
提醒一下,这里最受欢迎、最详细的两个答案都依赖于已废弃的 tasks.json 语法版本。 - NullPointerException
7个回答

49

你可以始终使用bash作为你的任务运行器,然后将任意终端命令指定为你的任务。

{
    "version": "0.1.0",
    "command": "bash",
    "isShellCommand": true,
    "showOutput": "always",
    "args": [
        "-c"
    ],
    "tasks": [
        {
            "taskName": "My First Command",
            "suppressTaskName": true,
            "isBuildCommand": true,
            "args": ["echo cmd1"]
        },
        {
            "taskName": "My Command Requiring .bash_profile",
            "suppressTaskName": true,
            "args": ["source ~/.bash_profile && echo cmd2"]
        },
        {
            "taskName": "My Python task",
            "suppressTaskName": true,
            "args": ["/usr/bin/python ${file}"]
        }
    ]
}

这里有一些说明:
  • 使用bash的-c参数在args列表中为所有任务设置,以便我们可以运行任意命令。 echo语句只是示例,但可以从您的bash终端执行任何内容。
  • args数组将包含要传递给bash -c的单个字符串(分隔项将被视为多个参数传递给bash命令而不是与-c参数相关联的命令)。
  • 正在使用suppressTaskName来保持taskName不参与混合
  • 第二个命令显示了如何加载您的~/.bash_profile,如果您需要它提供的任何内容,例如别名、环境变量等
  • 第三个命令显示了如何使用您提到的Python命令
这不会给您任何文件扩展名检测,但您至少可以使用cmd+p,然后键入“task”来获取您的任务列表。 您始终可以使用isBuildCommandisTestCommand标记您最常用的2个命令,以通过cmd+shift+bcmd+shift+t运行它们。 这个答案有一些有用的信息,可能对您有用。

我回来了,我真的很喜欢使用bash -c作为命令运行器的想法。这非常适合我。 - Niall
我创建了一个变体来编译一个简单的C++程序,类似于你上面提到的内容。不幸的是,我无法在评论中粘贴它。但是我注意到的是,任务的输出未显示在输出窗格中。例如,如果我的任务执行“bash -c helloworld”,那么输出窗格中不会出现“Hello world”。我正在努力解决如何做到这一点。 - andrea
这就是我收敛到的结果: https://github.com/ataiya/hellovsc请注意,由于某种原因,只有在执行“echoCommand”:false时,我才能看到计算机/运行输出,这特别不直观!而且当任务执行完成时,你根本不知道它已经完成了,这真是太糟糕了。 - andrea
我没有使用过echoCommand,所以不确定其中的细微差别。至于如何知道任务何时完成,您可以在命令末尾始终连接&& echo done。"args": ["g++ -v hello.cpp -o hello && echo done"] - bingles

21

最简单的方法是在shell中用;(或&&)将它们分开添加:

tasks.json:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "test",
            "type": "shell",
            "command": "cd ~/dev/xxxx;source ~/dev/yyyy;ls",
        }
    ]
}

2
这对于一些简短的命令是有效的,但不幸的是,在json中你不能有多行字符串,因此如果有许多命令,你无法添加换行符以实现可视化可读性。 - wisbucky

13

为什么这不是被接受的答案呢 :) - Nour
1
这将创建两个独立的终端。 - Neema Mashayekhi
补充上述评论,这意味着如果你在一个任务中使用了某个脚本,其效果不会应用到下一个任务中。 - Reza

10

tasks.json最近的更改似乎为列出的每个任务提供了一个可用的命令。请参见https://code.visualstudio.com/docs/editor/tasks,这使得很多内容都没有意义了。


原本的答案旨在提供更复杂的解决方案,但已接受的答案中呈现的简单shell运行器任务格式更加有用。请看下面的内容了解其样式。


在这里的限制是VS Code对于给定工作区只允许一个高级别构建任务/命令。允许使用多个子任务,但它们受限于使用顶层“command”,但可以提供不同的“arguments”。这非常适合使用类似于make、ant或msbuild的构建系统的环境。例如:

{
    "version": "0.1.0",
    "command": "make", // command must appear here
    "tasks" : [
        {
            "taskName": "clean",
            "suppressTaskName": false, // false by default
            //"command": "somethingelse", // not valid here
            "args": ["${file}"] // if required
        },
        {
            "taskName": "install"
            // ...
        }
    ]
}

有两种选择;

  • 使用自定义脚本尝试仅基于task.json中的参数运行编译/执行。

 -- the shell file would be a simple
 "$@" # run what I get
 -- the tasks.json
 "args": ["clang++", "-std=c++14", "-O2", "${file}"]

运行可执行文件(./a.out)需要更多的努力。简单地将其添加为参数并不起作用,如果存在,则需要 shell 脚本来执行它。

  • 将切换和输出的执行移交给自定义脚本,根据文件扩展名和文件名进行处理。这种方法更容易实现,并在 shell 脚本中提供了更多的控制。

 {
     "version": "0.1.0",
     "isShellCommand": true,
     "taskName": "generic build",
     "showOutput": "always",
     "args": ["${fileExtname}", "${file}"]
     "command": "./.vscode/compileme.sh", // expected in the "local settings" folder
     //"command": "~/compileme.sh", // if in HOME folder
 }

还有编译脚本,compileme.sh;

    #!/bin/sh
    # basic error checking not shown...
    echo "compilation being executed with the arguments;"
    echo "$@"
    filetype=$1
    file=$2
    if [ $filetype = ".cpp" -o $filetype = ".cxx" ] ; then 
        clang++ -std=c++14 -Wall -Wextra -pedantic -pthread $file && ./a.out
    elif [ $filetype = ".c" ]
        then 
        clang -std=c11 -Wall -Wextra -pedantic -pthread $file && ./a.out
    elif [ $filetype = ".sh" ]
        then
        $file
    elif [ $filetype = ".py" ]
        then
        python $file
    else
        echo "file type not supported..."
        exit 1
    fi

在上述选项中,第二个选项更可取。这个实现适用于OS X,但可以根据需要轻松移植到Linux和Windows。我会继续关注此事,并尝试跟踪VS Code构建任务的更改,基于文件的构建或多个命令的支持可能是一个受欢迎的补充。


我的tasks.json支持几个运行器,并且默认情况下构建会打印消息作为提醒。它使用shell作为运行器,现在看起来像...

{
    "version": "0.1.0",
    "isShellCommand": true,
    "taskName": "GenericBuild",
    "showOutput": "always",
    "command": "sh",
    "suppressTaskName": false,
    "args": ["-c"],
    "tasks": [
        {
            "taskName": "no build",
            "suppressTaskName": true,
            "isBuildCommand": true,
            "args": [
                "echo There is no default build task, run a task by name..."
            ]
        },
        {
            "taskName": "cpp",
            "suppressTaskName": true,
            "args": [
                "clang++ -std=c++14 -Wall -Wextra -pedantic -pthread \"${file}\" && ./a.out"
            ]
        },
        {
            "taskName": "shell",
            "suppressTaskName": true,
            "args": [
                "\"${file}\""
            ]
        },
        {
            "taskName": "python",
            "suppressTaskName": true,
            "args": [
                "python \"${file}\""
            ]
        },
        {
            "taskName": "c",
            "suppressTaskName": true,
            "args": [
                "clang -std=c11 -Wall -Wextra -pedantic -pthread \"${file}\" && ./a.out"
            ]
        }
    ]
}

1
您可以编写并运行自定义脚本文件,而不是直接使用python等。在脚本文件中,您需要提取文件扩展名以调用所需的编译器/翻译器,例如pythonclang等。因此,您的任务文件应如下所示:
// A task runner that runs a program
{
   "version": "0.1.0",
   "command": "${workspaceRoot}\\runProgram.sh",
   "args": ["${file}"]
}

1
从Adriel的回答中还有一点需要注意的是可以将列表传递给“command”关键字。配合“shell”标签,您可以以人类可读的格式传递多个CLI命令,而无需组合任务。
只需注意列表的元素由空格分隔,并且必须根据您希望shell如何解释它们进行正确的后缀。例如,您可以放置分号,使bash shell将它们分隔为单独的命令:
"version": "2.0.0",
"tasks": [
    {
        "label": "build",
        "type": "shell",
        "command": [
            "python -m module arg1 arg2;",
            "cp outputfile.json someproject/results;",
            "cp version.txt someproject/version"
        ]
    }
]

-1
我写了这个脚本。
它需要在你的环境中安装Python IDLE。 每次运行任务(CTRL+Shift+B),它都会打开IDLE并运行你的Python文件。
{
    "version": "0.1.0",             
    "command": "/usr/bin/idle",
    "isShellCommand": false,
    "showOutput": "never",
    "args": ["-r","${file}"]    
} 

你可以使用CTRL+D关闭IDLE。 - MrAlex6204

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接