10228 lines · 368.3 KB · Rust
RawDownload
pub mod dock;pub mod history_manager;pub mod item;mod modal_layer;pub mod notifications;pub mod pane;pub mod pane_group;mod persistence;pub mod searchable;pub mod shared_screen;mod status_bar;pub mod tasks;mod theme_preview;mod toast_layer;mod toolbar;mod workspace_settings; pub use toast_layer::{RunAction, ToastAction, ToastLayer, ToastView}; use anyhow::{Context as _, Result, anyhow};use call::{ActiveCall, call_settings::CallSettings};use client::{    ChannelId, Client, ErrorExt, Status, TypedEnvelope, UserStore,    proto::{self, ErrorCode, PanelId, PeerId},};use collections::{HashMap, HashSet, hash_map};pub use dock::Panel;use dock::{Dock, DockPosition, PanelButtons, PanelHandle, RESIZE_HANDLE_SIZE};use futures::{    Future, FutureExt, StreamExt,    channel::{        mpsc::{self, UnboundedReceiver, UnboundedSender},        oneshot,    },    future::try_join_all,};use gpui::{    Action, AnyEntity, AnyView, AnyWeakView, App, AsyncApp, AsyncWindowContext, Bounds, Context,    CursorStyle, Decorations, DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle,    Focusable, Global, HitboxBehavior, Hsla, KeyContext, Keystroke, ManagedView, MouseButton,    PathPromptOptions, Point, PromptLevel, Render, ResizeEdge, Size, Stateful, Subscription, Task,    Tiling, WeakEntity, WindowBounds, WindowHandle, WindowId, WindowOptions, action_as, actions,    canvas, impl_action_as, impl_actions, point, relative, size, transparent_black,};pub use history_manager::*;pub use item::{    FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,    ProjectItem, SerializableItem, SerializableItemHandle, WeakItemHandle,};use itertools::Itertools;use language::{Buffer, LanguageRegistry, Rope};pub use modal_layer::*;use node_runtime::NodeRuntime;use notifications::{    DetachAndPromptErr, Notifications, dismiss_app_notification,    simple_message_notification::MessageNotification,};pub use pane::*;pub use pane_group::*;use persistence::{    DB, SerializedWindowBounds,    model::{SerializedSshProject, SerializedWorkspace},};pub use persistence::{    DB as WORKSPACE_DB, WorkspaceDb, delete_unloaded_items,    model::{ItemId, LocalPaths, SerializedWorkspaceLocation},};use postage::stream::Stream;use project::{    DirectoryLister, Project, ProjectEntryId, ProjectPath, ResolvedPath, Worktree, WorktreeId,    debugger::{breakpoint_store::BreakpointStoreEvent, session::ThreadStatus},};use remote::{SshClientDelegate, SshConnectionOptions, ssh_session::ConnectionIdentifier};use schemars::JsonSchema;use serde::Deserialize;use session::AppSession;use settings::Settings;use shared_screen::SharedScreen;use sqlez::{    bindable::{Bind, Column, StaticColumnCount},    statement::Statement,};use status_bar::StatusBar;pub use status_bar::StatusItemView;use std::{    any::TypeId,    borrow::Cow,    cell::RefCell,    cmp,    collections::hash_map::DefaultHasher,    env,    hash::{Hash, Hasher},    path::{Path, PathBuf},    process::ExitStatus,    rc::Rc,    sync::{Arc, LazyLock, Weak, atomic::AtomicUsize},    time::Duration,};use task::{DebugScenario, SpawnInTerminal, TaskContext};use theme::{ActiveTheme, SystemAppearance, ThemeSettings};pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};pub use ui;use ui::{Window, prelude::*};use util::{ResultExt, TryFutureExt, paths::SanitizedPath, serde::default_true};use uuid::Uuid;pub use workspace_settings::{    AutosaveSetting, BottomDockLayout, RestoreOnStartupBehavior, TabBarSettings, WorkspaceSettings,};use zed_actions::{Spawn, feedback::FileBugReport}; use crate::notifications::NotificationId;use crate::persistence::{    SerializedAxis,    model::{DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup},}; pub const SERIALIZATION_THROTTLE_TIME: Duration = Duration::from_millis(200); static ZED_WINDOW_SIZE: LazyLock<Option<Size<Pixels>>> = LazyLock::new(|| {    env::var("ZED_WINDOW_SIZE")        .ok()        .as_deref()        .and_then(parse_pixel_size_env_var)}); static ZED_WINDOW_POSITION: LazyLock<Option<Point<Pixels>>> = LazyLock::new(|| {    env::var("ZED_WINDOW_POSITION")        .ok()        .as_deref()        .and_then(parse_pixel_position_env_var)}); pub trait TerminalProvider {    fn spawn(        &self,        task: SpawnInTerminal,        window: &mut Window,        cx: &mut App,    ) -> Task<Option<Result<ExitStatus>>>;} pub trait DebuggerProvider {    // `active_buffer` is used to resolve build task's name against language-specific tasks.    fn start_session(        &self,        definition: DebugScenario,        task_context: TaskContext,        active_buffer: Option<Entity<Buffer>>,        window: &mut Window,        cx: &mut App,    );     fn spawn_task_or_modal(        &self,        workspace: &mut Workspace,        action: &Spawn,        window: &mut Window,        cx: &mut Context<Workspace>,    );     fn task_scheduled(&self, cx: &mut App);    fn debug_scenario_scheduled(&self, cx: &mut App);    fn debug_scenario_scheduled_last(&self, cx: &App) -> bool;     fn active_thread_state(&self, cx: &App) -> Option<ThreadStatus>;} actions!(    workspace,    [        ActivateNextPane,        ActivatePreviousPane,        ActivateNextWindow,        ActivatePreviousWindow,        AddFolderToProject,        ClearAllNotifications,        CloseActiveDock,        CloseAllDocks,        CloseWindow,        Feedback,        FollowNextCollaborator,        MoveFocusedPanelToNextPosition,        NewCenterTerminal,        NewFile,        NewFileSplitVertical,        NewFileSplitHorizontal,        NewSearch,        NewTerminal,        NewWindow,        Open,        OpenFiles,        OpenInTerminal,        OpenComponentPreview,        ReloadActiveItem,        SaveAs,        SaveWithoutFormat,        ShutdownDebugAdapters,        SuppressNotification,        ToggleBottomDock,        ToggleCenteredLayout,        ToggleLeftDock,        ToggleRightDock,        ToggleZoom,        Unfollow,        Welcome,        RestoreBanner,        ToggleExpandItem,    ]); #[derive(Clone, PartialEq)]pub struct OpenPaths {    pub paths: Vec<PathBuf>,} #[derive(Clone, Deserialize, PartialEq, JsonSchema)]pub struct ActivatePane(pub usize); #[derive(Clone, Deserialize, PartialEq, JsonSchema)]#[serde(deny_unknown_fields)]pub struct MoveItemToPane {    pub destination: usize,    #[serde(default = "default_true")]    pub focus: bool,} #[derive(Clone, Deserialize, PartialEq, JsonSchema)]#[serde(deny_unknown_fields)]pub struct MoveItemToPaneInDirection {    pub direction: SplitDirection,    #[serde(default = "default_true")]    pub focus: bool,} #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]#[serde(deny_unknown_fields)]pub struct SaveAll {    pub save_intent: Option<SaveIntent>,} #[derive(Clone, PartialEq, Debug, Deserialize, JsonSchema)]#[serde(deny_unknown_fields)]pub struct Save {    pub save_intent: Option<SaveIntent>,} #[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)]#[serde(deny_unknown_fields)]pub struct CloseAllItemsAndPanes {    pub save_intent: Option<SaveIntent>,} #[derive(Clone, PartialEq, Debug, Deserialize, Default, JsonSchema)]#[serde(deny_unknown_fields)]pub struct CloseInactiveTabsAndPanes {    pub save_intent: Option<SaveIntent>,} #[derive(Clone, Deserialize, PartialEq, JsonSchema)]pub struct SendKeystrokes(pub String); #[derive(Clone, Deserialize, PartialEq, Default, JsonSchema)]#[serde(deny_unknown_fields)]pub struct Reload {    pub binary_path: Option<PathBuf>,} action_as!(project_symbols, ToggleProjectSymbols as Toggle); #[derive(Default, PartialEq, Eq, Clone, Deserialize, JsonSchema)]pub struct ToggleFileFinder {    #[serde(default)]    pub separate_history: bool,} impl_action_as!(file_finder, ToggleFileFinder as Toggle); impl_actions!(    workspace,    [        ActivatePane,        CloseAllItemsAndPanes,        CloseInactiveTabsAndPanes,        MoveItemToPane,        MoveItemToPaneInDirection,        OpenTerminal,        Reload,        Save,        SaveAll,        SendKeystrokes,    ]); actions!(    workspace,    [        ActivatePaneLeft,        ActivatePaneRight,        ActivatePaneUp,        ActivatePaneDown,        SwapPaneLeft,        SwapPaneRight,        SwapPaneUp,        SwapPaneDown,    ]); #[derive(PartialEq, Eq, Debug)]pub enum CloseIntent {    /// Quit the program entirely.    Quit,    /// Close a window.    CloseWindow,    /// Replace the workspace in an existing window.    ReplaceWindow,} #[derive(Clone)]pub struct Toast {    id: NotificationId,    msg: Cow<'static, str>,    autohide: bool,    on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut Window, &mut App)>)>,} impl Toast {    pub fn new<I: Into<Cow<'static, str>>>(id: NotificationId, msg: I) -> Self {        Toast {            id,            msg: msg.into(),            on_click: None,            autohide: false,        }    }     pub fn on_click<F, M>(mut self, message: M, on_click: F) -> Self    where        M: Into<Cow<'static, str>>,        F: Fn(&mut Window, &mut App) + 'static,    {        self.on_click = Some((message.into(), Arc::new(on_click)));        self    }     pub fn autohide(mut self) -> Self {        self.autohide = true;        self    }} impl PartialEq for Toast {    fn eq(&self, other: &Self) -> bool {        self.id == other.id            && self.msg == other.msg            && self.on_click.is_some() == other.on_click.is_some()    }} #[derive(Debug, Default, Clone, Deserialize, PartialEq, JsonSchema)]#[serde(deny_unknown_fields)]pub struct OpenTerminal {    pub working_directory: PathBuf,} #[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]pub struct WorkspaceId(i64); impl StaticColumnCount for WorkspaceId {}impl Bind for WorkspaceId {    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {        self.0.bind(statement, start_index)    }}impl Column for WorkspaceId {    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {        i64::column(statement, start_index)            .map(|(i, next_index)| (Self(i), next_index))            .with_context(|| format!("Failed to read WorkspaceId at index {start_index}"))    }}impl From<WorkspaceId> for i64 {    fn from(val: WorkspaceId) -> Self {        val.0    }} pub fn init_settings(cx: &mut App) {    WorkspaceSettings::register(cx);    ItemSettings::register(cx);    PreviewTabsSettings::register(cx);    TabBarSettings::register(cx);} fn prompt_and_open_paths(app_state: Arc<AppState>, options: PathPromptOptions, cx: &mut App) {    let paths = cx.prompt_for_paths(options);    cx.spawn(        async move |cx| match paths.await.anyhow().and_then(|res| res) {            Ok(Some(paths)) => {                cx.update(|cx| {                    open_paths(&paths, app_state, OpenOptions::default(), cx).detach_and_log_err(cx)                })                .ok();            }            Ok(None) => {}            Err(err) => {                util::log_err(&err);                cx.update(|cx| {                    if let Some(workspace_window) = cx                        .active_window()                        .and_then(|window| window.downcast::<Workspace>())                    {                        workspace_window                            .update(cx, |workspace, _, cx| {                                workspace.show_portal_error(err.to_string(), cx);                            })                            .ok();                    }                })                .ok();            }        },    )    .detach();} pub fn init(app_state: Arc<AppState>, cx: &mut App) {    init_settings(cx);    component::init();    theme_preview::init(cx);    toast_layer::init(cx);    history_manager::init(cx);     cx.on_action(Workspace::close_global);    cx.on_action(reload);     cx.on_action({        let app_state = Arc::downgrade(&app_state);        move |_: &Open, cx: &mut App| {            if let Some(app_state) = app_state.upgrade() {                prompt_and_open_paths(                    app_state,                    PathPromptOptions {                        files: true,                        directories: true,                        multiple: true,                    },                    cx,                );            }        }    });    cx.on_action({        let app_state = Arc::downgrade(&app_state);        move |_: &OpenFiles, cx: &mut App| {            let directories = cx.can_select_mixed_files_and_dirs();            if let Some(app_state) = app_state.upgrade() {                prompt_and_open_paths(                    app_state,                    PathPromptOptions {                        files: true,                        directories,                        multiple: true,                    },                    cx,                );            }        }    });} type BuildProjectItemFn =    fn(AnyEntity, Entity<Project>, Option<&Pane>, &mut Window, &mut App) -> Box<dyn ItemHandle>; type BuildProjectItemForPathFn =    fn(        &Entity<Project>,        &ProjectPath,        &mut Window,        &mut App,    ) -> Option<Task<Result<(Option<ProjectEntryId>, WorkspaceItemBuilder)>>>; #[derive(Clone, Default)]struct ProjectItemRegistry {    build_project_item_fns_by_type: HashMap<TypeId, BuildProjectItemFn>,    build_project_item_for_path_fns: Vec<BuildProjectItemForPathFn>,} impl ProjectItemRegistry {    fn register<T: ProjectItem>(&mut self) {        self.build_project_item_fns_by_type.insert(            TypeId::of::<T::Item>(),            |item, project, pane, window, cx| {                let item = item.downcast().unwrap();                Box::new(cx.new(|cx| T::for_project_item(project, pane, item, window, cx)))                    as Box<dyn ItemHandle>            },        );        self.build_project_item_for_path_fns            .push(|project, project_path, window, cx| {                let project_item =

Lines 1–500 of 10228.