Improve workflow step view (#16329)

* Improve the tab title: give it an icon, and indicate the step index.
* Display the line number ranges that the symbols resolve to.
* Don't open duplicate tabs for the same step

Release Notes:

- N/A
This commit is contained in:
Max Brunsfeld 2024-08-15 17:45:23 -07:00 committed by GitHub
parent 364a58a262
commit 09b6e3f2a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 63 additions and 25 deletions

View file

@ -2407,7 +2407,7 @@ impl ContextEditor {
let Some(step) = self let Some(step) = self
.context .context
.read(cx) .read(cx)
.workflow_step_for_range(step_range.clone()) .workflow_step_for_range(step_range.clone(), cx)
else { else {
return; return;
}; };
@ -2630,13 +2630,22 @@ impl ContextEditor {
.ok()??; .ok()??;
let context = self.context.read(cx); let context = self.context.read(cx);
let language_registry = context.language_registry(); let language_registry = context.language_registry();
let step = context.workflow_step_for_range(step_range)?; let step = context.workflow_step_for_range(step_range, cx)?;
let view = cx.new_view(|cx| { let context = self.context.clone();
WorkflowStepView::new(self.context.clone(), step, language_registry, cx)
});
cx.deref_mut().defer(move |cx| { cx.deref_mut().defer(move |cx| {
pane.update(cx, |pane, cx| { pane.update(cx, |pane, cx| {
let existing_item = pane
.items_of_type::<WorkflowStepView>()
.find(|item| *item.read(cx).step() == step.downgrade());
if let Some(item) = existing_item {
if let Some(index) = pane.index_for_item(&item) {
pane.activate_item(index, true, true, cx);
}
} else {
let view = cx
.new_view(|cx| WorkflowStepView::new(context, step, language_registry, cx));
pane.add_item(Box::new(view), true, true, None, cx); pane.add_item(Box::new(view), true, true, None, cx);
}
}); });
}); });
None None

View file

@ -872,14 +872,20 @@ impl Context {
pub fn workflow_step_for_range( pub fn workflow_step_for_range(
&self, &self,
range: Range<language::Anchor>, range: Range<language::Anchor>,
cx: &AppContext,
) -> Option<Model<WorkflowStep>> { ) -> Option<Model<WorkflowStep>> {
Some( let buffer = self.buffer.read(cx);
let index = self.workflow_step_index_for_range(&range, buffer).ok()?;
Some(self.workflow_steps[index].step.clone())
}
pub fn workflow_step_index_for_range(
&self,
tagged_range: &Range<text::Anchor>,
buffer: &text::BufferSnapshot,
) -> Result<usize, usize> {
self.workflow_steps self.workflow_steps
.iter() .binary_search_by(|probe| probe.range.cmp(&tagged_range, buffer))
.find(|step| step.range == range)?
.step
.clone(),
)
} }
pub fn pending_slash_commands(&self) -> &[PendingSlashCommand] { pub fn pending_slash_commands(&self) -> &[PendingSlashCommand] {
@ -1126,9 +1132,8 @@ impl Context {
..buffer.anchor_before(step_end_tag_start_ix); ..buffer.anchor_before(step_end_tag_start_ix);
// Check if a step with the same range already exists // Check if a step with the same range already exists
let existing_step_index = self let existing_step_index =
.workflow_steps self.workflow_step_index_for_range(&tagged_range, &buffer);
.binary_search_by(|probe| probe.range.cmp(&tagged_range, &buffer));
if let Err(ix) = existing_step_index { if let Err(ix) = existing_step_index {
new_edit_steps.push(( new_edit_steps.push((

View file

@ -11,10 +11,11 @@ use gpui::{
}; };
use language::{language_settings::SoftWrap, Anchor, Buffer, LanguageRegistry}; use language::{language_settings::SoftWrap, Anchor, Buffer, LanguageRegistry};
use std::{ops::DerefMut, sync::Arc}; use std::{ops::DerefMut, sync::Arc};
use text::OffsetRangeExt;
use theme::ActiveTheme as _; use theme::ActiveTheme as _;
use ui::{ use ui::{
h_flex, v_flex, ButtonCommon as _, ButtonLike, ButtonStyle, Color, InteractiveElement as _, h_flex, v_flex, ButtonCommon as _, ButtonLike, ButtonStyle, Color, Icon, IconName,
Label, LabelCommon as _, InteractiveElement as _, Label, LabelCommon as _,
}; };
use workspace::{ use workspace::{
item::{self, Item}, item::{self, Item},
@ -145,6 +146,10 @@ impl WorkflowStepView {
} }
} }
pub fn step(&self) -> &WeakModel<WorkflowStep> {
&self.step
}
fn render_result(&mut self, cx: &mut ViewContext<Self>) -> Option<AnyElement> { fn render_result(&mut self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
let step = self.step.upgrade()?; let step = self.step.upgrade()?;
let result = step.read(cx).resolution.as_ref()?; let result = step.read(cx).resolution.as_ref()?;
@ -155,14 +160,17 @@ impl WorkflowStepView {
.child(result.title.clone()) .child(result.title.clone())
.children(result.suggestion_groups.iter().filter_map( .children(result.suggestion_groups.iter().filter_map(
|(buffer, suggestion_groups)| { |(buffer, suggestion_groups)| {
let path = buffer.read(cx).file().map(|f| f.path()); let buffer = buffer.read(cx);
let path = buffer.file().map(|f| f.path());
let snapshot = buffer.snapshot();
v_flex() v_flex()
.mb_2() .mb_2()
.border_b_1() .border_b_1()
.children(path.map(|path| format!("path: {}", path.display()))) .children(path.map(|path| format!("path: {}", path.display())))
.children(suggestion_groups.iter().map(|group| { .children(suggestion_groups.iter().map(|group| {
v_flex().pl_2().children(group.suggestions.iter().map( v_flex().pt_2().pl_2().children(
|suggestion| { group.suggestions.iter().map(|suggestion| {
let range = suggestion.range().to_point(&snapshot);
v_flex() v_flex()
.children( .children(
suggestion.description().map(|desc| { suggestion.description().map(|desc| {
@ -173,8 +181,13 @@ impl WorkflowStepView {
.children(suggestion.symbol_path().map( .children(suggestion.symbol_path().map(
|path| format!("symbol path: {}", path.0), |path| format!("symbol path: {}", path.0),
)) ))
}, .child(format!(
"lines: {} - {}",
range.start.row + 1,
range.end.row + 1
)) ))
}),
)
})) }))
.into() .into()
}, },
@ -247,8 +260,19 @@ impl FocusableView for WorkflowStepView {
impl Item for WorkflowStepView { impl Item for WorkflowStepView {
type Event = EditorEvent; type Event = EditorEvent;
fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> { fn tab_content_text(&self, cx: &WindowContext) -> Option<SharedString> {
Some("workflow step".into()) let step = self.step.upgrade()?.read(cx);
let context = step.context.upgrade()?.read(cx);
let buffer = context.buffer().read(cx);
let index = context
.workflow_step_index_for_range(&step.context_buffer_range, buffer)
.ok()?
+ 1;
Some(format!("Step {index}").into())
}
fn tab_icon(&self, _cx: &WindowContext) -> Option<ui::Icon> {
Some(Icon::new(IconName::Pencil))
} }
fn to_item_events(event: &Self::Event, mut f: impl FnMut(item::ItemEvent)) { fn to_item_events(event: &Self::Event, mut f: impl FnMut(item::ItemEvent)) {