Attempting to continue rebase
This commit is contained in:
+4
-22
@@ -1781,21 +1781,6 @@ impl MutableAppContext {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_add_model<T, F>(&mut self, build_model: F) -> Result<ModelHandle<T>>
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut ModelContext<T>) -> Result<T>,
|
||||
{
|
||||
self.update(|this| {
|
||||
let model_id = post_inc(&mut this.next_entity_id);
|
||||
let handle = ModelHandle::new(model_id, &this.cx.ref_counts);
|
||||
let mut cx = ModelContext::new(this, model_id);
|
||||
let model = build_model(&mut cx)?;
|
||||
this.cx.models.insert(model_id, Box::new(model));
|
||||
Ok(handle)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_window<T, F>(
|
||||
&mut self,
|
||||
window_options: WindowOptions,
|
||||
@@ -1970,13 +1955,10 @@ impl MutableAppContext {
|
||||
for model_id in dropped_models {
|
||||
self.subscriptions.lock().remove(&model_id);
|
||||
self.observations.lock().remove(&model_id);
|
||||
//Model handles and IDs may have been created to instantiate a model without
|
||||
//finishing successfully (`try_add_model()`)
|
||||
if let Some(mut model) = self.cx.models.remove(&model_id) {
|
||||
model.release(self);
|
||||
self.pending_effects
|
||||
.push_back(Effect::ModelRelease { model_id, model });
|
||||
}
|
||||
let mut model = self.cx.models.remove(&model_id).unwrap();
|
||||
model.release(self);
|
||||
self.pending_effects
|
||||
.push_back(Effect::ModelRelease { model_id, model });
|
||||
}
|
||||
|
||||
for (window_id, view_id) in dropped_views {
|
||||
|
||||
@@ -6,10 +6,11 @@ use alacritty_terminal::{
|
||||
event::{Event as AlacTermEvent, EventListener, Notify},
|
||||
event_loop::{EventLoop, Msg, Notifier},
|
||||
grid::Scroll,
|
||||
selection::Selection,
|
||||
sync::FairMutex,
|
||||
term::{SizeInfo, TermMode},
|
||||
term::{cell::Cell, RenderableContent, SizeInfo, TermMode},
|
||||
tty::{self, setup_env},
|
||||
Term,
|
||||
Grid, Term,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use futures::channel::mpsc::{
|
||||
@@ -48,12 +49,13 @@ impl EventListener for ZedListener {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TerminalConnection {
|
||||
pub pty_tx: Notifier,
|
||||
pub term: Arc<FairMutex<Term<ZedListener>>>,
|
||||
pub title: String,
|
||||
pub associated_directory: Option<PathBuf>,
|
||||
pub cur_size: SizeInfo,
|
||||
pub enum TerminalConnection {
|
||||
Connected(Terminal),
|
||||
Disconnected {
|
||||
directory: Option<PathBuf>,
|
||||
shell: Option<Shell>,
|
||||
error: std::io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
impl TerminalConnection {
|
||||
@@ -63,7 +65,7 @@ impl TerminalConnection {
|
||||
env: Option<HashMap<String, String>>,
|
||||
initial_size: SizeInfo,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<TerminalConnection> {
|
||||
) -> TerminalConnection {
|
||||
let pty_config = {
|
||||
let shell = shell.and_then(|shell| match shell {
|
||||
Shell::System => None,
|
||||
@@ -99,7 +101,16 @@ impl TerminalConnection {
|
||||
let term = Arc::new(FairMutex::new(term));
|
||||
|
||||
//Setup the pty...
|
||||
let pty = tty::new(&pty_config, &initial_size, None)?;
|
||||
let pty = match tty::new(&pty_config, &initial_size, None) {
|
||||
Ok(pty) => pty,
|
||||
Err(error) => {
|
||||
return TerminalConnection::Disconnected {
|
||||
directory: working_directory,
|
||||
shell,
|
||||
error,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let shell = {
|
||||
let mut buf = [0; 1024];
|
||||
@@ -121,13 +132,20 @@ impl TerminalConnection {
|
||||
let pty_tx = event_loop.channel();
|
||||
let _io_thread = event_loop.spawn();
|
||||
|
||||
let terminal = Terminal {
|
||||
pty_tx: Notifier(pty_tx),
|
||||
term,
|
||||
title: DEFAULT_TITLE.to_string(),
|
||||
associated_directory: working_directory,
|
||||
};
|
||||
|
||||
cx.spawn_weak(|this, mut cx| async move {
|
||||
//Listen for terminal events
|
||||
while let Some(event) = events_rx.next().await {
|
||||
match this.upgrade(&cx) {
|
||||
Some(this) => {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.process_terminal_event(event, cx);
|
||||
terminal.process_terminal_event(event, cx);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
@@ -137,20 +155,30 @@ impl TerminalConnection {
|
||||
})
|
||||
.detach();
|
||||
|
||||
Ok(TerminalConnection {
|
||||
pty_tx: Notifier(pty_tx),
|
||||
term,
|
||||
title: shell.to_string(),
|
||||
cur_size: initial_size,
|
||||
associated_directory: working_directory,
|
||||
})
|
||||
TerminalConnection::Connected(terminal)
|
||||
}
|
||||
|
||||
pub fn get_terminal(&self) -> Option<&Terminal> {
|
||||
match self {
|
||||
TerminalConnection::Connected(conn) => Some(&conn),
|
||||
TerminalConnection::Disconnected { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Terminal {
|
||||
pty_tx: Notifier,
|
||||
term: Arc<FairMutex<Term<ZedListener>>>,
|
||||
pub title: String,
|
||||
pub associated_directory: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
///Takes events from Alacritty and translates them to behavior on this view
|
||||
fn process_terminal_event(
|
||||
&mut self,
|
||||
event: alacritty_terminal::event::Event,
|
||||
cx: &mut ModelContext<Self>,
|
||||
cx: &mut ModelContext<TerminalConnection>,
|
||||
) {
|
||||
match event {
|
||||
// TODO: Handle is_self_focused in subscription on terminal view
|
||||
@@ -198,12 +226,12 @@ impl TerminalConnection {
|
||||
}
|
||||
|
||||
///Write the Input payload to the tty. This locks the terminal so we can scroll it.
|
||||
pub fn write_to_pty(&mut self, input: String) {
|
||||
pub fn write_to_pty(&self, input: String) {
|
||||
self.write_bytes_to_pty(input.into_bytes());
|
||||
}
|
||||
|
||||
///Write the Input payload to the tty. This locks the terminal so we can scroll it.
|
||||
fn write_bytes_to_pty(&mut self, input: Vec<u8>) {
|
||||
fn write_bytes_to_pty(&self, input: Vec<u8>) {
|
||||
self.term.lock().scroll_display(Scroll::Bottom);
|
||||
self.pty_tx.notify(input);
|
||||
}
|
||||
@@ -214,12 +242,12 @@ impl TerminalConnection {
|
||||
self.term.lock().resize(new_size);
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
pub fn clear(&self) {
|
||||
self.write_to_pty("\x0c".into());
|
||||
self.term.lock().clear_screen(ClearMode::Saved);
|
||||
}
|
||||
|
||||
pub fn try_keystroke(&mut self, keystroke: &Keystroke) -> bool {
|
||||
pub fn try_keystroke(&self, keystroke: &Keystroke) -> bool {
|
||||
let guard = self.term.lock();
|
||||
let mode = guard.mode();
|
||||
let esc = to_esc_str(keystroke, mode);
|
||||
@@ -233,7 +261,7 @@ impl TerminalConnection {
|
||||
}
|
||||
|
||||
///Paste text into the terminal
|
||||
pub fn paste(&mut self, text: &str) {
|
||||
pub fn paste(&self, text: &str) {
|
||||
if self.term.lock().mode().contains(TermMode::BRACKETED_PASTE) {
|
||||
self.write_to_pty("\x1b[200~".to_string());
|
||||
self.write_to_pty(text.replace('\x1b', "").to_string());
|
||||
@@ -243,6 +271,32 @@ impl TerminalConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy(&self) -> Option<String> {
|
||||
let term = self.term.lock();
|
||||
term.selection_to_string()
|
||||
}
|
||||
|
||||
///Takes the selection out of the terminal
|
||||
pub fn take_selection(&self) -> Option<Selection> {
|
||||
self.term.lock().selection.take()
|
||||
}
|
||||
|
||||
///Sets the selection object on the terminal
|
||||
pub fn set_selection(&self, sel: Option<Selection>) {
|
||||
self.term.lock().selection = sel;
|
||||
}
|
||||
|
||||
///Get the relevant rendering values from the terminal
|
||||
pub fn renderable_content(&self) -> (RenderableContent, &Grid<Cell>) {
|
||||
let term = self.term.lock();
|
||||
(term.renderable_content(), term.grid())
|
||||
}
|
||||
|
||||
///Scroll the terminal
|
||||
pub fn scroll(&self, scroll: Scroll) {
|
||||
self.term.lock().scroll_display(scroll)
|
||||
}
|
||||
|
||||
// pub fn click(&mut self, pos: Vector2F, clicks: usize) {}
|
||||
|
||||
// pub fn drag(prev_pos: Vector2F, pos: Vector2F) {}
|
||||
@@ -252,7 +306,12 @@ impl TerminalConnection {
|
||||
|
||||
impl Drop for TerminalConnection {
|
||||
fn drop(&mut self) {
|
||||
self.pty_tx.0.send(Msg::Shutdown).ok();
|
||||
match self {
|
||||
TerminalConnection::Connected(conn) => {
|
||||
conn.pty_tx.0.send(Msg::Shutdown).ok();
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use gpui::{ModelHandle, ViewContext};
|
||||
use util::ResultExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::{get_wd_for_workspace, DeployModal, Event, Terminal, TerminalConnection};
|
||||
use crate::{get_wd_for_workspace, DeployModal, Event, TerminalConnection, TerminalView};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StoredConnection(ModelHandle<TerminalConnection>);
|
||||
@@ -17,7 +16,7 @@ pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewCon
|
||||
if let Some(StoredConnection(stored_connection)) = possible_connection {
|
||||
// Create a view from the stored connection
|
||||
workspace.toggle_modal(cx, |_, cx| {
|
||||
cx.add_view(|cx| Terminal::from_connection(stored_connection.clone(), true, cx))
|
||||
cx.add_view(|cx| TerminalView::from_connection(stored_connection.clone(), true, cx))
|
||||
});
|
||||
cx.set_global::<Option<StoredConnection>>(Some(StoredConnection(
|
||||
stored_connection.clone(),
|
||||
@@ -27,10 +26,7 @@ pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewCon
|
||||
if let Some(closed_terminal_handle) = workspace.toggle_modal(cx, |workspace, cx| {
|
||||
let wd = get_wd_for_workspace(workspace, cx);
|
||||
|
||||
//TODO: Create a 'failed to launch' view which prints the error and config details.
|
||||
let this = cx
|
||||
.add_option_view(|cx| Terminal::new(wd, true, cx).log_err())
|
||||
.unwrap();
|
||||
let this = cx.add_view(|cx| TerminalView::new(wd, true, cx));
|
||||
|
||||
let connection_handle = this.read(cx).connection.clone();
|
||||
cx.subscribe(&connection_handle, on_event).detach();
|
||||
@@ -60,7 +56,7 @@ pub fn on_event(
|
||||
if workspace
|
||||
.modal()
|
||||
.cloned()
|
||||
.and_then(|modal| modal.downcast::<Terminal>())
|
||||
.and_then(|modal| modal.downcast::<TerminalView>())
|
||||
.is_some()
|
||||
{
|
||||
workspace.dismiss_modal(cx)
|
||||
|
||||
@@ -4,7 +4,6 @@ mod modal;
|
||||
pub mod terminal_element;
|
||||
|
||||
use alacritty_terminal::term::SizeInfo;
|
||||
use anyhow::Result;
|
||||
use connection::{Event, TerminalConnection};
|
||||
use dirs::home_dir;
|
||||
use gpui::{
|
||||
@@ -17,7 +16,6 @@ use project::{LocalWorktree, Project, ProjectPath};
|
||||
use settings::{Settings, WorkingDirectory};
|
||||
use smallvec::SmallVec;
|
||||
use std::path::{Path, PathBuf};
|
||||
use util::ResultExt;
|
||||
use workspace::{Item, Workspace};
|
||||
|
||||
use crate::terminal_element::TerminalEl;
|
||||
@@ -50,21 +48,21 @@ actions!(
|
||||
///Initialize and register all of our action handlers
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
//Global binding overrrides
|
||||
cx.add_action(Terminal::ctrl_c);
|
||||
cx.add_action(Terminal::up);
|
||||
cx.add_action(Terminal::down);
|
||||
cx.add_action(Terminal::escape);
|
||||
cx.add_action(Terminal::enter);
|
||||
cx.add_action(TerminalView::ctrl_c);
|
||||
cx.add_action(TerminalView::up);
|
||||
cx.add_action(TerminalView::down);
|
||||
cx.add_action(TerminalView::escape);
|
||||
cx.add_action(TerminalView::enter);
|
||||
//Useful terminal actions
|
||||
cx.add_action(Terminal::deploy);
|
||||
cx.add_action(TerminalView::deploy);
|
||||
cx.add_action(deploy_modal);
|
||||
cx.add_action(Terminal::copy);
|
||||
cx.add_action(Terminal::paste);
|
||||
cx.add_action(Terminal::clear);
|
||||
cx.add_action(TerminalView::copy);
|
||||
cx.add_action(TerminalView::paste);
|
||||
cx.add_action(TerminalView::clear);
|
||||
}
|
||||
|
||||
///A terminal view, maintains the PTY's file handles and communicates with the terminal
|
||||
pub struct Terminal {
|
||||
pub struct TerminalView {
|
||||
connection: ModelHandle<TerminalConnection>,
|
||||
has_new_content: bool,
|
||||
//Currently using iTerm bell, show bell emoji in tab until input is received
|
||||
@@ -73,18 +71,14 @@ pub struct Terminal {
|
||||
modal: bool,
|
||||
}
|
||||
|
||||
impl Entity for Terminal {
|
||||
impl Entity for TerminalView {
|
||||
type Event = Event;
|
||||
}
|
||||
|
||||
impl Terminal {
|
||||
impl TerminalView {
|
||||
///Create a new Terminal view. This spawns a task, a thread, and opens the TTY devices
|
||||
///To get the right working directory from a workspace, use: `get_wd_for_workspace()`
|
||||
fn new(
|
||||
working_directory: Option<PathBuf>,
|
||||
modal: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Result<Self> {
|
||||
fn new(working_directory: Option<PathBuf>, modal: bool, cx: &mut ViewContext<Self>) -> Self {
|
||||
//The details here don't matter, the terminal will be resized on the first layout
|
||||
let size_info = SizeInfo::new(
|
||||
DEBUG_TERMINAL_WIDTH,
|
||||
@@ -103,18 +97,17 @@ impl Terminal {
|
||||
(shell, envs)
|
||||
};
|
||||
|
||||
let connection = cx.try_add_model(|cx| {
|
||||
TerminalConnection::new(working_directory, shell, envs, size_info, cx)
|
||||
})?;
|
||||
let connection = cx
|
||||
.add_model(|cx| TerminalConnection::new(working_directory, shell, envs, size_info, cx));
|
||||
|
||||
Ok(Terminal::from_connection(connection, modal, cx))
|
||||
TerminalView::from_connection(connection, modal, cx)
|
||||
}
|
||||
|
||||
fn from_connection(
|
||||
connection: ModelHandle<TerminalConnection>,
|
||||
modal: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Terminal {
|
||||
) -> TerminalView {
|
||||
cx.observe(&connection, |_, _, cx| cx.notify()).detach();
|
||||
cx.subscribe(&connection, |this, _, event, cx| match event {
|
||||
Event::Wakeup => {
|
||||
@@ -137,7 +130,7 @@ impl Terminal {
|
||||
})
|
||||
.detach();
|
||||
|
||||
Terminal {
|
||||
TerminalView {
|
||||
connection,
|
||||
has_new_content: true,
|
||||
has_bell: false,
|
||||
@@ -152,73 +145,79 @@ impl Terminal {
|
||||
|
||||
fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
|
||||
self.connection
|
||||
.update(cx, |connection, _| connection.clear());
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.clear());
|
||||
}
|
||||
|
||||
///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>) {
|
||||
let wd = get_wd_for_workspace(workspace, cx);
|
||||
if let Some(view) = cx.add_option_view(|cx| Terminal::new(wd, false, cx).log_err()) {
|
||||
workspace.add_item(Box::new(view), cx);
|
||||
}
|
||||
let view = cx.add_view(|cx| TerminalView::new(wd, false, cx));
|
||||
workspace.add_item(Box::new(view), cx);
|
||||
}
|
||||
|
||||
///Attempt to paste the clipboard into the terminal
|
||||
fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
|
||||
let term = self.connection.read(cx).term.lock();
|
||||
let copy_text = term.selection_to_string();
|
||||
match copy_text {
|
||||
Some(s) => cx.write_to_clipboard(ClipboardItem::new(s)),
|
||||
None => (),
|
||||
}
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.and_then(|term| term.copy())
|
||||
.map(|text| cx.write_to_clipboard(ClipboardItem::new(text)));
|
||||
}
|
||||
|
||||
///Attempt to paste the clipboard into the terminal
|
||||
fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
|
||||
if let Some(item) = cx.read_from_clipboard() {
|
||||
self.connection.update(cx, |connection, _| {
|
||||
connection.paste(item.text());
|
||||
})
|
||||
}
|
||||
cx.read_from_clipboard().map(|item| {
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.paste(item.text()));
|
||||
});
|
||||
}
|
||||
|
||||
///Synthesize the keyboard event corresponding to 'up'
|
||||
fn up(&mut self, _: &Up, cx: &mut ViewContext<Self>) {
|
||||
self.connection.update(cx, |connection, _| {
|
||||
connection.try_keystroke(&Keystroke::parse("up").unwrap());
|
||||
});
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.try_keystroke(&Keystroke::parse("up").unwrap()));
|
||||
}
|
||||
|
||||
///Synthesize the keyboard event corresponding to 'down'
|
||||
fn down(&mut self, _: &Down, cx: &mut ViewContext<Self>) {
|
||||
self.connection.update(cx, |connection, _| {
|
||||
connection.try_keystroke(&Keystroke::parse("down").unwrap());
|
||||
});
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.try_keystroke(&Keystroke::parse("down").unwrap()));
|
||||
}
|
||||
|
||||
///Synthesize the keyboard event corresponding to 'ctrl-c'
|
||||
fn ctrl_c(&mut self, _: &CtrlC, cx: &mut ViewContext<Self>) {
|
||||
self.connection.update(cx, |connection, _| {
|
||||
connection.try_keystroke(&Keystroke::parse("ctrl-c").unwrap());
|
||||
});
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.try_keystroke(&Keystroke::parse("ctrl-c").unwrap()));
|
||||
}
|
||||
|
||||
///Synthesize the keyboard event corresponding to 'escape'
|
||||
fn escape(&mut self, _: &Escape, cx: &mut ViewContext<Self>) {
|
||||
self.connection.update(cx, |connection, _| {
|
||||
connection.try_keystroke(&Keystroke::parse("escape").unwrap());
|
||||
});
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.try_keystroke(&Keystroke::parse("escape").unwrap()));
|
||||
}
|
||||
|
||||
///Synthesize the keyboard event corresponding to 'enter'
|
||||
fn enter(&mut self, _: &Enter, cx: &mut ViewContext<Self>) {
|
||||
self.connection.update(cx, |connection, _| {
|
||||
connection.try_keystroke(&Keystroke::parse("enter").unwrap());
|
||||
});
|
||||
self.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.map(|term| term.try_keystroke(&Keystroke::parse("enter").unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
impl View for Terminal {
|
||||
impl View for TerminalView {
|
||||
fn ui_name() -> &'static str {
|
||||
"Terminal"
|
||||
}
|
||||
@@ -252,36 +251,42 @@ impl View for Terminal {
|
||||
}
|
||||
}
|
||||
|
||||
impl Item for Terminal {
|
||||
impl Item for TerminalView {
|
||||
fn tab_content(
|
||||
&self,
|
||||
_detail: Option<usize>,
|
||||
tab_theme: &theme::Tab,
|
||||
cx: &gpui::AppContext,
|
||||
) -> ElementBox {
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(
|
||||
self.connection.read(cx).title.clone(),
|
||||
tab_theme.label.clone(),
|
||||
)
|
||||
let mut flex = Flex::row();
|
||||
|
||||
let title = match self.connection.read(cx) {
|
||||
TerminalConnection::Connected(conn) => conn.title,
|
||||
TerminalConnection::Disconnected { .. } => "Terminal".to_string(), //TODO ask nate about htis
|
||||
};
|
||||
|
||||
flex.with_child(
|
||||
Label::new(title, tab_theme.label.clone())
|
||||
.aligned()
|
||||
.contained()
|
||||
.boxed(),
|
||||
)
|
||||
.boxed()
|
||||
)
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn clone_on_split(&self, cx: &mut ViewContext<Self>) -> Option<Self> {
|
||||
//From what I can tell, there's no way to tell the current working
|
||||
//Directory of the terminal from outside the shell. There might be
|
||||
//solutions to this, but they are non-trivial and require more IPC
|
||||
Terminal::new(
|
||||
self.connection.read(cx).associated_directory.clone(),
|
||||
false,
|
||||
cx,
|
||||
)
|
||||
.ok()
|
||||
|
||||
let wd = self
|
||||
.connection
|
||||
.read(cx)
|
||||
.get_terminal()
|
||||
.and_then(|term| term.associated_directory)
|
||||
.clone();
|
||||
|
||||
Some(TerminalView::new(wd, false, cx))
|
||||
}
|
||||
|
||||
fn project_path(&self, _cx: &gpui::AppContext) -> Option<ProjectPath> {
|
||||
|
||||
@@ -105,17 +105,20 @@ impl TerminalEl {
|
||||
MouseButton::Left,
|
||||
move |MouseButtonEvent { position, .. }, cx| {
|
||||
if let Some(conn_handle) = mouse_down_connection.upgrade(cx.app) {
|
||||
conn_handle.update(cx.app, |conn, _cx| {
|
||||
let mut term = conn.term.lock();
|
||||
let (point, side) = mouse_to_cell_data(
|
||||
position,
|
||||
origin,
|
||||
conn.cur_size,
|
||||
term.renderable_content().display_offset,
|
||||
);
|
||||
term.selection =
|
||||
Some(Selection::new(SelectionType::Simple, point, side))
|
||||
});
|
||||
conn_handle.update(cx.app, |connection, cx| {
|
||||
connection.get_terminal().map(|terminal| {
|
||||
let (point, side) = mouse_to_cell_data(
|
||||
position,
|
||||
origin,
|
||||
cur_size,
|
||||
terminal.get_display_offset(),
|
||||
);
|
||||
|
||||
terminal.mouse_down(point, side);
|
||||
|
||||
cx.notify();
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -130,13 +133,11 @@ impl TerminalEl {
|
||||
cx.focus_parent_view();
|
||||
if let Some(conn_handle) = click_connection.upgrade(cx.app) {
|
||||
conn_handle.update(cx.app, |conn, cx| {
|
||||
let mut term = conn.term.lock();
|
||||
|
||||
let (point, side) = mouse_to_cell_data(
|
||||
position,
|
||||
origin,
|
||||
conn.cur_size,
|
||||
term.renderable_content().display_offset,
|
||||
// conn.cur_size,
|
||||
// term.renderable_content().display_offset,
|
||||
);
|
||||
|
||||
let selection_type = match click_count {
|
||||
@@ -150,9 +151,7 @@ impl TerminalEl {
|
||||
let selection = selection_type.map(|selection_type| {
|
||||
Selection::new(selection_type, point, side)
|
||||
});
|
||||
|
||||
term.selection = selection;
|
||||
|
||||
conn.set_selection(selection);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
@@ -162,22 +161,19 @@ impl TerminalEl {
|
||||
MouseButton::Left,
|
||||
move |_, MouseMovedEvent { position, .. }, cx| {
|
||||
if let Some(conn_handle) = drag_connection.upgrade(cx.app) {
|
||||
conn_handle.update(cx.app, |conn, cx| {
|
||||
let mut term = conn.term.lock();
|
||||
conn_handle.update(cx.app, |connection, cx| {
|
||||
connection.get_terminal().map(|terminal| {
|
||||
let (point, side) = mouse_to_cell_data(
|
||||
position,
|
||||
origin,
|
||||
cur_size,
|
||||
terminal.get_display_offset(),
|
||||
);
|
||||
|
||||
let (point, side) = mouse_to_cell_data(
|
||||
position,
|
||||
origin,
|
||||
conn.cur_size,
|
||||
term.renderable_content().display_offset,
|
||||
);
|
||||
terminal.drag(point, side);
|
||||
|
||||
if let Some(mut selection) = term.selection.take() {
|
||||
selection.update(point, side);
|
||||
term.selection = Some(selection);
|
||||
}
|
||||
|
||||
cx.notify()
|
||||
cx.notify()
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -197,14 +193,17 @@ impl Element for TerminalEl {
|
||||
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
|
||||
let tcx = TerminalLayoutContext::new(cx.global::<Settings>(), &cx.font_cache());
|
||||
|
||||
let term = {
|
||||
let connection = self.connection.upgrade(cx).unwrap().read(cx);
|
||||
//This locks the terminal, so resize it first.
|
||||
connection.set_size(make_new_size(constraint, &tcx.cell_width, &tcx.line_height));
|
||||
connection.term.lock()
|
||||
};
|
||||
let terminal = self
|
||||
.connection
|
||||
.upgrade(cx)
|
||||
.unwrap()
|
||||
.read(cx)
|
||||
.get_terminal() //TODO!
|
||||
.unwrap();
|
||||
//This locks the terminal, so resize it first.
|
||||
terminal.set_size(make_new_size(constraint, &tcx.cell_width, &tcx.line_height));
|
||||
|
||||
let content = term.renderable_content();
|
||||
let (content, grid) = terminal.renderable_content();
|
||||
|
||||
//Layout grid cells
|
||||
|
||||
@@ -219,7 +218,7 @@ impl Element for TerminalEl {
|
||||
|
||||
//Layout cursor
|
||||
let cursor = layout_cursor(
|
||||
term.grid(),
|
||||
grid,
|
||||
cx.text_layout_cache,
|
||||
&tcx,
|
||||
content.cursor.point,
|
||||
@@ -390,14 +389,12 @@ impl Element for TerminalEl {
|
||||
let vertical_scroll =
|
||||
(delta.y() / layout.line_height.0) * ALACRITTY_SCROLL_MULTIPLIER;
|
||||
|
||||
if let Some(connection) = self.connection.upgrade(cx.app) {
|
||||
connection.update(cx.app, |connection, _| {
|
||||
connection
|
||||
.term
|
||||
.lock()
|
||||
.scroll_display(Scroll::Delta(vertical_scroll.round() as i32));
|
||||
})
|
||||
}
|
||||
self.connection
|
||||
.upgrade(cx.app)
|
||||
.and_then(|handle| handle.read(cx.app).get_terminal())
|
||||
.map(|terminal| {
|
||||
terminal.scroll(Scroll::Delta(vertical_scroll.round() as i32));
|
||||
});
|
||||
})
|
||||
.is_some(),
|
||||
Event::KeyDown(KeyDownEvent { keystroke, .. }) => {
|
||||
@@ -412,16 +409,18 @@ impl Element for TerminalEl {
|
||||
|
||||
self.connection
|
||||
.upgrade(cx.app)
|
||||
.map(|connection| {
|
||||
connection
|
||||
.update(cx.app, |connection, _| connection.try_keystroke(keystroke))
|
||||
})
|
||||
.and_then(|model_handle| model_handle.read(cx.app).get_terminal())
|
||||
.map(|term| term.try_keystroke(keystroke))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<&dyn std::any::Any> {
|
||||
None
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
_bounds: gpui::geometry::rect::RectF,
|
||||
|
||||
@@ -29,7 +29,7 @@ impl<'a> TerminalTestContext<'a> {
|
||||
);
|
||||
|
||||
let connection =
|
||||
cx.add_model(|cx| TerminalConnection::new(None, None, None, size_info, cx).unwrap());
|
||||
cx.add_model(|cx| TerminalConnection::new(None, None, None, size_info, cx));
|
||||
|
||||
TerminalTestContext { cx, connection }
|
||||
}
|
||||
@@ -40,8 +40,11 @@ impl<'a> TerminalTestContext<'a> {
|
||||
{
|
||||
let command = command.to_string();
|
||||
self.connection.update(self.cx, |connection, _| {
|
||||
connection.write_to_pty(command);
|
||||
connection.write_to_pty("\r".to_string());
|
||||
connection.get_terminal().unwrap().write_to_pty(command);
|
||||
connection
|
||||
.get_terminal()
|
||||
.unwrap()
|
||||
.write_to_pty("\r".to_string());
|
||||
});
|
||||
|
||||
self.connection
|
||||
@@ -58,9 +61,8 @@ impl<'a> TerminalTestContext<'a> {
|
||||
}
|
||||
|
||||
fn grid_as_str(connection: &TerminalConnection) -> String {
|
||||
let term = connection.term.lock();
|
||||
let grid_iterator = term.renderable_content().display_iter;
|
||||
let lines = grid_iterator.group_by(|i| i.point.line.0);
|
||||
let (grid_iterator, _) = connection.get_terminal().unwrap().renderable_content();
|
||||
let lines = grid_iterator.display_iter.group_by(|i| i.point.line.0);
|
||||
lines
|
||||
.into_iter()
|
||||
.map(|(_, line)| line.map(|i| i.c).collect::<String>())
|
||||
|
||||
Reference in New Issue
Block a user