mod header;mod mouse; #[cfg(test)]pub(crate) use header::StickyHeader;pub use header::file_status_label_color;pub(crate) use header::{header_jump_data, render_buffer_header}; use crate::{ BUFFER_HEADER_PADDING, BlockId, ChunkRendererContext, ChunkReplacement, CodeActionSource, ConflictsOurs, ConflictsOursMarker, ConflictsOuter, ConflictsTheirs, ConflictsTheirsMarker, ContextMenuPlacement, CursorShape, CustomBlockId, DisplayDiffHunk, DisplayPoint, DisplayRow, EditDisplayMode, EditPrediction, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, FILE_HEADER_HEIGHT, FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, InlayHintRefreshReason, LineDown, LineHighlight, LineUp, MAX_LINE_LEN, MINIMAP_FONT_SIZE, PageDown, PageUp, Point, RowExt, RowRangeExt, Selection, SelectionDragState, SizingBehavior, SoftWrap, ToPoint, code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP}, column_pixels, display_map::{ Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins, HighlightKey, HighlightedChunk, ToDisplayPoint, }, editor_settings::{ CurrentLineHighlight, DocumentColorsRenderMode, Minimap, MinimapThumb, MinimapThumbBorder, ScrollBeyondLastLine, ScrollbarAxes, ScrollbarDiagnostics, ShowMinimap, }, git::blame::{BlameRenderer, GitBlame, GlobalBlameRenderer}, hover_popover::{ self, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT, POPOVER_RIGHT_OFFSET, }, inlay_hint_settings, scroll::{ ActiveScrollbarState, ScrollOffset, ScrollPixelOffset, ScrollbarThumbState, scroll_amount::ScrollAmount, },};use buffer_diff::{DiffHunkStatus, DiffHunkStatusKind};use collections::{BTreeMap, HashMap, HashSet};use feature_flags::{DiffReviewFeatureFlag, FeatureFlagAppExt as _};use git::{Oid, blame::BlameEntry, commit::ParsedCommitMessage};use gpui::{ Action, Along, AnyElement, App, AppContext, AvailableSpace, Axis as ScrollbarAxis, BorderStyle, Bounds, ClipboardItem, ContentMask, Context, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Focusable as _, Font, FontId, FontWeight, GlobalElementId, Hitbox, HitboxBehavior, Hsla, InteractiveElement, IntoElement, IsZero, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels, ScrollHandle, ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled, StyledText, TaskExt, TextAlign, TextRun, TextStyleRefinement, WeakEntity, Window, div, fill, outline, pattern_slash, point, px, quad, relative, size, solid_background, transparent_black,};use itertools::Itertools;use language::{ HighlightedText, IndentGuideSettings, LanguageAwareStyling, language_settings::ShowWhitespaceSetting,};use markdown::Markdown;use multi_buffer::{ Anchor, ExpandExcerptDirection, ExpandInfo, MultiBufferOffset, MultiBufferPoint, MultiBufferRow, RowInfo, ToOffset,}; use project::{ debugger::breakpoint_store::{Breakpoint, BreakpointSessionState}, project_settings::ProjectSettings,};use settings::{ GitGutterSetting, GitHunkStyleSetting, IndentGuideBackgroundColoring, IndentGuideColoring, Settings,};use smallvec::{SmallVec, smallvec};use std::{ any::TypeId, borrow::Cow, cell::Cell, cmp::{self, Ordering}, fmt::{self, Write}, iter, mem, ops::{Deref, Range}, rc::Rc, sync::Arc, time::Duration,};use sum_tree::Bias;use text::BufferId;use theme::{ActiveTheme, Appearance, PlayerColor};use theme_settings::BufferLineHeight;use ui::utils::ensure_minimum_contrast;use ui::{ButtonLike, POPOVER_Y_PADDING, Tooltip, prelude::*, scrollbars::ShowScrollbar};use unicode_segmentation::UnicodeSegmentation;use util::{ResultExt, debug_panic};use workspace::{ CollaboratorId, ItemHandle, Workspace, item::{Item, ItemBufferKind},}; /// Determines what kinds of highlights should be applied to a lines background.#[derive(Clone, Copy, Default)]struct LineHighlightSpec { selection: bool, breakpoint: bool, _active_stack_frame: bool,} enum LineNumberStyle { Breakpoint, DiffAdded, DiffDeleted, Active, Inactive,} impl LineNumberStyle { fn new(is_active: bool, is_breakpoint: bool, diff_status: Option<DiffHunkStatus>) -> Self { match ( is_active, is_breakpoint, diff_status.map(|status| status.kind), ) { (_, true, _) => Self::Breakpoint, (true, _, _) => Self::Active, (_, _, Some(DiffHunkStatusKind::Added)) => Self::DiffAdded, (_, _, Some(DiffHunkStatusKind::Deleted)) => Self::DiffDeleted, (_, _, _) => Self::Inactive, } } fn color(self, colors: &theme::ThemeColors) -> Hsla { match self { Self::Breakpoint => colors.debugger_accent, Self::DiffAdded => colors.version_control_added, Self::DiffDeleted => colors.version_control_deleted, Self::Active => colors.editor_active_line_number, Self::Inactive => colors.editor_line_number, } }} #[derive(Debug)]struct SelectionLayout { head: DisplayPoint, cursor_shape: CursorShape, is_newest: bool, is_local: bool, range: Range<DisplayPoint>, active_rows: Range<DisplayRow>, user_name: Option<SharedString>,} struct InlineBlameLayout { element: AnyElement, bounds: Bounds<Pixels>, buffer_id: BufferId, entry: BlameEntry,} impl SelectionLayout { fn new<T: ToPoint + ToDisplayPoint + Clone>( selection: Selection<T>, line_mode: bool, cursor_offset: bool, cursor_shape: CursorShape, map: &DisplaySnapshot, is_newest: bool, is_local: bool, user_name: Option<SharedString>, ) -> Self { let buffer_snapshot = map.buffer_snapshot(); let point_selection = selection.map(|p| p.to_point(buffer_snapshot)); let display_selection = point_selection.map(|p| p.to_display_point(map)); let mut range = display_selection.range(); let mut head = display_selection.head(); if !line_mode { let offset_range = point_selection.start.to_offset(buffer_snapshot) ..point_selection.end.to_offset(buffer_snapshot); if let Some(contiguous_range) = map.contiguous_display_point_range_for_buffer_range(offset_range) { range = contiguous_range; // Keep the cursor attached to the highlight boundary; the // anchor-bias display position may sit on the far side of a // boundary inlay the highlight excludes. head = if selection.reversed { range.start } else { range.end }; } } let mut active_rows = map.prev_line_boundary(point_selection.start).1.row() ..map.next_line_boundary(point_selection.end).1.row(); // vim visual line mode if line_mode { let point_range = map.expand_to_line(point_selection.range()); range = point_range.start.to_display_point(map)..point_range.end.to_display_point(map); } // any vim visual mode (including line mode) if cursor_offset && !range.is_empty() && !selection.reversed { if head.column() > 0 { head = map.clip_point(DisplayPoint::new(head.row(), head.column() - 1), Bias::Left); } else if head.row().0 > 0 && head != map.max_point() { head = map.clip_point( DisplayPoint::new( head.row().previous_row(), map.line_len(head.row().previous_row()), ), Bias::Left, ); // updating range.end is a no-op unless you're cursor is // on the newline containing a multi-buffer divider // in which case the clip_point may have moved the head up // an additional row. range.end = DisplayPoint::new(head.row().next_row(), 0); active_rows.end = head.row(); } } Self { head, cursor_shape, is_newest, is_local, range, active_rows, user_name, } }} #[derive(Default)]struct RenderBlocksOutput { // We store spacer blocks separately because they paint in a different order // (spacers -> indent guides -> non-spacers) non_spacer_blocks: Vec<BlockLayout>, spacer_blocks: Vec<BlockLayout>, row_block_types: HashMap<DisplayRow, bool>, resized_blocks: Option<HashMap<CustomBlockId, u32>>,} pub struct EditorElement { editor: Entity<Editor>, style: EditorStyle, split_side: Option<SplitSide>,} #[derive(Debug, Clone, Copy, PartialEq, Eq)]pub enum SplitSide { Left, Right,} impl EditorElement { pub(crate) const SCROLLBAR_WIDTH: Pixels = ui::EDITOR_SCROLLBAR_WIDTH; pub fn new(editor: &Entity<Editor>, style: EditorStyle) -> Self { Self { editor: editor.clone(), style, split_side: None, } } pub fn set_split_side(&mut self, side: SplitSide) { self.split_side = Some(side); } fn register_actions(&self, window: &mut Window, cx: &mut App) { let editor = &self.editor; editor.update(cx, |editor, cx| { for action in editor.editor_actions.borrow().values() { (action)(editor, window, cx) } }); crate::rust_analyzer_ext::apply_related_actions(editor, window, cx); crate::clangd_ext::apply_related_actions(editor, window, cx); register_action(editor, window, Editor::open_context_menu); register_action(editor, window, Editor::move_left); register_action(editor, window, Editor::move_right); register_action(editor, window, Editor::move_down); register_action(editor, window, Editor::move_down_by_lines); register_action(editor, window, Editor::select_down_by_lines); register_action(editor, window, Editor::move_up); register_action(editor, window, Editor::move_up_by_lines); register_action(editor, window, Editor::select_up_by_lines); register_action(editor, window, Editor::select_page_down); register_action(editor, window, Editor::select_page_up); register_action(editor, window, Editor::cancel); register_action(editor, window, Editor::blame_hover); register_action(editor, window, Editor::next_snippet_tabstop); register_action(editor, window, Editor::previous_snippet_tabstop); register_action(editor, window, Editor::copy); register_action(editor, window, Editor::copy_and_trim); register_action(editor, window, Editor::diff_clipboard_with_selection); register_action(editor, window, Editor::move_page_up); register_action(editor, window, Editor::move_page_down); register_action(editor, window, Editor::next_screen); register_action(editor, window, Editor::scroll_cursor_top); register_action(editor, window, Editor::scroll_cursor_center); register_action(editor, window, Editor::scroll_cursor_bottom); register_action(editor, window, Editor::scroll_cursor_center_top_bottom); register_action(editor, window, |editor, _: &LineDown, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Line(1.), window, cx) }); register_action(editor, window, |editor, _: &LineUp, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Line(-1.), window, cx) }); register_action(editor, window, |editor, _: &HalfPageDown, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(0.5), window, cx) }); register_action(editor, window, |editor, _: &HalfPageUp, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(-0.5), window, cx) }); register_action(editor, window, |editor, _: &PageDown, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(1.), window, cx) }); register_action(editor, window, |editor, _: &PageUp, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(-1.), window, cx) }); register_action(editor, window, Editor::move_to_previous_word_start); register_action(editor, window, Editor::move_to_previous_subword_start); register_action(editor, window, Editor::move_to_next_word_end); register_action(editor, window, Editor::move_to_next_subword_end); register_action(editor, window, Editor::move_to_beginning_of_line); register_action(editor, window, Editor::move_to_end_of_line); register_action(editor, window, Editor::move_to_start_of_paragraph); register_action(editor, window, Editor::move_to_end_of_paragraph); register_action(editor, window, Editor::move_to_next_comment_paragraph); register_action(editor, window, Editor::move_to_previous_comment_paragraph); register_action(editor, window, Editor::move_to_beginning); register_action(editor, window, Editor::move_to_end); register_action(editor, window, Editor::move_to_start_of_excerpt); register_action(editor, window, Editor::move_to_start_of_next_excerpt); register_action(editor, window, Editor::move_to_end_of_excerpt); register_action(editor, window, Editor::move_to_end_of_previous_excerpt); register_action(editor, window, Editor::select_up); register_action(editor, window, Editor::select_down); register_action(editor, window, Editor::select_left); register_action(editor, window, Editor::select_right); register_action(editor, window, Editor::select_to_previous_word_start); register_action(editor, window, Editor::select_to_previous_subword_start); register_action(editor, window, Editor::select_to_next_word_end); register_action(editor, window, Editor::select_to_next_subword_end); register_action(editor, window, Editor::select_to_beginning_of_line); register_action(editor, window, Editor::select_to_end_of_line); register_action(editor, window, Editor::select_to_start_of_paragraph); register_action(editor, window, Editor::select_to_end_of_paragraph); register_action(editor, window, Editor::select_to_start_of_excerpt); register_action(editor, window, Editor::select_to_start_of_next_excerpt); register_action(editor, window, Editor::select_to_end_of_excerpt); register_action(editor, window, Editor::select_to_end_of_previous_excerpt); register_action(editor, window, Editor::select_to_beginning); register_action(editor, window, Editor::select_to_end); register_action(editor, window, Editor::select_all); register_action(editor, window, |editor, action, window, cx| { editor.select_all_matches(action, window, cx).log_err(); }); register_action(editor, window, Editor::select_line); register_action(editor, window, Editor::split_selection_into_lines); register_action(editor, window, Editor::add_selection_above); register_action(editor, window, Editor::add_selection_below); register_action(editor, window, Editor::insert_snippet_at_selections); register_action(editor, window, |editor, action, window, cx| { editor.select_next(action, window, cx).log_err(); }); register_action(editor, window, |editor, action, window, cx| { editor.select_previous(action, window, cx).log_err(); }); register_action(editor, window, |editor, action, window, cx| { editor.find_next_match(action, window, cx).log_err(); }); register_action(editor, window, |editor, action, window, cx| { editor.find_previous_match(action, window, cx).log_err(); }); register_action(editor, window, Editor::select_larger_syntax_node); register_action(editor, window, Editor::select_smaller_syntax_node); register_action(editor, window, Editor::select_next_syntax_node); register_action(editor, window, Editor::select_prev_syntax_node); register_action( editor, window, Editor::select_to_start_of_larger_syntax_node, ); register_action(editor, window, Editor::select_to_end_of_larger_syntax_node); register_action(editor, window, Editor::move_to_start_of_larger_syntax_node); register_action(editor, window, Editor::move_to_end_of_larger_syntax_node); register_action(editor, window, Editor::select_enclosing_symbol); register_action(editor, window, Editor::move_to_enclosing_bracket); register_action(editor, window, Editor::select_inside_delimiters); register_action(editor, window, Editor::select_around_delimiters); register_action(editor, window, Editor::undo_selection); register_action(editor, window, Editor::redo_selection); if editor.read(cx).buffer_kind(cx) == ItemBufferKind::Multibuffer { register_action(editor, window, Editor::expand_excerpts); register_action(editor, window, Editor::expand_excerpts_up); register_action(editor, window, Editor::expand_excerpts_down); } register_action(editor, window, Editor::go_to_diagnostic); register_action(editor, window, Editor::go_to_prev_diagnostic); register_action(editor, window, Editor::go_to_next_hunk); register_action(editor, window, Editor::go_to_prev_hunk); register_action(editor, window, Editor::go_to_next_document_highlight); register_action(editor, window, Editor::go_to_prev_document_highlight); register_action(editor, window, |editor, action, window, cx| { editor .go_to_definition(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_definition_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_declaration(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_declaration_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_implementation(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_implementation_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_type_definition(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_type_definition_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, Editor::open_url); register_action(editor, window, Editor::open_selected_filename); register_action(editor, window, Editor::fold); register_action(editor, window, Editor::fold_at_level); register_action(editor, window, Editor::fold_at_level_1); register_action(editor, window, Editor::fold_at_level_2); register_action(editor, window, Editor::fold_at_level_3); register_action(editor, window, Editor::fold_at_level_4); register_action(editor, window, Editor::fold_at_level_5); register_action(editor, window, Editor::fold_at_level_6); register_action(editor, window, Editor::fold_at_level_7); register_action(editor, window, Editor::fold_at_level_8); register_action(editor, window, Editor::fold_at_level_9); register_action(editor, window, Editor::fold_all); register_action(editor, window, Editor::fold_function_bodies); register_action(editor, window, Editor::fold_recursive); register_action(editor, window, Editor::toggle_fold); register_action(editor, window, Editor::toggle_fold_recursive); register_action(editor, window, Editor::toggle_fold_all); register_action(editor, window, Editor::unfold_lines); register_action(editor, window, Editor::unfold_recursive); register_action(editor, window, Editor::unfold_all); register_action(editor, window, Editor::fold_selected_ranges); register_action(editor, window, Editor::set_mark); register_action(editor, window, Editor::save_location); register_action(editor, window, Editor::swap_selection_ends); register_action(editor, window, Editor::show_completions); register_action(editor, window, Editor::show_word_completions); register_action(editor, window, Editor::toggle_code_actions); register_action(editor, window, Editor::open_excerpts); register_action(editor, window, Editor::open_excerpts_in_split); register_action(editor, window, Editor::toggle_soft_wrap); register_action(editor, window, Editor::toggle_tab_bar); register_action(editor, window, Editor::toggle_breadcrumb); register_action(editor, window, Editor::toggle_line_numbers); register_action(editor, window, Editor::toggle_relative_line_numbers); register_action(editor, window, Editor::toggle_indent_guides); register_action(editor, window, Editor::toggle_inlay_hints); register_action(editor, window, Editor::toggle_inline_values); register_action(editor, window, Editor::toggle_code_lens_action); register_action(editor, window, Editor::toggle_semantic_highlights); register_action(editor, window, Editor::toggle_edit_predictions); if editor.read(cx).diagnostics_enabled() { register_action(editor, window, Editor::toggle_diagnostics); } if editor.read(cx).inline_diagnostics_enabled() { register_action(editor, window, Editor::toggle_inline_diagnostics); } if editor.read(cx).supports_minimap(cx) { register_action(editor, window, Editor::toggle_minimap); } register_action(editor, window, hover_popover::hover);Lines 1–500 of 12296. Load more
mod header; mod mouse; #[cfg(test)] pub(crate) use header::StickyHeader; pub use header::file_status_label_color; pub(crate) use header::{header_jump_data, render_buffer_header}; use crate::{ BUFFER_HEADER_PADDING, BlockId, ChunkRendererContext, ChunkReplacement, CodeActionSource, ConflictsOurs, ConflictsOursMarker, ConflictsOuter, ConflictsTheirs, ConflictsTheirsMarker, ContextMenuPlacement, CursorShape, CustomBlockId, DisplayDiffHunk, DisplayPoint, DisplayRow, EditDisplayMode, EditPrediction, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, FILE_HEADER_HEIGHT, FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput, HoveredCursor, InlayHintRefreshReason, LineDown, LineHighlight, LineUp, MAX_LINE_LEN, MINIMAP_FONT_SIZE, PageDown, PageUp, Point, RowExt, RowRangeExt, Selection, SelectionDragState, SizingBehavior, SoftWrap, ToPoint, code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP}, column_pixels, display_map::{ Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins, HighlightKey, HighlightedChunk, ToDisplayPoint, }, editor_settings::{ CurrentLineHighlight, DocumentColorsRenderMode, Minimap, MinimapThumb, MinimapThumbBorder, ScrollBeyondLastLine, ScrollbarAxes, ScrollbarDiagnostics, ShowMinimap, }, git::blame::{BlameRenderer, GitBlame, GlobalBlameRenderer}, hover_popover::{ self, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT, POPOVER_RIGHT_OFFSET, }, inlay_hint_settings, scroll::{ ActiveScrollbarState, ScrollOffset, ScrollPixelOffset, ScrollbarThumbState, scroll_amount::ScrollAmount, }, }; use buffer_diff::{DiffHunkStatus, DiffHunkStatusKind}; use collections::{BTreeMap, HashMap, HashSet}; use feature_flags::{DiffReviewFeatureFlag, FeatureFlagAppExt as _}; use git::{Oid, blame::BlameEntry, commit::ParsedCommitMessage}; use gpui::{ Action, Along, AnyElement, App, AppContext, AvailableSpace, Axis as ScrollbarAxis, BorderStyle, Bounds, ClipboardItem, ContentMask, Context, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Entity, Focusable as _, Font, FontId, FontWeight, GlobalElementId, Hitbox, HitboxBehavior, Hsla, InteractiveElement, IntoElement, IsZero, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad, ParentElement, Pixels, ScrollHandle, ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled, StyledText, TaskExt, TextAlign, TextRun, TextStyleRefinement, WeakEntity, Window, div, fill, outline, pattern_slash, point, px, quad, relative, size, solid_background, transparent_black, }; use itertools::Itertools; use language::{ HighlightedText, IndentGuideSettings, LanguageAwareStyling, language_settings::ShowWhitespaceSetting, }; use markdown::Markdown; use multi_buffer::{ Anchor, ExpandExcerptDirection, ExpandInfo, MultiBufferOffset, MultiBufferPoint, MultiBufferRow, RowInfo, ToOffset, }; use project::{ debugger::breakpoint_store::{Breakpoint, BreakpointSessionState}, project_settings::ProjectSettings, }; use settings::{ GitGutterSetting, GitHunkStyleSetting, IndentGuideBackgroundColoring, IndentGuideColoring, Settings, }; use smallvec::{SmallVec, smallvec}; use std::{ any::TypeId, borrow::Cow, cell::Cell, cmp::{self, Ordering}, fmt::{self, Write}, iter, mem, ops::{Deref, Range}, rc::Rc, sync::Arc, time::Duration, }; use sum_tree::Bias; use text::BufferId; use theme::{ActiveTheme, Appearance, PlayerColor}; use theme_settings::BufferLineHeight; use ui::utils::ensure_minimum_contrast; use ui::{ButtonLike, POPOVER_Y_PADDING, Tooltip, prelude::*, scrollbars::ShowScrollbar}; use unicode_segmentation::UnicodeSegmentation; use util::{ResultExt, debug_panic}; use workspace::{ CollaboratorId, ItemHandle, Workspace, item::{Item, ItemBufferKind}, }; /// Determines what kinds of highlights should be applied to a lines background. #[derive(Clone, Copy, Default)] struct LineHighlightSpec { selection: bool, breakpoint: bool, _active_stack_frame: bool, } enum LineNumberStyle { Breakpoint, DiffAdded, DiffDeleted, Active, Inactive, } impl LineNumberStyle { fn new(is_active: bool, is_breakpoint: bool, diff_status: Option<DiffHunkStatus>) -> Self { match ( is_active, is_breakpoint, diff_status.map(|status| status.kind), ) { (_, true, _) => Self::Breakpoint, (true, _, _) => Self::Active, (_, _, Some(DiffHunkStatusKind::Added)) => Self::DiffAdded, (_, _, Some(DiffHunkStatusKind::Deleted)) => Self::DiffDeleted, (_, _, _) => Self::Inactive, } } fn color(self, colors: &theme::ThemeColors) -> Hsla { match self { Self::Breakpoint => colors.debugger_accent, Self::DiffAdded => colors.version_control_added, Self::DiffDeleted => colors.version_control_deleted, Self::Active => colors.editor_active_line_number, Self::Inactive => colors.editor_line_number, } } } #[derive(Debug)] struct SelectionLayout { head: DisplayPoint, cursor_shape: CursorShape, is_newest: bool, is_local: bool, range: Range<DisplayPoint>, active_rows: Range<DisplayRow>, user_name: Option<SharedString>, } struct InlineBlameLayout { element: AnyElement, bounds: Bounds<Pixels>, buffer_id: BufferId, entry: BlameEntry, } impl SelectionLayout { fn new<T: ToPoint + ToDisplayPoint + Clone>( selection: Selection<T>, line_mode: bool, cursor_offset: bool, cursor_shape: CursorShape, map: &DisplaySnapshot, is_newest: bool, is_local: bool, user_name: Option<SharedString>, ) -> Self { let buffer_snapshot = map.buffer_snapshot(); let point_selection = selection.map(|p| p.to_point(buffer_snapshot)); let display_selection = point_selection.map(|p| p.to_display_point(map)); let mut range = display_selection.range(); let mut head = display_selection.head(); if !line_mode { let offset_range = point_selection.start.to_offset(buffer_snapshot) ..point_selection.end.to_offset(buffer_snapshot); if let Some(contiguous_range) = map.contiguous_display_point_range_for_buffer_range(offset_range) { range = contiguous_range; // Keep the cursor attached to the highlight boundary; the // anchor-bias display position may sit on the far side of a // boundary inlay the highlight excludes. head = if selection.reversed { range.start } else { range.end }; } } let mut active_rows = map.prev_line_boundary(point_selection.start).1.row() ..map.next_line_boundary(point_selection.end).1.row(); // vim visual line mode if line_mode { let point_range = map.expand_to_line(point_selection.range()); range = point_range.start.to_display_point(map)..point_range.end.to_display_point(map); } // any vim visual mode (including line mode) if cursor_offset && !range.is_empty() && !selection.reversed { if head.column() > 0 { head = map.clip_point(DisplayPoint::new(head.row(), head.column() - 1), Bias::Left); } else if head.row().0 > 0 && head != map.max_point() { head = map.clip_point( DisplayPoint::new( head.row().previous_row(), map.line_len(head.row().previous_row()), ), Bias::Left, ); // updating range.end is a no-op unless you're cursor is // on the newline containing a multi-buffer divider // in which case the clip_point may have moved the head up // an additional row. range.end = DisplayPoint::new(head.row().next_row(), 0); active_rows.end = head.row(); } } Self { head, cursor_shape, is_newest, is_local, range, active_rows, user_name, } } } #[derive(Default)] struct RenderBlocksOutput { // We store spacer blocks separately because they paint in a different order // (spacers -> indent guides -> non-spacers) non_spacer_blocks: Vec<BlockLayout>, spacer_blocks: Vec<BlockLayout>, row_block_types: HashMap<DisplayRow, bool>, resized_blocks: Option<HashMap<CustomBlockId, u32>>, } pub struct EditorElement { editor: Entity<Editor>, style: EditorStyle, split_side: Option<SplitSide>, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SplitSide { Left, Right, } impl EditorElement { pub(crate) const SCROLLBAR_WIDTH: Pixels = ui::EDITOR_SCROLLBAR_WIDTH; pub fn new(editor: &Entity<Editor>, style: EditorStyle) -> Self { Self { editor: editor.clone(), style, split_side: None, } } pub fn set_split_side(&mut self, side: SplitSide) { self.split_side = Some(side); } fn register_actions(&self, window: &mut Window, cx: &mut App) { let editor = &self.editor; editor.update(cx, |editor, cx| { for action in editor.editor_actions.borrow().values() { (action)(editor, window, cx) } }); crate::rust_analyzer_ext::apply_related_actions(editor, window, cx); crate::clangd_ext::apply_related_actions(editor, window, cx); register_action(editor, window, Editor::open_context_menu); register_action(editor, window, Editor::move_left); register_action(editor, window, Editor::move_right); register_action(editor, window, Editor::move_down); register_action(editor, window, Editor::move_down_by_lines); register_action(editor, window, Editor::select_down_by_lines); register_action(editor, window, Editor::move_up); register_action(editor, window, Editor::move_up_by_lines); register_action(editor, window, Editor::select_up_by_lines); register_action(editor, window, Editor::select_page_down); register_action(editor, window, Editor::select_page_up); register_action(editor, window, Editor::cancel); register_action(editor, window, Editor::blame_hover); register_action(editor, window, Editor::next_snippet_tabstop); register_action(editor, window, Editor::previous_snippet_tabstop); register_action(editor, window, Editor::copy); register_action(editor, window, Editor::copy_and_trim); register_action(editor, window, Editor::diff_clipboard_with_selection); register_action(editor, window, Editor::move_page_up); register_action(editor, window, Editor::move_page_down); register_action(editor, window, Editor::next_screen); register_action(editor, window, Editor::scroll_cursor_top); register_action(editor, window, Editor::scroll_cursor_center); register_action(editor, window, Editor::scroll_cursor_bottom); register_action(editor, window, Editor::scroll_cursor_center_top_bottom); register_action(editor, window, |editor, _: &LineDown, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Line(1.), window, cx) }); register_action(editor, window, |editor, _: &LineUp, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Line(-1.), window, cx) }); register_action(editor, window, |editor, _: &HalfPageDown, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(0.5), window, cx) }); register_action(editor, window, |editor, _: &HalfPageUp, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(-0.5), window, cx) }); register_action(editor, window, |editor, _: &PageDown, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(1.), window, cx) }); register_action(editor, window, |editor, _: &PageUp, window, cx| { editor.scroll_screen_with_cursor_margin(&ScrollAmount::Page(-1.), window, cx) }); register_action(editor, window, Editor::move_to_previous_word_start); register_action(editor, window, Editor::move_to_previous_subword_start); register_action(editor, window, Editor::move_to_next_word_end); register_action(editor, window, Editor::move_to_next_subword_end); register_action(editor, window, Editor::move_to_beginning_of_line); register_action(editor, window, Editor::move_to_end_of_line); register_action(editor, window, Editor::move_to_start_of_paragraph); register_action(editor, window, Editor::move_to_end_of_paragraph); register_action(editor, window, Editor::move_to_next_comment_paragraph); register_action(editor, window, Editor::move_to_previous_comment_paragraph); register_action(editor, window, Editor::move_to_beginning); register_action(editor, window, Editor::move_to_end); register_action(editor, window, Editor::move_to_start_of_excerpt); register_action(editor, window, Editor::move_to_start_of_next_excerpt); register_action(editor, window, Editor::move_to_end_of_excerpt); register_action(editor, window, Editor::move_to_end_of_previous_excerpt); register_action(editor, window, Editor::select_up); register_action(editor, window, Editor::select_down); register_action(editor, window, Editor::select_left); register_action(editor, window, Editor::select_right); register_action(editor, window, Editor::select_to_previous_word_start); register_action(editor, window, Editor::select_to_previous_subword_start); register_action(editor, window, Editor::select_to_next_word_end); register_action(editor, window, Editor::select_to_next_subword_end); register_action(editor, window, Editor::select_to_beginning_of_line); register_action(editor, window, Editor::select_to_end_of_line); register_action(editor, window, Editor::select_to_start_of_paragraph); register_action(editor, window, Editor::select_to_end_of_paragraph); register_action(editor, window, Editor::select_to_start_of_excerpt); register_action(editor, window, Editor::select_to_start_of_next_excerpt); register_action(editor, window, Editor::select_to_end_of_excerpt); register_action(editor, window, Editor::select_to_end_of_previous_excerpt); register_action(editor, window, Editor::select_to_beginning); register_action(editor, window, Editor::select_to_end); register_action(editor, window, Editor::select_all); register_action(editor, window, |editor, action, window, cx| { editor.select_all_matches(action, window, cx).log_err(); }); register_action(editor, window, Editor::select_line); register_action(editor, window, Editor::split_selection_into_lines); register_action(editor, window, Editor::add_selection_above); register_action(editor, window, Editor::add_selection_below); register_action(editor, window, Editor::insert_snippet_at_selections); register_action(editor, window, |editor, action, window, cx| { editor.select_next(action, window, cx).log_err(); }); register_action(editor, window, |editor, action, window, cx| { editor.select_previous(action, window, cx).log_err(); }); register_action(editor, window, |editor, action, window, cx| { editor.find_next_match(action, window, cx).log_err(); }); register_action(editor, window, |editor, action, window, cx| { editor.find_previous_match(action, window, cx).log_err(); }); register_action(editor, window, Editor::select_larger_syntax_node); register_action(editor, window, Editor::select_smaller_syntax_node); register_action(editor, window, Editor::select_next_syntax_node); register_action(editor, window, Editor::select_prev_syntax_node); register_action( editor, window, Editor::select_to_start_of_larger_syntax_node, ); register_action(editor, window, Editor::select_to_end_of_larger_syntax_node); register_action(editor, window, Editor::move_to_start_of_larger_syntax_node); register_action(editor, window, Editor::move_to_end_of_larger_syntax_node); register_action(editor, window, Editor::select_enclosing_symbol); register_action(editor, window, Editor::move_to_enclosing_bracket); register_action(editor, window, Editor::select_inside_delimiters); register_action(editor, window, Editor::select_around_delimiters); register_action(editor, window, Editor::undo_selection); register_action(editor, window, Editor::redo_selection); if editor.read(cx).buffer_kind(cx) == ItemBufferKind::Multibuffer { register_action(editor, window, Editor::expand_excerpts); register_action(editor, window, Editor::expand_excerpts_up); register_action(editor, window, Editor::expand_excerpts_down); } register_action(editor, window, Editor::go_to_diagnostic); register_action(editor, window, Editor::go_to_prev_diagnostic); register_action(editor, window, Editor::go_to_next_hunk); register_action(editor, window, Editor::go_to_prev_hunk); register_action(editor, window, Editor::go_to_next_document_highlight); register_action(editor, window, Editor::go_to_prev_document_highlight); register_action(editor, window, |editor, action, window, cx| { editor .go_to_definition(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_definition_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_declaration(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_declaration_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_implementation(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_implementation_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_type_definition(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, |editor, action, window, cx| { editor .go_to_type_definition_split(action, window, cx) .detach_and_log_err(cx); }); register_action(editor, window, Editor::open_url); register_action(editor, window, Editor::open_selected_filename); register_action(editor, window, Editor::fold); register_action(editor, window, Editor::fold_at_level); register_action(editor, window, Editor::fold_at_level_1); register_action(editor, window, Editor::fold_at_level_2); register_action(editor, window, Editor::fold_at_level_3); register_action(editor, window, Editor::fold_at_level_4); register_action(editor, window, Editor::fold_at_level_5); register_action(editor, window, Editor::fold_at_level_6); register_action(editor, window, Editor::fold_at_level_7); register_action(editor, window, Editor::fold_at_level_8); register_action(editor, window, Editor::fold_at_level_9); register_action(editor, window, Editor::fold_all); register_action(editor, window, Editor::fold_function_bodies); register_action(editor, window, Editor::fold_recursive); register_action(editor, window, Editor::toggle_fold); register_action(editor, window, Editor::toggle_fold_recursive); register_action(editor, window, Editor::toggle_fold_all); register_action(editor, window, Editor::unfold_lines); register_action(editor, window, Editor::unfold_recursive); register_action(editor, window, Editor::unfold_all); register_action(editor, window, Editor::fold_selected_ranges); register_action(editor, window, Editor::set_mark); register_action(editor, window, Editor::save_location); register_action(editor, window, Editor::swap_selection_ends); register_action(editor, window, Editor::show_completions); register_action(editor, window, Editor::show_word_completions); register_action(editor, window, Editor::toggle_code_actions); register_action(editor, window, Editor::open_excerpts); register_action(editor, window, Editor::open_excerpts_in_split); register_action(editor, window, Editor::toggle_soft_wrap); register_action(editor, window, Editor::toggle_tab_bar); register_action(editor, window, Editor::toggle_breadcrumb); register_action(editor, window, Editor::toggle_line_numbers); register_action(editor, window, Editor::toggle_relative_line_numbers); register_action(editor, window, Editor::toggle_indent_guides); register_action(editor, window, Editor::toggle_inlay_hints); register_action(editor, window, Editor::toggle_inline_values); register_action(editor, window, Editor::toggle_code_lens_action); register_action(editor, window, Editor::toggle_semantic_highlights); register_action(editor, window, Editor::toggle_edit_predictions); if editor.read(cx).diagnostics_enabled() { register_action(editor, window, Editor::toggle_diagnostics); } if editor.read(cx).inline_diagnostics_enabled() { register_action(editor, window, Editor::toggle_inline_diagnostics); } if editor.read(cx).supports_minimap(cx) { register_action(editor, window, Editor::toggle_minimap); } register_action(editor, window, hover_popover::hover);