forked from wezterm/wezterm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathterminal.rs
141 lines (125 loc) · 4.15 KB
/
terminal.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use super::*;
use crate::terminalstate::performer::Performer;
use std::sync::Arc;
use termwiz::escape::parser::Parser;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
pub enum ClipboardSelection {
Clipboard,
PrimarySelection,
}
pub trait Clipboard {
fn set_contents(
&self,
selection: ClipboardSelection,
data: Option<String>,
) -> anyhow::Result<()>;
}
impl Clipboard for Box<dyn Clipboard> {
fn set_contents(
&self,
selection: ClipboardSelection,
data: Option<String>,
) -> anyhow::Result<()> {
self.as_ref().set_contents(selection, data)
}
}
pub trait DeviceControlHandler {
fn handle_device_control(&mut self, _control: termwiz::escape::DeviceControlMode);
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
pub enum Alert {
Bell,
ToastNotification {
/// The title text for the notification.
title: Option<String>,
/// The message body
body: String,
/// Whether clicking on the notification should focus the
/// window/tab/pane that generated it
focus: bool,
},
/// When the title, or something that likely influences the title,
/// has been changed
TitleMaybeChanged,
/// When the color palette has been updated
PaletteChanged,
}
pub trait AlertHandler {
fn alert(&mut self, alert: Alert);
}
/// Represents an instance of a terminal emulator.
pub struct Terminal {
/// The terminal model/state
state: TerminalState,
/// Baseline terminal escape sequence parser
parser: Parser,
}
impl Deref for Terminal {
type Target = TerminalState;
fn deref(&self) -> &TerminalState {
&self.state
}
}
impl DerefMut for Terminal {
fn deref_mut(&mut self) -> &mut TerminalState {
&mut self.state
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct TerminalSize {
pub physical_rows: usize,
pub physical_cols: usize,
pub pixel_width: usize,
pub pixel_height: usize,
}
impl Terminal {
/// Construct a new Terminal.
/// `physical_rows` and `physical_cols` describe the dimensions
/// of the visible portion of the terminal display in terms of
/// the number of text cells.
///
/// `pixel_width` and `pixel_height` describe the dimensions of
/// that same visible area but in pixels.
///
/// `term_program` and `term_version` are required to identify
/// the host terminal program; they are used to respond to the
/// terminal identification sequence `\033[>q`.
///
/// `writer` is anything that implements `std::io::Write`; it
/// is used to send input to the connected program; both keyboard
/// and mouse input is encoded and written to that stream, as
/// are answerback responses to a number of escape sequences.
pub fn new(
size: TerminalSize,
config: Arc<dyn TerminalConfiguration>,
term_program: &str,
term_version: &str,
// writing to the writer sends data to input of the pty
writer: Box<dyn std::io::Write + Send>,
) -> Terminal {
Terminal {
state: TerminalState::new(size, config, term_program, term_version, writer),
parser: Parser::new(),
}
}
/// Feed the terminal parser a slice of bytes from the output
/// of the associated program.
/// The slice is not required to be a complete sequence of escape
/// characters; it is valid to feed in chunks of data as they arrive.
/// The output is parsed and applied to the terminal model.
pub fn advance_bytes<B: AsRef<[u8]>>(&mut self, bytes: B) {
self.state.increment_seqno();
let bytes = bytes.as_ref();
let mut performer = Performer::new(&mut self.state);
self.parser.parse(bytes, |action| performer.perform(action));
}
pub fn perform_actions(&mut self, actions: Vec<termwiz::escape::Action>) {
self.state.increment_seqno();
let mut performer = Performer::new(&mut self.state);
for action in actions {
performer.perform(action);
}
}
}