-
Notifications
You must be signed in to change notification settings - Fork 131
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
add property for controlling escaping arguments for the runInTerminal
request
#146
Comments
Today "preserving of characters in args" is not explicitly mentioned in the spec, but client implementations that rely on command line interpreters ("shells") try to do their best to escape many characters from being interpreted by the shell. So the undocumented semantics of the
However, some clients are not that strict and exclude a few characters from escaping, most notably the input/output redirections In order to cleanup this "fuzzyness" I propose the following:
For debug extension authors this means: If a debug extension contributes an @roblourens @connor4312 what do you think? Do you have better naming suggestions for |
I dislike "negative" boolean flags, perhaps it can be named |
I think the simple solution here is just to document that arguments must never be modified or escaped. if the debug adapter wishes to use a command shell interpreter to do anything at all it must put the command interpreter as the effective argv0 (e.g. We shouldn't add flags to indicate whether or not to 'escape for shell' because we haven't got any specification for what a 'shell' is or which shell should/would be used by the client. For example, if the user's default shell is 'powershell', is the client somehow expected to know how to escape commands for that by magic? Currently, clients are expected, I believe not to use a shell at all and rather run command supplied directly (as if by calling In any case, I'm not sure I followed how a client should interpret the new flag if they currently don't inject arbitrary shell commands into the command line. The suggestion, by having the flag, is that somehow clients are expected to be sticking some shell in front of the command and then escaping the arguments, unless this flag is supplied. That seems backwards to me, and means that all of a sudden clients like mine which don't inject shells into commands become nonconforming, despite doing what would ostensibly be the most portable and understandable thing. [1] - I realise that on windows |
@connor4312 yes, I don't like negative flags (e.g "dontX...") too, but I even more dislike a flag semantics where a missing flag means "true". I prefer the "falsy" semantics: "undefined" or "false". |
Maybe then we can call it @puremourning for context on this, this came up from microsoft/vscode#148887 in which it appears that quite a few users were dependent on VS Code not escaping arguments entirely correctly (7 👍's is a decently high number for debug issues.) Though I think it is reasonable that the default would be to not escape arguments, VS Code has been escaping them to greater or lesser degree for quite a few years, so ultimately at least one implementation will become non-confirming. |
Unless you specify what escaping rules should be applied so that all clients can implement it, then not only will good-citizen clients du jour become nonconforming, but the specification becomes ruled by de facto implementation which makes it impossible for independent client implementers to actually conform. |
@puremourning the issue we are trying to solve is microsoft/vscode#149910 and microsoft/vscode#148887. The I do not see a need why a debug adapter should introduce another command line interpreter. If users want to run the debuggee in the integrated terminal (which they have configured to use PowerShell), why should the DA use "bash" on top of that? However, some users know what they are doing and they want to pass shell syntax to the underlying command line interpreter running in the terminal. They accept the fact that doing so does not work on all platforms. They want to be able to pass arguments in a "raw" but predictable form, e.g. a |
BTW, I still like the approach to use a new
you could say:
(and this would help in cases where VS Code's variable substitution is used to pass a full command line). |
This makes the most sense to me: as a user, either you let the tooling handle all the quoting and escaping, or you're in full control but also responsible for all of it. |
We are talking about the I agree that the client is best suited to escape for a particular shell, being the thing that is starting the shell and sending text into it. The |
Oh and also if I want to pass a real space in an arg with |
Sorry for the stream of consciousness but actually you are saying that I would continue to use |
@roblourens you asked:
yes, that would be my second proposal. |
Does it actually need a separate property though? Perhaps just allow "args" to be a string rather than an array? It feels like it'd make more sense from the naming perspective, at least - "commandLine" sounds like the entirety of the command line, but in practice you'd still have the actual run target specified separately. |
We seem to mix two things here: on one side we have the DAP spec for In case of DAP I suggest not to allow a single string for |
I know it's about run in terminal. But that does NOT imply a shell. A pty is not a shell.
I don't think the client should spawn a command shell at all.
|
|
Nothing here implies a command interpreter is required. It states it's for running the debuggee, not a shell. A terminal is not a shell. To be clear there is no need to run a shell to run a program. Windows explorer is a shell, bash is a shell. these call system calls (execpe / createprocess) that create processes and attach them to pseudo terminals. Given the above definition it's perfectly reasonable and sensible to launch the requested image whiteout using and intermediary (and pointless) command interpreter. |
Yes, a shell is an implementation detail of However, when a user creates a debug config for launching the debuggee in VS Code's integrated terminal, then users are very well aware of the fact what shell is running in the integrated terminal. We are not trying to solve problems for the case where no "pointless command interpreter" is used. |
and if you're in full control of it, you can be the one to instruct a shell to be executed, i.e,:
|
That's basically one of the proposals here. What problems do you see with that approach? |
I think the contention here is that, for clients that implement "runInTerminal" by doing exec() directly, the semantics of "commandLine" is unclear since you're supposed to provide an array, but there are no clear rules according to which the command line is to be split. But then I'd expect such clients to not support "commandLine" at all. It would still be a conditional feature with a client feature flag, right? |
It's an implementation detail of VSCode not a requirement of the protocol.
If the user wan't to use it, they can be the one to instruct it, as above. Look, I get it. I realise the dilemma is that vscode behaved one way, arguably out of the obvious interpretation of the protocol, people started to rely on that, vscode changed to be more like the protocol interpretation and some users got broken. Now we're looking for a way to unbreak them by giving them a dial to turn to "I know what I'm doing". My major concern is that we introduce something into the protocol that requires clients to start working like vscode, by exposing options which debug adapters rely on and are extremely difficult and complex to implement well. (and are naturally only ever tested in vscode, and usually ignoring client capabilities). Today all we have to do is execute the command given directly by creating a process and attaching it to a Pty. But tomorrow we might have to start inventing command lines (like Let's take a practical example - theoretical, but likely. Today:
Dystopian Future:
@int19h re
Adapters can expose 'commandLine' to the user via their launch arguments if they wish. |
I'm just not sure what the difference between |
So what terminals out there do not use command interpreters? |
I feel like that's conflating the idea of a 'terminal' - a pty - and a command interpreter - a shell.
When you double click on a console-mode .exe in windows, it doesn't start cmd.exe and ask it to launch the .exe, it launches the .exe and displays its stdout (and attaches its stdin) to a console (aka terminal). Ditto in non-windows, you can create a pty and execute a command directly in it. That's what happens when you launch a terminal application from a shell, or when you launch a terminal emulator with a specified command (like xterm above) - which is effectively what vim's In case it's not clear, the client (vim in this case, but could be anything) is doing the job of the "shell" - launching the application and attaching its standard streams, then displaying the console and providing interactivity. This is exactly what the terminal window in vscode does, but for some reason vscode executes a command interpreter in its terminal, then asks that to run the provided
I naturally disagree on that point. It's creating a pty and exec'ing the requested command with its stdout and stdin attached to the pty, exactly like a shell would to put it another way, if a client implemented the "external console" by doing effectively doing |
I don't get why you would want to go through all the hassles of using The purpose of |
Whether or not terminal implies shell - I get the distinction and now understand where you are coming from - I think this discussion shows exactly why we didn't want to allow shell characters in the first place. When you create a launch config that includes shell characters, now that launch config is tied to a particular shell. The user is responsible for configuring this that based on their knowledge of the client's shell support and personal configuration. This is awkward but I feel that it's the tradeoff that we have accepted in deciding to support this use case. If they write powershell in So then it follows that if someone implements a DAP client that doesn't spawn any shell for a However if I was just reading the spec from scratch, I would have assumed that the purpose of the @weinand also suggested that this new flag would only be enabled by a new client capability flag
|
I guess this sort of got a little off the original topic, and I suppose that's probably my fault. I suppose we can put aside whether or not it's correct to launch the app as specified, or first launch a shell, and ask the shell to launch the app, and accept that both are reasonable interpretations and behaviours:
Given that, I guess the proposal is workable, if a little difficult to explain. In the interests of contributing something positive to this, I'd suggest some wording something like: Launching the applicationClient implementations are free to launch the application however they choose including issuing the command to a command line interpreter. However the command line in Some users may wish to take advantage of shell processing in the Specifically the meaning if
Thoughts? If we define it that way, I don't see the need for a client capability. The point is that what can a debug adapter do if the client does't have the capability and the user requested it? Just fail? |
@puremourning thanks for putting my proposal into proper words.
If we had a client capability then a debug adapter could post an alert and warn the user that shell syntax doesn't work because no intermediate shell is used. Here is another version of the proposal: Launching the debuggee from the debug adapterDebug adapters are free to launch the debuggee however they choose. Typically the debuggee is launched as a child process and its output channels are connected to a client's debug console via DAP Implementing
|
How about adding:
Regarding:
I guess we have to allow it. If the client launches the app with |
@puremourning thanks for the improved wording. I'll create a new version...
Yes, that was my thinking. Leaving all the escaping to the user is less confusing than having a mix. |
I fear that will even further bind your users to your internal implementation and the internal implementation details of the debug adapters, but as this won't actually affect me, I don't have "skin in the game" as they say :D |
@roblourens @connor4312 @puremourning @int19h here is a new proposal. Let me know if this works for you or whether another round is needed... Launching the debuggee from the debug adapterDebug adapters are free to launch the debuggee however they choose. Typically the debuggee is launched as a child process and its output channels are connected to a client's debug console via DAP Implementing
|
Sorry, I lost track of what we are proposing right now, is all of the above text to go into the RunInTerminalRequest description? It seems like more detail than needed for the request. And are we settling on not including a client capability? It seems like the behavior would be better to have a client capability and let the debug adapter decide what to do, rather than sort of fail silently. |
@roblourens the description from above tries to explain the rational behind this new property. The fact that we have had this rather lengthy discussion is evidence that the existing specification is inadequate. Whether we will fold the full description into the Client capability: |
In #146 (comment), I think the first paragraph could be worked into the overview page for DAP, in "Launching and Attaching", if we need more context on why an adapter would use The second paragraph makes sense in the description for |
@roblourens great, thanks! |
Sent this proposal, take a look: #305 |
Currently it is not possible to control the escaping of the
args
property on therunInTerminal
request.As a consequence the client (frontend) has to guess how to escape the arguments when passing them to a command shell.
This does not always result in the intended behavior.
This feature request asks for a mechanism to control the escaping.
The text was updated successfully, but these errors were encountered: