Skip to content
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

Allow "args" to be specified as a single string. #1210

Open
zjturner opened this issue Nov 7, 2017 · 19 comments
Open

Allow "args" to be specified as a single string. #1210

zjturner opened this issue Nov 7, 2017 · 19 comments

Comments

@zjturner
Copy link

zjturner commented Nov 7, 2017

When configuring the launch.json file, it expects args to be an array of strings that are passed to the process, where each item in the array is one argument. This is extremely user-unfriendly when dealing with long command lines. For example, here is my use case.

Problem: I want to debug clang when you run clang-cl.exe /c foo.cpp

Step 1: Run clang-cl.exe /c foo.cpp -###

E:\src\llvmbuild\ninja>bin\clang-cl /c foo.cpp -###
clang version 6.0.0
Target: i686-pc-windows-msvc
Thread model: posix
InstalledDir: E:\src\llvmbuild\ninja\bin
 "E:\\src\\llvmbuild\\ninja\\bin\\clang-cl.exe" "-cc1" "-triple" "i686-pc-windows-msvc19.11.25508" "-emit-obj"
"-mrelax-all" "-mincremental-linker-compatible" "-disable-free" "-main-file-name" "foo.cpp" "-mrelocation-model"
"static" "-mthread-model" "posix" "-mdisable-fp-elim" "-relaxed-aliasing" "-fmath-errno" "-masm-verbose"
"-mconstructor-aliases" "-target-cpu" "pentium4" "-D_MT" "-flto-visibility-public-std" "--dependent-lib=libcmt"
"--dependent-lib=oldnames" "-stack-protector" "2" "-fms-volatile" "-fdiagnostics-format" "msvc"
"-dwarf-column-info" "-debugger-tuning=gdb" "-coverage-notes-file" "E:\\src\\llvmbuild\\ninja\\foo.gcno" "-resource-dir" "E:\\src\\llvmbuild\\ninja\\lib\\clang\\6.0.0"
"-internal-isystem" "E:\\src\\llvmbuild\\ninja\\lib\\clang\\6.0.0\\include"
"-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\VC\\Tools\\MSVC\\14.11.25503\\ATLMFC\\include"
"-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\VC\\Tools\\MSVC\\14.11.25503\\include"
"-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.6.1\\include\\um"
"-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.16299.0\\ucrt"
"-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.16299.0\\shared" 
"-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.16299.0\\um"
"-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.16299.0\\winrt"
"-fdeprecated-macro" "-fdebug-compilation-dir" "E:\\src\\llvmbuild\\ninja" "-ferror-limit" "19"
"-fmessage-length" "120" "-fno-use-cxa-atexit" "-fms-extensions" "-fms-compatibility"
"-fms-compatibility-version=19.11.25508" "-std=c++14" "-fdelayed-template-parsing"
"-fobjc-runtime=gcc" "-fdiagnostics-show-option" "-fcolor-diagnostics" "-o" "foo.obj" "-x" "c++" "foo.cpp"

Step 2: Take the resulting command line, and debug that. this is necessary because the original invocation actually spawns a child process whose command line is the second invocation, and it is that child invocation that actually needs to be debugged.

In order for me to do this, I have to manually add commas to this huge list of command line arguments.

Worse, if I change one little option to the original clang-cl.exe this entire line could end up being different, and I have to do this all over again. It would be nice if I could just paste this somewhere as a single string.

In regular VS there is one box where I can just paste this. Even in GDB I can just run gdb against clang-cl.exe and then pass command line arguments as a single string. This is a very big productivity hit for projects that frequently debug processes with long command lines.

@pieandcakes
Copy link
Contributor

Fastest way I can see would be to do a find and replace of " " with ",".

You can make it all one string but then its passed to the program as one string and many programs don't like it as one string. We offer this option to allow users the flexibility of specifying separate arguments or arguments with spaces in them.

If you want them as one string, you can replace each " with /" and it will pass it as one string with your quotes.

@zjturner
Copy link
Author

zjturner commented Nov 9, 2017 via email

@pieandcakes
Copy link
Contributor

I added it as a feature request. I assume we can provide a shortcut but this might be more beneficial to ask VS Code itself to have this feature instead of it only being available for the CPP extension.

@zjturner
Copy link
Author

I asked in vscode github and they said to just make an extension. That's about what I expected them to say, but I believe this is useful enough that vscode should support it directly, if not in the larger project in the cpptools extension. Setting a debugging command line is an extremely difficult and awkward thing to do right without it.

@pieandcakes
Copy link
Contributor

I marked it as a Feature request and we can take a look at what it would take.

@geajack
Copy link

geajack commented Jun 27, 2020

I'd like this to, so that I can specify the args as an input:

"args": "${input:arguments}"

@chatziko
Copy link

chatziko commented Jul 4, 2020

And also as a configuration parameter:

"args": "${config:program_args}"

Not not mention that it's just the canonical way people have been providing program args in shells for decades 😄

@audetto
Copy link

audetto commented Jan 14, 2022

Has this ever been implemented?
Might not work in 100% case, but it will save time to 99% people 99% of the time.

It could be flexible and handle both an array (of string) or a single string.

@resk8
Copy link

resk8 commented Mar 24, 2022

any status on this? having to separate my 20+ args in comas and quotes is really painful.

@ShadyBoukhary
Copy link

Been bothered by this for years. Might make my own extension.

@ShadyBoukhary
Copy link

I'm working on an extension for this at the moment.

@ShadyBoukhary
Copy link

Done. If anybody is interested @resk8 @zjturner @audetto here's the extension
https://marketplace.visualstudio.com/items?itemName=shadyboukhary.paste-as-string-array

@emaglic
Copy link

emaglic commented Apr 13, 2023

I found this thread while trying to resolve this multiple args as single string issue with VS Code's debugger for a node project and I found a kind of hacky solution that seems to work for me, perhaps it can work here as well.

I found that the args array always wrapped my string input in a single set of quotes. But by modifying the args line in launch.json to have a closing quote at the start and a closing quote at the end I was able to step out of the quotes altogether and have my input string be added directly as regular bash options.

You end up with an empty set of quotes at the start and end of the output in the Debug Console, but that didn't seem to cause any issues on my end.

// Input value for promptString
--version 1.0 --path ./test

// launch.json
"args": "\" ${input:args} \""

"inputs": [
    {
      "id": "args",
      "description": "Input Args",
      "type": "promptString"
    }
  ]

// Debug Console Output
"C:\Program Files\nodejs\node.exe" .\test.js "" --version 1.0 --path ./test ""

@AndrewJRichardson
Copy link

AndrewJRichardson commented Aug 9, 2023

After experimenting with @emaglic 's solution I noticed something.

The behaviour of "args": "" and "args":[""] are different. Not sure if it is intentional.

If you use a single string no quoutes are added, if you use an array with spaces in any argument then quotes will be added.
Tried this with cppvsdbg not tested cppdbg

Example config:

    "configurations": [
            {
                "type": "cppvsdbg",
                "program": "C:\\Program Files\\nodejs\\node.exe",
                "name": "ArgTest",
                "cwd": "${workspaceRoot}",
                "request": "launch",
            }

Array style:

  "args": ["--version 1.0 --path ./test"],
  
  Output:  bad option: --version 1.0 --path ./test

Single string style:
It might complain about args not being an array but it will work when run.

   "args":"--version 1.0 --path ./test",
   
   Output:  v20.4.0

I suspect this isn't intended behaviour as it is inconsistent and undocumented. However, It does allow a single string and it does expand variables like ${input:myvar}.

I think a better solution might be to do something like tasks args having the quoting option, but allow us to specify "none" which will stop the adding of quotes.

"tasks": [
        {
            "label": "My Task",
            "type": "shell",
            "command": "echo",
            "args": [ { "quoting": "none", "value": "myArg1 myArg2"}],
            "problemMatcher": []
        }
    ]

@JPHutchins
Copy link

@pieandcakes

VSCode's launch.json now supports the required feature for non-hacky implementation. The "args" field can either be an array or a string. If it is a string, then it is interpreted as space-separated arguments, allowing launch.json to specify a single "input" that contains 0 or more arguments, rather than an array of inputs that each contain 1 or fewer arguments.

cppdbg does not support this VSCode feature - instead it enforces "args" as an array, requiring verbose hacks to get simple behavior.

Info from VSCode team about support:

Without this feature, "args" is an array, hard coding 4 possible positional arguments:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "my_program",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/my_program",
            "args": [
                "${input:arg1}",
                "${input:arg2}",
                "${input:arg3}",
                "${input:arg4}",
            ],
        },
    ],
    "inputs": [
        {
            "id": "arg1",
            "type": "promptString",
            "description": "required 1st arg"
        },
        {
            "id": "arg2",
            "type": "promptString",
            "description": "optional 2nd arg"
        },
        {
            "id": "arg3",
            "type": "promptString",
            "description": "optional 3rd arg"
        },
        {
            "id": "arg4",
            "type": "promptString",
            "description": "optional 4th arg"
        }
    ]
}

With this feature, "args" is a string; both config and usage are simple and extensible. The user does not have to come back to the launch.json and add more dummy inputs in case the program being run adds more args. The user does not have to hit enter on dummy prompts just because the program CAN take more args.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "my_program",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/my_program",
            "args": "${input:args}",
        },
    ],
    "inputs": [
        {
            "id": "args",
            "type": "promptString",
            "description": "space separated args"
        },
    ]
}

@aqnuep
Copy link

aqnuep commented Oct 12, 2023

I agree that this is a much needed feature. It would be great to get support for it as it imposes severe limitations on the usability of the launch.json for C++ projects.

@Vishwas-Adiga
Copy link

Vishwas-Adiga commented Oct 27, 2023

A workaround for now would be to pass the arguments to gdb directly instead of using the launch config's args field, like so:

"setupCommands": [
  {
    "description": "Set command line arguments",
    "text": "-gdb-set args ${input:commandLineArgs}",
    "ignoreFailures": true
  }
]

Or if using static text,

"setupCommands": [
  {
    "description": "Set command line arguments",
    "text": "-gdb-set args arg1 arg2 arg3 arg4",
    "ignoreFailures": true
  }
]

@stewpend0us
Copy link

A workaround for now would be to pass the arguments to gdb directly instead of using the launch config's args field, like so:

"setupCommands": [
  {
    "description": "Set command line arguments",
    "text": "-gdb-set args ${input:commandLineArgs}",
    "ignoreFailures": true
  }
]

Or if using static text,

"setupCommands": [
  {
    "description": "Set command line arguments",
    "text": "-gdb-set args arg1 arg2 arg3 arg4",
    "ignoreFailures": true
  }
]

this seems like the answer to me! not a workaround

@marcelrend
Copy link

I'd like this to, so that I can specify the args as an input:

"args": "${input:arguments}"

I just tried this in version 1.85.1 and it's working now! Make sure you provide a single string with all your args and don't use an array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests