Use both language and LSP icons for LSP tasks (#31773)
Make more explicit which language LSP tasks are used. Before:  After:   Release Notes: - N/A
This commit is contained in:
parent
a539a38f13
commit
f881cacd8a
4 changed files with 65 additions and 20 deletions
|
@ -27,9 +27,9 @@ use theme::ThemeSettings;
|
||||||
use ui::{
|
use ui::{
|
||||||
ActiveTheme, Button, ButtonCommon, ButtonSize, CheckboxWithLabel, Clickable, Color, Context,
|
ActiveTheme, Button, ButtonCommon, ButtonSize, CheckboxWithLabel, Clickable, Color, Context,
|
||||||
ContextMenu, Disableable, DropdownMenu, FluentBuilder, Icon, IconButton, IconName, IconSize,
|
ContextMenu, Disableable, DropdownMenu, FluentBuilder, Icon, IconButton, IconName, IconSize,
|
||||||
InteractiveElement, IntoElement, Label, LabelCommon as _, ListItem, ListItemSpacing,
|
IconWithIndicator, Indicator, InteractiveElement, IntoElement, Label, LabelCommon as _,
|
||||||
ParentElement, RenderOnce, SharedString, Styled, StyledExt, ToggleButton, ToggleState,
|
ListItem, ListItemSpacing, ParentElement, RenderOnce, SharedString, Styled, StyledExt,
|
||||||
Toggleable, Window, div, h_flex, relative, rems, v_flex,
|
ToggleButton, ToggleState, Toggleable, Window, div, h_flex, relative, rems, v_flex,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::{ModalView, Workspace, pane};
|
use workspace::{ModalView, Workspace, pane};
|
||||||
|
@ -1222,21 +1222,32 @@ impl PickerDelegate for DebugScenarioDelegate {
|
||||||
let task_kind = &self.candidates[hit.candidate_id].0;
|
let task_kind = &self.candidates[hit.candidate_id].0;
|
||||||
|
|
||||||
let icon = match task_kind {
|
let icon = match task_kind {
|
||||||
Some(TaskSourceKind::Lsp(..)) => Some(Icon::new(IconName::BoltFilled)),
|
|
||||||
Some(TaskSourceKind::UserInput) => Some(Icon::new(IconName::Terminal)),
|
Some(TaskSourceKind::UserInput) => Some(Icon::new(IconName::Terminal)),
|
||||||
Some(TaskSourceKind::AbsPath { .. }) => Some(Icon::new(IconName::Settings)),
|
Some(TaskSourceKind::AbsPath { .. }) => Some(Icon::new(IconName::Settings)),
|
||||||
Some(TaskSourceKind::Worktree { .. }) => Some(Icon::new(IconName::FileTree)),
|
Some(TaskSourceKind::Worktree { .. }) => Some(Icon::new(IconName::FileTree)),
|
||||||
Some(TaskSourceKind::Language { name }) => file_icons::FileIcons::get(cx)
|
Some(TaskSourceKind::Lsp {
|
||||||
|
language_name: name,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
| Some(TaskSourceKind::Language { name }) => file_icons::FileIcons::get(cx)
|
||||||
.get_icon_for_type(&name.to_lowercase(), cx)
|
.get_icon_for_type(&name.to_lowercase(), cx)
|
||||||
.map(Icon::from_path),
|
.map(Icon::from_path),
|
||||||
None => Some(Icon::new(IconName::HistoryRerun)),
|
None => Some(Icon::new(IconName::HistoryRerun)),
|
||||||
}
|
}
|
||||||
.map(|icon| icon.color(Color::Muted).size(ui::IconSize::Small));
|
.map(|icon| icon.color(Color::Muted).size(IconSize::Small));
|
||||||
|
let indicator = if matches!(task_kind, Some(TaskSourceKind::Lsp { .. })) {
|
||||||
|
Some(Indicator::icon(
|
||||||
|
Icon::new(IconName::BoltFilled).color(Color::Muted),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let icon = icon.map(|icon| IconWithIndicator::new(icon, indicator));
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
ListItem::new(SharedString::from(format!("debug-scenario-selection-{ix}")))
|
ListItem::new(SharedString::from(format!("debug-scenario-selection-{ix}")))
|
||||||
.inset(true)
|
.inset(true)
|
||||||
.start_slot::<Icon>(icon)
|
.start_slot::<IconWithIndicator>(icon)
|
||||||
.spacing(ListItemSpacing::Sparse)
|
.spacing(ListItemSpacing::Sparse)
|
||||||
.toggle_state(selected)
|
.toggle_state(selected)
|
||||||
.child(highlighted_location.render(window, cx)),
|
.child(highlighted_location.render(window, cx)),
|
||||||
|
|
|
@ -22,6 +22,7 @@ use smol::stream::StreamExt;
|
||||||
use task::ResolvedTask;
|
use task::ResolvedTask;
|
||||||
use task::TaskContext;
|
use task::TaskContext;
|
||||||
use text::BufferId;
|
use text::BufferId;
|
||||||
|
use ui::SharedString;
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
|
|
||||||
pub(crate) fn find_specific_language_server_in_selection<F>(
|
pub(crate) fn find_specific_language_server_in_selection<F>(
|
||||||
|
@ -133,13 +134,22 @@ pub fn lsp_tasks(
|
||||||
|
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
let mut lsp_tasks = Vec::new();
|
let mut lsp_tasks = HashMap::default();
|
||||||
while let Some(server_to_query) = lsp_task_sources.next().await {
|
while let Some(server_to_query) = lsp_task_sources.next().await {
|
||||||
if let Some((server_id, buffers)) = server_to_query {
|
if let Some((server_id, buffers)) = server_to_query {
|
||||||
let source_kind = TaskSourceKind::Lsp(server_id);
|
|
||||||
let id_base = source_kind.to_id_base();
|
|
||||||
let mut new_lsp_tasks = Vec::new();
|
let mut new_lsp_tasks = Vec::new();
|
||||||
for buffer in buffers {
|
for buffer in buffers {
|
||||||
|
let source_kind = match buffer.update(cx, |buffer, _| {
|
||||||
|
buffer.language().map(|language| language.name())
|
||||||
|
}) {
|
||||||
|
Ok(Some(language_name)) => TaskSourceKind::Lsp {
|
||||||
|
server: server_id,
|
||||||
|
language_name: SharedString::from(language_name),
|
||||||
|
},
|
||||||
|
Ok(None) => continue,
|
||||||
|
Err(_) => return Vec::new(),
|
||||||
|
};
|
||||||
|
let id_base = source_kind.to_id_base();
|
||||||
let lsp_buffer_context = lsp_task_context(&project, &buffer, cx)
|
let lsp_buffer_context = lsp_task_context(&project, &buffer, cx)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
@ -168,11 +178,14 @@ pub fn lsp_tasks(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lsp_tasks
|
||||||
|
.entry(source_kind)
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.append(&mut new_lsp_tasks);
|
||||||
}
|
}
|
||||||
lsp_tasks.push((source_kind, new_lsp_tasks));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lsp_tasks
|
lsp_tasks.into_iter().collect()
|
||||||
})
|
})
|
||||||
.race({
|
.race({
|
||||||
// `lsp::LSP_REQUEST_TIMEOUT` is larger than we want for the modal to open fast
|
// `lsp::LSP_REQUEST_TIMEOUT` is larger than we want for the modal to open fast
|
||||||
|
|
|
@ -132,7 +132,10 @@ pub enum TaskSourceKind {
|
||||||
/// Languages-specific tasks coming from extensions.
|
/// Languages-specific tasks coming from extensions.
|
||||||
Language { name: SharedString },
|
Language { name: SharedString },
|
||||||
/// Language-specific tasks coming from LSP servers.
|
/// Language-specific tasks coming from LSP servers.
|
||||||
Lsp(LanguageServerId),
|
Lsp {
|
||||||
|
language_name: SharedString,
|
||||||
|
server: LanguageServerId,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of task contexts, derived from the current state of the workspace.
|
/// A collection of task contexts, derived from the current state of the workspace.
|
||||||
|
@ -211,7 +214,10 @@ impl TaskSourceKind {
|
||||||
format!("{id_base}_{id}_{}", directory_in_worktree.display())
|
format!("{id_base}_{id}_{}", directory_in_worktree.display())
|
||||||
}
|
}
|
||||||
Self::Language { name } => format!("language_{name}"),
|
Self::Language { name } => format!("language_{name}"),
|
||||||
Self::Lsp(server_id) => format!("lsp_{server_id}"),
|
Self::Lsp {
|
||||||
|
server,
|
||||||
|
language_name,
|
||||||
|
} => format!("lsp_{language_name}_{server}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,7 +718,7 @@ fn task_lru_comparator(
|
||||||
|
|
||||||
fn task_source_kind_preference(kind: &TaskSourceKind) -> u32 {
|
fn task_source_kind_preference(kind: &TaskSourceKind) -> u32 {
|
||||||
match kind {
|
match kind {
|
||||||
TaskSourceKind::Lsp(..) => 0,
|
TaskSourceKind::Lsp { .. } => 0,
|
||||||
TaskSourceKind::Language { .. } => 1,
|
TaskSourceKind::Language { .. } => 1,
|
||||||
TaskSourceKind::UserInput => 2,
|
TaskSourceKind::UserInput => 2,
|
||||||
TaskSourceKind::Worktree { .. } => 3,
|
TaskSourceKind::Worktree { .. } => 3,
|
||||||
|
|
|
@ -14,8 +14,9 @@ use project::{TaskSourceKind, task_store::TaskStore};
|
||||||
use task::{DebugScenario, ResolvedTask, RevealTarget, TaskContext, TaskTemplate};
|
use task::{DebugScenario, ResolvedTask, RevealTarget, TaskContext, TaskTemplate};
|
||||||
use ui::{
|
use ui::{
|
||||||
ActiveTheme, Button, ButtonCommon, ButtonSize, Clickable, Color, FluentBuilder as _, Icon,
|
ActiveTheme, Button, ButtonCommon, ButtonSize, Clickable, Color, FluentBuilder as _, Icon,
|
||||||
IconButton, IconButtonShape, IconName, IconSize, IntoElement, KeyBinding, Label, LabelSize,
|
IconButton, IconButtonShape, IconName, IconSize, IconWithIndicator, Indicator, IntoElement,
|
||||||
ListItem, ListItemSpacing, RenderOnce, Toggleable, Tooltip, div, h_flex, v_flex,
|
KeyBinding, Label, LabelSize, ListItem, ListItemSpacing, RenderOnce, Toggleable, Tooltip, div,
|
||||||
|
h_flex, v_flex,
|
||||||
};
|
};
|
||||||
|
|
||||||
use util::{ResultExt, truncate_and_trailoff};
|
use util::{ResultExt, truncate_and_trailoff};
|
||||||
|
@ -448,15 +449,29 @@ impl PickerDelegate for TasksModalDelegate {
|
||||||
color: Color::Default,
|
color: Color::Default,
|
||||||
};
|
};
|
||||||
let icon = match source_kind {
|
let icon = match source_kind {
|
||||||
TaskSourceKind::Lsp(..) => Some(Icon::new(IconName::BoltFilled)),
|
|
||||||
TaskSourceKind::UserInput => Some(Icon::new(IconName::Terminal)),
|
TaskSourceKind::UserInput => Some(Icon::new(IconName::Terminal)),
|
||||||
TaskSourceKind::AbsPath { .. } => Some(Icon::new(IconName::Settings)),
|
TaskSourceKind::AbsPath { .. } => Some(Icon::new(IconName::Settings)),
|
||||||
TaskSourceKind::Worktree { .. } => Some(Icon::new(IconName::FileTree)),
|
TaskSourceKind::Worktree { .. } => Some(Icon::new(IconName::FileTree)),
|
||||||
TaskSourceKind::Language { name } => file_icons::FileIcons::get(cx)
|
TaskSourceKind::Lsp {
|
||||||
|
language_name: name,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| TaskSourceKind::Language { name } => file_icons::FileIcons::get(cx)
|
||||||
.get_icon_for_type(&name.to_lowercase(), cx)
|
.get_icon_for_type(&name.to_lowercase(), cx)
|
||||||
.map(Icon::from_path),
|
.map(Icon::from_path),
|
||||||
}
|
}
|
||||||
.map(|icon| icon.color(Color::Muted).size(IconSize::Small));
|
.map(|icon| icon.color(Color::Muted).size(IconSize::Small));
|
||||||
|
let indicator = if matches!(source_kind, TaskSourceKind::Lsp { .. }) {
|
||||||
|
Some(Indicator::icon(
|
||||||
|
Icon::new(IconName::Bolt).size(IconSize::Small),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let icon = icon.map(|icon| {
|
||||||
|
IconWithIndicator::new(icon, indicator)
|
||||||
|
.indicator_border_color(Some(cx.theme().colors().border_transparent))
|
||||||
|
});
|
||||||
let history_run_icon = if Some(ix) <= self.divider_index {
|
let history_run_icon = if Some(ix) <= self.divider_index {
|
||||||
Some(
|
Some(
|
||||||
Icon::new(IconName::HistoryRerun)
|
Icon::new(IconName::HistoryRerun)
|
||||||
|
@ -476,7 +491,7 @@ impl PickerDelegate for TasksModalDelegate {
|
||||||
Some(
|
Some(
|
||||||
ListItem::new(SharedString::from(format!("tasks-modal-{ix}")))
|
ListItem::new(SharedString::from(format!("tasks-modal-{ix}")))
|
||||||
.inset(true)
|
.inset(true)
|
||||||
.start_slot::<Icon>(icon)
|
.start_slot::<IconWithIndicator>(icon)
|
||||||
.end_slot::<AnyElement>(
|
.end_slot::<AnyElement>(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue