Use different icons for terminal tasks (#9876)
This commit is contained in:
parent
687d2a41d6
commit
ce37885f49
5 changed files with 60 additions and 27 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -87,9 +87,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alacritty_terminal"
|
name = "alacritty_terminal"
|
||||||
version = "0.23.0-rc1"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc2c16faa5425a10be102dda76f73d76049b44746e18ddeefc44d78bbe76cbce"
|
checksum = "f6d1ea4484c8676f295307a4892d478c70ac8da1dbd8c7c10830a504b7f1022f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.0",
|
"base64 0.22.0",
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
|
|
|
@ -6,7 +6,7 @@ use smol::channel::bounded;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use terminal::{
|
use terminal::{
|
||||||
terminal_settings::{self, Shell, TerminalSettings, VenvSettingsContent},
|
terminal_settings::{self, Shell, TerminalSettings, VenvSettingsContent},
|
||||||
SpawnTask, TaskState, Terminal, TerminalBuilder,
|
SpawnTask, TaskState, TaskStatus, Terminal, TerminalBuilder,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ impl Project {
|
||||||
Some(TaskState {
|
Some(TaskState {
|
||||||
id: spawn_task.id,
|
id: spawn_task.id,
|
||||||
label: spawn_task.label,
|
label: spawn_task.label,
|
||||||
completed: false,
|
status: TaskStatus::Running,
|
||||||
completion_rx,
|
completion_rx,
|
||||||
}),
|
}),
|
||||||
Shell::WithArguments {
|
Shell::WithArguments {
|
||||||
|
|
|
@ -14,8 +14,7 @@ doctest = false
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# TODO: when new version of this crate is released, change it
|
alacritty_terminal = "0.23"
|
||||||
alacritty_terminal = "0.23.0-rc1"
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
|
|
|
@ -595,10 +595,36 @@ pub struct Terminal {
|
||||||
pub struct TaskState {
|
pub struct TaskState {
|
||||||
pub id: TaskId,
|
pub id: TaskId,
|
||||||
pub label: String,
|
pub label: String,
|
||||||
pub completed: bool,
|
pub status: TaskStatus,
|
||||||
pub completion_rx: Receiver<()>,
|
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 {
|
impl Terminal {
|
||||||
fn process_event(&mut self, event: &AlacTermEvent, cx: &mut ModelContext<Self>) {
|
fn process_event(&mut self, event: &AlacTermEvent, cx: &mut ModelContext<Self>) {
|
||||||
match event {
|
match event {
|
||||||
|
@ -630,7 +656,7 @@ impl Terminal {
|
||||||
}
|
}
|
||||||
AlacTermEvent::Exit => match &mut self.task {
|
AlacTermEvent::Exit => match &mut self.task {
|
||||||
Some(task) => {
|
Some(task) => {
|
||||||
task.completed = true;
|
task.status.register_terminal_exit();
|
||||||
self.completion_tx.try_send(()).ok();
|
self.completion_tx.try_send(()).ok();
|
||||||
}
|
}
|
||||||
None => cx.emit(Event::CloseTerminal),
|
None => cx.emit(Event::CloseTerminal),
|
||||||
|
@ -649,8 +675,11 @@ impl Terminal {
|
||||||
self.events
|
self.events
|
||||||
.push_back(InternalEvent::ColorRequest(*idx, fun_ptr.clone()));
|
.push_back(InternalEvent::ColorRequest(*idx, fun_ptr.clone()));
|
||||||
}
|
}
|
||||||
AlacTermEvent::ChildExit(_) => {
|
AlacTermEvent::ChildExit(error_code) => {
|
||||||
// TODO: Handle child exit
|
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<()> {
|
pub fn wait_for_completed_task(&self, cx: &mut AppContext) -> Task<()> {
|
||||||
match self.task() {
|
if let Some(task) = self.task() {
|
||||||
Some(task) => {
|
if task.status == TaskStatus::Running {
|
||||||
if task.completed {
|
|
||||||
Task::ready(())
|
|
||||||
} else {
|
|
||||||
let mut completion_receiver = task.completion_rx.clone();
|
let mut completion_receiver = task.completion_rx.clone();
|
||||||
cx.spawn(|_| async move {
|
return cx.spawn(|_| async move {
|
||||||
completion_receiver.next().await;
|
completion_receiver.next().await;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Task::ready(()),
|
Task::ready(())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ use terminal::{
|
||||||
term::{search::RegexSearch, TermMode},
|
term::{search::RegexSearch, TermMode},
|
||||||
},
|
},
|
||||||
terminal_settings::{TerminalBlink, TerminalSettings, WorkingDirectory},
|
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 terminal_element::TerminalElement;
|
||||||
use ui::{h_flex, prelude::*, ContextMenu, Icon, IconName, Label};
|
use ui::{h_flex, prelude::*, ContextMenu, Icon, IconName, Label};
|
||||||
|
@ -788,10 +788,19 @@ impl Item for TerminalView {
|
||||||
) -> AnyElement {
|
) -> AnyElement {
|
||||||
let terminal = self.terminal().read(cx);
|
let terminal = self.terminal().read(cx);
|
||||||
let title = terminal.title(true);
|
let title = terminal.title(true);
|
||||||
let icon = if terminal.task().is_some() {
|
let icon = match terminal.task() {
|
||||||
IconName::Play
|
Some(terminal_task) => match &terminal_task.status {
|
||||||
|
TaskStatus::Unknown => IconName::ExclamationTriangle,
|
||||||
|
TaskStatus::Running => IconName::Play,
|
||||||
|
TaskStatus::Completed { success } => {
|
||||||
|
if *success {
|
||||||
|
IconName::Check
|
||||||
} else {
|
} else {
|
||||||
IconName::Terminal
|
IconName::XCircle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => IconName::Terminal,
|
||||||
};
|
};
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
|
@ -829,7 +838,7 @@ impl Item for TerminalView {
|
||||||
|
|
||||||
fn is_dirty(&self, cx: &gpui::AppContext) -> bool {
|
fn is_dirty(&self, cx: &gpui::AppContext) -> bool {
|
||||||
match self.terminal.read(cx).task() {
|
match self.terminal.read(cx).task() {
|
||||||
Some(task) => !task.completed,
|
Some(task) => task.status == TaskStatus::Running,
|
||||||
None => self.has_bell(),
|
None => self.has_bell(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue