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

Consider supporting dispatching editor commands from the integrated terminal via VT #77145

Closed
oising opened this issue Jul 10, 2019 · 18 comments
Closed
Assignees
Labels
info-needed Issue requires more information from poster terminal General terminal issues that don't fall under another label

Comments

@oising
Copy link

oising commented Jul 10, 2019

It would be nice to be able to write (or use) commands from the integrated terminal to manage the current workspace (or do other things), e.g. open <file> or find foo from bash, powershell, cmd etc. Since I've been doing a bit of work on virtual terminals recently, it strikes me that using APC (Application Program Command) would be a good way to enable shell-agnostic support for automation of the editor. Typically APC sequences are ignored by the terminal parser, and picked up by other applications on the end of a pipe, for example. They are intended for in-band signalling, by design.

XTermJS allows VT sequence extensions for CSI/OSC commands by allowing the hosting application to register handlers. They also support generalized extension for handling unknown ESC sequences, so even if they don't explicitly support APC (though I have asked: xtermjs/xterm.js#2300 ) I think VS code could register a general handler for ESC codes and implement APC itself until if/when the xtermjs guys get around to adding it. The format of APC is ESC_<string>ST, where string is an arbitrary length string, terminated by ST. The convention is usually to reserve the first few letters of the string as your application code, so an open file command might look like ESC_VSC:file:open:<path>ST, possibly base64 encoded to evade encoding issues for quirky filenames.

What I like about this approach is that it is shell agnostic. If a subset of VS Code commands can be supported with APC, then anyone can write a bash/cmd/powershell/pwsh script or binary command to do automation, on any platform.

Thoughts?

@vscodebot vscodebot bot added the terminal General terminal issues that don't fall under another label label Jul 10, 2019
@Tyriar
Copy link
Member

Tyriar commented Jul 10, 2019

@oising isn't this essentially what the CLI is for, code <file>, but that works across shells and across terminals? Do you want to be able to do something like this: code --command "editor.action.format"?

@Tyriar Tyriar added the info-needed Issue requires more information from poster label Jul 10, 2019
@oising
Copy link
Author

oising commented Jul 11, 2019

Yes, exactly -- be able to pass commands to the running/hosting instance, but also with parameters: imagine if you're in the terminal and you're checking in some code and you wanted to issue a search command, or do some kind of programmatic manipulation of files in the workspace.

If you run code foo, how does it know which instance to load files into if you have multiple code windows open? The focused one?

@TylerLeonhardt
Copy link
Member

This is something we always wanted to add to the PowerShell extension, but never had the chance to.

PowerShell/vscode-powershell#804

@Tyriar
Copy link
Member

Tyriar commented Jul 11, 2019

@oising yes it's the focused one, that's why code -r <folder> will open the folder in the window of the terminal running.

@oising
Copy link
Author

oising commented Jul 11, 2019

If you have two instances of code, and you invoke code foo.html from a cmd or pwsh, then neither instance is focused. How does it choose then?

I guess the point of this post is more of a "how" you could do this rather than a "what." The only downside is that it would only work from within the integrated terminal. If you've already got an RPC-like protocol with the code "cli" then I suppose there's no need. If you don't have a protocol, then maybe this could work.

@Tyriar
Copy link
Member

Tyriar commented Jul 11, 2019

The CLI works on the last active window, it sounds like the APC thing is non-standard in which case we probably want to stay away. The CLI could theoretically get powerful enough to drive arbitrary windows, that would probably be preferable to non-standard sequences/commands.

@oising
Copy link
Author

oising commented Jul 12, 2019

APC is a standard with respect to VT. VT is specific to teletypes/terminals - it's not a standard for editors, of course. APC allows arbitrary strings to be passed between applications that use a terminal as in-band signalling. Nothing more, nothing less. By default it's an open protocol vector. If there was a "standard" for controlling VS Code, you'd have written it yourself. Using your CLI.

@jerch
Copy link

jerch commented Jul 12, 2019

@oising The parser in xterm.js tries to follow as close as possible the DEC parser described at vt100.net (https://www.vt100.net/emu/dec_ansi_parser). If you compare the byte handling for OSC, DCS and APC you will find many similarities (beside APC completely being ignored atm):

  • C0 (minus ESC itself) is only allowed for DCS as payload (we have one exception to this rule in OSC allowing BEL to terminate, as xterm does)
  • C1 is allowed (most bytes have no meaning, those that have are the introducers to other VT states)

This pretty much narrows the allowed payload bytes to ASCII printables for any of these commands. Since our parser operates on unicode codepoints we additionally allow any codepoint > C1 to pass.

So beside some differences in additional arguments at introducer level (DCS is more capable here) these are the same at payload level. None of them allows to embed other terminal stream chunks directly (not even DCS, it keeps ESC meaningful), thus we would have to encode them anyway.

My stance against APC is simple - we already have 2 quite similar command types with OSC and DCS with enough free "command space". No need to get the hands dirty with a command type that was brought up over 30ys ago but never really spec'ed out. Furthermore OSC support is relatively wide spread in emulators and less likely to break with half of the terminal ecosystem (which is important even for a vscode private embedding solution when tmux or ssh shall play nice too). DCS is not that well supported though.

Last but not least the originally intended separation of commands into OS, application and device business never really took place (idk, maybe DEC died to early), applications always mixed them as needed. This is not much of a surprise - shells, originally thought as OS component, took the opposite direction under UNIX and developed into being more exchangeable and more "application like". Technically this separation does not make much sense either, for a terminal everything comes from one data source (pty master or serial line) and the terminal protocol never advanced to a state to layer/cascade commands without re-encoding/escaping.

TL;DR: Sorry for the longish post. Imho the embedding idea sounds good, but no need to mess around with APC since we could use some custom OSC command.

@oising
Copy link
Author

oising commented Jul 12, 2019

Thanks @jerch for the thoughtful reply. I guess I'm just pushing to see if I can learn more about what others people's thoughts are on the matter. I appreciate your input. The pragmatist in me knows that OSC is a better option given that most - if not all - terminal emulators will just swallow unrecognized codes. With respect to APC, you're totally right -- it doesn't even seem to have been fleshed out, with the result that most emulators (including xtermjs) seem to swallow the APC preamble but write the string to the terminal when in fact they should ignore it as far as my understanding of what documentation is out there; ergo, OSC is far less likely to make a mess of things. Again, thanks to you and @Tyriar for your thoughts.

@Tyriar
Copy link
Member

Tyriar commented Jul 12, 2019

I'm going to close this off as I don't think it's the direction we want to go, we may expand the CLI's power in the future but it can already do a lot of what you seem to be asking:

# pipe a file
echo some_file | code --

# open file
code some_file

# automation
code --install-extension ext.id

For the remote case, when using the remote extensions the CLI is available inside the terminal as well, there may be some holes in functionality but we want to get parity where possible.

@Tyriar Tyriar closed this as completed Jul 12, 2019
@TylerLeonhardt
Copy link
Member

While we’re all here I do wanna say that it would be relatively straightforward to add this to the PowerShell extension.

We already have mechanisms to show messages:
image

get editor state:
image

etc

A generic addition would just need to be added to support:

$psEditor.invokeCommand("editor.action.format")

Happy to walk through the change needed - though I don’t have bandwidth to do it myself.

@Tyriar
Copy link
Member

Tyriar commented Jul 12, 2019

@TylerLeonhardt if you can pull that info with $PSEditor, can't you run a command as well inside the ext?

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jul 12, 2019

Yeah it’s totally doable but the $psEditor object that we expose doesn’t have an API for firing off any arbitrary vscode command.

The way $psEditor works is that it sends custom LSP messages from the language server (PowerShell Editor Services) to the client (aka the PowerShell extension).

We’d just need to add another API & message to $psEditor that has an example payload of:

{
    "command":"editor.action.format"
}

and then the PowerShell extension would just run:

languageClient.onRequest(
    "powershell/executeEditorCommand"
    async (args) => await commands.executeCommand(args.command));

We could make it more interesting if we wanted to handle results of these commands but a simple “run this command” seems like a good start

@Tyriar
Copy link
Member

Tyriar commented Jul 12, 2019

Oh an API in LSP? Since LSP's focus isn't really automation I'm not sure that would happen?

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Jul 12, 2019

LSP gives you the ability to create custom messages that go over the same protocol. We leverage this already in the PowerShell extension and the language server sends the message here. It’s just a matter of adding another custom message to the PowerShell extension. It’s a very trivial thing to do (for a language server extension).

didn’t mean to hijack this issue. Just wanted to point out that it’s probably easier to implement this in the PowerShell extension than the code executable, though adding it to the code executable would allow more users to get their hands on such a feature.

@oising
Copy link
Author

oising commented Jul 12, 2019

@TylerLeonhardt I didn't realize we had a VS DTE style API floating around -- but I just tried $pseditor and it's null for me. Anyway, I like the idea. I think accepting parametric commands would be important too. On occasion enough to be mildly piquing, I wish I could script and automate some large scale refactoring with regex find/replace for example, or generate a commit message by parsing source, or whatever from scripting in the terminal. I'm a total automation junkie obviously, but having a way to dispatch editor commands this way would be very nice. This opens the gates to have people wrap up things up as scripted macros in the future.

Ultimately I suggested VT to keep things shell-agnostic, but it's a bit unwieldy using OSC/APC or whatever, but it was just about establishing a channel.

@TylerLeonhardt
Copy link
Member

It must be run in the PowerShell Integrated Console provided by the PowerShell extension. There’s no way for us to hook into vscode from anything other than the integrated console that we provide.

@oising
Copy link
Author

oising commented Jul 12, 2019

Ah, okay -- I never use the powershell integrated terminal since the generalized terminal was added. Perhaps another reason why VT with an OSC handler is more flexible -- any shell in the terminal could issue commands. That said, I'll take something over nothing :)

@vscodebot vscodebot bot locked and limited conversation to collaborators Aug 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
info-needed Issue requires more information from poster terminal General terminal issues that don't fall under another label
Projects
None yet
Development

No branches or pull requests

4 participants