terminal.rs

 1use gpui::{App, AppContext, Context, Entity};
 2use language::LanguageRegistry;
 3use markdown::Markdown;
 4use std::{path::PathBuf, process::ExitStatus, sync::Arc, time::Instant};
 5
 6pub struct Terminal {
 7    command: Entity<Markdown>,
 8    working_dir: Option<PathBuf>,
 9    terminal: Entity<terminal::Terminal>,
10    started_at: Instant,
11    output: Option<TerminalOutput>,
12}
13
14pub struct TerminalOutput {
15    pub ended_at: Instant,
16    pub exit_status: Option<ExitStatus>,
17    pub was_content_truncated: bool,
18    pub original_content_len: usize,
19    pub content_line_count: usize,
20    pub finished_with_empty_output: bool,
21}
22
23impl Terminal {
24    pub fn new(
25        command: String,
26        working_dir: Option<PathBuf>,
27        terminal: Entity<terminal::Terminal>,
28        language_registry: Arc<LanguageRegistry>,
29        cx: &mut Context<Self>,
30    ) -> Self {
31        Self {
32            command: cx.new(|cx| {
33                Markdown::new(
34                    format!("```\n{}\n```", command).into(),
35                    Some(language_registry.clone()),
36                    None,
37                    cx,
38                )
39            }),
40            working_dir,
41            terminal,
42            started_at: Instant::now(),
43            output: None,
44        }
45    }
46
47    pub fn finish(
48        &mut self,
49        exit_status: Option<ExitStatus>,
50        original_content_len: usize,
51        truncated_content_len: usize,
52        content_line_count: usize,
53        finished_with_empty_output: bool,
54        cx: &mut Context<Self>,
55    ) {
56        self.output = Some(TerminalOutput {
57            ended_at: Instant::now(),
58            exit_status,
59            was_content_truncated: truncated_content_len < original_content_len,
60            original_content_len,
61            content_line_count,
62            finished_with_empty_output,
63        });
64        cx.notify();
65    }
66
67    pub fn command(&self) -> &Entity<Markdown> {
68        &self.command
69    }
70
71    pub fn working_dir(&self) -> &Option<PathBuf> {
72        &self.working_dir
73    }
74
75    pub fn started_at(&self) -> Instant {
76        self.started_at
77    }
78
79    pub fn output(&self) -> Option<&TerminalOutput> {
80        self.output.as_ref()
81    }
82
83    pub fn inner(&self) -> &Entity<terminal::Terminal> {
84        &self.terminal
85    }
86
87    pub fn to_markdown(&self, cx: &App) -> String {
88        format!(
89            "Terminal:\n```\n{}\n```\n",
90            self.terminal.read(cx).get_content()
91        )
92    }
93}