Conrad Irwinfix merge conflicts7adcf901 year agoHistory
7669 lines · 305.0 KB · Rust
RawDownload
use crate::{    blame_entry_tooltip::{blame_entry_relative_timestamp, BlameEntryTooltip},    code_context_menus::CodeActionsMenu,    display_map::{        Block, BlockContext, BlockStyle, DisplaySnapshot, HighlightedChunk, ToDisplayPoint,    },    editor_settings::{        CurrentLineHighlight, DoubleClickInMultibuffer, MultiCursorModifier, ScrollBeyondLastLine,        ShowScrollbar,    },    git::blame::{CommitDetails, GitBlame},    hover_popover::{        self, hover_at, HOVER_POPOVER_GAP, MIN_POPOVER_CHARACTER_WIDTH, MIN_POPOVER_LINE_HEIGHT,    },    hunk_diff::{diff_hunk_to_display, DisplayDiffHunk},    hunk_status,    items::BufferSearchHighlights,    mouse_context_menu::{self, MenuPosition, MouseContextMenu},    scroll::{axis_pair, scroll_amount::ScrollAmount, AxisPair},    BlockId, ChunkReplacement, CursorShape, CustomBlockId, DisplayPoint, DisplayRow,    DocumentHighlightRead, DocumentHighlightWrite, Editor, EditorMode, EditorSettings,    EditorSnapshot, EditorStyle, ExpandExcerpts, FocusedBlock, GutterDimensions, HalfPageDown,    HalfPageUp, HandleInput, HoveredCursor, HoveredHunk, InlineCompletion, JumpData, LineDown,    LineUp, OpenExcerpts, PageDown, PageUp, Point, RowExt, RowInfo, RowRangeExt, SelectPhase,    Selection, SoftWrap, ToPoint, ToggleFold, CURSORS_VISIBLE_FOR, FILE_HEADER_HEIGHT,    GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED, MAX_LINE_LEN, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,};use client::ParticipantIndex;use collections::{BTreeMap, HashMap, HashSet};use file_icons::FileIcons;use git::{blame::BlameEntry, diff::DiffHunkStatus, Oid};use gpui::{    anchored, deferred, div, fill, outline, point, px, quad, relative, size, svg,    transparent_black, Action, AnyElement, AvailableSpace, Axis, Bounds, ClickEvent, ClipboardItem,    ContentMask, Corner, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler,    Entity, FontId, GlobalElementId, Hitbox, Hsla, InteractiveElement, IntoElement, Length,    ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, PaintQuad,    ParentElement, Pixels, ScrollDelta, ScrollWheelEvent, ShapedLine, SharedString, Size,    StatefulInteractiveElement, Style, Styled, Subscription, TextRun, TextStyleRefinement, View,    ViewContext, WeakView, WindowContext,};use itertools::Itertools;use language::{    language_settings::{        IndentGuideBackgroundColoring, IndentGuideColoring, IndentGuideSettings,        ShowWhitespaceSetting,    },    ChunkRendererContext,};use lsp::DiagnosticSeverity;use multi_buffer::{    Anchor, AnchorRangeExt, ExcerptId, ExcerptInfo, ExpandExcerptDirection, MultiBufferPoint,    MultiBufferRow, MultiBufferSnapshot, ToOffset,};use project::{    project_settings::{GitGutterSetting, ProjectSettings},    ProjectPath,};use settings::Settings;use smallvec::{smallvec, SmallVec};use std::{    any::TypeId,    borrow::Cow,    cmp::{self, Ordering},    fmt::{self, Write},    iter, mem,    ops::{Deref, Range},    rc::Rc,    sync::Arc,};use sum_tree::Bias;use theme::{ActiveTheme, Appearance, PlayerColor};use ui::{h_flex, ButtonLike, ButtonStyle, ContextMenu, Tooltip};use ui::{prelude::*, POPOVER_Y_PADDING};use unicode_segmentation::UnicodeSegmentation;use util::RangeExt;use util::ResultExt;use workspace::{item::Item, Workspace}; struct SelectionLayout {    head: DisplayPoint,    cursor_shape: CursorShape,    is_newest: bool,    is_local: bool,    range: Range<DisplayPoint>,    active_rows: Range<DisplayRow>,    user_name: Option<SharedString>,} impl SelectionLayout {    fn new<T: ToPoint + ToDisplayPoint + Clone>(        selection: Selection<T>,        line_mode: bool,        cursor_shape: CursorShape,        map: &DisplaySnapshot,        is_newest: bool,        is_local: bool,        user_name: Option<SharedString>,    ) -> Self {        let point_selection = selection.map(|p| p.to_point(&map.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();        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_shape == CursorShape::Block || cursor_shape == CursorShape::Hollow)            && !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,        }    }} pub struct EditorElement {    editor: View<Editor>,    style: EditorStyle,} type DisplayRowDelta = u32; impl EditorElement {    pub(crate) const SCROLLBAR_WIDTH: Pixels = px(15.);     pub fn new(editor: &View<Editor>, style: EditorStyle) -> Self {        Self {            editor: editor.clone(),            style,        }    }     fn register_actions(&self, cx: &mut WindowContext) {        let view = &self.editor;        view.update(cx, |editor, cx| {            for action in editor.editor_actions.borrow().values() {                (action)(cx)            }        });         crate::rust_analyzer_ext::apply_related_actions(view, cx);        crate::clangd_ext::apply_related_actions(view, cx);        register_action(view, cx, Editor::open_context_menu);        register_action(view, cx, Editor::move_left);        register_action(view, cx, Editor::move_right);        register_action(view, cx, Editor::move_down);        register_action(view, cx, Editor::move_down_by_lines);        register_action(view, cx, Editor::select_down_by_lines);        register_action(view, cx, Editor::move_up);        register_action(view, cx, Editor::move_up_by_lines);        register_action(view, cx, Editor::select_up_by_lines);        register_action(view, cx, Editor::select_page_down);        register_action(view, cx, Editor::select_page_up);        register_action(view, cx, Editor::cancel);        register_action(view, cx, Editor::newline);        register_action(view, cx, Editor::newline_above);        register_action(view, cx, Editor::newline_below);        register_action(view, cx, Editor::backspace);        register_action(view, cx, Editor::delete);        register_action(view, cx, Editor::tab);        register_action(view, cx, Editor::tab_prev);        register_action(view, cx, Editor::indent);        register_action(view, cx, Editor::outdent);        register_action(view, cx, Editor::autoindent);        register_action(view, cx, Editor::delete_line);        register_action(view, cx, Editor::join_lines);        register_action(view, cx, Editor::sort_lines_case_sensitive);        register_action(view, cx, Editor::sort_lines_case_insensitive);        register_action(view, cx, Editor::reverse_lines);        register_action(view, cx, Editor::shuffle_lines);        register_action(view, cx, Editor::convert_to_upper_case);        register_action(view, cx, Editor::convert_to_lower_case);        register_action(view, cx, Editor::convert_to_title_case);        register_action(view, cx, Editor::convert_to_snake_case);        register_action(view, cx, Editor::convert_to_kebab_case);        register_action(view, cx, Editor::convert_to_upper_camel_case);        register_action(view, cx, Editor::convert_to_lower_camel_case);        register_action(view, cx, Editor::convert_to_opposite_case);        register_action(view, cx, Editor::delete_to_previous_word_start);        register_action(view, cx, Editor::delete_to_previous_subword_start);        register_action(view, cx, Editor::delete_to_next_word_end);        register_action(view, cx, Editor::delete_to_next_subword_end);        register_action(view, cx, Editor::delete_to_beginning_of_line);        register_action(view, cx, Editor::delete_to_end_of_line);        register_action(view, cx, Editor::cut_to_end_of_line);        register_action(view, cx, Editor::duplicate_line_up);        register_action(view, cx, Editor::duplicate_line_down);        register_action(view, cx, Editor::duplicate_selection);        register_action(view, cx, Editor::move_line_up);        register_action(view, cx, Editor::move_line_down);        register_action(view, cx, Editor::transpose);        register_action(view, cx, Editor::rewrap);        register_action(view, cx, Editor::cut);        register_action(view, cx, Editor::kill_ring_cut);        register_action(view, cx, Editor::kill_ring_yank);        register_action(view, cx, Editor::copy);        register_action(view, cx, Editor::paste);        register_action(view, cx, Editor::undo);        register_action(view, cx, Editor::redo);        register_action(view, cx, Editor::move_page_up);        register_action(view, cx, Editor::move_page_down);        register_action(view, cx, Editor::next_screen);        register_action(view, cx, Editor::scroll_cursor_top);        register_action(view, cx, Editor::scroll_cursor_center);        register_action(view, cx, Editor::scroll_cursor_bottom);        register_action(view, cx, Editor::scroll_cursor_center_top_bottom);        register_action(view, cx, |editor, _: &LineDown, cx| {            editor.scroll_screen(&ScrollAmount::Line(1.), cx)        });        register_action(view, cx, |editor, _: &LineUp, cx| {            editor.scroll_screen(&ScrollAmount::Line(-1.), cx)        });        register_action(view, cx, |editor, _: &HalfPageDown, cx| {            editor.scroll_screen(&ScrollAmount::Page(0.5), cx)        });        register_action(view, cx, |editor, HandleInput(text): &HandleInput, cx| {            if text.is_empty() {                return;            }            editor.handle_input(text, cx);        });        register_action(view, cx, |editor, _: &HalfPageUp, cx| {            editor.scroll_screen(&ScrollAmount::Page(-0.5), cx)        });        register_action(view, cx, |editor, _: &PageDown, cx| {            editor.scroll_screen(&ScrollAmount::Page(1.), cx)        });        register_action(view, cx, |editor, _: &PageUp, cx| {            editor.scroll_screen(&ScrollAmount::Page(-1.), cx)        });        register_action(view, cx, Editor::move_to_previous_word_start);        register_action(view, cx, Editor::move_to_previous_subword_start);        register_action(view, cx, Editor::move_to_next_word_end);        register_action(view, cx, Editor::move_to_next_subword_end);        register_action(view, cx, Editor::move_to_beginning_of_line);        register_action(view, cx, Editor::move_to_end_of_line);        register_action(view, cx, Editor::move_to_start_of_paragraph);        register_action(view, cx, Editor::move_to_end_of_paragraph);        register_action(view, cx, Editor::move_to_beginning);        register_action(view, cx, Editor::move_to_end);        register_action(view, cx, Editor::select_up);        register_action(view, cx, Editor::select_down);        register_action(view, cx, Editor::select_left);        register_action(view, cx, Editor::select_right);        register_action(view, cx, Editor::select_to_previous_word_start);        register_action(view, cx, Editor::select_to_previous_subword_start);        register_action(view, cx, Editor::select_to_next_word_end);        register_action(view, cx, Editor::select_to_next_subword_end);        register_action(view, cx, Editor::select_to_beginning_of_line);        register_action(view, cx, Editor::select_to_end_of_line);        register_action(view, cx, Editor::select_to_start_of_paragraph);        register_action(view, cx, Editor::select_to_end_of_paragraph);        register_action(view, cx, Editor::select_to_beginning);        register_action(view, cx, Editor::select_to_end);        register_action(view, cx, Editor::select_all);        register_action(view, cx, |editor, action, cx| {            editor.select_all_matches(action, cx).log_err();        });        register_action(view, cx, Editor::select_line);        register_action(view, cx, Editor::split_selection_into_lines);        register_action(view, cx, Editor::add_selection_above);        register_action(view, cx, Editor::add_selection_below);        register_action(view, cx, |editor, action, cx| {            editor.select_next(action, cx).log_err();        });        register_action(view, cx, |editor, action, cx| {            editor.select_previous(action, cx).log_err();        });        register_action(view, cx, Editor::toggle_comments);        register_action(view, cx, Editor::select_larger_syntax_node);        register_action(view, cx, Editor::select_smaller_syntax_node);        register_action(view, cx, Editor::select_enclosing_symbol);        register_action(view, cx, Editor::move_to_enclosing_bracket);        register_action(view, cx, Editor::undo_selection);        register_action(view, cx, Editor::redo_selection);        if !view.read(cx).is_singleton(cx) {            register_action(view, cx, Editor::expand_excerpts);            register_action(view, cx, Editor::expand_excerpts_up);            register_action(view, cx, Editor::expand_excerpts_down);        }        register_action(view, cx, Editor::go_to_diagnostic);        register_action(view, cx, Editor::go_to_prev_diagnostic);        register_action(view, cx, Editor::go_to_next_hunk);        register_action(view, cx, Editor::go_to_prev_hunk);        register_action(view, cx, |editor, a, cx| {            editor.go_to_definition(a, cx).detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor.go_to_definition_split(a, cx).detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor.go_to_declaration(a, cx).detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor.go_to_declaration_split(a, cx).detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor.go_to_implementation(a, cx).detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor                .go_to_implementation_split(a, cx)                .detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor.go_to_type_definition(a, cx).detach_and_log_err(cx);        });        register_action(view, cx, |editor, a, cx| {            editor                .go_to_type_definition_split(a, cx)                .detach_and_log_err(cx);        });        register_action(view, cx, Editor::open_url);        register_action(view, cx, Editor::open_file);        register_action(view, cx, Editor::fold);        register_action(view, cx, Editor::fold_at_level);        register_action(view, cx, Editor::fold_all);        register_action(view, cx, Editor::fold_function_bodies);        register_action(view, cx, Editor::fold_at);        register_action(view, cx, Editor::fold_recursive);        register_action(view, cx, Editor::toggle_fold);        register_action(view, cx, Editor::toggle_fold_recursive);        register_action(view, cx, Editor::unfold_lines);        register_action(view, cx, Editor::unfold_recursive);        register_action(view, cx, Editor::unfold_all);        register_action(view, cx, Editor::unfold_at);        register_action(view, cx, Editor::fold_selected_ranges);        register_action(view, cx, Editor::show_completions);        register_action(view, cx, Editor::toggle_code_actions);        register_action(view, cx, Editor::open_excerpts);        register_action(view, cx, Editor::open_excerpts_in_split);        register_action(view, cx, Editor::open_proposed_changes_editor);        register_action(view, cx, Editor::toggle_soft_wrap);        register_action(view, cx, Editor::toggle_tab_bar);        register_action(view, cx, Editor::toggle_line_numbers);        register_action(view, cx, Editor::toggle_relative_line_numbers);        register_action(view, cx, Editor::toggle_indent_guides);        register_action(view, cx, Editor::toggle_inlay_hints);        register_action(view, cx, Editor::toggle_inline_completions);        register_action(view, cx, hover_popover::hover);        register_action(view, cx, Editor::reveal_in_finder);        register_action(view, cx, Editor::copy_path);        register_action(view, cx, Editor::copy_relative_path);        register_action(view, cx, Editor::copy_highlight_json);        register_action(view, cx, Editor::copy_permalink_to_line);        register_action(view, cx, Editor::open_permalink_to_line);        register_action(view, cx, Editor::copy_file_location);        register_action(view, cx, Editor::toggle_git_blame);        register_action(view, cx, Editor::toggle_git_blame_inline);        register_action(view, cx, Editor::toggle_hunk_diff);        register_action(view, cx, Editor::expand_all_diff_hunks);        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.format(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.format_selections(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, Editor::restart_language_server);        register_action(view, cx, Editor::cancel_language_server_work);        register_action(view, cx, Editor::show_character_palette);        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.confirm_completion(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.compose_completion(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.confirm_code_action(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.rename(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.confirm_rename(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, |editor, action, cx| {            if let Some(task) = editor.find_all_references(action, cx) {                task.detach_and_log_err(cx);            } else {                cx.propagate();            }        });        register_action(view, cx, Editor::show_signature_help);        register_action(view, cx, Editor::next_inline_completion);        register_action(view, cx, Editor::previous_inline_completion);        register_action(view, cx, Editor::show_inline_completion);        register_action(view, cx, Editor::context_menu_first);        register_action(view, cx, Editor::context_menu_prev);        register_action(view, cx, Editor::context_menu_next);        register_action(view, cx, Editor::context_menu_last);        register_action(view, cx, Editor::display_cursor_names);        register_action(view, cx, Editor::unique_lines_case_insensitive);        register_action(view, cx, Editor::unique_lines_case_sensitive);        register_action(view, cx, Editor::accept_partial_inline_completion);        register_action(view, cx, Editor::accept_inline_completion);        register_action(view, cx, Editor::revert_file);        register_action(view, cx, Editor::revert_selected_hunks);        register_action(view, cx, Editor::apply_all_diff_hunks);        register_action(view, cx, Editor::apply_selected_diff_hunks);        register_action(view, cx, Editor::open_active_item_in_terminal);        register_action(view, cx, Editor::reload_file);        register_action(view, cx, Editor::spawn_nearest_task);        register_action(view, cx, Editor::insert_uuid_v4);        register_action(view, cx, Editor::insert_uuid_v7);    }     fn register_key_listeners(&self, cx: &mut WindowContext, layout: &EditorLayout) {        let position_map = layout.position_map.clone();        cx.on_key_event({            let editor = self.editor.clone();            let text_hitbox = layout.text_hitbox.clone();            move |event: &ModifiersChangedEvent, phase, cx| {                if phase != DispatchPhase::Bubble {                    return;                }                editor.update(cx, |editor, cx| {                    if editor.hover_state.focused(cx) {                        return;                    }                    Self::modifiers_changed(editor, event, &position_map, &text_hitbox, cx)                })            }        });    }     fn modifiers_changed(        editor: &mut Editor,        event: &ModifiersChangedEvent,        position_map: &PositionMap,        text_hitbox: &Hitbox,        cx: &mut ViewContext<Editor>,    ) {        let mouse_position = cx.mouse_position();        if !text_hitbox.is_hovered(cx) {            return;        }         editor.update_hovered_link(            position_map.point_for_position(text_hitbox.bounds, mouse_position),

Lines 1–500 of 7669.