Skip to content

Commit 7d02be5

Browse files
committed
Handle CPR sequence
1 parent cc914e4 commit 7d02be5

File tree

10 files changed

+110
-45
lines changed

10 files changed

+110
-45
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ which = "6.0.1"
5555
xdg = "2.5.2"
5656
termwiz = "0.23.3"
5757
bitflags = { version = "2.3.3", features = ["serde"] }
58-
compact_str = { version = "0.7.1", features = ["serde"] }
58+
compact_str = { version = "0.9.0", features = ["serde"] }
5959
bincode = "1.3.3"
6060
tokio-util = { version = "0.7.8", features = ["full"] }
6161
bytes = "1.5.0"

src/proc/handle.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{
22
msg::{ProcCmd, ProcEvent},
3-
CopyMode, Proc,
3+
CopyMode, Proc, ReplySender,
44
};
55

66
use std::time::Instant;
@@ -42,7 +42,7 @@ impl ProcHandle {
4242
}
4343

4444
pub fn rename(&mut self, name: &str) {
45-
self.name.replace_range(.., &name);
45+
self.name.replace_range(.., name);
4646
}
4747

4848
pub fn id(&self) -> usize {
@@ -60,7 +60,7 @@ impl ProcHandle {
6060
.vt
6161
.read()
6262
.map_or(ProcViewFrame::Empty, |vt| ProcViewFrame::Vt(vt)),
63-
super::ProcState::Error(err) => ProcViewFrame::Err(&err),
63+
super::ProcState::Error(err) => ProcViewFrame::Err(err),
6464
}
6565
}
6666

@@ -131,12 +131,15 @@ impl ProcHandle {
131131
self.last_start = Some(Instant::now());
132132
self.is_up = true;
133133
}
134+
ProcEvent::TermReply(s) => {
135+
self.send(ProcCmd::SendRaw(s));
136+
}
134137
}
135138
}
136139
}
137140

138141
pub enum ProcViewFrame<'a> {
139142
Empty,
140-
Vt(std::sync::RwLockReadGuard<'a, vt100::Parser>),
143+
Vt(std::sync::RwLockReadGuard<'a, vt100::Parser<ReplySender>>),
141144
Err(&'a str),
142145
}

src/proc/mod.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ use std::time::Duration;
99

1010
use anyhow::bail;
1111
use assert_matches::assert_matches;
12+
use compact_str::CompactString;
1213
use crossterm::event::{MouseButton, MouseEventKind};
1314
use portable_pty::MasterPty;
1415
use portable_pty::{native_pty_system, ChildKiller, CommandBuilder, PtySize};
1516
use serde::{Deserialize, Serialize};
1617
use tokio::sync::mpsc::UnboundedSender;
1718
use tokio::task::spawn_blocking;
1819
use tui::layout::Rect;
19-
use vt100::MouseProtocolMode;
20+
use vt100::{MouseProtocolMode, TermReplySender};
2021

2122
use crate::config::ProcConfig;
2223
use crate::encode_term::{encode_key, encode_mouse_event, KeyCodeEncodeModes};
@@ -48,7 +49,7 @@ impl Debug for Inst {
4849
}
4950
}
5051

51-
pub type VtWrap = Arc<RwLock<vt100::Parser>>;
52+
pub type VtWrap = Arc<RwLock<vt100::Parser<ReplySender>>>;
5253

5354
impl Inst {
5455
fn spawn(
@@ -58,7 +59,15 @@ impl Inst {
5859
size: &Size,
5960
scrollback_len: usize,
6061
) -> anyhow::Result<Self> {
61-
let vt = vt100::Parser::new(size.height, size.width, scrollback_len);
62+
let vt = vt100::Parser::new(
63+
size.height,
64+
size.width,
65+
scrollback_len,
66+
ReplySender {
67+
proc_id: id,
68+
sender: tx.clone(),
69+
},
70+
);
6271
let vt = Arc::new(RwLock::new(vt));
6372

6473
let pty_system = native_pty_system();
@@ -309,7 +318,7 @@ impl Proc {
309318

310319
pub fn lock_vt(
311320
&self,
312-
) -> Option<std::sync::RwLockReadGuard<'_, vt100::Parser>> {
321+
) -> Option<std::sync::RwLockReadGuard<'_, vt100::Parser<ReplySender>>> {
313322
match &self.inst {
314323
ProcState::None => None,
315324
ProcState::Some(inst) => inst.vt.read().ok(),
@@ -319,7 +328,7 @@ impl Proc {
319328

320329
pub fn lock_vt_mut(
321330
&mut self,
322-
) -> Option<std::sync::RwLockWriteGuard<'_, vt100::Parser>> {
331+
) -> Option<std::sync::RwLockWriteGuard<'_, vt100::Parser<ReplySender>>> {
323332
match &self.inst {
324333
ProcState::None => None,
325334
ProcState::Some(inst) => inst.vt.write().ok(),
@@ -430,12 +439,12 @@ impl Proc {
430439
}
431440
}
432441

433-
fn scroll_vt_up(vt: &mut vt100::Parser, n: usize) {
442+
fn scroll_vt_up(vt: &mut vt100::Parser<ReplySender>, n: usize) {
434443
let pos = usize::saturating_add(vt.screen().scrollback(), n);
435444
vt.set_scrollback(pos);
436445
}
437446

438-
fn scroll_screen_up(screen: &mut vt100::Screen, n: usize) {
447+
fn scroll_screen_up(screen: &mut vt100::Screen<ReplySender>, n: usize) {
439448
let pos = usize::saturating_add(screen.scrollback(), n);
440449
screen.set_scrollback(pos);
441450
}
@@ -453,12 +462,12 @@ impl Proc {
453462
}
454463
}
455464

456-
fn scroll_vt_down(vt: &mut vt100::Parser, n: usize) {
465+
fn scroll_vt_down(vt: &mut vt100::Parser<ReplySender>, n: usize) {
457466
let pos = usize::saturating_sub(vt.screen().scrollback(), n);
458467
vt.set_scrollback(pos);
459468
}
460469

461-
fn scroll_screen_down(screen: &mut vt100::Screen, n: usize) {
470+
fn scroll_screen_down(screen: &mut vt100::Screen<ReplySender>, n: usize) {
462471
let pos = usize::saturating_sub(screen.scrollback(), n);
463472
screen.set_scrollback(pos);
464473
}
@@ -602,6 +611,13 @@ impl Proc {
602611

603612
ProcCmd::SendKey(key) => self.send_key(&key),
604613
ProcCmd::SendMouse(event) => self.handle_mouse(event),
614+
ProcCmd::SendRaw(s) => match &mut self.inst {
615+
ProcState::None => (),
616+
ProcState::Some(inst) => {
617+
let _ = inst.master.write_all(s.as_bytes());
618+
}
619+
ProcState::Error(_) => (),
620+
},
605621

606622
ProcCmd::ScrollUp => self.scroll_half_screen_up(),
607623
ProcCmd::ScrollDown => self.scroll_half_screen_down(),
@@ -708,8 +724,8 @@ impl Size {
708724

709725
pub enum CopyMode {
710726
None(Option<Pos>),
711-
Start(vt100::Screen, Pos),
712-
Range(vt100::Screen, Pos, Pos),
727+
Start(vt100::Screen<ReplySender>, Pos),
728+
Range(vt100::Screen<ReplySender>, Pos, Pos),
713729
}
714730

715731
impl Default for CopyMode {
@@ -762,3 +778,15 @@ impl Pos {
762778
}
763779
}
764780
}
781+
782+
#[derive(Clone)]
783+
pub struct ReplySender {
784+
proc_id: usize,
785+
sender: UnboundedSender<(usize, ProcEvent)>,
786+
}
787+
788+
impl TermReplySender for ReplySender {
789+
fn reply(&self, s: CompactString) {
790+
let _ = self.sender.send((self.proc_id, ProcEvent::TermReply(s)));
791+
}
792+
}

src/proc/msg.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use compact_str::CompactString;
2+
13
use crate::{event::CopyMove, key::Key, mouse::MouseEvent};
24

35
#[derive(Debug)]
@@ -8,6 +10,7 @@ pub enum ProcCmd {
810

911
SendKey(Key),
1012
SendMouse(MouseEvent),
13+
SendRaw(CompactString),
1114

1215
ScrollUp,
1316
ScrollDown,
@@ -28,4 +31,5 @@ pub enum ProcEvent {
2831
Render,
2932
Stopped(u32),
3033
Started,
34+
TermReply(CompactString),
3135
}

src/ui_term.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use tui::{
88
};
99

1010
use crate::{
11-
proc::{handle::ProcViewFrame, CopyMode, Pos},
11+
proc::{handle::ProcViewFrame, CopyMode, Pos, ReplySender},
1212
state::{Scope, State},
1313
theme::Theme,
1414
};
@@ -102,12 +102,15 @@ pub fn render_term(
102102
}
103103

104104
pub struct UiTerm<'a> {
105-
screen: &'a vt100::Screen,
105+
screen: &'a vt100::Screen<ReplySender>,
106106
copy_mode: &'a CopyMode,
107107
}
108108

109109
impl<'a> UiTerm<'a> {
110-
pub fn new(screen: &'a vt100::Screen, copy_mode: &'a CopyMode) -> Self {
110+
pub fn new(
111+
screen: &'a vt100::Screen<ReplySender>,
112+
copy_mode: &'a CopyMode,
113+
) -> Self {
111114
UiTerm { screen, copy_mode }
112115
}
113116
}

vendor/vt100/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ mod row;
5454
mod screen;
5555
mod size;
5656
mod term;
57+
mod term_reply;
5758

5859
pub use attrs::Color;
5960
pub use cell::Cell;
6061
pub use parser::Parser;
6162
pub use screen::{MouseProtocolEncoding, MouseProtocolMode, Screen};
6263
pub use size::Size;
64+
pub use term_reply::TermReplySender;

vendor/vt100/src/parser.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
use std::sync::{Arc, Mutex};
22

3+
use crate::TermReplySender;
4+
35
/// A parser for terminal output which produces an in-memory representation of
46
/// the terminal contents.
5-
pub struct Parser {
7+
pub struct Parser<Reply: TermReplySender + Clone> {
68
parser: Arc<Mutex<termwiz::escape::parser::Parser>>,
7-
screen: crate::screen::Screen,
9+
screen: crate::screen::Screen<Reply>,
810
}
911

10-
impl Parser {
12+
impl<Reply: TermReplySender + Clone> Parser<Reply> {
1113
/// Creates a new terminal parser of the given size and with the given
1214
/// amount of scrollback.
1315
#[must_use]
14-
pub fn new(rows: u16, cols: u16, scrollback_len: usize) -> Self {
16+
pub fn new(
17+
rows: u16,
18+
cols: u16,
19+
scrollback_len: usize,
20+
reply_sender: Reply,
21+
) -> Self {
1522
let parser = Arc::new(Mutex::new(termwiz::escape::parser::Parser::new()));
1623
Self {
1724
parser,
1825
screen: crate::screen::Screen::new(
1926
crate::grid::Size { rows, cols },
2027
scrollback_len,
28+
reply_sender,
2129
),
2230
}
2331
}
@@ -53,19 +61,12 @@ impl Parser {
5361
/// Returns a reference to a `Screen` object containing the terminal
5462
/// state.
5563
#[must_use]
56-
pub fn screen(&self) -> &crate::screen::Screen {
64+
pub fn screen(&self) -> &crate::screen::Screen<Reply> {
5765
&self.screen
5866
}
5967
}
6068

61-
impl Default for Parser {
62-
/// Returns a parser with dimensions 80x24 and no scrollback.
63-
fn default() -> Self {
64-
Self::new(24, 80, 0)
65-
}
66-
}
67-
68-
impl std::io::Write for Parser {
69+
impl<Reply: TermReplySender + Clone> std::io::Write for Parser<Reply> {
6970
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
7071
self.process(buf);
7172
Ok(buf.len())

0 commit comments

Comments
 (0)