Compiling with new result based error handling

This commit is contained in:
Mikayla Maki 2022-07-20 16:48:40 -07:00
parent 9b6df1fb61
commit 061dde5a9b
6 changed files with 192 additions and 159 deletions

View file

@ -56,15 +56,16 @@ impl EventListener for ZedListener {
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub struct TerminalError { pub struct TerminalError {
directory: Option<PathBuf>, pub directory: Option<PathBuf>,
shell: Option<Shell>, pub shell: Option<Shell>,
source: std::io::Error, pub source: std::io::Error,
} }
impl Display for TerminalError { impl Display for TerminalError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let dir_string: String = self let dir_string: String = self
.directory .directory
.clone()
.map(|path| { .map(|path| {
match path match path
.into_os_string() .into_os_string()
@ -77,7 +78,7 @@ impl Display for TerminalError {
}) })
.unwrap_or_else(|| { .unwrap_or_else(|| {
let default_dir = let default_dir =
dirs::home_dir().map(|buf| buf.into_os_string().to_string_lossy()); dirs::home_dir().map(|buf| buf.into_os_string().to_string_lossy().to_string());
match default_dir { match default_dir {
Some(dir) => format!("<none specified, using home> {}", dir), Some(dir) => format!("<none specified, using home> {}", dir),
None => "<none specified, could not find home>".to_string(), None => "<none specified, could not find home>".to_string(),
@ -86,6 +87,7 @@ impl Display for TerminalError {
let shell = self let shell = self
.shell .shell
.clone()
.map(|shell| match shell { .map(|shell| match shell {
Shell::System => { Shell::System => {
let mut buf = [0; 1024]; let mut buf = [0; 1024];
@ -160,7 +162,7 @@ impl DisconnectedPTY {
setup_env(&config); setup_env(&config);
//Spawn a task so the Alacritty EventLoop can communicate with us in a view context //Spawn a task so the Alacritty EventLoop can communicate with us in a view context
let (events_tx, mut events_rx) = unbounded(); let (events_tx, events_rx) = unbounded();
//Set up the terminal... //Set up the terminal...
let term = Term::new(&config, &initial_size, ZedListener(events_tx.clone())); let term = Term::new(&config, &initial_size, ZedListener(events_tx.clone()));
@ -218,7 +220,7 @@ impl DisconnectedPTY {
}) })
} }
pub fn connect(self, cx: &mut ModelContext<Terminal>) -> Terminal { pub fn connect(mut self, cx: &mut ModelContext<Terminal>) -> Terminal {
cx.spawn_weak(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
//Listen for terminal events //Listen for terminal events
while let Some(event) = self.events_rx.next().await { while let Some(event) = self.events_rx.next().await {
@ -417,12 +419,6 @@ impl Terminal {
} }
} }
impl Drop for DisconnectedPTY {
fn drop(&mut self) {
self.terminal.pty_tx.0.send(Msg::Shutdown).ok();
}
}
impl Drop for Terminal { impl Drop for Terminal {
fn drop(&mut self) { fn drop(&mut self) {
self.pty_tx.0.send(Msg::Shutdown).ok(); self.pty_tx.0.send(Msg::Shutdown).ok();

View file

@ -16,7 +16,13 @@ pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewCon
if let Some(StoredConnection(stored_connection)) = possible_connection { if let Some(StoredConnection(stored_connection)) = possible_connection {
// Create a view from the stored connection // Create a view from the stored connection
workspace.toggle_modal(cx, |_, cx| { workspace.toggle_modal(cx, |_, cx| {
cx.add_view(|cx| TerminalView::from_connection(stored_connection.clone(), true, cx)) cx.add_view(|cx| {
TerminalView::from_connection(
crate::TerminalConnection(Ok(stored_connection.clone())),
true,
cx,
)
})
}); });
cx.set_global::<Option<StoredConnection>>(Some(StoredConnection( cx.set_global::<Option<StoredConnection>>(Some(StoredConnection(
stored_connection.clone(), stored_connection.clone(),
@ -28,7 +34,7 @@ pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewCon
let this = cx.add_view(|cx| TerminalView::new(wd, true, cx)); let this = cx.add_view(|cx| TerminalView::new(wd, true, cx));
let connection_handle = this.read(cx).connection.clone(); let connection_handle = this.read(cx).connection.0.as_ref().unwrap().clone();
cx.subscribe(&connection_handle, on_event).detach(); cx.subscribe(&connection_handle, on_event).detach();
//Set the global immediately, in case the user opens the command palette //Set the global immediately, in case the user opens the command palette
cx.set_global::<Option<StoredConnection>>(Some(StoredConnection( cx.set_global::<Option<StoredConnection>>(Some(StoredConnection(
@ -36,7 +42,13 @@ pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewCon
))); )));
this this
}) { }) {
let connection = closed_terminal_handle.read(cx).connection.clone(); let connection = closed_terminal_handle
.read(cx)
.connection
.0
.as_ref()
.unwrap()
.clone();
cx.set_global(Some(StoredConnection(connection))); cx.set_global(Some(StoredConnection(connection)));
} }
} }

View file

@ -15,7 +15,7 @@ use project::{LocalWorktree, Project, ProjectPath};
use settings::{Settings, WorkingDirectory}; use settings::{Settings, WorkingDirectory};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use terminal_element::TerminalDimensions; use terminal_element::{terminal_layout_context::TerminalLayoutData, TerminalDimensions};
use workspace::{Item, Workspace}; use workspace::{Item, Workspace};
@ -62,9 +62,12 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(TerminalView::clear); cx.add_action(TerminalView::clear);
} }
//New Type to make terminal connection's easier
struct TerminalConnection(Result<ModelHandle<Terminal>, TerminalError>);
///A terminal view, maintains the PTY's file handles and communicates with the terminal ///A terminal view, maintains the PTY's file handles and communicates with the terminal
pub struct TerminalView { pub struct TerminalView {
connection: Result<ModelHandle<Terminal>, TerminalError>, connection: TerminalConnection,
has_new_content: bool, has_new_content: bool,
//Currently using iTerm bell, show bell emoji in tab until input is received //Currently using iTerm bell, show bell emoji in tab until input is received
has_bell: bool, has_bell: bool,
@ -87,12 +90,9 @@ impl TerminalView {
vec2f(DEBUG_TERMINAL_WIDTH, DEBUG_TERMINAL_HEIGHT), vec2f(DEBUG_TERMINAL_WIDTH, DEBUG_TERMINAL_HEIGHT),
); );
let (shell, envs) = {
let settings = cx.global::<Settings>(); let settings = cx.global::<Settings>();
let shell = settings.terminal_overrides.shell.clone(); let shell = settings.terminal_overrides.shell.clone();
let envs = settings.terminal_overrides.env.clone(); //Should be short and cheap. let envs = settings.terminal_overrides.env.clone(); //Should be short and cheap.
(shell, envs)
};
let connection = DisconnectedPTY::new(working_directory, shell, envs, size_info) let connection = DisconnectedPTY::new(working_directory, shell, envs, size_info)
.map(|pty| cx.add_model(|cx| pty.connect(cx))) .map(|pty| cx.add_model(|cx| pty.connect(cx)))
@ -103,16 +103,18 @@ impl TerminalView {
} }
}); });
TerminalView::from_connection(connection, modal, cx) TerminalView::from_connection(TerminalConnection(connection), modal, cx)
} }
fn from_connection( fn from_connection(
connection: Result<ModelHandle<Terminal>, TerminalError>, connection: TerminalConnection,
modal: bool, modal: bool,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> TerminalView { ) -> TerminalView {
cx.observe(&connection, |_, _, cx| cx.notify()).detach(); match connection.0.as_ref() {
cx.subscribe(&connection, |this, _, event, cx| match event { Ok(conn) => {
cx.observe(conn, |_, _, cx| cx.notify()).detach();
cx.subscribe(conn, |this, _, event, cx| match event {
Event::Wakeup => { Event::Wakeup => {
if cx.is_self_focused() { if cx.is_self_focused() {
cx.notify() cx.notify()
@ -125,13 +127,12 @@ impl TerminalView {
this.has_bell = true; this.has_bell = true;
cx.emit(Event::TitleChanged); cx.emit(Event::TitleChanged);
} }
// Event::Input => {
// this.has_bell = false;
// cx.emit(Event::TitleChanged);
// }
_ => cx.emit(*event), _ => cx.emit(*event),
}) })
.detach(); .detach();
}
Err(_) => { /* Leave it as is */ }
}
TerminalView { TerminalView {
connection, connection,
@ -146,13 +147,6 @@ impl TerminalView {
cx.emit(Event::TitleChanged); cx.emit(Event::TitleChanged);
} }
fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
self.connection
.read(cx)
.get_terminal()
.map(|term| term.clear());
}
///Create a new Terminal in the current working directory or the user's home directory ///Create a new Terminal in the current working directory or the user's home directory
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) { fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
let wd = get_wd_for_workspace(workspace, cx); let wd = get_wd_for_workspace(workspace, cx);
@ -160,63 +154,85 @@ impl TerminalView {
workspace.add_item(Box::new(view), cx); workspace.add_item(Box::new(view), cx);
} }
fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
self.connection
.0
.as_ref()
.map(|term_handle| term_handle.read(cx).clear())
.ok();
}
///Attempt to paste the clipboard into the terminal ///Attempt to paste the clipboard into the terminal
fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) { fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.and_then(|term| term.copy()) .map(|handle| handle.read(cx))
.map(|text| cx.write_to_clipboard(ClipboardItem::new(text))); .map(|term| term.copy())
.map(|text| text.map(|text| cx.write_to_clipboard(ClipboardItem::new(text))))
.ok();
} }
///Attempt to paste the clipboard into the terminal ///Attempt to paste the clipboard into the terminal
fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) { fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
cx.read_from_clipboard().map(|item| { cx.read_from_clipboard().map(|item| {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.map(|term| term.paste(item.text())); .map(|handle| handle.read(cx))
.map(|term| term.paste(item.text()))
.ok();
}); });
} }
///Synthesize the keyboard event corresponding to 'up' ///Synthesize the keyboard event corresponding to 'up'
fn up(&mut self, _: &Up, cx: &mut ViewContext<Self>) { fn up(&mut self, _: &Up, cx: &mut ViewContext<Self>) {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.map(|term| term.try_keystroke(&Keystroke::parse("up").unwrap())); .map(|handle| handle.read(cx))
.map(|term| term.try_keystroke(&Keystroke::parse("up").unwrap()))
.ok();
} }
///Synthesize the keyboard event corresponding to 'down' ///Synthesize the keyboard event corresponding to 'down'
fn down(&mut self, _: &Down, cx: &mut ViewContext<Self>) { fn down(&mut self, _: &Down, cx: &mut ViewContext<Self>) {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.map(|term| term.try_keystroke(&Keystroke::parse("down").unwrap())); .map(|handle| handle.read(cx))
.map(|term| term.try_keystroke(&Keystroke::parse("down").unwrap()))
.ok();
} }
///Synthesize the keyboard event corresponding to 'ctrl-c' ///Synthesize the keyboard event corresponding to 'ctrl-c'
fn ctrl_c(&mut self, _: &CtrlC, cx: &mut ViewContext<Self>) { fn ctrl_c(&mut self, _: &CtrlC, cx: &mut ViewContext<Self>) {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.map(|term| term.try_keystroke(&Keystroke::parse("ctrl-c").unwrap())); .map(|handle| handle.read(cx))
.map(|term| term.try_keystroke(&Keystroke::parse("ctrl-c").unwrap()))
.ok();
} }
///Synthesize the keyboard event corresponding to 'escape' ///Synthesize the keyboard event corresponding to 'escape'
fn escape(&mut self, _: &Escape, cx: &mut ViewContext<Self>) { fn escape(&mut self, _: &Escape, cx: &mut ViewContext<Self>) {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.map(|term| term.try_keystroke(&Keystroke::parse("escape").unwrap())); .map(|handle| handle.read(cx))
.map(|term| term.try_keystroke(&Keystroke::parse("escape").unwrap()))
.ok();
} }
///Synthesize the keyboard event corresponding to 'enter' ///Synthesize the keyboard event corresponding to 'enter'
fn enter(&mut self, _: &Enter, cx: &mut ViewContext<Self>) { fn enter(&mut self, _: &Enter, cx: &mut ViewContext<Self>) {
self.connection self.connection
.read(cx) .0
.get_terminal() .as_ref()
.map(|term| term.try_keystroke(&Keystroke::parse("enter").unwrap())); .map(|handle| handle.read(cx))
.map(|term| term.try_keystroke(&Keystroke::parse("enter").unwrap()))
.ok();
} }
} }
@ -226,9 +242,34 @@ impl View for TerminalView {
} }
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox { fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
let element = { let element = match self.connection.0.as_ref() {
let connection_handle = self.connection.clone().downgrade(); Ok(handle) => {
let connection_handle = handle.clone().downgrade();
TerminalEl::new(cx.handle(), connection_handle, self.modal).contained() TerminalEl::new(cx.handle(), connection_handle, self.modal).contained()
}
Err(e) => {
let settings = cx.global::<Settings>();
let style = TerminalLayoutData::make_text_style(cx.font_cache(), settings);
Flex::column()
.with_child(
Flex::row()
.with_child(
Label::new(
format!(
"Failed to open the terminal. Info: \n{}",
e.to_string()
),
style,
)
.boxed(),
)
.aligned()
.boxed(),
)
.aligned()
.contained()
}
}; };
if self.modal { if self.modal {
@ -261,9 +302,9 @@ impl Item for TerminalView {
tab_theme: &theme::Tab, tab_theme: &theme::Tab,
cx: &gpui::AppContext, cx: &gpui::AppContext,
) -> ElementBox { ) -> ElementBox {
let title = match self.connection.read(cx) { let title = match self.connection.0.as_ref() {
TerminalConnection::Connected(conn) => conn.title.clone(), Ok(handle) => handle.read(cx).title.clone(),
TerminalConnection::Disconnected { .. } => "Terminal".to_string(), //TODO ask nate about htis Err(_) => "Terminal".to_string(),
}; };
Flex::row() Flex::row()
@ -281,12 +322,10 @@ impl Item for TerminalView {
//Directory of the terminal from outside the shell. There might be //Directory of the terminal from outside the shell. There might be
//solutions to this, but they are non-trivial and require more IPC //solutions to this, but they are non-trivial and require more IPC
let wd = self let wd = match self.connection.0.as_ref() {
.connection Ok(term_handle) => term_handle.read(cx).associated_directory.clone(),
.read(cx) Err(e) => e.directory.clone(),
.get_terminal() };
.and_then(|term| term.associated_directory.clone())
.clone();
Some(TerminalView::new(wd, false, cx)) Some(TerminalView::new(wd, false, cx))
} }

View file

@ -32,7 +32,7 @@ use util::ResultExt;
use std::{cmp::min, ops::Range}; use std::{cmp::min, ops::Range};
use std::{fmt::Debug, ops::Sub}; use std::{fmt::Debug, ops::Sub};
use crate::{color_translation::convert_color, connection::TerminalConnection, TerminalView}; use crate::{color_translation::convert_color, connection::Terminal, TerminalView};
use self::terminal_layout_context::TerminalLayoutData; use self::terminal_layout_context::TerminalLayoutData;
@ -44,7 +44,7 @@ const ALACRITTY_SCROLL_MULTIPLIER: f32 = 3.;
///The GPUI element that paints the terminal. ///The GPUI element that paints the terminal.
///We need to keep a reference to the view for mouse events, do we need it for any other terminal stuff, or can we move that to connection? ///We need to keep a reference to the view for mouse events, do we need it for any other terminal stuff, or can we move that to connection?
pub struct TerminalEl { pub struct TerminalEl {
connection: WeakModelHandle<TerminalConnection>, connection: WeakModelHandle<Terminal>,
view: WeakViewHandle<TerminalView>, view: WeakViewHandle<TerminalView>,
modal: bool, modal: bool,
} }
@ -228,7 +228,7 @@ pub struct LayoutState {
impl TerminalEl { impl TerminalEl {
pub fn new( pub fn new(
view: WeakViewHandle<TerminalView>, view: WeakViewHandle<TerminalView>,
connection: WeakModelHandle<TerminalConnection>, connection: WeakModelHandle<Terminal>,
modal: bool, modal: bool,
) -> TerminalEl { ) -> TerminalEl {
TerminalEl { TerminalEl {
@ -255,8 +255,7 @@ impl TerminalEl {
MouseButton::Left, MouseButton::Left,
move |MouseButtonEvent { position, .. }, cx| { move |MouseButtonEvent { position, .. }, cx| {
if let Some(conn_handle) = mouse_down_connection.upgrade(cx.app) { if let Some(conn_handle) = mouse_down_connection.upgrade(cx.app) {
conn_handle.update(cx.app, |connection, cx| { conn_handle.update(cx.app, |terminal, cx| {
connection.get_terminal().map(|terminal| {
let (point, side) = mouse_to_cell_data( let (point, side) = mouse_to_cell_data(
position, position,
origin, origin,
@ -267,7 +266,6 @@ impl TerminalEl {
terminal.mouse_down(point, side); terminal.mouse_down(point, side);
cx.notify(); cx.notify();
});
}) })
} }
}, },
@ -282,8 +280,7 @@ impl TerminalEl {
cx| { cx| {
cx.focus_parent_view(); cx.focus_parent_view();
if let Some(conn_handle) = click_connection.upgrade(cx.app) { if let Some(conn_handle) = click_connection.upgrade(cx.app) {
conn_handle.update(cx.app, |connection, cx| { conn_handle.update(cx.app, |terminal, cx| {
connection.get_terminal().map(|terminal| {
let (point, side) = mouse_to_cell_data( let (point, side) = mouse_to_cell_data(
position, position,
origin, origin,
@ -294,7 +291,6 @@ impl TerminalEl {
terminal.click(point, side, click_count); terminal.click(point, side, click_count);
cx.notify(); cx.notify();
})
}); });
} }
}, },
@ -303,8 +299,7 @@ impl TerminalEl {
MouseButton::Left, MouseButton::Left,
move |_, MouseMovedEvent { position, .. }, cx| { move |_, MouseMovedEvent { position, .. }, cx| {
if let Some(conn_handle) = drag_connection.upgrade(cx.app) { if let Some(conn_handle) = drag_connection.upgrade(cx.app) {
conn_handle.update(cx.app, |connection, cx| { conn_handle.update(cx.app, |terminal, cx| {
connection.get_terminal().map(|terminal| {
let (point, side) = mouse_to_cell_data( let (point, side) = mouse_to_cell_data(
position, position,
origin, origin,
@ -316,7 +311,6 @@ impl TerminalEl {
cx.notify() cx.notify()
}); });
});
} }
}, },
), ),
@ -336,13 +330,7 @@ impl Element for TerminalEl {
let layout = let layout =
TerminalLayoutData::new(cx.global::<Settings>(), &cx.font_cache(), constraint.max); TerminalLayoutData::new(cx.global::<Settings>(), &cx.font_cache(), constraint.max);
let terminal = self let terminal = self.connection.upgrade(cx).unwrap().read(cx);
.connection
.upgrade(cx)
.unwrap()
.read(cx)
.get_terminal()
.unwrap();
let (cursor, cells, rects, highlights) = let (cursor, cells, rects, highlights) =
terminal.render_lock(Some(layout.size.clone()), |content| { terminal.render_lock(Some(layout.size.clone()), |content| {
@ -488,11 +476,10 @@ impl Element for TerminalEl {
let vertical_scroll = let vertical_scroll =
(delta.y() / layout.size.line_height) * ALACRITTY_SCROLL_MULTIPLIER; (delta.y() / layout.size.line_height) * ALACRITTY_SCROLL_MULTIPLIER;
self.connection self.connection.upgrade(cx.app).map(|terminal| {
.upgrade(cx.app) terminal
.and_then(|handle| handle.read(cx.app).get_terminal()) .read(cx.app)
.map(|terminal| { .scroll(Scroll::Delta(vertical_scroll.round() as i32));
terminal.scroll(Scroll::Delta(vertical_scroll.round() as i32));
}); });
}) })
.is_some(), .is_some(),
@ -508,7 +495,7 @@ impl Element for TerminalEl {
self.connection self.connection
.upgrade(cx.app) .upgrade(cx.app)
.and_then(|model_handle| model_handle.read(cx.app).get_terminal()) .map(|model_handle| model_handle.read(cx.app))
.map(|term| term.try_keystroke(keystroke)) .map(|term| term.try_keystroke(keystroke))
.unwrap_or(false) .unwrap_or(false)
} }

View file

@ -14,6 +14,7 @@ impl<'a> TerminalLayoutData<'a> {
let terminal_theme = &settings.theme.terminal; let terminal_theme = &settings.theme.terminal;
let line_height = font_cache.line_height(text_style.font_size); let line_height = font_cache.line_height(text_style.font_size);
let cell_width = font_cache.em_advance(text_style.font_id, text_style.font_size); let cell_width = font_cache.em_advance(text_style.font_id, text_style.font_size);
let dimensions = TerminalDimensions::new(line_height, cell_width, constraint); let dimensions = TerminalDimensions::new(line_height, cell_width, constraint);
@ -26,7 +27,7 @@ impl<'a> TerminalLayoutData<'a> {
} }
///Configures a text style from the current settings. ///Configures a text style from the current settings.
fn make_text_style(font_cache: &FontCache, settings: &Settings) -> TextStyle { pub fn make_text_style(font_cache: &FontCache, settings: &Settings) -> TextStyle {
// Pull the font family from settings properly overriding // Pull the font family from settings properly overriding
let family_id = settings let family_id = settings
.terminal_overrides .terminal_overrides

View file

@ -4,13 +4,14 @@ use gpui::{geometry::vector::vec2f, AppContext, ModelHandle, ReadModelWith, Test
use itertools::Itertools; use itertools::Itertools;
use crate::{ use crate::{
connection::TerminalConnection, terminal_element::TerminalDimensions, DEBUG_CELL_WIDTH, connection::{DisconnectedPTY, Terminal},
DEBUG_LINE_HEIGHT, DEBUG_TERMINAL_HEIGHT, DEBUG_TERMINAL_WIDTH, terminal_element::TerminalDimensions,
DEBUG_CELL_WIDTH, DEBUG_LINE_HEIGHT, DEBUG_TERMINAL_HEIGHT, DEBUG_TERMINAL_WIDTH,
}; };
pub struct TerminalTestContext<'a> { pub struct TerminalTestContext<'a> {
pub cx: &'a mut TestAppContext, pub cx: &'a mut TestAppContext,
pub connection: ModelHandle<TerminalConnection>, pub connection: ModelHandle<Terminal>,
} }
impl<'a> TerminalTestContext<'a> { impl<'a> TerminalTestContext<'a> {
@ -23,8 +24,11 @@ impl<'a> TerminalTestContext<'a> {
vec2f(DEBUG_TERMINAL_WIDTH, DEBUG_TERMINAL_HEIGHT), vec2f(DEBUG_TERMINAL_WIDTH, DEBUG_TERMINAL_HEIGHT),
); );
let connection = let connection = cx.add_model(|cx| {
cx.add_model(|cx| TerminalConnection::new_tty(None, None, None, size_info, cx)); DisconnectedPTY::new(None, None, None, size_info)
.unwrap()
.connect(cx)
});
TerminalTestContext { cx, connection } TerminalTestContext { cx, connection }
} }
@ -35,11 +39,8 @@ impl<'a> TerminalTestContext<'a> {
{ {
let command = command.to_string(); let command = command.to_string();
self.connection.update(self.cx, |connection, _| { self.connection.update(self.cx, |connection, _| {
connection.get_terminal().unwrap().write_to_pty(command); connection.write_to_pty(command);
connection connection.write_to_pty("\r".to_string());
.get_terminal()
.unwrap()
.write_to_pty("\r".to_string());
}); });
self.connection self.connection
@ -55,11 +56,8 @@ impl<'a> TerminalTestContext<'a> {
}) })
} }
fn grid_as_str(connection: &TerminalConnection) -> String { fn grid_as_str(connection: &Terminal) -> String {
connection connection.render_lock(None, |content| {
.get_terminal()
.unwrap()
.render_lock(None, |content| {
let lines = content.display_iter.group_by(|i| i.point.line.0); let lines = content.display_iter.group_by(|i| i.point.line.0);
lines lines
.into_iter() .into_iter()