Detailed changes
@@ -1677,8 +1677,10 @@ impl ContextEditor {
});
}
- fn cursors(&self, cx: &AppContext) -> Vec<usize> {
- let selections = self.editor.read(cx).selections.all::<usize>(cx);
+ fn cursors(&self, cx: &mut WindowContext) -> Vec<usize> {
+ let selections = self
+ .editor
+ .update(cx, |editor, cx| editor.selections.all::<usize>(cx));
selections
.into_iter()
.map(|selection| selection.head())
@@ -2385,7 +2387,9 @@ impl ContextEditor {
}
fn update_active_patch(&mut self, cx: &mut ViewContext<Self>) {
- let newest_cursor = self.editor.read(cx).selections.newest::<Point>(cx).head();
+ let newest_cursor = self.editor.update(cx, |editor, cx| {
+ editor.selections.newest::<Point>(cx).head()
+ });
let context = self.context.read(cx);
let new_patch = context.patch_containing(newest_cursor, cx).cloned();
@@ -2792,39 +2796,40 @@ impl ContextEditor {
) -> Option<(String, bool)> {
const CODE_FENCE_DELIMITER: &'static str = "```";
- let context_editor = context_editor_view.read(cx).editor.read(cx);
-
- if context_editor.selections.newest::<Point>(cx).is_empty() {
- let snapshot = context_editor.buffer().read(cx).snapshot(cx);
- let (_, _, snapshot) = snapshot.as_singleton()?;
-
- let head = context_editor.selections.newest::<Point>(cx).head();
- let offset = snapshot.point_to_offset(head);
+ let context_editor = context_editor_view.read(cx).editor.clone();
+ context_editor.update(cx, |context_editor, cx| {
+ if context_editor.selections.newest::<Point>(cx).is_empty() {
+ let snapshot = context_editor.buffer().read(cx).snapshot(cx);
+ let (_, _, snapshot) = snapshot.as_singleton()?;
+
+ let head = context_editor.selections.newest::<Point>(cx).head();
+ let offset = snapshot.point_to_offset(head);
+
+ let surrounding_code_block_range = find_surrounding_code_block(snapshot, offset)?;
+ let mut text = snapshot
+ .text_for_range(surrounding_code_block_range)
+ .collect::<String>();
+
+ // If there is no newline trailing the closing three-backticks, then
+ // tree-sitter-md extends the range of the content node to include
+ // the backticks.
+ if text.ends_with(CODE_FENCE_DELIMITER) {
+ text.drain((text.len() - CODE_FENCE_DELIMITER.len())..);
+ }
- let surrounding_code_block_range = find_surrounding_code_block(snapshot, offset)?;
- let mut text = snapshot
- .text_for_range(surrounding_code_block_range)
- .collect::<String>();
+ (!text.is_empty()).then_some((text, true))
+ } else {
+ let anchor = context_editor.selections.newest_anchor();
+ let text = context_editor
+ .buffer()
+ .read(cx)
+ .read(cx)
+ .text_for_range(anchor.range())
+ .collect::<String>();
- // If there is no newline trailing the closing three-backticks, then
- // tree-sitter-md extends the range of the content node to include
- // the backticks.
- if text.ends_with(CODE_FENCE_DELIMITER) {
- text.drain((text.len() - CODE_FENCE_DELIMITER.len())..);
+ (!text.is_empty()).then_some((text, false))
}
-
- (!text.is_empty()).then_some((text, true))
- } else {
- let anchor = context_editor.selections.newest_anchor();
- let text = context_editor
- .buffer()
- .read(cx)
- .read(cx)
- .text_for_range(anchor.range())
- .collect::<String>();
-
- (!text.is_empty()).then_some((text, false))
- }
+ })
}
fn insert_selection(
@@ -189,11 +189,16 @@ impl InlineAssistant {
initial_prompt: Option<String>,
cx: &mut WindowContext,
) {
- let snapshot = editor.read(cx).buffer().read(cx).snapshot(cx);
+ let (snapshot, initial_selections) = editor.update(cx, |editor, cx| {
+ (
+ editor.buffer().read(cx).snapshot(cx),
+ editor.selections.all::<Point>(cx),
+ )
+ });
let mut selections = Vec::<Selection<Point>>::new();
let mut newest_selection = None;
- for mut selection in editor.read(cx).selections.all::<Point>(cx) {
+ for mut selection in initial_selections {
if selection.end > selection.start {
selection.start.column = 0;
// If the selection ends at the start of the line, we don't want to include it.
@@ -566,10 +571,13 @@ impl InlineAssistant {
return;
};
- let editor = editor.read(cx);
- if editor.selections.count() == 1 {
- let selection = editor.selections.newest::<usize>(cx);
- let buffer = editor.buffer().read(cx).snapshot(cx);
+ if editor.read(cx).selections.count() == 1 {
+ let (selection, buffer) = editor.update(cx, |editor, cx| {
+ (
+ editor.selections.newest::<usize>(cx),
+ editor.buffer().read(cx).snapshot(cx),
+ )
+ });
for assist_id in &editor_assists.assist_ids {
let assist = &self.assists[assist_id];
let assist_range = assist.range.to_offset(&buffer);
@@ -594,10 +602,13 @@ impl InlineAssistant {
return;
};
- let editor = editor.read(cx);
- if editor.selections.count() == 1 {
- let selection = editor.selections.newest::<usize>(cx);
- let buffer = editor.buffer().read(cx).snapshot(cx);
+ if editor.read(cx).selections.count() == 1 {
+ let (selection, buffer) = editor.update(cx, |editor, cx| {
+ (
+ editor.selections.newest::<usize>(cx),
+ editor.buffer().read(cx).snapshot(cx),
+ )
+ });
let mut closest_assist_fallback = None;
for assist_id in &editor_assists.assist_ids {
let assist = &self.assists[assist_id];
@@ -1957,9 +1957,10 @@ async fn test_following_to_channel_notes_without_a_shared_project(
});
channel_notes_1_b.update(cx_b, |notes, cx| {
assert_eq!(notes.channel(cx).unwrap().name, "channel-1");
- let editor = notes.editor.read(cx);
- assert_eq!(editor.text(cx), "Hello from A.");
- assert_eq!(editor.selections.ranges::<usize>(cx), &[3..4]);
+ notes.editor.update(cx, |editor, cx| {
+ assert_eq!(editor.text(cx), "Hello from A.");
+ assert_eq!(editor.selections.ranges::<usize>(cx), &[3..4]);
+ })
});
// Client A opens the notes for channel 2.
@@ -136,11 +136,12 @@ impl DiagnosticIndicator {
}
fn update(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
- let editor = editor.read(cx);
- let buffer = editor.buffer().read(cx);
- let cursor_position = editor.selections.newest::<usize>(cx).head();
+ let (buffer, cursor_position) = editor.update(cx, |editor, cx| {
+ let buffer = editor.buffer().read(cx).snapshot(cx);
+ let cursor_position = editor.selections.newest::<usize>(cx).head();
+ (buffer, cursor_position)
+ });
let new_diagnostic = buffer
- .snapshot(cx)
.diagnostics_in_range::<_, usize>(cursor_position..cursor_position, false)
.filter(|entry| !entry.range.is_empty())
.min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))
@@ -9629,8 +9629,8 @@ impl Editor {
let Some(provider) = self.semantics_provider.clone() else {
return Task::ready(Ok(Navigated::No));
};
- let buffer = self.buffer.read(cx);
let head = self.selections.newest::<usize>(cx).head();
+ let buffer = self.buffer.read(cx);
let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
text_anchor
} else {
@@ -9937,8 +9937,8 @@ impl Editor {
_: &FindAllReferences,
cx: &mut ViewContext<Self>,
) -> Option<Task<Result<Navigated>>> {
- let multi_buffer = self.buffer.read(cx);
let selection = self.selections.newest::<usize>(cx);
+ let multi_buffer = self.buffer.read(cx);
let head = selection.head();
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
@@ -10345,8 +10345,9 @@ impl Editor {
self.show_local_selections = true;
if moving_cursor {
- let rename_editor = rename.editor.read(cx);
- let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
+ let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
+ editor.selections.newest::<usize>(cx).head()
+ });
// Update the selection to match the position of the selection inside
// the rename editor.
@@ -11592,9 +11593,9 @@ impl Editor {
}
pub fn copy_file_location(&mut self, _: &CopyFileLocation, cx: &mut ViewContext<Self>) {
+ let selection = self.selections.newest::<Point>(cx).start.row + 1;
if let Some(file) = self.target_file(cx) {
if let Some(path) = file.path().to_str() {
- let selection = self.selections.newest::<Point>(cx).start.row + 1;
cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
}
}
@@ -12370,9 +12371,10 @@ impl Editor {
return;
};
+ let selections = self.selections.all::<usize>(cx);
let buffer = self.buffer.read(cx);
let mut new_selections_by_buffer = HashMap::default();
- for selection in self.selections.all::<usize>(cx) {
+ for selection in selections {
for (buffer, range, _) in
buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
{
@@ -12417,6 +12419,7 @@ impl Editor {
}
fn open_excerpts_common(&mut self, split: bool, cx: &mut ViewContext<Self>) {
+ let selections = self.selections.all::<usize>(cx);
let buffer = self.buffer.read(cx);
if buffer.is_singleton() {
cx.propagate();
@@ -12429,7 +12432,7 @@ impl Editor {
};
let mut new_selections_by_buffer = HashMap::default();
- for selection in self.selections.all::<usize>(cx) {
+ for selection in selections {
for (mut buffer_handle, mut range, _) in
buffer.range_to_buffer_ranges(selection.range(), cx)
{
@@ -12545,7 +12548,7 @@ impl Editor {
fn selection_replacement_ranges(
&self,
range: Range<OffsetUtf16>,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Vec<Range<OffsetUtf16>> {
let selections = self.selections.all::<OffsetUtf16>(cx);
let newest_selection = selections
@@ -824,129 +824,131 @@ impl EditorElement {
let mut selections: Vec<(PlayerColor, Vec<SelectionLayout>)> = Vec::new();
let mut active_rows = BTreeMap::new();
let mut newest_selection_head = None;
- let editor = self.editor.read(cx);
-
- if editor.show_local_selections {
- let mut local_selections: Vec<Selection<Point>> = editor
- .selections
- .disjoint_in_range(start_anchor..end_anchor, cx);
- local_selections.extend(editor.selections.pending(cx));
- let mut layouts = Vec::new();
- let newest = editor.selections.newest(cx);
- for selection in local_selections.drain(..) {
- let is_empty = selection.start == selection.end;
- let is_newest = selection == newest;
-
- let layout = SelectionLayout::new(
- selection,
- editor.selections.line_mode,
- editor.cursor_shape,
- &snapshot.display_snapshot,
- is_newest,
- editor.leader_peer_id.is_none(),
- None,
- );
- if is_newest {
- newest_selection_head = Some(layout.head);
- }
+ self.editor.update(cx, |editor, cx| {
+ if editor.show_local_selections {
+ let mut local_selections: Vec<Selection<Point>> = editor
+ .selections
+ .disjoint_in_range(start_anchor..end_anchor, cx);
+ local_selections.extend(editor.selections.pending(cx));
+ let mut layouts = Vec::new();
+ let newest = editor.selections.newest(cx);
+ for selection in local_selections.drain(..) {
+ let is_empty = selection.start == selection.end;
+ let is_newest = selection == newest;
+
+ let layout = SelectionLayout::new(
+ selection,
+ editor.selections.line_mode,
+ editor.cursor_shape,
+ &snapshot.display_snapshot,
+ is_newest,
+ editor.leader_peer_id.is_none(),
+ None,
+ );
+ if is_newest {
+ newest_selection_head = Some(layout.head);
+ }
- for row in cmp::max(layout.active_rows.start.0, start_row.0)
- ..=cmp::min(layout.active_rows.end.0, end_row.0)
- {
- let contains_non_empty_selection =
- active_rows.entry(DisplayRow(row)).or_insert(!is_empty);
- *contains_non_empty_selection |= !is_empty;
+ for row in cmp::max(layout.active_rows.start.0, start_row.0)
+ ..=cmp::min(layout.active_rows.end.0, end_row.0)
+ {
+ let contains_non_empty_selection =
+ active_rows.entry(DisplayRow(row)).or_insert(!is_empty);
+ *contains_non_empty_selection |= !is_empty;
+ }
+ layouts.push(layout);
}
- layouts.push(layout);
- }
- let player = if editor.read_only(cx) {
- cx.theme().players().read_only()
- } else {
- self.style.local_player
- };
+ let player = if editor.read_only(cx) {
+ cx.theme().players().read_only()
+ } else {
+ self.style.local_player
+ };
- selections.push((player, layouts));
- }
+ selections.push((player, layouts));
+ }
- if let Some(collaboration_hub) = &editor.collaboration_hub {
- // When following someone, render the local selections in their color.
- if let Some(leader_id) = editor.leader_peer_id {
- if let Some(collaborator) = collaboration_hub.collaborators(cx).get(&leader_id) {
- if let Some(participant_index) = collaboration_hub
- .user_participant_indices(cx)
- .get(&collaborator.user_id)
+ if let Some(collaboration_hub) = &editor.collaboration_hub {
+ // When following someone, render the local selections in their color.
+ if let Some(leader_id) = editor.leader_peer_id {
+ if let Some(collaborator) = collaboration_hub.collaborators(cx).get(&leader_id)
{
- if let Some((local_selection_style, _)) = selections.first_mut() {
- *local_selection_style = cx
- .theme()
- .players()
- .color_for_participant(participant_index.0);
+ if let Some(participant_index) = collaboration_hub
+ .user_participant_indices(cx)
+ .get(&collaborator.user_id)
+ {
+ if let Some((local_selection_style, _)) = selections.first_mut() {
+ *local_selection_style = cx
+ .theme()
+ .players()
+ .color_for_participant(participant_index.0);
+ }
}
}
}
- }
- let mut remote_selections = HashMap::default();
- for selection in snapshot.remote_selections_in_range(
- &(start_anchor..end_anchor),
- collaboration_hub.as_ref(),
- cx,
- ) {
- let selection_style = Self::get_participant_color(selection.participant_index, cx);
+ let mut remote_selections = HashMap::default();
+ for selection in snapshot.remote_selections_in_range(
+ &(start_anchor..end_anchor),
+ collaboration_hub.as_ref(),
+ cx,
+ ) {
+ let selection_style =
+ Self::get_participant_color(selection.participant_index, cx);
+
+ // Don't re-render the leader's selections, since the local selections
+ // match theirs.
+ if Some(selection.peer_id) == editor.leader_peer_id {
+ continue;
+ }
+ let key = HoveredCursor {
+ replica_id: selection.replica_id,
+ selection_id: selection.selection.id,
+ };
- // Don't re-render the leader's selections, since the local selections
- // match theirs.
- if Some(selection.peer_id) == editor.leader_peer_id {
- continue;
+ let is_shown =
+ editor.show_cursor_names || editor.hovered_cursors.contains_key(&key);
+
+ remote_selections
+ .entry(selection.replica_id)
+ .or_insert((selection_style, Vec::new()))
+ .1
+ .push(SelectionLayout::new(
+ selection.selection,
+ selection.line_mode,
+ selection.cursor_shape,
+ &snapshot.display_snapshot,
+ false,
+ false,
+ if is_shown { selection.user_name } else { None },
+ ));
}
- let key = HoveredCursor {
- replica_id: selection.replica_id,
- selection_id: selection.selection.id,
- };
- let is_shown =
- editor.show_cursor_names || editor.hovered_cursors.contains_key(&key);
-
- remote_selections
- .entry(selection.replica_id)
- .or_insert((selection_style, Vec::new()))
- .1
- .push(SelectionLayout::new(
- selection.selection,
- selection.line_mode,
- selection.cursor_shape,
- &snapshot.display_snapshot,
- false,
- false,
- if is_shown { selection.user_name } else { None },
- ));
+ selections.extend(remote_selections.into_values());
+ } else if !editor.is_focused(cx) && editor.show_cursor_when_unfocused {
+ let player = if editor.read_only(cx) {
+ cx.theme().players().read_only()
+ } else {
+ self.style.local_player
+ };
+ let layouts = snapshot
+ .buffer_snapshot
+ .selections_in_range(&(start_anchor..end_anchor), true)
+ .map(move |(_, line_mode, cursor_shape, selection)| {
+ SelectionLayout::new(
+ selection,
+ line_mode,
+ cursor_shape,
+ &snapshot.display_snapshot,
+ false,
+ false,
+ None,
+ )
+ })
+ .collect::<Vec<_>>();
+ selections.push((player, layouts));
}
-
- selections.extend(remote_selections.into_values());
- } else if !editor.is_focused(cx) && editor.show_cursor_when_unfocused {
- let player = if editor.read_only(cx) {
- cx.theme().players().read_only()
- } else {
- self.style.local_player
- };
- let layouts = snapshot
- .buffer_snapshot
- .selections_in_range(&(start_anchor..end_anchor), true)
- .map(move |(_, line_mode, cursor_shape, selection)| {
- SelectionLayout::new(
- selection,
- line_mode,
- cursor_shape,
- &snapshot.display_snapshot,
- false,
- false,
- None,
- )
- })
- .collect::<Vec<_>>();
- selections.push((player, layouts));
- }
+ });
(selections, active_rows, newest_selection_head)
}
@@ -1848,23 +1850,25 @@ impl EditorElement {
return Vec::new();
}
- let editor = self.editor.read(cx);
- let newest_selection_head = newest_selection_head.unwrap_or_else(|| {
- let newest = editor.selections.newest::<Point>(cx);
- SelectionLayout::new(
- newest,
- editor.selections.line_mode,
- editor.cursor_shape,
- &snapshot.display_snapshot,
- true,
- true,
- None,
- )
- .head
+ let (newest_selection_head, is_relative) = self.editor.update(cx, |editor, cx| {
+ let newest_selection_head = newest_selection_head.unwrap_or_else(|| {
+ let newest = editor.selections.newest::<Point>(cx);
+ SelectionLayout::new(
+ newest,
+ editor.selections.line_mode,
+ editor.cursor_shape,
+ &snapshot.display_snapshot,
+ true,
+ true,
+ None,
+ )
+ .head
+ });
+ let is_relative = editor.should_use_relative_line_numbers(cx);
+ (newest_selection_head, is_relative)
});
let font_size = self.style.text.font_size.to_pixels(cx.rem_size());
- let is_relative = editor.should_use_relative_line_numbers(cx);
let relative_to = if is_relative {
Some(newest_selection_head.row())
} else {
@@ -41,9 +41,9 @@ pub(super) fn refresh_linked_ranges(this: &mut Editor, cx: &mut ViewContext<Edit
return None;
}
let project = this.project.clone()?;
+ let selections = this.selections.all::<usize>(cx);
let buffer = this.buffer.read(cx);
let mut applicable_selections = vec![];
- let selections = this.selections.all::<usize>(cx);
let snapshot = buffer.snapshot(cx);
for selection in selections {
let cursor_position = selection.head();
@@ -8,14 +8,14 @@ use std::{
use collections::HashMap;
use gpui::{AppContext, Model, Pixels};
use itertools::Itertools;
-use language::{Bias, Point, Selection, SelectionGoal, TextDimension, ToPoint};
+use language::{Bias, Point, Selection, SelectionGoal, TextDimension};
use util::post_inc;
use crate::{
display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
movement::TextLayoutDetails,
Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode,
- ToOffset,
+ ToOffset, ToPoint,
};
#[derive(Debug, Clone)]
@@ -96,7 +96,7 @@ impl SelectionsCollection {
pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Option<Selection<D>> {
self.pending_anchor()
.as_ref()
@@ -107,7 +107,7 @@ impl SelectionsCollection {
self.pending.as_ref().map(|pending| pending.mode.clone())
}
- pub fn all<'a, D>(&self, cx: &AppContext) -> Vec<Selection<D>>
+ pub fn all<'a, D>(&self, cx: &mut AppContext) -> Vec<Selection<D>>
where
D: 'a + TextDimension + Ord + Sub<D, Output = D>,
{
@@ -194,7 +194,7 @@ impl SelectionsCollection {
pub fn disjoint_in_range<'a, D>(
&self,
range: Range<Anchor>,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Vec<Selection<D>>
where
D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
@@ -239,9 +239,10 @@ impl SelectionsCollection {
pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Selection<D> {
- resolve(self.newest_anchor(), &self.buffer(cx))
+ let buffer = self.buffer(cx);
+ self.newest_anchor().map(|p| p.summary::<D>(&buffer))
}
pub fn newest_display(&self, cx: &mut AppContext) -> Selection<DisplayPoint> {
@@ -262,9 +263,10 @@ impl SelectionsCollection {
pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Selection<D> {
- resolve(self.oldest_anchor(), &self.buffer(cx))
+ let buffer = self.buffer(cx);
+ self.oldest_anchor().map(|p| p.summary::<D>(&buffer))
}
pub fn first_anchor(&self) -> Selection<Anchor> {
@@ -276,14 +278,14 @@ impl SelectionsCollection {
pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Selection<D> {
self.all(cx).first().unwrap().clone()
}
pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
&self,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Selection<D> {
self.all(cx).last().unwrap().clone()
}
@@ -298,7 +300,7 @@ impl SelectionsCollection {
#[cfg(any(test, feature = "test-support"))]
pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
&self,
- cx: &AppContext,
+ cx: &mut AppContext,
) -> Vec<Range<D>> {
self.all::<D>(cx)
.iter()
@@ -475,7 +477,7 @@ impl<'a> MutableSelectionsCollection<'a> {
where
T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
{
- let mut selections = self.all(self.cx);
+ let mut selections = self.collection.all(self.cx);
let mut start = range.start.to_offset(&self.buffer());
let mut end = range.end.to_offset(&self.buffer());
let reversed = if start > end {
@@ -649,6 +651,7 @@ impl<'a> MutableSelectionsCollection<'a> {
let mut changed = false;
let display_map = self.display_map();
let selections = self
+ .collection
.all::<Point>(self.cx)
.into_iter()
.map(|selection| {
@@ -676,6 +679,7 @@ impl<'a> MutableSelectionsCollection<'a> {
let mut changed = false;
let snapshot = self.buffer().clone();
let selections = self
+ .collection
.all::<usize>(self.cx)
.into_iter()
.map(|selection| {
@@ -869,10 +873,3 @@ where
goal: s.goal,
})
}
-
-fn resolve<D: TextDimension + Ord + Sub<D, Output = D>>(
- selection: &Selection<Anchor>,
- buffer: &MultiBufferSnapshot,
-) -> Selection<D> {
- selection.map(|p| p.summary::<D>(buffer))
-}
@@ -37,34 +37,34 @@ impl CursorPosition {
}
fn update_position(&mut self, editor: View<Editor>, cx: &mut ViewContext<Self>) {
- let editor = editor.read(cx);
- let buffer = editor.buffer().read(cx).snapshot(cx);
-
- self.selected_count = Default::default();
- self.selected_count.selections = editor.selections.count();
- let mut last_selection: Option<Selection<usize>> = None;
- for selection in editor.selections.all::<usize>(cx) {
- self.selected_count.characters += buffer
- .text_for_range(selection.start..selection.end)
- .map(|t| t.chars().count())
- .sum::<usize>();
- if last_selection
- .as_ref()
- .map_or(true, |last_selection| selection.id > last_selection.id)
- {
- last_selection = Some(selection);
+ editor.update(cx, |editor, cx| {
+ let buffer = editor.buffer().read(cx).snapshot(cx);
+
+ self.selected_count = Default::default();
+ self.selected_count.selections = editor.selections.count();
+ let mut last_selection: Option<Selection<usize>> = None;
+ for selection in editor.selections.all::<usize>(cx) {
+ self.selected_count.characters += buffer
+ .text_for_range(selection.start..selection.end)
+ .map(|t| t.chars().count())
+ .sum::<usize>();
+ if last_selection
+ .as_ref()
+ .map_or(true, |last_selection| selection.id > last_selection.id)
+ {
+ last_selection = Some(selection);
+ }
}
- }
- for selection in editor.selections.all::<Point>(cx) {
- if selection.end != selection.start {
- self.selected_count.lines += (selection.end.row - selection.start.row) as usize;
- if selection.end.column != 0 {
- self.selected_count.lines += 1;
+ for selection in editor.selections.all::<Point>(cx) {
+ if selection.end != selection.start {
+ self.selected_count.lines += (selection.end.row - selection.start.row) as usize;
+ if selection.end.column != 0 {
+ self.selected_count.lines += 1;
+ }
}
}
- }
- self.position = last_selection.map(|s| s.head().to_point(&buffer));
-
+ self.position = last_selection.map(|s| s.head().to_point(&buffer));
+ });
cx.notify();
}
@@ -56,8 +56,8 @@ impl GoToLine {
}
pub fn new(active_editor: View<Editor>, cx: &mut ViewContext<Self>) -> Self {
- let editor = active_editor.read(cx);
- let cursor = editor.selections.last::<Point>(cx).head();
+ let cursor =
+ active_editor.update(cx, |editor, cx| editor.selections.last::<Point>(cx).head());
let line = cursor.row + 1;
let column = cursor.column + 1;
@@ -128,12 +128,14 @@ impl SyntaxTreeView {
fn editor_updated(&mut self, did_reparse: bool, cx: &mut ViewContext<Self>) -> Option<()> {
// Find which excerpt the cursor is in, and the position within that excerpted buffer.
let editor_state = self.editor.as_mut()?;
- let editor = &editor_state.editor.read(cx);
- let selection_range = editor.selections.last::<usize>(cx).range();
- let multibuffer = editor.buffer().read(cx);
- let (buffer, range, excerpt_id) = multibuffer
- .range_to_buffer_ranges(selection_range, cx)
- .pop()?;
+ let (buffer, range, excerpt_id) = editor_state.editor.update(cx, |editor, cx| {
+ let selection_range = editor.selections.last::<usize>(cx).range();
+ editor
+ .buffer()
+ .read(cx)
+ .range_to_buffer_ranges(selection_range, cx)
+ .pop()
+ })?;
// If the cursor has moved into a different excerpt, retrieve a new syntax layer
// from that buffer.
@@ -301,8 +301,8 @@ impl MarkdownPreviewView {
this.parse_markdown_from_active_editor(true, cx);
}
EditorEvent::SelectionsChanged { .. } => {
- let editor = editor.read(cx);
- let selection_range = editor.selections.last::<usize>(cx).range();
+ let selection_range =
+ editor.update(cx, |editor, cx| editor.selections.last::<usize>(cx).range());
this.selected_block = this.get_block_index_under_cursor(selection_range);
this.list_state.scroll_to_reveal_item(this.selected_block);
cx.notify();
@@ -194,9 +194,11 @@ impl PickerDelegate for OutlineViewDelegate {
})
.collect();
- let editor = self.active_editor.read(cx);
- let cursor_offset = editor.selections.newest::<usize>(cx).head();
- let buffer = editor.buffer().read(cx).snapshot(cx);
+ let (buffer, cursor_offset) = self.active_editor.update(cx, |editor, cx| {
+ let buffer = editor.buffer().read(cx).snapshot(cx);
+ let cursor_offset = editor.selections.newest::<usize>(cx).head();
+ (buffer, cursor_offset)
+ });
selected_index = self
.outline
.items
@@ -2410,11 +2410,9 @@ impl OutlinePanel {
editor: &View<Editor>,
cx: &mut ViewContext<Self>,
) -> Option<PanelEntry> {
- let selection = editor
- .read(cx)
- .selections
- .newest::<language::Point>(cx)
- .head();
+ let selection = editor.update(cx, |editor, cx| {
+ editor.selections.newest::<language::Point>(cx).head()
+ });
let editor_snapshot = editor.update(cx, |editor, cx| editor.snapshot(cx));
let multi_buffer = editor.read(cx).buffer();
let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
@@ -5,7 +5,7 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use editor::Editor;
-use gpui::{prelude::*, AppContext, Entity, View, WeakView, WindowContext};
+use gpui::{prelude::*, Entity, View, WeakView, WindowContext};
use language::{BufferSnapshot, Language, LanguageName, Point};
use crate::repl_store::ReplStore;
@@ -103,7 +103,7 @@ pub enum SessionSupport {
Unsupported,
}
-pub fn session(editor: WeakView<Editor>, cx: &mut AppContext) -> SessionSupport {
+pub fn session(editor: WeakView<Editor>, cx: &mut WindowContext) -> SessionSupport {
let store = ReplStore::global(cx);
let entity_id = editor.entity_id();
@@ -311,17 +311,21 @@ fn language_supported(language: &Arc<Language>) -> bool {
}
}
-fn get_language(editor: WeakView<Editor>, cx: &mut AppContext) -> Option<Arc<Language>> {
- let editor = editor.upgrade()?;
- let selection = editor.read(cx).selections.newest::<usize>(cx);
- let buffer = editor.read(cx).buffer().read(cx).snapshot(cx);
- buffer.language_at(selection.head()).cloned()
+fn get_language(editor: WeakView<Editor>, cx: &mut WindowContext) -> Option<Arc<Language>> {
+ editor
+ .update(cx, |editor, cx| {
+ let selection = editor.selections.newest::<usize>(cx);
+ let buffer = editor.buffer().read(cx).snapshot(cx);
+ buffer.language_at(selection.head()).cloned()
+ })
+ .ok()
+ .flatten()
}
#[cfg(test)]
mod tests {
use super::*;
- use gpui::Context;
+ use gpui::{AppContext, Context};
use indoc::indoc;
use language::{Buffer, Language, LanguageConfig, LanguageRegistry};
@@ -281,7 +281,7 @@ impl VimGlobals {
&mut self,
register: Option<char>,
editor: Option<&mut Editor>,
- cx: &ViewContext<Editor>,
+ cx: &mut ViewContext<Editor>,
) -> Option<Register> {
let Some(register) = register.filter(|reg| *reg != '"') else {
let setting = VimSettings::get_global(cx).use_system_clipboard;
@@ -620,9 +620,11 @@ impl Vim {
let Some(editor) = self.editor() else {
return;
};
+ let newest_selection_empty = editor.update(cx, |editor, cx| {
+ editor.selections.newest::<usize>(cx).is_empty()
+ });
let editor = editor.read(cx);
let editor_mode = editor.mode();
- let newest_selection_empty = editor.selections.newest::<usize>(cx).is_empty();
if editor_mode == EditorMode::Full
&& !newest_selection_empty
@@ -717,11 +719,12 @@ impl Vim {
globals.recorded_count = None;
let selections = self.editor().map(|editor| {
- let editor = editor.read(cx);
- (
- editor.selections.oldest::<Point>(cx),
- editor.selections.newest::<Point>(cx),
- )
+ editor.update(cx, |editor, cx| {
+ (
+ editor.selections.oldest::<Point>(cx),
+ editor.selections.newest::<Point>(cx),
+ )
+ })
});
if let Some((oldest, newest)) = selections {