19922 lines · 718.7 KB · Rust
RawDownload
#![allow(rustdoc::private_intra_doc_links)]//! This is the place where everything editor-related is stored (data-wise) and displayed (ui-wise).//! The main point of interest in this crate is [`Editor`] type, which is used in every other Zed part as a user input element.//! It comes in different flavors: single line, multiline and a fixed height one.//!//! Editor contains of multiple large submodules://! * [`element`] — the place where all rendering happens//! * [`display_map`] - chunks up text in the editor into the logical blocks, establishes coordinates and mapping between each of them.//!   Contains all metadata related to text transformations (folds, fake inlay text insertions, soft wraps, tab markup, etc.).//! * [`inlay_hint_cache`] - is a storage of inlay hints out of LSP requests, responsible for querying LSP and updating `display_map`'s state accordingly.//!//! All other submodules and structs are mostly concerned with holding editor data about the way it displays current buffer region(s).//!//! If you're looking to improve Vim mode, you should check out Vim crate that wraps Editor and overrides its behavior.pub mod actions;mod blink_manager;mod clangd_ext;mod code_context_menus;pub mod commit_tooltip;pub mod display_map;mod editor_settings;mod editor_settings_controls;mod element;mod git;mod highlight_matching_bracket;mod hover_links;mod hover_popover;mod indent_guides;mod inlay_hint_cache;pub mod items;mod jsx_tag_auto_close;mod linked_editing_ranges;mod lsp_ext;mod mouse_context_menu;pub mod movement;mod persistence;mod proposed_changes_editor;mod rust_analyzer_ext;pub mod scroll;mod selections_collection;pub mod tasks; #[cfg(test)]mod editor_tests;#[cfg(test)]mod inline_completion_tests;mod signature_help;#[cfg(any(test, feature = "test-support"))]pub mod test; pub(crate) use actions::*;pub use actions::{AcceptEditPrediction, OpenExcerpts, OpenExcerptsSplit};use aho_corasick::AhoCorasick;use anyhow::{anyhow, Context as _, Result};use blink_manager::BlinkManager;use buffer_diff::DiffHunkStatus;use client::{Collaborator, ParticipantIndex};use clock::ReplicaId;use collections::{BTreeMap, HashMap, HashSet, VecDeque};use convert_case::{Case, Casing};use display_map::*;pub use display_map::{DisplayPoint, FoldPlaceholder};use editor_settings::GoToDefinitionFallback;pub use editor_settings::{    CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,};pub use editor_settings_controls::*;use element::{layout_line, AcceptEditPredictionBinding, LineWithInvisibles, PositionMap};pub use element::{    CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,};use feature_flags::{Debugger, FeatureFlagAppExt};use futures::{    future::{self, join, Shared},    FutureExt,};use fuzzy::StringMatchCandidate; use ::git::Restore;use code_context_menus::{    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,    CompletionsMenu, ContextMenuOrigin,};use git::blame::GitBlame;use gpui::{    div, impl_actions, point, prelude::*, pulsating_between, px, relative, size, Action, Animation,    AnimationExt, AnyElement, App, AppContext, AsyncWindowContext, AvailableSpace, Background,    Bounds, ClickEvent, ClipboardEntry, ClipboardItem, Context, DispatchPhase, Edges, Entity,    EntityInputHandler, EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight,    Global, HighlightStyle, Hsla, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad,    ParentElement, Pixels, Render, SharedString, Size, Stateful, Styled, StyledText, Subscription,    Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle,    WeakEntity, WeakFocusHandle, Window,};use highlight_matching_bracket::refresh_matching_bracket_highlights;use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};use hover_popover::{hide_hover, HoverState};use indent_guides::ActiveIndentGuidesState;use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};pub use inline_completion::Direction;use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};pub use items::MAX_TAB_TITLE_LEN;use itertools::Itertools;use language::{    language_settings::{        self, all_language_settings, language_settings, InlayHintSettings, RewrapBehavior,        WordsCompletionMode,    },    point_from_lsp, text_diff_with_options, AutoindentMode, BracketMatch, BracketPair, Buffer,    Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, EditPredictionsMode,    EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,    Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions, WordsQuery,};use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};use linked_editing_ranges::refresh_linked_ranges;use mouse_context_menu::MouseContextMenu;use persistence::DB;use project::{    debugger::breakpoint_store::{        BreakpointEditAction, BreakpointState, BreakpointStore, BreakpointStoreEvent,    },    ProjectPath,}; pub use proposed_changes_editor::{    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,};use smallvec::smallvec;use std::{cell::OnceCell, iter::Peekable};use task::{ResolvedTask, TaskTemplate, TaskVariables}; pub use lsp::CompletionContext;use lsp::{    CodeActionKind, CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity,    InsertTextFormat, LanguageServerId, LanguageServerName,}; use language::BufferSnapshot;use movement::TextLayoutDetails;pub use multi_buffer::{    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,    ToOffset, ToPoint,};use multi_buffer::{    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,    MultiOrSingleBufferOffsetRange, ToOffsetUtf16,};use parking_lot::Mutex;use project::{    debugger::breakpoint_store::{Breakpoint, BreakpointKind},    lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle},    project_settings::{GitGutterSetting, ProjectSettings},    CodeAction, Completion, CompletionIntent, CompletionSource, DocumentHighlight, InlayHint,    Location, LocationLink, PrepareRenameResponse, Project, ProjectItem, ProjectTransaction,    TaskSourceKind,};use rand::prelude::*;use rpc::{proto::*, ErrorExt};use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};use selections_collection::{    resolve_selections, MutableSelectionsCollection, SelectionsCollection,};use serde::{Deserialize, Serialize};use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};use smallvec::SmallVec;use snippet::Snippet;use std::sync::Arc;use std::{    any::TypeId,    borrow::Cow,    cell::RefCell,    cmp::{self, Ordering, Reverse},    mem,    num::NonZeroU32,    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},    path::{Path, PathBuf},    rc::Rc,    time::{Duration, Instant},};pub use sum_tree::Bias;use sum_tree::TreeMap;use text::{BufferId, OffsetUtf16, Rope};use theme::{    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,    ThemeColors, ThemeSettings,};use ui::{    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,    Tooltip,};use util::{maybe, post_inc, RangeExt, ResultExt, TryFutureExt};use workspace::{    item::{ItemHandle, PreviewTabsSettings},    notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt},    searchable::SearchEvent,    Item as WorkspaceItem, ItemId, ItemNavHistory, OpenInTerminal, OpenTerminal,    RestoreOnStartupBehavior, SplitDirection, TabBarSettings, Toast, ViewId, Workspace,    WorkspaceId, WorkspaceSettings, SERIALIZATION_THROTTLE_TIME,}; use crate::hover_links::{find_url, find_url_from_range};use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState}; pub const FILE_HEADER_HEIGHT: u32 = 2;pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);const MAX_LINE_LEN: usize = 1024;const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;const MAX_SELECTION_HISTORY_LEN: usize = 1024;pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);#[doc(hidden)]pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250); pub(crate) const CODE_ACTION_TIMEOUT: Duration = Duration::from_secs(5);pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(5);pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1); pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";pub(crate) const MIN_LINE_NUMBER_DIGITS: u32 = 4; const COLUMNAR_SELECTION_MODIFIERS: Modifiers = Modifiers {    alt: true,    shift: true,    control: false,    platform: false,    function: false,}; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]pub enum InlayId {    InlineCompletion(usize),    Hint(usize),} impl InlayId {    fn id(&self) -> usize {        match self {            Self::InlineCompletion(id) => *id,            Self::Hint(id) => *id,        }    }} pub enum DebugCurrentRowHighlight {}enum DocumentHighlightRead {}enum DocumentHighlightWrite {}enum InputComposition {}enum SelectedTextHighlight {} #[derive(Debug, Copy, Clone, PartialEq, Eq)]pub enum Navigated {    Yes,    No,} impl Navigated {    pub fn from_bool(yes: bool) -> Navigated {        if yes {            Navigated::Yes        } else {            Navigated::No        }    }} #[derive(Debug, Clone, PartialEq, Eq)]enum DisplayDiffHunk {    Folded {        display_row: DisplayRow,    },    Unfolded {        is_created_file: bool,        diff_base_byte_range: Range<usize>,        display_row_range: Range<DisplayRow>,        multi_buffer_range: Range<Anchor>,        status: DiffHunkStatus,    },} pub fn init_settings(cx: &mut App) {    EditorSettings::register(cx);} pub fn init(cx: &mut App) {    init_settings(cx);     workspace::register_project_item::<Editor>(cx);    workspace::FollowableViewRegistry::register::<Editor>(cx);    workspace::register_serializable_item::<Editor>(cx);     cx.observe_new(        |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {            workspace.register_action(Editor::new_file);            workspace.register_action(Editor::new_file_vertical);            workspace.register_action(Editor::new_file_horizontal);            workspace.register_action(Editor::cancel_language_server_work);        },    )    .detach();     cx.on_action(move |_: &workspace::NewFile, cx| {        let app_state = workspace::AppState::global(cx);        if let Some(app_state) = app_state.upgrade() {            workspace::open_new(                Default::default(),                app_state,                cx,                |workspace, window, cx| {                    Editor::new_file(workspace, &Default::default(), window, cx)                },            )            .detach();        }    });    cx.on_action(move |_: &workspace::NewWindow, cx| {        let app_state = workspace::AppState::global(cx);        if let Some(app_state) = app_state.upgrade() {            workspace::open_new(                Default::default(),                app_state,                cx,                |workspace, window, cx| {                    cx.activate(true);                    Editor::new_file(workspace, &Default::default(), window, cx)                },            )            .detach();        }    });} pub struct SearchWithinRange; trait InvalidationRegion {    fn ranges(&self) -> &[Range<Anchor>];} #[derive(Clone, Debug, PartialEq)]pub enum SelectPhase {    Begin {        position: DisplayPoint,        add: bool,        click_count: usize,    },    BeginColumnar {        position: DisplayPoint,        reset: bool,        goal_column: u32,    },    Extend {        position: DisplayPoint,        click_count: usize,    },    Update {        position: DisplayPoint,        goal_column: u32,        scroll_delta: gpui::Point<f32>,    },    End,} #[derive(Clone, Debug)]pub enum SelectMode {    Character,    Word(Range<Anchor>),    Line(Range<Anchor>),    All,} #[derive(Copy, Clone, PartialEq, Eq, Debug)]pub enum EditorMode {    SingleLine { auto_width: bool },    AutoHeight { max_lines: usize },    Full,} #[derive(Copy, Clone, Debug)]pub enum SoftWrap {    /// Prefer not to wrap at all.    ///    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.    GitDiff,    /// Prefer a single line generally, unless an overly long line is encountered.    None,    /// Soft wrap lines that exceed the editor width.    EditorWidth,    /// Soft wrap lines at the preferred line length.    Column(u32),    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).    Bounded(u32),} #[derive(Clone)]pub struct EditorStyle {    pub background: Hsla,    pub local_player: PlayerColor,    pub text: TextStyle,    pub scrollbar_width: Pixels,    pub syntax: Arc<SyntaxTheme>,    pub status: StatusColors,    pub inlay_hints_style: HighlightStyle,    pub inline_completion_styles: InlineCompletionStyles,    pub unnecessary_code_fade: f32,} 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(),            inlay_hints_style: HighlightStyle::default(),            inline_completion_styles: InlineCompletionStyles {                insertion: HighlightStyle::default(),                whitespace: HighlightStyle::default(),            },            unnecessary_code_fade: Default::default(),        }    }} pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {    let show_background = language_settings::language_settings(None, None, cx)        .inlay_hints        .show_background;     HighlightStyle {        color: Some(cx.theme().status().hint),        background_color: show_background.then(|| cx.theme().status().hint_background),        ..HighlightStyle::default()    }} pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {    InlineCompletionStyles {        insertion: HighlightStyle {            color: Some(cx.theme().status().predictive),            ..HighlightStyle::default()        },        whitespace: HighlightStyle {            background_color: Some(cx.theme().status().created_background),            ..HighlightStyle::default()        },    }} type CompletionId = usize; pub(crate) enum EditDisplayMode {    TabAccept,    DiffPopover,    Inline,} enum InlineCompletion {    Edit {        edits: Vec<(Range<Anchor>, String)>,        edit_preview: Option<EditPreview>,        display_mode: EditDisplayMode,        snapshot: BufferSnapshot,    },    Move {        target: Anchor,        snapshot: BufferSnapshot,    },} struct InlineCompletionState {    inlay_ids: Vec<InlayId>,    completion: InlineCompletion,    completion_id: Option<SharedString>,    invalidation_range: Range<Anchor>,} enum EditPredictionSettings {    Disabled,    Enabled {        show_in_menu: bool,        preview_requires_modifier: bool,    },} enum InlineCompletionHighlight {} #[derive(Debug, Clone)]struct InlineDiagnostic {    message: SharedString,    group_id: usize,    is_primary: bool,    start: Point,    severity: DiagnosticSeverity,

Lines 1–500 of 19922.