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

tmux-cc: force DcsPassThrough in tmux-cc mode #977

Closed
wants to merge 1 commit into from

Conversation

skyline75489
Copy link
Contributor

The thing about tmux-cc is that the pane-output actually contains escape sequences.

The output has any characters less than ASCII 32 and the \ character replaced with their octal equivalent, so \ becomes \134. Otherwise, it is exactly what the application running in the pane sent to tmux. It may not be valid UTF-8 and may contain escape sequences which will be as expected by tmux

See: https://github.com/tmux/tmux/wiki/Control-Mode#pane-output

When the app is in tmux-cc mode, all characters received must be passed through the the DCS handler. The tmux-cc mode can only be terminated by "a %exit line and a corresponding ST (\033) sequence"

@skyline75489
Copy link
Contributor Author

The issue in the current implementation is that if %output contains a \x9c, the state machine (in localpane) will return to ground state, because it is the correct thing to do with normal terminal output. However with tmux-cc mode, that's not the case.

My implementation here is obviously a naive one. I hope my description of the issue is clear.

@@ -173,6 +180,9 @@ impl<'a, F: FnMut(Action)> VTActor for Performer<'a, F> {
data: vec![],
});
} else {
if byte == b'p' && params == vec![1000] {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid making a vec for this; the vec is undesirable because it represents an unconditional heap allocation just for a comparison.

Suggested change
if byte == b'p' && params == vec![1000] {
if byte == b'p' && params == [1000] {

@@ -173,6 +180,9 @@ impl<'a, F: FnMut(Action)> VTActor for Performer<'a, F> {
data: vec![],
});
} else {
if byte == b'p' && params == vec![1000] {
self.state.tmux_cc = true;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see anything that will exit this state, so as-written, this feels like it will "break" the pane when the mode is exited :-/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in iTerm2 you need to manually break the state. In Wezterm I guess "press q"? I'll see where to add this.


/// Force DCS pass through for tmux cc
pub fn force_dcs_passthrough(&mut self, bytes: &[u8], actor: &mut dyn VTActor) {
for b in bytes {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to batch pass through the entire buffer? That would help the performance a lot.


/// Force DCS pass through for tmux cc
pub fn force_dcs_passthrough(&mut self, bytes: &[u8], actor: &mut dyn VTActor) {
for b in bytes {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this bit is in vtparse. Layering wise this makes things very difficult. I'd suggest doing this rerouting in the termwiz crate where we have the higher level state instead of here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I'll try to think of something else. By the way I have an experimental branch tmux-cc at https://github.com/skyline75489/wezterm/tree/dev/tmux-cc-prototype, which handles the output part, very roughly but works. Take a look if you want :)

(bear with all my amateur Rust code)

self.state_machine.parse(bytes, &mut perform);

if perform.state.tmux_cc {
self.state_machine.force_dcs_passthrough(bytes, &mut perform);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked to make sure this suggestion is good, but I think that we could add DeviceControlMode::Bytes(Vec<u8>) and pass that bytes through at the termwiz layer rather than having this special state cut across to the vtparse layer.

For that to work, I think we need a bit more state for tmux in here, so that we can match for a sequence like \n%exit to break out of tmux-cc mode.

When in tmux-cc mode, we can simply bypass the vtparse parser and redirect straight through to DeviceControlMode::Bytes which would get handled in the same way as DeviceControlMode::Data, but with the advantage that it's a bit more efficient to pass the vec through there, rather than the individual Data items.

@skyline75489
Copy link
Contributor Author

Closed in favor of #1090

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

Successfully merging this pull request may close these issues.

None yet

2 participants