1use crate::Project;
2use gpui::{AnyWindowHandle, ModelContext, ModelHandle, WeakModelHandle};
3use std::path::PathBuf;
4use terminal::{Terminal, TerminalBuilder, TerminalSettings};
5
6pub struct Terminals {
7 pub(crate) local_handles: Vec<WeakModelHandle<terminal::Terminal>>,
8}
9
10impl Project {
11 pub fn create_terminal(
12 &mut self,
13 working_directory: Option<PathBuf>,
14 window: AnyWindowHandle,
15 cx: &mut ModelContext<Self>,
16 ) -> anyhow::Result<ModelHandle<Terminal>> {
17 if self.is_remote() {
18 return Err(anyhow::anyhow!(
19 "creating terminals as a guest is not supported yet"
20 ));
21 } else {
22 let settings = settings::get::<TerminalSettings>(cx);
23
24 let terminal = TerminalBuilder::new(
25 working_directory.clone(),
26 settings.shell.clone(),
27 settings.env.clone(),
28 Some(settings.blinking.clone()),
29 settings.alternate_scroll,
30 window,
31 )
32 .map(|builder| {
33 let terminal_handle = cx.add_model(|cx| builder.subscribe(cx));
34
35 self.terminals
36 .local_handles
37 .push(terminal_handle.downgrade());
38
39 let id = terminal_handle.id();
40 cx.observe_release(&terminal_handle, move |project, _terminal, cx| {
41 let handles = &mut project.terminals.local_handles;
42
43 if let Some(index) = handles.iter().position(|terminal| terminal.id() == id) {
44 handles.remove(index);
45 cx.notify();
46 }
47 })
48 .detach();
49
50 terminal_handle
51 });
52
53 terminal
54 }
55 }
56
57 pub fn local_terminal_handles(&self) -> &Vec<WeakModelHandle<terminal::Terminal>> {
58 &self.terminals.local_handles
59 }
60}
61
62// TODO: Add a few tests for adding and removing terminal tabs