Merge branch 'main' into instrument-keyboard-events

This commit is contained in:
Joseph T. Lyons
2024-01-10 16:03:01 -05:00
188 changed files with 3391 additions and 1997 deletions
-1
View File
@@ -1015,7 +1015,6 @@ pub mod tests {
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
.unwrap_or(10);
let _test_platform = &cx.test_platform;
let mut tab_size = rng.gen_range(1..=4);
let buffer_start_excerpt_header_height = rng.gen_range(1..=5);
let excerpt_header_height = rng.gen_range(1..=5);
+26 -12
View File
@@ -99,8 +99,8 @@ use sum_tree::TreeMap;
use text::{OffsetUtf16, Rope};
use theme::{ActiveTheme, PlayerColor, StatusColors, SyntaxTheme, ThemeColors, ThemeSettings};
use ui::{
h_stack, prelude::*, ButtonSize, ButtonStyle, Icon, IconButton, IconSize, ListItem, Popover,
Tooltip,
h_stack, prelude::*, ButtonSize, ButtonStyle, IconButton, IconName, IconSize, ListItem,
Popover, Tooltip,
};
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
use workspace::{searchable::SearchEvent, ItemNavHistory, Pane, SplitDirection, ViewId, Workspace};
@@ -507,7 +507,7 @@ pub enum SoftWrap {
Column(u32),
}
#[derive(Clone, Default)]
#[derive(Clone)]
pub struct EditorStyle {
pub background: Hsla,
pub local_player: PlayerColor,
@@ -519,6 +519,24 @@ pub struct EditorStyle {
pub suggestions_style: HighlightStyle,
}
impl Default for EditorStyle {
fn default() -> Self {
Self {
background: Hsla::default(),
local_player: PlayerColor::default(),
text: TextStyle::default(),
scrollbar_width: Pixels::default(),
syntax: Default::default(),
// HACK: Status colors don't have a real default.
// We should look into removing the status colors from the editor
// style and retrieve them directly from the theme.
status: StatusColors::dark(),
inlays_style: HighlightStyle::default(),
suggestions_style: HighlightStyle::default(),
}
}
}
type CompletionId = usize;
// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
@@ -1811,10 +1829,6 @@ impl Editor {
this.end_selection(cx);
this.scroll_manager.show_scrollbar(cx);
// todo!("use a different mechanism")
// let editor_created_event = EditorCreated(cx.handle());
// cx.emit_global(editor_created_event);
if mode == EditorMode::Full {
let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
@@ -4223,7 +4237,7 @@ impl Editor {
) -> Option<IconButton> {
if self.available_code_actions.is_some() {
Some(
IconButton::new("code_actions_indicator", ui::Icon::Bolt)
IconButton::new("code_actions_indicator", ui::IconName::Bolt)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.selected(is_active)
@@ -4257,7 +4271,7 @@ impl Editor {
fold_data
.map(|(fold_status, buffer_row, active)| {
(active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
IconButton::new(ix as usize, ui::Icon::ChevronDown)
IconButton::new(ix as usize, ui::IconName::ChevronDown)
.on_click(cx.listener(move |editor, _e, cx| match fold_status {
FoldStatus::Folded => {
editor.unfold_at(&UnfoldAt { buffer_row }, cx);
@@ -4269,7 +4283,7 @@ impl Editor {
.icon_color(ui::Color::Muted)
.icon_size(ui::IconSize::Small)
.selected(fold_status == FoldStatus::Folded)
.selected_icon(ui::Icon::ChevronRight)
.selected_icon(ui::IconName::ChevronRight)
.size(ui::ButtonSize::None)
})
})
@@ -7036,7 +7050,7 @@ impl Editor {
let buffer = self.buffer.read(cx).snapshot(cx);
let selection = self.selections.newest::<usize>(cx);
// If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
// If there is an active Diagnostic Popover jump to its diagnostic instead.
if direction == Direction::Next {
if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
let (group_id, jump_to) = popover.activation_info();
@@ -9743,7 +9757,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> Ren
),
)
.child(
IconButton::new(("copy-block", cx.block_id), Icon::Copy)
IconButton::new(("copy-block", cx.block_id), IconName::Copy)
.icon_color(Color::Muted)
.size(ButtonSize::Compact)
.style(ButtonStyle::Transparent)
-9
View File
@@ -539,7 +539,6 @@ fn test_clone(cx: &mut TestAppContext) {
);
}
//todo!(editor navigate)
#[gpui::test]
async fn test_navigation_history(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -993,7 +992,6 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) {
});
}
//todo!(finish editor tests)
#[gpui::test]
fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -1259,7 +1257,6 @@ fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
});
}
//todo!(finish editor tests)
#[gpui::test]
fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -1318,7 +1315,6 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) {
});
}
//todo!(simulate_resize)
#[gpui::test]
async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
@@ -2546,7 +2542,6 @@ fn test_delete_line(cx: &mut TestAppContext) {
});
}
//todo!(select_anchor_ranges)
#[gpui::test]
fn test_join_lines_with_single_selection(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -3114,7 +3109,6 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
});
}
//todo!(test_transpose)
#[gpui::test]
fn test_transpose(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -4860,7 +4854,6 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
});
}
// todo!(select_anchor_ranges)
#[gpui::test]
async fn test_snippets(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
@@ -6455,7 +6448,6 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) {
});
}
// todo!(following)
#[gpui::test]
async fn test_following(cx: &mut gpui::TestAppContext) {
init_test(cx, |_| {});
@@ -7094,7 +7086,6 @@ async fn test_move_to_enclosing_bracket(cx: &mut gpui::TestAppContext) {
);
}
// todo!(completions)
#[gpui::test(iterations = 10)]
async fn test_copilot(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
// flaky
+74 -52
View File
@@ -28,7 +28,7 @@ use gpui::{
AnchorCorner, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners,
CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Hsla, InteractiveBounds,
InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton, MouseDownEvent,
MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollWheelEvent, ShapedLine,
MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine,
SharedString, Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun,
TextStyle, View, ViewContext, WindowContext,
};
@@ -581,41 +581,6 @@ impl EditorElement {
}
}
fn scroll(
editor: &mut Editor,
event: &ScrollWheelEvent,
position_map: &PositionMap,
bounds: &InteractiveBounds,
cx: &mut ViewContext<Editor>,
) {
if !bounds.visibly_contains(&event.position, cx) {
return;
}
let line_height = position_map.line_height;
let max_glyph_width = position_map.em_width;
let (delta, axis) = match event.delta {
gpui::ScrollDelta::Pixels(mut pixels) => {
//Trackpad
let axis = position_map.snapshot.ongoing_scroll.filter(&mut pixels);
(pixels, axis)
}
gpui::ScrollDelta::Lines(lines) => {
//Not trackpad
let pixels = point(lines.x * max_glyph_width, lines.y * line_height);
(pixels, None)
}
};
let scroll_position = position_map.snapshot.scroll_position();
let x = f32::from((scroll_position.x * max_glyph_width - delta.x) / max_glyph_width);
let y = f32::from((scroll_position.y * line_height - delta.y) / line_height);
let scroll_position = point(x, y).clamp(&point(0., 0.), &position_map.scroll_max);
editor.scroll(scroll_position, axis, cx);
cx.stop_propagation();
}
fn paint_background(
&self,
gutter_bounds: Bounds<Pixels>,
@@ -839,9 +804,22 @@ impl EditorElement {
let start_row = display_row_range.start;
let end_row = display_row_range.end;
// If we're in a multibuffer, row range span might include an
// excerpt header, so if we were to draw the marker straight away,
// the hunk might include the rows of that header.
// Making the range inclusive doesn't quite cut it, as we rely on the exclusivity for the soft wrap.
// Instead, we simply check whether the range we're dealing with includes
// any custom elements and if so, we stop painting the diff hunk on the first row of that custom element.
let end_row_in_current_excerpt = layout
.position_map
.snapshot
.blocks_in_range(start_row..end_row)
.next()
.map(|(start_row, _)| start_row)
.unwrap_or(end_row);
let start_y = start_row as f32 * line_height - scroll_top;
let end_y = end_row as f32 * line_height - scroll_top;
let end_y = end_row_in_current_excerpt as f32 * line_height - scroll_top;
let width = 0.275 * line_height;
let highlight_origin = bounds.origin + point(-width, start_y);
@@ -2450,6 +2428,64 @@ impl EditorElement {
)
}
fn paint_scroll_wheel_listener(
&mut self,
interactive_bounds: &InteractiveBounds,
layout: &LayoutState,
cx: &mut WindowContext,
) {
cx.on_mouse_event({
let position_map = layout.position_map.clone();
let editor = self.editor.clone();
let interactive_bounds = interactive_bounds.clone();
let mut delta = ScrollDelta::default();
move |event: &ScrollWheelEvent, phase, cx| {
if phase == DispatchPhase::Bubble
&& interactive_bounds.visibly_contains(&event.position, cx)
{
delta = delta.coalesce(event.delta);
editor.update(cx, |editor, cx| {
let position = event.position;
let position_map: &PositionMap = &position_map;
let bounds = &interactive_bounds;
if !bounds.visibly_contains(&position, cx) {
return;
}
let line_height = position_map.line_height;
let max_glyph_width = position_map.em_width;
let (delta, axis) = match delta {
gpui::ScrollDelta::Pixels(mut pixels) => {
//Trackpad
let axis = position_map.snapshot.ongoing_scroll.filter(&mut pixels);
(pixels, axis)
}
gpui::ScrollDelta::Lines(lines) => {
//Not trackpad
let pixels =
point(lines.x * max_glyph_width, lines.y * line_height);
(pixels, None)
}
};
let scroll_position = position_map.snapshot.scroll_position();
let x = f32::from(
(scroll_position.x * max_glyph_width - delta.x) / max_glyph_width,
);
let y =
f32::from((scroll_position.y * line_height - delta.y) / line_height);
let scroll_position =
point(x, y).clamp(&point(0., 0.), &position_map.scroll_max);
editor.scroll(scroll_position, axis, cx);
cx.stop_propagation();
});
}
}
});
}
fn paint_mouse_listeners(
&mut self,
bounds: Bounds<Pixels>,
@@ -2463,21 +2499,7 @@ impl EditorElement {
stacking_order: cx.stacking_order().clone(),
};
cx.on_mouse_event({
let position_map = layout.position_map.clone();
let editor = self.editor.clone();
let interactive_bounds = interactive_bounds.clone();
move |event: &ScrollWheelEvent, phase, cx| {
if phase == DispatchPhase::Bubble
&& interactive_bounds.visibly_contains(&event.position, cx)
{
editor.update(cx, |editor, cx| {
Self::scroll(editor, event, &position_map, &interactive_bounds, cx)
});
}
}
});
self.paint_scroll_wheel_listener(&interactive_bounds, layout, cx);
cx.on_mouse_event({
let position_map = layout.position_map.clone();
+13 -11
View File
@@ -16,7 +16,7 @@ use lsp::DiagnosticSeverity;
use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart, Project};
use settings::Settings;
use std::{ops::Range, sync::Arc, time::Duration};
use ui::{StyledExt, Tooltip};
use ui::{prelude::*, Tooltip};
use util::TryFutureExt;
use workspace::Workspace;
@@ -514,6 +514,8 @@ impl DiagnosticPopover {
None => self.local_diagnostic.diagnostic.message.clone(),
};
let status_colors = cx.theme().status();
struct DiagnosticColors {
pub background: Hsla,
pub border: Hsla,
@@ -521,24 +523,24 @@ impl DiagnosticPopover {
let diagnostic_colors = match self.local_diagnostic.diagnostic.severity {
DiagnosticSeverity::ERROR => DiagnosticColors {
background: style.status.error_background,
border: style.status.error_border,
background: status_colors.error_background,
border: status_colors.error_border,
},
DiagnosticSeverity::WARNING => DiagnosticColors {
background: style.status.warning_background,
border: style.status.warning_border,
background: status_colors.warning_background,
border: status_colors.warning_border,
},
DiagnosticSeverity::INFORMATION => DiagnosticColors {
background: style.status.info_background,
border: style.status.info_border,
background: status_colors.info_background,
border: status_colors.info_border,
},
DiagnosticSeverity::HINT => DiagnosticColors {
background: style.status.hint_background,
border: style.status.hint_border,
background: status_colors.hint_background,
border: status_colors.hint_border,
},
_ => DiagnosticColors {
background: style.status.ignored_background,
border: style.status.ignored_border,
background: status_colors.ignored_background,
border: status_colors.ignored_border,
},
};
+1 -1
View File
@@ -95,7 +95,7 @@ pub fn up_by_rows(
text_layout_details: &TextLayoutDetails,
) -> (DisplayPoint, SelectionGoal) {
let mut goal_x = match goal {
SelectionGoal::HorizontalPosition(x) => x.into(), // todo!("Can the fields in SelectionGoal by Pixels? We should extract a geometry crate and depend on that.")
SelectionGoal::HorizontalPosition(x) => x.into(),
SelectionGoal::WrappedHorizontalPosition((_, x)) => x.into(),
SelectionGoal::HorizontalRange { end, .. } => end.into(),
_ => map.x_for_display_point(start, text_layout_details),
+6 -4
View File
@@ -384,10 +384,12 @@ impl Editor {
) {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
let top_row = scroll_anchor
.anchor
.to_point(&self.buffer().read(cx).snapshot(cx))
.row;
let snapshot = &self.buffer().read(cx).snapshot(cx);
if !scroll_anchor.anchor.is_valid(snapshot) {
log::warn!("Invalid scroll anchor: {:?}", scroll_anchor);
return;
}
let top_row = scroll_anchor.anchor.to_point(snapshot).row;
self.scroll_manager
.set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
}
+3 -4
View File
@@ -11,10 +11,9 @@ impl Editor {
return;
}
// todo!()
// if self.mouse_context_menu.read(cx).visible() {
// return None;
// }
if self.mouse_context_menu.is_some() {
return;
}
if matches!(self.mode, EditorMode::SingleLine) {
cx.propagate();
+2 -4
View File
@@ -60,8 +60,7 @@ pub fn assert_text_with_selections(
#[allow(dead_code)]
#[cfg(any(test, feature = "test-support"))]
pub(crate) fn build_editor(buffer: Model<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
// todo!()
Editor::new(EditorMode::Full, buffer, None, /*None,*/ cx)
Editor::new(EditorMode::Full, buffer, None, cx)
}
pub(crate) fn build_editor_with_project(
@@ -69,6 +68,5 @@ pub(crate) fn build_editor_with_project(
buffer: Model<MultiBuffer>,
cx: &mut ViewContext<Editor>,
) -> Editor {
// todo!()
Editor::new(EditorMode::Full, buffer, Some(project), /*None,*/ cx)
Editor::new(EditorMode::Full, buffer, Some(project), cx)
}