terminals.rs

 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