Checkpoint, build failing

This commit is contained in:
Mikayla Maki 2022-07-25 15:54:49 -07:00
parent 27e76e3ca2
commit be4873b92b
4 changed files with 40 additions and 25 deletions

View file

@ -0,0 +1,8 @@
Design notes:
This crate is split into two conceptual halves:
- The terminal.rs file and the ./src/mappings/ folder, these contain the code for interacting with Alacritty and maintaining the pty event loop. Some behavior in this file is constrained by terminal protocols and standards. The Zed init function is also placed here.
- Everything else. These other files integrate the `Terminal` struct created in terminal.rs into the rest of GPUI. The main entry point for GPUI is the terminal_view.rs file and the modal.rs file.
Terminals are created externally, and so can fail in unexpected ways However, GPUI currently does not have an API for models than can fail to instantiate. `TerminalBuilder` solves this by using Rust's type system to split `Terminal` instantiation into a 2 step process: first attempt to create the file handles with `TerminalBuilder::new()`, check the result, then call `TerminalBuilder::subscribe(cx)` from within a model context.
The TerminalView struct abstracts over failed and successful terminals, and provides other constructs a standardized way of instantiating an always-successful terminal view.

View file

@ -2,7 +2,7 @@ use gpui::{ModelHandle, ViewContext};
use workspace::Workspace; use workspace::Workspace;
use crate::{ use crate::{
terminal_tab::{get_working_directory, DeployModal, TerminalContent, TerminalView}, terminal_view::{get_working_directory, DeployModal, TerminalContent, TerminalView},
Event, Terminal, Event, Terminal,
}; };

View file

@ -2,7 +2,7 @@ pub mod connected_el;
pub mod connected_view; pub mod connected_view;
pub mod mappings; pub mod mappings;
pub mod modal; pub mod modal;
pub mod terminal_tab; pub mod terminal_view;
use alacritty_terminal::{ use alacritty_terminal::{
ansi::{ClearMode, Handler}, ansi::{ClearMode, Handler},
@ -22,7 +22,7 @@ use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
use modal::deploy_modal; use modal::deploy_modal;
use settings::{Settings, Shell}; use settings::{Settings, Shell};
use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration}; use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration};
use terminal_tab::TerminalView; use terminal_view::TerminalView;
use thiserror::Error; use thiserror::Error;
use gpui::{ use gpui::{
@ -319,6 +319,7 @@ impl TerminalBuilder {
pty_tx: Notifier(pty_tx), pty_tx: Notifier(pty_tx),
term, term,
title: shell_txt.to_string(), title: shell_txt.to_string(),
event_stack: vec![],
}; };
Ok(TerminalBuilder { Ok(TerminalBuilder {
@ -330,8 +331,8 @@ impl TerminalBuilder {
pub fn subscribe(mut self, cx: &mut ModelContext<Terminal>) -> Terminal { pub fn subscribe(mut self, cx: &mut ModelContext<Terminal>) -> Terminal {
cx.spawn_weak(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
'outer: loop { 'outer: loop {
//Even as low as 45 locks zed up //TODO: Pending GPUI updates, sync this to some higher, smarter system.
let delay = cx.background().timer(Duration::from_secs_f32(1.0 / 30.)); let delay = cx.background().timer(Duration::from_secs_f32(1.0 / 60.));
let mut events = vec![]; let mut events = vec![];
@ -349,9 +350,8 @@ impl TerminalBuilder {
match this.upgrade(&cx) { match this.upgrade(&cx) {
Some(this) => { Some(this) => {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
for event in events { this.push_events(events);
this.process_terminal_event(event, cx); cx.notify();
}
}); });
} }
None => break 'outer, None => break 'outer,
@ -370,13 +370,19 @@ pub struct Terminal {
pty_tx: Notifier, pty_tx: Notifier,
term: Arc<FairMutex<Term<ZedListener>>>, term: Arc<FairMutex<Term<ZedListener>>>,
pub title: String, pub title: String,
event_stack: Vec<AlacTermEvent>,
} }
impl Terminal { impl Terminal {
fn push_events(&mut self, events: Vec<AlacTermEvent>) {
self.event_stack.extend(events)
}
///Takes events from Alacritty and translates them to behavior on this view ///Takes events from Alacritty and translates them to behavior on this view
fn process_terminal_event( fn process_terminal_event(
&mut self, &mut self,
event: alacritty_terminal::event::Event, event: alacritty_terminal::event::Event,
term: &mut Term<ZedListener>,
cx: &mut ModelContext<Terminal>, cx: &mut ModelContext<Terminal>,
) { ) {
match event { match event {
@ -384,7 +390,10 @@ impl Terminal {
AlacTermEvent::Wakeup => { AlacTermEvent::Wakeup => {
cx.emit(Event::Wakeup); cx.emit(Event::Wakeup);
} }
AlacTermEvent::PtyWrite(out) => self.write_to_pty(out), AlacTermEvent::PtyWrite(out) => {
term.scroll_display(Scroll::Bottom);
self.pty_tx.notify(out.into_bytes())
}
AlacTermEvent::MouseCursorDirty => { AlacTermEvent::MouseCursorDirty => {
//Calculate new cursor style. //Calculate new cursor style.
//TODO: alacritty/src/input.rs:L922-L939 //TODO: alacritty/src/input.rs:L922-L939
@ -408,7 +417,7 @@ impl Terminal {
.unwrap_or("".to_string()), .unwrap_or("".to_string()),
)), )),
AlacTermEvent::ColorRequest(index, format) => { AlacTermEvent::ColorRequest(index, format) => {
let color = self.term.lock().colors()[index].unwrap_or_else(|| { let color = term.colors()[index].unwrap_or_else(|| {
let term_style = &cx.global::<Settings>().theme.terminal; let term_style = &cx.global::<Settings>().theme.terminal;
to_alac_rgb(get_color_at_index(&index, &term_style.colors)) to_alac_rgb(get_color_at_index(&index, &term_style.colors))
}); });
@ -427,13 +436,7 @@ impl Terminal {
///Write the Input payload to the tty. This locks the terminal so we can scroll it. ///Write the Input payload to the tty. This locks the terminal so we can scroll it.
pub fn write_to_pty(&self, input: String) { pub fn write_to_pty(&self, input: String) {
self.write_bytes_to_pty(input.into_bytes()); self.event_stack.push(AlacTermEvent::PtyWrite(input))
}
///Write the Input payload to the tty. This locks the terminal so we can scroll it.
fn write_bytes_to_pty(&self, input: Vec<u8>) {
self.term.lock().scroll_display(Scroll::Bottom);
self.pty_tx.notify(input);
} }
///Resize the terminal and the PTY. This locks the terminal. ///Resize the terminal and the PTY. This locks the terminal.
@ -487,19 +490,23 @@ impl Terminal {
self.term.lock().selection = sel; self.term.lock().selection = sel;
} }
pub fn render_lock<F, T>(&self, new_size: Option<TermDimensions>, f: F) -> T pub fn render_lock<F, T>(&self, cx: &mut ModelContext<Self>, f: F) -> T
where where
F: FnOnce(RenderableContent, char) -> T, F: FnOnce(RenderableContent, char) -> T,
{ {
if let Some(new_size) = new_size {
self.pty_tx.0.send(Msg::Resize(new_size.into())).ok(); //Give the PTY a chance to react to the new size
//TODO: Is this bad for performance?
}
let mut term = self.term.lock(); //Lock let mut term = self.term.lock(); //Lock
if let Some(new_size) = new_size { //TODO, handle resizes
term.resize(new_size); //Reflow // if let Some(new_size) = new_size {
// self.pty_tx.0.send(Msg::Resize(new_size.into())).ok();
// }
// if let Some(new_size) = new_size {
// term.resize(new_size); //Reflow
// }
for event in self.event_stack.drain(..) {
self.process_terminal_event(event, &mut term, cx)
} }
let content = term.renderable_content(); let content = term.renderable_content();