'Run VS Code task on specific file/folder selectable via a drop-down list

I am trying to figure out how to run a VS Code task on a specific folder/file that is selectable over a drop-down list.

Example:

  1. open Command Palette (Ctrl+Shift+P)
  2. filter on 'tasks' -> select 'Tasks: Run Tasks'
  3. Select the task to run, e.g. Cpplint
  4. NEW PART: now instead of executing it right away, there should open up a drop-down list to select the folder/file you want to run the task on or you can select 'all' and it works as before and the task is run on all folders, beginning at the root (here: src) folder.

structure:

ws
|   
+-- .env
|   |  
|   +-- ...
|    
+-- src
    |  
    +-- dir1
    |   |
    |   +-- file 1.1
    |   +-- ... 
    |   +-- file 1.n
    +-- dir2
    |   |
    |   +-- file 2.1
    |   +-- ... 
    |   +-- file 2.n 
    |   +-- dir2.2
    |       |
    |       +-- file 2.2.1
    |       +-- ...
    |       +-- file 2.2.n 
    +-- ...
    |
    +-- dirn
        |
        +-- file n.1 
        +-- ... 

Is there a way to make this work? If not, is there another way to make something similar work? Thank you for your help.

Further Questions:
I was trying to run multiple linters at once with a task "Lint all". This task depends on two other tasks. To avoid parallel execution "Lint all" has "dependsOrder": "sequence", but somehow the drop-down list just appears for the first sub-task. Also just the first sub-task gets executed and then the execution stops. Now I have two questions:

  1. Is there a way to get the drop-down list for every sub-task?
  2. Is there a way to get the drop-down list just for the first sub-task and then the following sub-tasks remember the input an execute automatically with that?
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Lint all",
            "detail": "Run all linters",
            "dependsOrder": "sequence",
            "dependsOn":["Cpplint", "Pylint"],
            "problemMatcher": []
        },
        {
            "label": "Cpplint",
            "type": "shell",
            "command": "cpplint --recursive ${input:selectDir}",
            "problemMatcher": []
        },
        {
            "label": "Pylint",
            "type": "shell",
            "command": "pylint ${input:selectDir}",
            "problemMatcher": []
        }
    ],
    "inputs": [
        {
            "id": "selectDir",
            "type": "command",
            "command": "extension.commandvariable.pickStringRemember",
            "args": {
                "description": "Which directory to Lint?",
                "options": [
                    ["All", "src/"],
                    ["Rerun task", "${remember:toRemember}"],
                    ["Pick directory", "${pickFile:directory}"]
                ],
                "default": null,
                "pickFile": {
                    "directory": {
                        "description": "Which directory?",
                        "include": "src/**",
                        "showDirs": true,
                        "keyRemember":"toRemember"
                    }
                }
            }
        }
    ]
}


Solution 1:[1]

You can use an ${input} variable

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "cpp lint",
      "type": "shell",
      "command": "cpplint ${input:selectDir}"
    }
  ],
  "inputs": [
    {
      "id": "selectDir",
      "type": "pickString",
      "description": "What directory to lint?",
      "options": [
        {"label": "All", "value": "" },
        "dir1",
        "dir2",
        "dir3"
      ]
    }
  ]
}

Edit

With the extension Command Variable v1.35.0 you can get a dynamic list of directories.

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "cpp lint",
      "type": "shell",
      "command": "cpplint ${input:selectDir}"
    }
  ],
  "inputs": [
    {
      "id": "selectDir",
      "type": "command",
      "command": "extension.commandvariable.pickStringRemember",
      "args": {
        "description": "Which directory to Lint for C++?",
        "options": [
          ["Use previous directory", "${remember:srcSubDir}"],
          ["All", "all"],
          ["Pick directory", "${pickFile:srcSubDir}"]
        ],
        "default": null,
        "pickFile": {
          "srcSubDir": {
            "description": "Which directory?",
            "include": "src/**/*.{cpp,h}",
            "showDirs": true,
            "keyRemember": "srcSubDir"
          }
        }
      }
    }
  ]
}

If you pick a src sub directory you get the full path of the directory. I have created an issue to get results relative to workspace. You can use the extension.commandvariable.transform command to remove the workspace folder part.


Edit 2

In Command Variable v1.35.1:

  • Fixed the storing of raw value in pickStringRemember. Now the value after variable substitution is stored.
  • Fixed the escaping of the pickString and pickFile UI to abort the task.
  • Add a property in example to pickFile to store the picked file under a name
  • Add an option in example to pickString to use/remember the previous pickFile
  • Add a default property to example in pickString to escape the UI

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1