2

Let's say we have the following custom task :

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "do smthg",
            "type": "shell",
            "command": "echo \"selected option: ${input:option_name}\"",
            "problemMatcher": [],
            "presentation": {
                "panel": "dedicated",
                "focus": true
            }
        }
    ],
    "inputs": [
        {
            "type": "pickString",
            "id": "option_name",
            "description": "select an option :",
            "options": [
                // want possible options to be the output of a command
            ],
            "default": ""
        }
    ]
}

But I want the available options to be the result of a command,
like ls, or a cat smthg.txt | grep -oP '\"value\:\"\K\w*',

how can I do that ? Is it only possible ?

3
  • you don't post a valid tasks.json file Commented Apr 6, 2022 at 14:53
  • 1
    @rioV8 Of course this is a simplified, minimalistic and thus non-exhaustive snippet. I updated the code tho. Commented Apr 6, 2022 at 16:04
  • after a search I found Tasks Shell Input, it looks like to match what you want Commented Apr 8, 2022 at 11:48

2 Answers 2

3

You can use the extension Command Variable v1.34.0

Use the replacement for pickString named extension.commandvariable.pickStringRemember.

This command can read options from a file, you determine the format with a regexp like the problem matcher of tasks.

An example:

  "inputs": [
    {
      "type": "command",
      "id": "option_name",
      "command": "extension.commandvariable.pickStringRemember",
      "args": {
        "description": "select an option :",
        "options": [
          ["always 1", "5000"],
          ["always 2", "5100"]
        ],
        "default": "",
        "fileName": "${workspaceFolder}/foo-bar.txt",
        "pattern": {
          "regexp": "^\\s*(?!#)([^=]+?)\\s*=\\s*(?:(\\{.+\\})|(.+))$",
          "label": "$1",
          "json": "$2",
          "value": "$3"
        }
      }
    }
  ]

If you don't have label - value lines you can simplify the pattern to

        "pattern": {
          "regexp": "^\\s*(?!#)(.+)$"
        }

If you don't have static options (always 1/2 in example) you can remove the options property from args.

With an additional task you create the file with a command or a shell script if grep-ping and file redirection might be a problem (pass the output file name, using variables, as argument to the script).

You can construct a sequence of tasks, a compound task, see VSC doc.

Sign up to request clarification or add additional context in comments.

6 Comments

As you seems to be the author of this extension, I suppose you dig the question a lot, so there's no way to achieve this without relying on another extension ? Sadly, installing a new extension is often not an acceptable option for most companies.
@Guss the build in pickString is very limited and only allows hard coded options in the task/launch file. You can look at the source code in the extension, download the vsix and use an unzip tool. So if you use Python you don't install the Python extension because it is not part of the default install? In VSC almost all functionality is an extension.
@Guss then you can write a script that modifies your tasks.json and fills in the options for the pickString input, additional possibility in v1.42 release notes
Yes I indeed ended up with a task configure that detect/replace/inject the options I want into my run task. I whish there were a more elegant way to achieve this.
@Guss without an extension VSC has no option to do this
|
2

This rough approach avoids the use of either a custom or external extension. The only presumption is that Python is already installed on the system. Using the python module json (assuming there are no comments in your task.json), a "pre-task" is made to modify the options key within the list for the inputs key in task.json. In this example, the "main task" will use echo in the terminal to say "Hi" to a chosen user from the updated input options after the "pre-task" runs. A directory has a set of folders that follow a naming scheme USER_[insert_username]:

.vscode/
├─ task.json
USER_CindycinErean
USER_Link/
USER_Mario/
USER_Ness/
USER_ShihTzu/

With python, the "pre-task" will scan the directory that matches this schema and update the options key as a list within inputs. The block below is how the code normally looks in a typical python script:

import json, os
base_folder = os.getcwd()
list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)]
path = base_folder + r'\\.vscode\\tasks.json'
path = r'{}'.format(path)
j = open(path, 'r');ex = json.load(j)
j.close()
j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users
ex['inputs'][0]['default'] = list_of_users[0]
json.dump(ex,j, indent=4);j.close()

And here is the code in a single line:

import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()

The "pre-task" is created using the single line code after double quotes have been escaped and the Python command argument (-c) has been used.

"command": "python3 -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""

Now with that defined, here is the before state of task.json for Windows, OSX, and Linux:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Say Hi to selected user",
            "type": "shell",
            "dependsOn":["Update for User Selection"],
            "command": "echo Hi ${input:userSelect} !!!",
            "problemMatcher": []
        },
        {
            "label": "Update for User Selection",
            "type": "shell",
            "linux": {
                "options": {
                    "cwd": "${workspaceFolder}"
                },
                "command": "python3 -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""
            },
            "osx": {
                "options": {
                    "cwd": "${workspaceFolder}"
                },
                "command": "python3 -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""
            },
            "windows": {
                "options": {
                    "shell": {
                        "executable": "C:\\Windows\\system32\\cmd.exe",
                        "args": [
                            "/d",
                            "/c"
                        ]
                    },
                    "cwd": "${workspaceFolder}"
                },
                "command": "python -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""
            },
            "problemMatcher": []
        }
    ],
    "inputs": [
        {
            "type": "pickString",
            "id": "userSelect",
            "description": "Choose a user from the directory to say Hi to!",
            "options": [
                "UserA",
                "UserB",
                "UserC",
                "UserD"
            ],
            "default": "UserA"
        }
    ]
}

And this is the after state:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Say Hi to selected user",
            "type": "shell",
            "dependsOn": [
                "Update for User Selection"
            ],
            "command": "echo Hi ${input:userSelect} !!!",
            "problemMatcher": []
        },
        {
            "label": "Update for User Selection",
            "type": "shell",
            "linux": {
                "options": {
                    "cwd": "${workspaceFolder}"
                },
                "command": "python3 -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""
            },
            "osx": {
                "options": {
                    "cwd": "${workspaceFolder}"
                },
                "command": "python3 -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""
            },
            "windows": {
                "options": {
                    "shell": {
                        "executable": "C:\\Windows\\system32\\cmd.exe",
                        "args": [
                            "/d",
                            "/c"
                        ]
                    },
                    "cwd": "${workspaceFolder}"
                },
                "command": "python -c \"import json, os;base_folder = os.getcwd();list_of_users = [f.name.split('_')[1] for f in os.scandir(base_folder) if (f.is_dir() and 'USER' in f.name)];path = base_folder + r'\\.vscode\\tasks.json';path = r'{}'.format(path);j = open(path, 'r');ex = json.load(j);j.close();j = open(path, 'w');ex['inputs'][0]['options'] = list_of_users;ex['inputs'][0]['default'] = list_of_users[0];json.dump(ex,j, indent=4);j.close()\""
            },
            "problemMatcher": []
        }
    ],
    "inputs": [
        {
            "type": "pickString",
            "id": "userSelect",
            "description": "Choose a user from the directory to say Hi to!",
            "options": [
                "CindycinErean",
                "Link",
                "Mario",
                "Ness",
                "ShihTzu"
            ],
            "default": "CindycinErean"
        }
    ]
}

Below is a demonstration of the task Update for User Selection being executed with the user Mario selected after changes to the task.json: enter image description here

2 Comments

Interesting approach ! In the end, my way to do this was to use CMake (as this is a C++ project) to generate and inject the list of options I needed. That may sound sub-optimale, but it works pretty well
why don't you use os.path.join(), that will also work on Linux/Mac, path = r'{}'.format(path) is a nop statement, it is not Pythonic to use ;, why don't you use context managers, you program Python 2.4 style. Why add the script 3 times to your task.json file when you could add a python script to the .vscode folder and call that script, you only need to edit 1 location incase you change the working and it keeps it readable if you don't use ;, why do you use \\ in an r string

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.