Detailed changes
@@ -87,9 +87,9 @@ dependencies = [
[[package]]
name = "alacritty_terminal"
-version = "0.23.0-rc1"
+version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc2c16faa5425a10be102dda76f73d76049b44746e18ddeefc44d78bbe76cbce"
+checksum = "f6d1ea4484c8676f295307a4892d478c70ac8da1dbd8c7c10830a504b7f1022f"
dependencies = [
"base64 0.22.0",
"bitflags 2.4.2",
@@ -6,7 +6,7 @@ use smol::channel::bounded;
use std::path::{Path, PathBuf};
use terminal::{
terminal_settings::{self, Shell, TerminalSettings, VenvSettingsContent},
- SpawnTask, TaskState, Terminal, TerminalBuilder,
+ SpawnTask, TaskState, TaskStatus, Terminal, TerminalBuilder,
};
use util::ResultExt;
@@ -53,7 +53,7 @@ impl Project {
Some(TaskState {
id: spawn_task.id,
label: spawn_task.label,
- completed: false,
+ status: TaskStatus::Running,
completion_rx,
}),
Shell::WithArguments {
@@ -14,8 +14,7 @@ doctest = false
[dependencies]
-# TODO: when new version of this crate is released, change it
-alacritty_terminal = "0.23.0-rc1"
+alacritty_terminal = "0.23"
anyhow.workspace = true
collections.workspace = true
dirs = "4.0.0"
@@ -595,10 +595,36 @@ pub struct Terminal {
pub struct TaskState {
pub id: TaskId,
pub label: String,
- pub completed: bool,
+ pub status: TaskStatus,
pub completion_rx: Receiver<()>,
}
+/// A status of the current terminal tab's task.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum TaskStatus {
+ /// The task had been started, but got cancelled or somehow otherwise it did not
+ /// report its exit code before the terminal event loop was shut down.
+ Unknown,
+ /// The task is started and running currently.
+ Running,
+ /// After the start, the task stopped running and reported its error code back.
+ Completed { success: bool },
+}
+
+impl TaskStatus {
+ fn register_terminal_exit(&mut self) {
+ if self == &Self::Running {
+ *self = Self::Unknown;
+ }
+ }
+
+ fn register_task_exit(&mut self, error_code: i32) {
+ *self = TaskStatus::Completed {
+ success: error_code == 0,
+ };
+ }
+}
+
impl Terminal {
fn process_event(&mut self, event: &AlacTermEvent, cx: &mut ModelContext<Self>) {
match event {
@@ -630,7 +656,7 @@ impl Terminal {
}
AlacTermEvent::Exit => match &mut self.task {
Some(task) => {
- task.completed = true;
+ task.status.register_terminal_exit();
self.completion_tx.try_send(()).ok();
}
None => cx.emit(Event::CloseTerminal),
@@ -649,8 +675,11 @@ impl Terminal {
self.events
.push_back(InternalEvent::ColorRequest(*idx, fun_ptr.clone()));
}
- AlacTermEvent::ChildExit(_) => {
- // TODO: Handle child exit
+ AlacTermEvent::ChildExit(error_code) => {
+ if let Some(task) = &mut self.task {
+ task.status.register_task_exit(*error_code);
+ self.completion_tx.try_send(()).ok();
+ }
}
}
}
@@ -1381,19 +1410,15 @@ impl Terminal {
}
pub fn wait_for_completed_task(&self, cx: &mut AppContext) -> Task<()> {
- match self.task() {
- Some(task) => {
- if task.completed {
- Task::ready(())
- } else {
- let mut completion_receiver = task.completion_rx.clone();
- cx.spawn(|_| async move {
- completion_receiver.next().await;
- })
- }
+ if let Some(task) = self.task() {
+ if task.status == TaskStatus::Running {
+ let mut completion_receiver = task.completion_rx.clone();
+ return cx.spawn(|_| async move {
+ completion_receiver.next().await;
+ });
}
- None => Task::ready(()),
}
+ Task::ready(())
}
}
@@ -20,7 +20,7 @@ use terminal::{
term::{search::RegexSearch, TermMode},
},
terminal_settings::{TerminalBlink, TerminalSettings, WorkingDirectory},
- Clear, Copy, Event, MaybeNavigationTarget, Paste, ShowCharacterPalette, Terminal,
+ Clear, Copy, Event, MaybeNavigationTarget, Paste, ShowCharacterPalette, TaskStatus, Terminal,
};
use terminal_element::TerminalElement;
use ui::{h_flex, prelude::*, ContextMenu, Icon, IconName, Label};
@@ -788,10 +788,19 @@ impl Item for TerminalView {
) -> AnyElement {
let terminal = self.terminal().read(cx);
let title = terminal.title(true);
- let icon = if terminal.task().is_some() {
- IconName::Play
- } else {
- IconName::Terminal
+ let icon = match terminal.task() {
+ Some(terminal_task) => match &terminal_task.status {
+ TaskStatus::Unknown => IconName::ExclamationTriangle,
+ TaskStatus::Running => IconName::Play,
+ TaskStatus::Completed { success } => {
+ if *success {
+ IconName::Check
+ } else {
+ IconName::XCircle
+ }
+ }
+ },
+ None => IconName::Terminal,
};
h_flex()
.gap_2()
@@ -829,7 +838,7 @@ impl Item for TerminalView {
fn is_dirty(&self, cx: &gpui::AppContext) -> bool {
match self.terminal.read(cx).task() {
- Some(task) => !task.completed,
+ Some(task) => task.status == TaskStatus::Running,
None => self.has_bell(),
}
}