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 adding custom APC handlers, similar to CSI/OSC handlers. #2300

Closed
oising opened this issue Jul 10, 2019 · 13 comments
Closed
Labels
area/api area/parser help wanted type/enhancement Features or improvements to existing features

Comments

@oising
Copy link

oising commented Jul 10, 2019

It's not clear to me if an APC (application program command -- ESC_<string>ST) could be handled by an application hosting xtermjs by using the EscHandler plumbing, but it would useful to allow it for commands run in the terminal to pass commands to the terminal hosting application. An example might be for an open <file> command in the VS code terminal that emits a sequence to instruct VS Code to load <file> into the editor, etc. Such a command could be written in batch, bash, powershell or anything that can write VT. This would allow very easy dispatch of editor commands from the terminal, should VS code opt to wire up an APC handler.

@oising oising changed the title Consider supporting adding custom APC handlers, like CSI/OSC. Consider supporting adding custom APC handlers, similar to CSI/OSC handlers. Jul 10, 2019
@Tyriar
Copy link
Member

Tyriar commented Jul 11, 2019

We wanted to add an addEscHandler API anyway 👍

@Tyriar Tyriar added area/api area/parser type/enhancement Features or improvements to existing features help wanted labels Jul 11, 2019
@jerch
Copy link
Member

jerch commented Jul 11, 2019

@oising Is there a specific reason why you would like to see this under APC? Currently APC and PM realms are not specified by any official document, there is no prior art to learn from beside the global ignore rule (which almost every VT parser applies) and some private usage in one or two emulators. Thus we'd have to spec this carefully first, not sure if the spec hassles are worth it since DCS and OSC commands can carry almost the same payload (and binary data would have to be escaped/transport encoded anyway to avoid escape sequence clashes).

In this regard I really like the way iTerm2 handles this - it has its own private OSC command (OSC 1337 ... ST), which supports tons of private submodes. I'd favor this or a DCS equivalent more than getting into APC business.

@Tyriar
Copy link
Member

Tyriar commented Jul 11, 2019

We can leave the APC discussion to microsoft/vscode#77145, I'm not sure that's the direction we want to go. But I think we should expose the handler API as suggested regardless.

@oising
Copy link
Author

oising commented Jul 11, 2019

@jerch I guess I'd prefer APC because well, OSC is for operating system commands, and APC is for applications. It seems that in this case anyway, the distinction is clear. In the case for both methods, namespacing is equally out in the open (e.g. iTerm2 chose 1337 for OSC - leet reference aside - fairly arbitrarily) -- but I will submit that an unrecognized OSC sequence is less likely to interfere with rendering than an APC sequence. The latter's payload should be ignored and not rendered but frequently is rendered in common terminals as far as I can tell (because they intrinsically don't understand/support APC). So perhaps you're right.

@Tyriar Tyriar added type/enhancement Features or improvements to existing features and removed type/enhancement Features or improvements to existing features labels Jul 11, 2019
@jerch
Copy link
Member

jerch commented Jul 13, 2019

I think we can close this issue? @oising Feel free to open a new issue if you have unanswered questions or ideas regarding the issue. Imho the big "picture discussion" is better done at the vscode thread.

Regarding extending the parser with more add... methods - I already have this on the schedule.

@KernelDeimos
Copy link

I'd appreciate if anyone could tell me, what would be the most correct way for somebody to implement a terminal addon that interprets APC codes? For example if I want to add support for kitty's terminal graphics protocol. Do I simply override terminal.write?

@jerch
Copy link
Member

jerch commented Jul 21, 2024

@KernelDeimos Well thats almost impossible with xterm.js as it is atm, for APC you'd need to extend the parser itself (the FSM), write handler hooks and expose that on the public API.
For the kitty graphic protocol all renderers would have to expose different output layers internally to get the z-index idea working. Different output layers with correct transparent color handling cannot be achieved with the DOM renderer in a reasonable and performant way, so thats a no-go.
Both cannot be done from within an addon alone.

Also the kitty graphics is the only sequence using APC in newer terminals, which is seen as a big design fault by many terminal devs. Again a big no-go.

All in all - not worth wasting your time.

@KernelDeimos
Copy link

Ah okay, I was starting to get that feeling when I started doing my research, that kitty's decision to use APC might not have been the best choice. My motivation for doing this was to implement an existing sequence that's not yet supported by xtermjs as a stepping-stone to adding my own feature but I think I'm just going to move onto that. I noticed it's really hard to find a CSI prefix/final combo that isn't already in use so what I'm thinking is something like this:

<ESC>[=<vendor_id>;...|

In this way I've chosen to reserve = + | but with <vendor_id> I give other developers the option to use this too without conflicting with me. What do you think, is this the right approach? (we can move this to a discussion thread if that's more appropriate)

@jerch
Copy link
Member

jerch commented Jul 21, 2024

So you want to write your own custom sequence? For that I'd suggest to read https://xtermjs.org/docs/guides/hooks/ as an introduction. Whether to use an CSI, OSC or DCS sequence (these sequence types are fully supported for customization), depends alot on your type of playload. CSI works only for a limited amount of integers, OCS and DCS can transport printables (thus binary as BASE64).

(we can move this to a discussion thread if that's more appropriate)

Yes its better to discuss those things in a discussion, not below some random other issue thread.

@KernelDeimos
Copy link

KernelDeimos commented Jul 21, 2024

Thanks! The crux of it is I want to get a string of arbitrary length (the string is known not to contain <ESC>), and then render an element in xterm based on that string. It looks like OSC might be a good choice for this - in that case I'd choose an arbitrary high number for the identifier, right?

@jerch
Copy link
Member

jerch commented Jul 21, 2024

Yes OSC is prolly the easiest way. It only expects a single function identifier number in decimal digits, >1000 is typically safe to choose from. If you want to stay compatible to other terminals, you also should consult their docs and see if they have own custom functions you might collide with. Sadly there are no uniform docs about taken function identifiers, so you are a bit on your own here.

@jerch
Copy link
Member

jerch commented Jul 22, 2024

Addendum:
Beside ESC there are several more control chars, that should not occur in OSC:

// osc
table.add(0x5d, ParserState.ESCAPE, ParserAction.OSC_START, ParserState.OSC_STRING);
table.addMany(PRINTABLES, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);
table.add(0x7f, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);
table.addMany([0x9c, 0x1b, 0x18, 0x1a, 0x07], ParserState.OSC_STRING, ParserAction.OSC_END, ParserState.GROUND);
table.addMany(r(0x1c, 0x20), ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING);

[0x9c, 0x1b, 0x18, 0x1a, 0x07] will also finish an OSC sequence, + ST, CSI, DCS, OSC and [0x98, 0x9e, 0x9f] (not shown above).
[0x1c, 0x1d, 0x1e, 0x1f] will be ignored.

Furthermore our parser has a special feature to treat any codepoint >= 0xa0 as printable, so will let pass higher unicode always as printables. But for compat with other TEs you cannot rely on that, if you have unicode to pass along - use a transport encoding like base64 on the data.

@KernelDeimos
Copy link

Hi, thanks a ton for clarifying that! This inspired the encoding parameter that I added in my project, which I just open-sourced and opened a discussion about

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/api area/parser help wanted type/enhancement Features or improvements to existing features
Projects
None yet
Development

No branches or pull requests

4 participants