@@ -1,6 +1,7 @@
mod ignore;
mod lsp_command;
pub mod search;
+pub mod terminals;
pub mod worktree;
#[cfg(test)]
@@ -61,7 +62,8 @@ use std::{
},
time::{Duration, Instant, SystemTime},
};
-use terminal::{Terminal, TerminalBuilder};
+use terminals::Terminals;
+
use util::{debug_panic, defer, post_inc, ResultExt, TryFutureExt as _};
pub use fs::*;
@@ -123,6 +125,7 @@ pub struct Project {
buffers_being_formatted: HashSet<usize>,
nonce: u128,
_maintain_buffer_languages: Task<()>,
+ terminals: Terminals,
}
enum OpenBuffer {
@@ -439,6 +442,9 @@ impl Project {
buffers_being_formatted: Default::default(),
next_language_server_id: 0,
nonce: StdRng::from_entropy().gen(),
+ terminals: Terminals {
+ local_handles: Vec::new(),
+ },
})
}
@@ -516,6 +522,9 @@ impl Project {
buffers_being_formatted: Default::default(),
buffer_snapshots: Default::default(),
nonce: StdRng::from_entropy().gen(),
+ terminals: Terminals {
+ local_handles: Vec::new(),
+ },
};
for worktree in worktrees {
let _ = this.add_worktree(&worktree, cx);
@@ -1184,34 +1193,6 @@ impl Project {
!self.is_local()
}
- pub fn create_terminal(
- &mut self,
- working_directory: Option<PathBuf>,
- window_id: usize,
- cx: &mut ModelContext<Self>,
- ) -> Result<ModelHandle<Terminal>> {
- if self.is_remote() {
- return Err(anyhow!(
- "creating terminals as a guest is not supported yet"
- ));
- } else {
- let settings = cx.global::<Settings>();
- let shell = settings.terminal_shell();
- let envs = settings.terminal_env();
- let scroll = settings.terminal_scroll();
-
- TerminalBuilder::new(
- working_directory.clone(),
- shell,
- envs,
- settings.terminal_overrides.blinking.clone(),
- scroll,
- window_id,
- )
- .map(|builder| cx.add_model(|cx| builder.subscribe(cx)))
- }
- }
-
pub fn create_buffer(
&mut self,
text: &str,
@@ -0,0 +1,63 @@
+use std::path::PathBuf;
+
+use gpui::{ModelContext, ModelHandle, WeakModelHandle};
+use settings::Settings;
+use terminal::{Terminal, TerminalBuilder};
+
+use crate::Project;
+
+pub struct Terminals {
+ pub(crate) local_handles: Vec<WeakModelHandle<terminal::Terminal>>,
+}
+
+impl Project {
+ pub fn create_terminal(
+ &mut self,
+ working_directory: Option<PathBuf>,
+ window_id: usize,
+ cx: &mut ModelContext<Self>,
+ ) -> anyhow::Result<ModelHandle<Terminal>> {
+ if self.is_remote() {
+ return Err(anyhow::anyhow!(
+ "creating terminals as a guest is not supported yet"
+ ));
+ } else {
+ let settings = cx.global::<Settings>();
+ let shell = settings.terminal_shell();
+ let envs = settings.terminal_env();
+ let scroll = settings.terminal_scroll();
+
+ let terminal = TerminalBuilder::new(
+ working_directory.clone(),
+ shell,
+ envs,
+ settings.terminal_overrides.blinking.clone(),
+ scroll,
+ window_id,
+ )
+ .map(|builder| {
+ let terminal_handle = cx.add_model(|cx| builder.subscribe(cx));
+
+ self.terminals
+ .local_handles
+ .push(terminal_handle.downgrade());
+
+ let id = terminal_handle.id();
+ cx.observe_release(&terminal_handle, move |project, _terminal, _cx| {
+ let handles = &mut project.terminals.local_handles;
+
+ if let Some(index) = handles.iter().position(|terminal| terminal.id() == id) {
+ handles.remove(index);
+ }
+ })
+ .detach();
+
+ terminal_handle
+ });
+
+ terminal
+ }
+ }
+}
+
+// TODO: Add a few tests for adding and removing terminal tabs
@@ -11,9 +11,10 @@ pub struct TerminalButton {
workspace: WeakViewHandle<Workspace>,
}
+// TODO: Rename this to `DeployTerminalButton`
impl TerminalButton {
pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
- // When dock moves, redraw so that the icon and toggle status matches.
+ // When terminal moves, redraw so that the icon and toggle status matches.
cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
Self {
@@ -63,6 +64,7 @@ impl View for TerminalButton {
})
.with_cursor_style(CursorStyle::PointingHand)
.on_up(MouseButton::Left, move |_, _| {
+ // TODO: Do we need this stuff?
// let dock_pane = workspace.read(cx.app).dock_pane();
// let drop_index = dock_pane.read(cx.app).items_len() + 1;
// handle_dropped_item(event, &dock_pane.downgrade(), drop_index, false, None, cx);