Rework hunk controls (#24814)

- Remove prev hunk arrow
- Replace next hunk arrow with "Skip" labelled button
- New "Stage"/"Unstage" labelled button

cc @iamnbutler 

Release Notes:

- N/A

---------

Co-authored-by: Nate <nate@zed.dev>
Co-authored-by: Nate Butler <iamnbutler@gmail.com>
This commit is contained in:
Cole Miller 2025-02-13 14:38:20 -05:00 committed by GitHub
parent 74e8164cd7
commit a6a8d79d86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 68 additions and 63 deletions

View file

@ -6975,10 +6975,10 @@ impl Editor {
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
let selections = self.selections.all(cx).into_iter().map(|s| s.range()); let selections = self.selections.all(cx).into_iter().map(|s| s.range());
self.revert_hunks_in_ranges(selections, window, cx); self.discard_hunks_in_ranges(selections, window, cx);
} }
fn revert_hunks_in_ranges( fn discard_hunks_in_ranges(
&mut self, &mut self,
ranges: impl Iterator<Item = Range<Point>>, ranges: impl Iterator<Item = Range<Point>>,
window: &mut Window, window: &mut Window,

View file

@ -18,10 +18,10 @@ use crate::{
BlockId, ChunkReplacement, CursorShape, CustomBlockId, DisplayPoint, DisplayRow, BlockId, ChunkReplacement, CursorShape, CustomBlockId, DisplayPoint, DisplayRow,
DocumentHighlightRead, DocumentHighlightWrite, EditDisplayMode, Editor, EditorMode, DocumentHighlightRead, DocumentHighlightWrite, EditDisplayMode, Editor, EditorMode,
EditorSettings, EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GoToHunk, EditorSettings, EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GoToHunk,
GoToPrevHunk, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, InlineCompletion,
InlineCompletion, JumpData, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, JumpData, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, RevertSelectedHunks, RowExt,
RevertSelectedHunks, RowExt, RowRangeExt, SelectPhase, Selection, SoftWrap, RowRangeExt, SelectPhase, Selection, SoftWrap, StickyHeaderExcerpt, ToPoint, ToggleFold,
StickyHeaderExcerpt, ToPoint, ToggleFold, CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT, ToggleStagedSelectedDiffHunks, CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT,
GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
}; };
use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus}; use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus};
@ -33,8 +33,8 @@ use gpui::{
anchored, deferred, div, fill, linear_color_stop, linear_gradient, outline, pattern_slash, anchored, deferred, div, fill, linear_color_stop, linear_gradient, outline, pattern_slash,
point, px, quad, relative, size, svg, transparent_black, Action, AnyElement, App, point, px, quad, relative, size, svg, transparent_black, Action, AnyElement, App,
AvailableSpace, Axis, Bounds, ClickEvent, ClipboardItem, ContentMask, Context, Corner, Corners, AvailableSpace, Axis, Bounds, ClickEvent, ClipboardItem, ContentMask, Context, Corner, Corners,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Focusable as _, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Focusable, FontId,
FontId, GlobalElementId, Hitbox, Hsla, InteractiveElement, IntoElement, Keystroke, Length, GlobalElementId, Hitbox, Hsla, InteractiveElement, IntoElement, Keystroke, Length,
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad,
ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size,
StatefulInteractiveElement, Style, Styled, Subscription, TextRun, TextStyleRefinement, StatefulInteractiveElement, Style, Styled, Subscription, TextRun, TextStyleRefinement,
@ -4166,13 +4166,16 @@ impl EditorElement {
let y = display_row_range.start.as_f32() * line_height let y = display_row_range.start.as_f32() * line_height
+ text_hitbox.bounds.top() + text_hitbox.bounds.top()
- scroll_pixel_position.y; - scroll_pixel_position.y;
let x = text_hitbox.bounds.right() - px(100.); let x = text_hitbox.bounds.right()
- rems(6.).to_pixels(window.rem_size())
- px(33.);
let mut element = diff_hunk_controls( let mut element = diff_hunk_controls(
display_row_range.start.0, display_row_range.start.0,
multi_buffer_range.clone(), multi_buffer_range.clone(),
line_height, line_height,
&editor, &editor,
window,
cx, cx,
); );
element.prepaint_as_root( element.prepaint_as_root(
@ -8916,8 +8919,13 @@ fn diff_hunk_controls(
hunk_range: Range<Anchor>, hunk_range: Range<Anchor>,
line_height: Pixels, line_height: Pixels,
editor: &Entity<Editor>, editor: &Entity<Editor>,
_window: &mut Window,
cx: &mut App, cx: &mut App,
) -> AnyElement { ) -> AnyElement {
let stage = editor.update(cx, |editor, cx| {
let snapshot = editor.buffer.read(cx).snapshot(cx);
editor.has_stageable_diff_hunks_in_ranges(&[hunk_range.start..hunk_range.start], &snapshot)
});
h_flex() h_flex()
.h(line_height) .h(line_height)
.mr_1() .mr_1()
@ -8930,59 +8938,7 @@ fn diff_hunk_controls(
.bg(cx.theme().colors().editor_background) .bg(cx.theme().colors().editor_background)
.gap_1() .gap_1()
.child( .child(
IconButton::new(("next-hunk", row as u64), IconName::ArrowDown) IconButton::new(("discard-hunk", row as u64), IconName::Undo)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
// .disabled(!has_multiple_hunks)
.tooltip({
let focus_handle = editor.focus_handle(cx);
move |window, cx| {
Tooltip::for_action_in("Next Hunk", &GoToHunk, &focus_handle, window, cx)
}
})
.on_click({
let editor = editor.clone();
move |_event, window, cx| {
editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(window, cx);
let position = hunk_range.end.to_point(&snapshot.buffer_snapshot);
editor.go_to_hunk_after_position(&snapshot, position, window, cx);
editor.expand_selected_diff_hunks(cx);
});
}
}),
)
.child(
IconButton::new(("prev-hunk", row as u64), IconName::ArrowUp)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
// .disabled(!has_multiple_hunks)
.tooltip({
let focus_handle = editor.focus_handle(cx);
move |window, cx| {
Tooltip::for_action_in(
"Previous Hunk",
&GoToPrevHunk,
&focus_handle,
window,
cx,
)
}
})
.on_click({
let editor = editor.clone();
move |_event, window, cx| {
editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(window, cx);
let point = hunk_range.start.to_point(&snapshot.buffer_snapshot);
editor.go_to_hunk_before_position(&snapshot, point, window, cx);
editor.expand_selected_diff_hunks(cx);
});
}
}),
)
.child(
IconButton::new("discard", IconName::Undo)
.shape(IconButtonShape::Square) .shape(IconButtonShape::Square)
.icon_size(IconSize::Small) .icon_size(IconSize::Small)
.tooltip({ .tooltip({
@ -9003,10 +8959,59 @@ fn diff_hunk_controls(
editor.update(cx, |editor, cx| { editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(window, cx); let snapshot = editor.snapshot(window, cx);
let point = hunk_range.start.to_point(&snapshot.buffer_snapshot); let point = hunk_range.start.to_point(&snapshot.buffer_snapshot);
editor.revert_hunks_in_ranges([point..point].into_iter(), window, cx); editor.discard_hunks_in_ranges([point..point].into_iter(), window, cx);
}); });
} }
}), }),
) )
.child(
Button::new(("skip-hunk", row as u64), "Skip")
.label_size(LabelSize::Small)
.tooltip({
let focus_handle = editor.focus_handle(cx);
move |window, cx| {
Tooltip::for_action_in("Skip Hunk", &GoToHunk, &focus_handle, window, cx)
}
})
.on_click({
let editor = editor.clone();
move |_event, window, cx| {
editor.update(cx, |editor, cx| {
let snapshot = editor.snapshot(window, cx);
let position = hunk_range.end.to_point(&snapshot.buffer_snapshot);
editor.go_to_hunk_after_position(&snapshot, position, window, cx);
editor.expand_selected_diff_hunks(cx);
});
}
}),
)
.child(
Button::new(
("stage-unstage-hunk", row as u64),
if stage { "Stage" } else { "Unstage" },
)
.label_size(LabelSize::Small)
.tooltip({
let focus_handle = editor.focus_handle(cx);
move |window, cx| {
Tooltip::for_action_in(
if stage { "Stage Hunk" } else { "Unstage Hunk" },
&ToggleStagedSelectedDiffHunks,
&focus_handle,
window,
cx,
)
}
})
.on_click({
let editor = editor.clone();
move |_event, _window, cx| {
editor.update(cx, |editor, cx| {
editor
.stage_or_unstage_diff_hunks(&[hunk_range.start..hunk_range.start], cx);
});
}
}),
)
.into_any_element() .into_any_element()
} }