terminals.rs

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