mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-16 17:07:14 +03:00
task: Add re-run task button to terminal title (#12379)
Release Notes: - Added re-run task button to terminal title. Close #12277 ## Demo https://github.com/zed-industries/zed/assets/5518/4cd05fa5-4255-412b-8583-68e22f86561e --------- Co-authored-by: Piotr Osiewicz <piotr@zed.dev>
This commit is contained in:
parent
36d0b71f27
commit
3c6c850390
7
assets/icons/rerun.svg
Normal file
7
assets/icons/rerun.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3 12C3 9.61305 3.94821 7.32387 5.63604 5.63604C7.32387 3.94821 9.61305 3 12 3C14.516 3.00947 16.931 3.99122 18.74 5.74L21 8" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M21 3V8H16" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M21 12C21 14.3869 20.0518 16.6761 18.364 18.364C16.6761 20.0518 14.3869 21 12 21C9.48395 20.9905 7.06897 20.0088 5.26 18.26L3 16" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M8 16H3V21" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M10 9.37052C10 8.98462 10.4186 8.74419 10.7519 8.93863L15.2596 11.5681C15.5904 11.761 15.5904 12.2389 15.2596 12.4319L10.7519 15.0614C10.4186 15.2558 10 15.0154 10 14.6295V9.37052Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 949 B |
@ -348,10 +348,21 @@ impl Inventory {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the last scheduled task, if any of the sources contains one with the matching id.
|
/// Returns the last scheduled task by task_id if provided.
|
||||||
pub fn last_scheduled_task(&self) -> Option<(TaskSourceKind, ResolvedTask)> {
|
/// Otherwise, returns the last scheduled task.
|
||||||
|
pub fn last_scheduled_task(
|
||||||
|
&self,
|
||||||
|
task_id: Option<&TaskId>,
|
||||||
|
) -> Option<(TaskSourceKind, ResolvedTask)> {
|
||||||
|
if let Some(task_id) = task_id {
|
||||||
|
self.last_scheduled_tasks
|
||||||
|
.iter()
|
||||||
|
.find(|(_, task)| &task.id == task_id)
|
||||||
|
.cloned()
|
||||||
|
} else {
|
||||||
self.last_scheduled_tasks.back().cloned()
|
self.last_scheduled_tasks.back().cloned()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Registers task "usage" as being scheduled – to be used for LRU sorting when listing all tasks.
|
/// Registers task "usage" as being scheduled – to be used for LRU sorting when listing all tasks.
|
||||||
pub fn task_scheduled(
|
pub fn task_scheduled(
|
||||||
|
@ -7,7 +7,7 @@ mod vscode_format;
|
|||||||
|
|
||||||
use collections::{hash_map, HashMap, HashSet};
|
use collections::{hash_map, HashMap, HashSet};
|
||||||
use gpui::SharedString;
|
use gpui::SharedString;
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{borrow::Cow, path::Path};
|
use std::{borrow::Cow, path::Path};
|
||||||
@ -17,7 +17,7 @@ pub use vscode_format::VsCodeTaskFile;
|
|||||||
|
|
||||||
/// Task identifier, unique within the application.
|
/// Task identifier, unique within the application.
|
||||||
/// Based on it, task reruns and terminal tabs are managed.
|
/// Based on it, task reruns and terminal tabs are managed.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Deserialize)]
|
||||||
pub struct TaskId(pub String);
|
pub struct TaskId(pub String);
|
||||||
|
|
||||||
/// TerminalWorkDir describes where a task should be run
|
/// TerminalWorkDir describes where a task should be run
|
||||||
|
@ -9,7 +9,7 @@ use workspace::{tasks::schedule_resolved_task, Workspace};
|
|||||||
mod modal;
|
mod modal;
|
||||||
mod settings;
|
mod settings;
|
||||||
|
|
||||||
pub use modal::Spawn;
|
pub use modal::{Rerun, Spawn};
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
settings::TaskSettings::register(cx);
|
settings::TaskSettings::register(cx);
|
||||||
@ -20,7 +20,10 @@ pub fn init(cx: &mut AppContext) {
|
|||||||
.register_action(move |workspace, action: &modal::Rerun, cx| {
|
.register_action(move |workspace, action: &modal::Rerun, cx| {
|
||||||
if let Some((task_source_kind, mut last_scheduled_task)) =
|
if let Some((task_source_kind, mut last_scheduled_task)) =
|
||||||
workspace.project().update(cx, |project, cx| {
|
workspace.project().update(cx, |project, cx| {
|
||||||
project.task_inventory().read(cx).last_scheduled_task()
|
project
|
||||||
|
.task_inventory()
|
||||||
|
.read(cx)
|
||||||
|
.last_scheduled_task(action.task_id.as_ref())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
if action.reevaluate_context {
|
if action.reevaluate_context {
|
||||||
|
@ -9,7 +9,7 @@ use gpui::{
|
|||||||
};
|
};
|
||||||
use picker::{highlighted_match_with_paths::HighlightedText, Picker, PickerDelegate};
|
use picker::{highlighted_match_with_paths::HighlightedText, Picker, PickerDelegate};
|
||||||
use project::{Project, TaskSourceKind};
|
use project::{Project, TaskSourceKind};
|
||||||
use task::{ResolvedTask, TaskContext, TaskTemplate};
|
use task::{ResolvedTask, TaskContext, TaskId, TaskTemplate};
|
||||||
use ui::{
|
use ui::{
|
||||||
div, h_flex, v_flex, ActiveTheme, Button, ButtonCommon, ButtonSize, Clickable, Color,
|
div, h_flex, v_flex, ActiveTheme, Button, ButtonCommon, ButtonSize, Clickable, Color,
|
||||||
FluentBuilder as _, Icon, IconButton, IconButtonShape, IconName, IconSize, IntoElement,
|
FluentBuilder as _, Icon, IconButton, IconButtonShape, IconName, IconSize, IntoElement,
|
||||||
@ -54,6 +54,9 @@ pub struct Rerun {
|
|||||||
/// Default: null
|
/// Default: null
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub use_new_terminal: Option<bool>,
|
pub use_new_terminal: Option<bool>,
|
||||||
|
|
||||||
|
/// If present, rerun the task with this ID, otherwise rerun the last task.
|
||||||
|
pub task_id: Option<TaskId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_actions!(task, [Rerun, Spawn]);
|
impl_actions!(task, [Rerun, Spawn]);
|
||||||
|
@ -24,7 +24,7 @@ use terminal::{
|
|||||||
Clear, Copy, Event, MaybeNavigationTarget, Paste, ShowCharacterPalette, TaskStatus, 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, Tooltip};
|
||||||
use util::{paths::PathLikeWithPosition, ResultExt};
|
use util::{paths::PathLikeWithPosition, ResultExt};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::{BreadcrumbText, Item, ItemEvent, TabContentParams},
|
item::{BreadcrumbText, Item, ItemEvent, TabContentParams},
|
||||||
@ -787,23 +787,58 @@ impl Item for TerminalView {
|
|||||||
fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
|
fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> 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, icon_color) = match terminal.task() {
|
|
||||||
|
let (icon, icon_color, rerun_btn) = match terminal.task() {
|
||||||
Some(terminal_task) => match &terminal_task.status {
|
Some(terminal_task) => match &terminal_task.status {
|
||||||
TaskStatus::Unknown => (IconName::ExclamationTriangle, Color::Warning),
|
TaskStatus::Unknown => (IconName::ExclamationTriangle, Color::Warning, None),
|
||||||
TaskStatus::Running => (IconName::Play, Color::Default),
|
TaskStatus::Running => (IconName::Play, Color::Disabled, None),
|
||||||
TaskStatus::Completed { success } => {
|
TaskStatus::Completed { success } => {
|
||||||
|
let task_id = terminal_task.id.clone();
|
||||||
|
let rerun_btn = IconButton::new("rerun-icon", IconName::Rerun)
|
||||||
|
.icon_size(IconSize::Small)
|
||||||
|
.size(ButtonSize::Compact)
|
||||||
|
.icon_color(Color::Default)
|
||||||
|
.shape(ui::IconButtonShape::Square)
|
||||||
|
.tooltip(|cx| Tooltip::text("Rerun task", cx))
|
||||||
|
.on_click(move |_, cx| {
|
||||||
|
cx.dispatch_action(Box::new(tasks_ui::Rerun {
|
||||||
|
task_id: Some(task_id.clone()),
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
if *success {
|
if *success {
|
||||||
(IconName::Check, Color::Success)
|
(IconName::Check, Color::Success, Some(rerun_btn))
|
||||||
} else {
|
} else {
|
||||||
(IconName::XCircle, Color::Error)
|
(IconName::XCircle, Color::Error, Some(rerun_btn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => (IconName::Terminal, Color::Muted),
|
None => (IconName::Terminal, Color::Muted, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(Icon::new(icon).color(icon_color))
|
.group("term-tab-icon")
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.group("term-tab-icon")
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.when(rerun_btn.is_some(), |this| {
|
||||||
|
this.hover(|style| style.invisible().w_0())
|
||||||
|
})
|
||||||
|
.child(Icon::new(icon).color(icon_color)),
|
||||||
|
)
|
||||||
|
.when_some(rerun_btn, |this, rerun_btn| {
|
||||||
|
this.child(
|
||||||
|
div()
|
||||||
|
.absolute()
|
||||||
|
.visible_on_hover("term-tab-icon")
|
||||||
|
.child(rerun_btn),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
.child(Label::new(title).color(if params.selected {
|
.child(Label::new(title).color(if params.selected {
|
||||||
Color::Default
|
Color::Default
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,6 +163,7 @@ pub enum IconName {
|
|||||||
ReplaceAll,
|
ReplaceAll,
|
||||||
ReplaceNext,
|
ReplaceNext,
|
||||||
ReplyArrowRight,
|
ReplyArrowRight,
|
||||||
|
Rerun,
|
||||||
Return,
|
Return,
|
||||||
Reveal,
|
Reveal,
|
||||||
Save,
|
Save,
|
||||||
@ -284,6 +285,7 @@ impl IconName {
|
|||||||
IconName::ReplaceAll => "icons/replace_all.svg",
|
IconName::ReplaceAll => "icons/replace_all.svg",
|
||||||
IconName::ReplaceNext => "icons/replace_next.svg",
|
IconName::ReplaceNext => "icons/replace_next.svg",
|
||||||
IconName::ReplyArrowRight => "icons/reply_arrow_right.svg",
|
IconName::ReplyArrowRight => "icons/reply_arrow_right.svg",
|
||||||
|
IconName::Rerun => "icons/rerun.svg",
|
||||||
IconName::Return => "icons/return.svg",
|
IconName::Return => "icons/return.svg",
|
||||||
IconName::Save => "icons/save.svg",
|
IconName::Save => "icons/save.svg",
|
||||||
IconName::Screen => "icons/desktop.svg",
|
IconName::Screen => "icons/desktop.svg",
|
||||||
|
Loading…
Reference in New Issue
Block a user