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
33 .new(|cx| Markdown::new(command.into(), Some(language_registry.clone()), None, cx)),
34 working_dir,
35 terminal,
36 started_at: Instant::now(),
37 output: None,
38 }
39 }
40
41 pub fn finish(
42 &mut self,
43 exit_status: Option<ExitStatus>,
44 original_content_len: usize,
45 truncated_content_len: usize,
46 content_line_count: usize,
47 finished_with_empty_output: bool,
48 cx: &mut Context<Self>,
49 ) {
50 self.output = Some(TerminalOutput {
51 ended_at: Instant::now(),
52 exit_status,
53 was_content_truncated: truncated_content_len < original_content_len,
54 original_content_len,
55 content_line_count,
56 finished_with_empty_output,
57 });
58 cx.notify();
59 }
60
61 pub fn command(&self) -> &Entity<Markdown> {
62 &self.command
63 }
64
65 pub fn working_dir(&self) -> &Option<PathBuf> {
66 &self.working_dir
67 }
68
69 pub fn started_at(&self) -> Instant {
70 self.started_at
71 }
72
73 pub fn output(&self) -> Option<&TerminalOutput> {
74 self.output.as_ref()
75 }
76
77 pub fn inner(&self) -> &Entity<terminal::Terminal> {
78 &self.terminal
79 }
80
81 pub fn to_markdown(&self, cx: &App) -> String {
82 format!(
83 "Terminal:\n```\n{}\n```\n",
84 self.terminal.read(cx).get_content()
85 )
86 }
87}