Persist selections for editors (#25083)

Part of https://github.com/zed-industries/zed/issues/7371
Closes https://github.com/zed-industries/zed/issues/12853

Release Notes:

- Started to persist latest selections for editors, to restore those on
restart
This commit is contained in:
Kirill Bulatov 2025-02-18 16:27:00 +02:00 committed by GitHub
parent b34037876e
commit 80458ffb96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 159 additions and 5 deletions

View file

@ -106,6 +106,7 @@ use language::{
use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
use linked_editing_ranges::refresh_linked_ranges;
use mouse_context_menu::MouseContextMenu;
use persistence::DB;
pub use proposed_changes_editor::{
ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
};
@ -171,8 +172,14 @@ use ui::{
Tooltip,
};
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
use workspace::item::{ItemHandle, PreviewTabsSettings};
use workspace::notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt};
use workspace::{
item::{ItemHandle, PreviewTabsSettings},
ItemId, RestoreOnStartupBehavior,
};
use workspace::{
notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt},
WorkspaceSettings,
};
use workspace::{
searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
};
@ -763,6 +770,7 @@ pub struct Editor {
selection_mark_mode: bool,
toggle_fold_multiple_buffers: Task<()>,
_scroll_cursor_center_top_bottom_task: Task<()>,
serialize_selections: Task<()>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@ -1475,6 +1483,7 @@ impl Editor {
_scroll_cursor_center_top_bottom_task: Task::ready(()),
selection_mark_mode: false,
toggle_fold_multiple_buffers: Task::ready(()),
serialize_selections: Task::ready(()),
text_style_refinement: None,
load_diff_task: load_uncommitted_diff,
};
@ -2181,9 +2190,37 @@ impl Editor {
self.blink_manager.update(cx, BlinkManager::pause_blinking);
cx.emit(EditorEvent::SelectionsChanged { local });
if self.selections.disjoint_anchors().len() == 1 {
let selections = &self.selections.disjoint;
if selections.len() == 1 {
cx.emit(SearchEvent::ActiveMatchChanged)
}
if local
&& WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
{
if let Some(workspace_id) = self.workspace.as_ref().and_then(|workspace| workspace.1) {
let background_executor = cx.background_executor().clone();
let editor_id = cx.entity().entity_id().as_u64() as ItemId;
let snapshot = self.buffer().read(cx).snapshot(cx);
let selections = selections.clone();
self.serialize_selections = cx.background_spawn(async move {
background_executor.timer(Duration::from_millis(100)).await;
let selections = selections
.iter()
.map(|selection| {
(
selection.start.to_offset(&snapshot),
selection.end.to_offset(&snapshot),
)
})
.collect();
DB.save_editor_selections(editor_id, workspace_id, selections)
.await
.context("persisting editor selections")
.log_err();
});
}
}
cx.notify();
}
@ -2197,7 +2234,7 @@ impl Editor {
self.change_selections_inner(autoscroll, true, window, cx, change)
}
pub fn change_selections_inner<R>(
fn change_selections_inner<R>(
&mut self,
autoscroll: Option<Autoscroll>,
request_completions: bool,
@ -14982,6 +15019,31 @@ impl Editor {
pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
self.load_diff_task.clone()
}
fn read_selections_from_db(
&mut self,
item_id: u64,
workspace_id: WorkspaceId,
window: &mut Window,
cx: &mut Context<Editor>,
) {
if WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None {
return;
}
let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err() else {
return;
};
if selections.is_empty() {
return;
}
let snapshot = self.buffer.read(cx).snapshot(cx);
self.change_selections(None, window, cx, |s| {
s.select_ranges(selections.into_iter().map(|(start, end)| {
snapshot.clip_offset(start, Bias::Left)..snapshot.clip_offset(end, Bias::Right)
}));
});
}
}
fn get_uncommitted_diff_for_buffer(