-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support expanding input parameters into multiple arguments #83678
Comments
@anatolyburakov I understand the usefulness of your feature. But how should it actually work? Today the input prompting mechanism is based on variable substitution: a specific pattern With your feature the variable's value becomes an array. So the pattern that occurs in a string now needs to be replaced by by an array. How do you envision would the syntax look like and how would you explain the semantics? |
Thanks for creating this issue! We figured it's missing some basic information or in some other way doesn't follow our issue reporting guidelines. Please take the time to review these and update the issue. Happy Coding! |
The easiest way i can think of is add another input type (instead of it being a "string" or a "choice", also add something like "argument list"), and split it into an array the way shell does (something every programmer should be familiar with). This would be the most sensible. The launch config does not allow specifying full command strings anyway and mandates making an "args" array for arguments - so array expansion inside this array shouldn't be too hard (i'm not familiar enough with JS, but it works find in Python with one line of slicing magic). |
@anatolyburakov thanks, but I understand how to make a variable returning an array. That's not the problem. The question is: how would the launch config look like that allows for substituting a variable by an array. Your example syntax does not work because the variable {
"name": "myexe",
"type": "cppdbg",
"request": "launch",
"program": "myexepath",
"args": [
"${input:mystr}"
]
} And something like this cannot work either because its is no longer valid JSON: {
"name": "myexe",
"type": "cppdbg",
"request": "launch",
"program": "myexepath",
"args": ${input:mystr}
} |
@weinand i'm not well versed in either JS or in internals of VSCode, so i wouldn't know how to do that. however, with Python, it's done trivially:
i'm sure there's probably a better way to write this, but the point is, i don't understand the problem with implementing such a simple array transform. perhaps i'm missing something? |
The problem is that launch.json is json, not a programming language. The examples that @weinand give in #83678 (comment) illustrate this very nicely. You either have invalid json or a string. |
@alexr00 yes, but whatever handles that JSON presumably is a programming language? |
In the example we have:
So replace |
@alexr00 basically yes, replace that with an array. if it matches without being the entire string (i.e. "something ${input:mystr} something else"), simply throw an error (or don't replace). EDIT: to be more precise, remove it, and insert an array in the middle. "replacing" with an array will just yield an array within an array... the replacement is already being performed - so, regardless of whether or not "JSON is not a programming language", there presumably is some kind of pre-processing already being performed on this JSON data that involves "a programming language" (unless JSON has that built-in somehow? please excuse my ignorance on this matter). i'm simply suggesting adding one more step, albeit a slightly more complex one than simply string replacement. |
We are all programmers, so we don't have to discuss how to implement this feature. The issue is that there is an "end user aspect": How does the syntax look like that an end user would use and what exactly is the semantics of that syntax. This "end user aspect" is completely independent from implementation details. Let me try a proposal "for end users": Variable substitution is only performed in strings and the syntax is If the type of at least one variable is a not string, its value will be used to replace the entire enclosing string (and all the other variables are ignored). So if the variable "BAR" is the number 123, the JSON expression
would effectively become:
Any surrounding text or additional variables inside the original string are dropped. If the value of "BAR" is an array
This syntax and semantics is a bit strange for my taste.... @alexr00 @isidorn @roblourens @dbaeumer what do you think? |
@weinand my apologies, it seems that i was consistently misunderstanding the nature of the questions i'm getting. speaking of your proposal, that works only if you do simple replacement. you don't have to do that, and it would limit usefulness of this feature, because it would now be not possible to have some predefined arguments and custom ones at the same time. in a perfect world, i would like something like:
turning into
That's the main goal of this proposal. What happens when |
While I see how this could be useful, I agree with @weinand that the semantics of this are a bit strange. We have taught users that |
Well, i'm open to suggestions on how to get this functionality without building it into VSCode. when introducing VSCode to my coworkers, this is one of the first things that i have to explain away, and make known. we're all used to running gdb with arguments, The nature of software we're working on is such that there is a huge number of command-line parameters, so creating a launch configuration for every permutation gets a bit tedious. |
@alexr00 @weinand is this kind of thing possible to do with an extension? As in, intercepting all calls to debug targets, and modifying arguments before actually running debug target? Or maybe there is a better way to achieve this? This really sounds like a good excuse to try my hand at VSCode extension development, as it seems simple enough to get it fixed quickly, and annoys me strongly enough to give me motivation to fix it... :) |
Good morning, I have found the input feature very useful in the context of debugging. However, as @anatolyburakov has mentioned, there are many cases when it would be very useful to type in an entire list of args that is passed to the "args" debug parameter as an array of strings. For example, I do much of my development in Perl, and the ability to pass multiple arguments to a script is essential. The current functionality using string substitution will not work in Perl when passing more than one argument since it treats the entire string as a single argument. Being able to type in the args and have them substituted as an array would solve the issue. Concerning how this particular feature would be added, we could do it along the lines of the existing framework, as mentioned in the previous discussions:
The new type, To remedy this, I suggest a new type of variable with the format
In the debug configuration above, say that we enter the following argument list in the input box:
The new array type variable,
With this new variable type, we thus remove the confusion between string substitution and array substitution. The string variable convention remains in place without being disturbed by a change in semantics. The usefulness of this feature would extend past debug configurations and into tasks, where arrays of strings would be useful for passing multiple distinct arguments. I do not think this feature would be hard to implement and believe that it would turn out to be very useful. In my case, it would enable input of multiple args to my Perl scripts, which is currently not possible. If you would like more/alternate suggestions and/or details regarding this feature, please let me know. I am happy to contribute however I can to the development of this idea, and I very much hope that this feature will be added. Thank-you for listening. Your time and patience is much appreciated. |
I think the solution proposed by @weinand above is a great idea and would very much like to see this added. |
+1 for having an option to pass several args as a string from input. |
Any news about this? Looks like this is still tagged as "under discussion" but as far as I understand from this conversation the implementation is clear, isn't it? |
Any news about this? |
Does anyone have an idea to work around this issue, while we wait for news? My current
Sometimes I need to add more than one flag, but only for a one-off test. My only solution right now is to add them into the If this issue was solved, I could stuff everything in a single string, and have a single |
I built a work-around into my (python) project for the time being. Essentially I check the environment to determine if it is vscode, then split the single argument into multiples and update sys.argv as the program inits In my case it's a CLI program for convenience I wanted to be able to specify the command to run via drop-down, and also to remember the last command I ran so for repeat tests I can just hit enter. __init__ checks the following if os.environ.get("TERM_PROGRAM") == "vscode":
from .vscodeargs import vscode_arg_handler
vscode_arg_handler() Then the module that breaks out the single "arg1 arg2 arg3" into ["arg1", "arg2", "arg3"] is here Note: it has some stuff likely specific to my needs, and honestly there are a couple of things in there... that I can't recall why, so it could be simplified. Again, this not only breaks the args up, but also updates launch.json (so the drop-downs default value is whatever the last command was). launch.json would need to be formatted accordingly. |
Why not just add an 'empty' option to the "quoting" types of args to not perform any quoting? So for instance: Then if my_app_args gets the input: "-d -e" |
As a workaround I do not use the 'args' property at all and instead place all of the flags (both static and input) straight in the command string: |
This didn't work for me, namely on bashdb. They support a different attribute, argsString, that takes care of this. Feels like this (dynamic input arguments) problem is solved by some debugger extensions in different ways, but would be better solved at the IDE level. { |
"args": [
"a",
"b",
{ "type": "split", "from": "${input:arguments}" },
"d",
] |
Given the fact that this issue is open since 2019, with yet not a clear solution from the VSCode side, I think it's reasonable that each extension implements their own way around it. After all, the Debug configuration is mostly passed as is from VS Code to the Debug extensions, so it's up to them what to do with that data. My understanding is that As a reference, there is the Bash Debug implementation: #83678 (comment). |
@felipecrs your assessment of the problem is correct: VS Code knows nothing about |
So... one possible conclusion for this issue would be "Won't fix", encouraging extension authors to implement it. PS: I'm saying this because some extensions are reluctant to add it given the fact that this issue is still open and, in the backlog (like this). |
Today I was looking exactly for such a feature and landed on this thread that delivers the bad news. For now I am using a static solution that kinda solves my problem, but sure looks bad: launch.json (without the rest of my configs): {
"version": "0.2.0",
"inputs": [
{"type": "promptString", "id": "arg1", "description": "Insert arg 1", "default": ""},
{"type": "promptString", "id": "arg2", "description": "Insert arg 2", "default": ""},
{"type": "promptString", "id": "arg3", "description": "Insert arg 3", "default": ""},
{"type": "promptString", "id": "arg4", "description": "Insert arg 4", "default": ""},
{"type": "promptString", "id": "arg5", "description": "Insert arg 5", "default": ""},
{"type": "promptString", "id": "arg6", "description": "Insert arg 6", "default": ""},
{"type": "promptString", "id": "arg7", "description": "Insert arg 7", "default": ""},
{"type": "promptString", "id": "arg8", "description": "Insert arg 8", "default": ""},
{"type": "promptString", "id": "arg9", "description": "Insert arg 9", "default": ""},
{"type": "promptString", "id": "arg10", "description": "Insert arg 10", "default": ""}
],
"configurations": [
{
"name": "Py: Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": []
},
{
"name": "Py: 1 arg Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}"]
},
{
"name": "Py: 2 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}"]
},
{
"name": "Py: 3 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}"]
},
{
"name": "Py: 4 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}"]
},
{
"name": "Py: 5 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}"]
},
{
"name": "Py: 6 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}", "${input:arg6}"]
},
{
"name": "Py: 7 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}", "${input:arg6}", "${input:arg7}"]
},
{
"name": "Py: 8 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}", "${input:arg6}", "${input:arg7}", "${input:arg8}"]
},
{
"name": "Py: 9 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}", "${input:arg6}", "${input:arg7}", "${input:arg8}", "${input:arg9}"]
},
{
"name": "Py: 10 args Current File", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}", "${input:arg6}", "${input:arg7}", "${input:arg8}", "${input:arg9}", "${input:arg10}"]
},
]
} With this from the debug drop down list I select how many args I want to input and then insert one by one on the prompt boxes. It is also possible to choose more args than needed and simply press enter a couple of times until all args are exhausted, but that is also not ideal. Other thing that crossed my mind, that is also very hacky, was making a task that would run a script that would modify the I really hope the VSCode team finds a suitable solution for this. EDIT: Something like this, launch.json: {
"version": "0.2.0",
"inputs": [
{"id": "arg1", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg1", "description": "Enter Arg 1" }},
{"id": "arg2", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg2", "description": "Enter Arg 2" }},
{"id": "arg3", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg3", "description": "Enter Arg 3" }},
{"id": "arg4", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg4", "description": "Enter Arg 4" }},
{"id": "arg5", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg5", "description": "Enter Arg 5" }},
{"id": "arg6", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg6", "description": "Enter Arg 6" }},
{"id": "arg7", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg7", "description": "Enter Arg 7" }},
{"id": "arg8", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg8", "description": "Enter Arg 8" }},
{"id": "arg9", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg9", "description": "Enter Arg 9" }},
{"id": "arg10", "type": "command", "command": "extension.commandvariable.promptStringRemember", "args": { "key": "arg10", "description": "Enter Arg 10" }},
{"id": "rememberArg1", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg1" }},
{"id": "rememberArg2", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg2" }},
{"id": "rememberArg3", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg3" }},
{"id": "rememberArg4", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg4" }},
{"id": "rememberArg5", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg5" }},
{"id": "rememberArg6", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg6" }},
{"id": "rememberArg7", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg7" }},
{"id": "rememberArg8", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg8" }},
{"id": "rememberArg9", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg9" }},
{"id": "rememberArg10", "type": "command", "command": "extension.commandvariable.remember", "args": { "key": "arg10" }}
],
"configurations": [
{
"name": "Py: Current File (no args)", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": []
},
{
"name": "Py: Current File (store)", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:arg1}", "${input:arg2}", "${input:arg3}", "${input:arg4}", "${input:arg5}", "${input:arg6}", "${input:arg7}", "${input:arg8}", "${input:arg9}", "${input:arg10}"]
},
{
"name": "Py: Current File (recall)", "type": "python", "request": "launch", "console": "integratedTerminal", "justMyCode": false,
"program": "${file}",
"args": ["${input:rememberArg1}", "${input:rememberArg2}", "${input:rememberArg3}", "${input:rememberArg4}", "${input:rememberArg5}", "${input:rememberArg6}", "${input:rememberArg7}", "${input:rememberArg8}", "${input:rememberArg9}", "${input:rememberArg10}"]
}
]
} |
@jcbastosportela The July release has a new feature that helps debug extension authors to solve the problem. In the July release only VS Code's built-in JS debugger has adopted the new feature, but I expect Python to follow soon. /cc @roblourens |
i may be missing something obvious, but i don't see how this solves the desire to
can you give an example of how to use this? thanks. |
@bmacnaughton This makes it possible to use a command line like the following in a launch.json: "args": "`echo hello world` > outfile", Instead of having this command line literal in the launch.json you can use an "args": "${input:commandline}", |
thank you! i can miss the most obvious things at times. i appreciate your time. |
For future me, a quick {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current file debugging",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"args": "${input:args}",
},
],
"inputs": [
{
"id": "args",
"type": "promptString",
"description": "Args for the program",
}
]
} It will warn that the |
with VS Code's support for uninterpreted arguments (see comment above), we have no further plans to work on this issue. |
Currently, it is possible to specify debug arguments from input, using this syntax:
And having this prompt appear in launch.json:
This will cause a prompt to appear, asking for arguments to pass to the application. However, it is only possible to pass one argument that way.
It would be nice if it was possible to expand this:
into this:
This would make opportunistic debugging (testing with different parameters quickly) much easier, and will avoid polluting the
launch.json
with targets that are used only once and then discarded.The text was updated successfully, but these errors were encountered: