@@ -1,11 +1,13 @@
mod anchor;
mod point;
+mod selection;
mod text;
pub use anchor::*;
use futures_core::future::LocalBoxFuture;
pub use point::*;
use seahash::SeaHasher;
+pub use selection::*;
pub use text::*;
use crate::{
@@ -23,7 +25,6 @@ use std::{
cmp::{self, Ordering},
hash::BuildHasher,
iter::{self, Iterator},
- mem,
ops::{AddAssign, Range},
path::PathBuf,
str,
@@ -33,9 +34,6 @@ use std::{
const UNDO_GROUP_INTERVAL: Duration = Duration::from_millis(300);
-pub type SelectionSetId = time::Lamport;
-pub type SelectionsVersion = usize;
-
#[derive(Clone, Default)]
struct DeterministicState;
@@ -149,13 +147,6 @@ impl History {
}
}
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Selection {
- pub start: Anchor,
- pub end: Anchor,
- pub reversed: bool,
-}
-
#[derive(Clone, Default, Debug)]
struct UndoMap(HashMap<time::Local, Vec<UndoOperation>>);
@@ -679,45 +670,46 @@ impl Buffer {
(old_ranges, new_text, operations)
}
- pub fn add_selection_set<I>(&mut self, ranges: I) -> Result<(SelectionSetId, Operation)>
- where
- I: IntoIterator<Item = Range<Point>>,
- {
- let selections = self.selections_from_ranges(ranges)?;
+ pub fn add_selection_set(
+ &mut self,
+ selections: Vec<Selection>,
+ ctx: Option<&mut ModelContext<Self>>,
+ ) -> (SelectionSetId, Operation) {
let lamport_timestamp = self.lamport_clock.tick();
self.selections
.insert(lamport_timestamp, selections.clone());
self.selections_last_update += 1;
- Ok((
+ if let Some(ctx) = ctx {
+ ctx.notify();
+ }
+
+ (
lamport_timestamp,
Operation::UpdateSelections {
set_id: lamport_timestamp,
selections: Some(selections),
lamport_timestamp,
},
- ))
+ )
}
- pub fn replace_selection_set<I>(
+ pub fn update_selection_set(
&mut self,
set_id: SelectionSetId,
- ranges: I,
- ) -> Result<Operation>
- where
- I: IntoIterator<Item = Range<Point>>,
- {
- self.selections
- .remove(&set_id)
- .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
-
- let mut selections = self.selections_from_ranges(ranges)?;
+ mut selections: Vec<Selection>,
+ ctx: Option<&mut ModelContext<Self>>,
+ ) -> Result<Operation> {
self.merge_selections(&mut selections);
self.selections.insert(set_id, selections.clone());
let lamport_timestamp = self.lamport_clock.tick();
self.selections_last_update += 1;
+ if let Some(ctx) = ctx {
+ ctx.notify();
+ }
+
Ok(Operation::UpdateSelections {
set_id,
selections: Some(selections),
@@ -725,12 +717,21 @@ impl Buffer {
})
}
- pub fn remove_selection_set(&mut self, set_id: SelectionSetId) -> Result<Operation> {
+ pub fn remove_selection_set(
+ &mut self,
+ set_id: SelectionSetId,
+ ctx: Option<&mut ModelContext<Self>>,
+ ) -> Result<Operation> {
self.selections
.remove(&set_id)
.ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
let lamport_timestamp = self.lamport_clock.tick();
self.selections_last_update += 1;
+
+ if let Some(ctx) = ctx {
+ ctx.notify();
+ }
+
Ok(Operation::UpdateSelections {
set_id,
selections: None,
@@ -738,15 +739,18 @@ impl Buffer {
})
}
+ pub fn selections(&self, set_id: SelectionSetId) -> Result<&[Selection]> {
+ self.selections
+ .get(&set_id)
+ .map(|s| s.as_slice())
+ .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))
+ }
+
pub fn selection_ranges<'a>(
&'a self,
set_id: SelectionSetId,
) -> Result<impl Iterator<Item = Range<Point>> + 'a> {
- let selections = self
- .selections
- .get(&set_id)
- .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
- Ok(selections.iter().map(move |selection| {
+ Ok(self.selections(set_id)?.iter().map(move |selection| {
let start = selection.start.to_point(self).unwrap();
let end = selection.end.to_point(self).unwrap();
if selection.reversed {
@@ -770,49 +774,25 @@ impl Buffer {
}
fn merge_selections(&mut self, selections: &mut Vec<Selection>) {
- let mut new_selections = Vec::with_capacity(selections.len());
- {
- let mut old_selections = selections.drain(..);
- if let Some(mut prev_selection) = old_selections.next() {
- for selection in old_selections {
- if prev_selection.end.cmp(&selection.start, self).unwrap() >= Ordering::Equal {
- if selection.end.cmp(&prev_selection.end, self).unwrap() > Ordering::Equal {
- prev_selection.end = selection.end;
- }
- } else {
- new_selections.push(mem::replace(&mut prev_selection, selection));
- }
+ let mut i = 1;
+ while i < selections.len() {
+ if selections[i - 1]
+ .end
+ .cmp(&selections[i].start, self)
+ .unwrap()
+ >= Ordering::Equal
+ {
+ let removed = selections.remove(i);
+ if removed.start.cmp(&selections[i - 1].start, self).unwrap() < Ordering::Equal {
+ selections[i - 1].start = removed.start;
+ }
+ if removed.end.cmp(&selections[i - 1].end, self).unwrap() > Ordering::Equal {
+ selections[i - 1].end = removed.end;
}
- new_selections.push(prev_selection);
- }
- }
- *selections = new_selections;
- }
-
- fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
- where
- I: IntoIterator<Item = Range<Point>>,
- {
- let mut ranges = ranges.into_iter().collect::<Vec<_>>();
- ranges.sort_unstable_by_key(|range| range.start);
-
- let mut selections = Vec::with_capacity(ranges.len());
- for range in ranges {
- if range.start > range.end {
- selections.push(Selection {
- start: self.anchor_before(range.end)?,
- end: self.anchor_before(range.start)?,
- reversed: true,
- });
} else {
- selections.push(Selection {
- start: self.anchor_after(range.start)?,
- end: self.anchor_before(range.end)?,
- reversed: false,
- });
+ i += 1;
}
}
- Ok(selections)
}
pub fn apply_ops<I: IntoIterator<Item = Operation>>(
@@ -1927,48 +1907,6 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
// collector.into_inner().changes
// }
-impl Selection {
- pub fn head(&self) -> &Anchor {
- if self.reversed {
- &self.start
- } else {
- &self.end
- }
- }
-
- pub fn set_head<S>(&mut self, buffer: &Buffer, cursor: Anchor) {
- if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal {
- if !self.reversed {
- mem::swap(&mut self.start, &mut self.end);
- self.reversed = true;
- }
- self.start = cursor;
- } else {
- if self.reversed {
- mem::swap(&mut self.start, &mut self.end);
- self.reversed = false;
- }
- self.end = cursor;
- }
- }
-
- pub fn tail(&self) -> &Anchor {
- if self.reversed {
- &self.end
- } else {
- &self.start
- }
- }
-
- pub fn is_empty(&self, buffer: &Buffer) -> bool {
- self.start.to_offset(buffer).unwrap() == self.end.to_offset(buffer).unwrap()
- }
-
- pub fn anchor_range(&self) -> Range<Anchor> {
- self.start.clone()..self.end.clone()
- }
-}
-
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
struct FragmentId(Arc<[u16]>);
@@ -3049,7 +2987,7 @@ mod tests {
.collect::<Vec<_>>();
let set_id = replica_selection_sets.choose(rng);
if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
- let op = self.remove_selection_set(*set_id.unwrap()).unwrap();
+ let op = self.remove_selection_set(*set_id.unwrap(), None).unwrap();
operations.push(op);
} else {
let mut ranges = Vec::new();
@@ -3060,11 +2998,12 @@ mod tests {
let end_point = self.point_for_offset(end).unwrap();
ranges.push(start_point..end_point);
}
+ let new_selections = self.selections_from_ranges(ranges).unwrap();
let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
- self.add_selection_set(ranges).unwrap().1
+ self.add_selection_set(new_selections, None).1
} else {
- self.replace_selection_set(*set_id.unwrap(), ranges)
+ self.update_selection_set(*set_id.unwrap(), new_selections, None)
.unwrap()
};
operations.push(op);
@@ -3082,6 +3021,34 @@ mod tests {
}
ops
}
+
+ fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>
+ where
+ I: IntoIterator<Item = Range<Point>>,
+ {
+ let mut ranges = ranges.into_iter().collect::<Vec<_>>();
+ ranges.sort_unstable_by_key(|range| range.start);
+
+ let mut selections = Vec::with_capacity(ranges.len());
+ for range in ranges {
+ if range.start > range.end {
+ selections.push(Selection {
+ start: self.anchor_before(range.end)?,
+ end: self.anchor_before(range.start)?,
+ reversed: true,
+ goal_column: None,
+ });
+ } else {
+ selections.push(Selection {
+ start: self.anchor_after(range.start)?,
+ end: self.anchor_before(range.end)?,
+ reversed: false,
+ goal_column: None,
+ });
+ }
+ }
+ Ok(selections)
+ }
}
impl Operation {
@@ -1,6 +1,6 @@
use super::{
buffer, movement, Anchor, Bias, Buffer, BufferElement, DisplayMap, DisplayPoint, Point,
- ToOffset, ToPoint,
+ Selection, SelectionSetId, ToOffset,
};
use crate::{settings::Settings, watch, workspace};
use anyhow::Result;
@@ -16,7 +16,6 @@ use smol::Timer;
use std::{
cmp::{self, Ordering},
fmt::Write,
- mem,
ops::Range,
sync::Arc,
time::Duration,
@@ -90,7 +89,7 @@ pub struct BufferView {
handle: WeakViewHandle<Self>,
buffer: ModelHandle<Buffer>,
display_map: ModelHandle<DisplayMap>,
- selections: Vec<Selection>,
+ selection_set_id: SelectionSetId,
pending_selection: Option<Selection>,
scroll_position: Mutex<Vector2F>,
autoscroll_requested: Mutex<bool>,
@@ -128,17 +127,22 @@ impl BufferView {
});
ctx.observe(&display_map, Self::on_display_map_changed);
- let buffer_ref = buffer.as_ref(ctx);
+ let (selection_set_id, ops) = buffer.update(ctx, |buffer, ctx| {
+ buffer.add_selection_set(
+ vec![Selection {
+ start: buffer.anchor_before(0).unwrap(),
+ end: buffer.anchor_before(0).unwrap(),
+ reversed: false,
+ goal_column: None,
+ }],
+ Some(ctx),
+ )
+ });
Self {
handle: ctx.handle().downgrade(),
buffer,
display_map,
- selections: vec![Selection {
- start: buffer_ref.anchor_before(0).unwrap(),
- end: buffer_ref.anchor_before(0).unwrap(),
- reversed: false,
- goal_column: None,
- }],
+ selection_set_id,
pending_selection: None,
scroll_position: Mutex::new(Vector2F::zero()),
autoscroll_requested: Mutex::new(false),
@@ -194,7 +198,7 @@ impl BufferView {
let map = self.display_map.as_ref(app);
let visible_lines = viewport_height / line_height;
let first_cursor_top = self
- .selections
+ .selections(app)
.first()
.unwrap()
.head()
@@ -202,7 +206,7 @@ impl BufferView {
.unwrap()
.row() as f32;
let last_cursor_bottom = self
- .selections
+ .selections(app)
.last()
.unwrap()
.head()
@@ -245,7 +249,7 @@ impl BufferView {
let mut target_left = std::f32::INFINITY;
let mut target_right = 0.0_f32;
- for selection in &self.selections {
+ for selection in self.selections(app) {
let head = selection.head().to_display_point(map, app).unwrap();
let start_column = head.column().saturating_sub(3);
let end_column = cmp::min(map.line_len(head.row(), app).unwrap(), head.column() + 3);
@@ -302,7 +306,7 @@ impl BufferView {
};
if !add {
- self.selections.clear();
+ self.update_selections(Vec::new(), ctx);
}
self.pending_selection = Some(selection);
@@ -333,9 +337,9 @@ impl BufferView {
fn end_selection(&mut self, ctx: &mut ViewContext<Self>) {
if let Some(selection) = self.pending_selection.take() {
let ix = self.selection_insertion_index(&selection.start, ctx.app());
- self.selections.insert(ix, selection);
- self.merge_selections(ctx.app());
- ctx.notify();
+ let mut selections = self.selections(ctx.app()).to_vec();
+ selections.insert(ix, selection);
+ self.update_selections(selections, ctx);
} else {
log::error!("end_selection dispatched with no pending selection");
}
@@ -350,7 +354,6 @@ impl BufferView {
where
T: IntoIterator<Item = &'a Range<DisplayPoint>>,
{
- let buffer = self.buffer.as_ref(ctx);
let map = self.display_map.as_ref(ctx);
let mut selections = Vec::new();
for range in ranges {
@@ -361,51 +364,50 @@ impl BufferView {
goal_column: None,
});
}
- selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
- self.selections = selections;
- self.merge_selections(ctx.app());
- ctx.notify();
+ self.update_selections(selections, ctx);
Ok(())
}
fn insert(&mut self, text: &String, ctx: &mut ViewContext<Self>) {
- let buffer = self.buffer.as_ref(ctx);
let mut offset_ranges = SmallVec::<[Range<usize>; 32]>::new();
- for selection in &self.selections {
- let start = selection.start.to_offset(buffer).unwrap();
- let end = selection.end.to_offset(buffer).unwrap();
- offset_ranges.push(start..end);
+ {
+ let buffer = self.buffer.as_ref(ctx);
+ for selection in self.selections(ctx.app()) {
+ let start = selection.start.to_offset(buffer).unwrap();
+ let end = selection.end.to_offset(buffer).unwrap();
+ offset_ranges.push(start..end);
+ }
}
+ let mut new_selections = Vec::new();
self.buffer.update(ctx, |buffer, ctx| {
if let Err(error) = buffer.edit(offset_ranges.iter().cloned(), text.as_str(), Some(ctx))
{
log::error!("error inserting text: {}", error);
};
+ let char_count = text.chars().count() as isize;
+ let mut delta = 0_isize;
+ new_selections = offset_ranges
+ .into_iter()
+ .map(|range| {
+ let start = range.start as isize;
+ let end = range.end as isize;
+ let anchor = buffer
+ .anchor_before((start + delta + char_count) as usize)
+ .unwrap();
+ let deleted_count = end - start;
+ delta += char_count - deleted_count;
+ Selection {
+ start: anchor.clone(),
+ end: anchor,
+ reversed: false,
+ goal_column: None,
+ }
+ })
+ .collect();
});
- let buffer = self.buffer.as_ref(ctx);
- let char_count = text.chars().count() as isize;
- let mut delta = 0_isize;
- self.selections = offset_ranges
- .into_iter()
- .map(|range| {
- let start = range.start as isize;
- let end = range.end as isize;
- let anchor = buffer
- .anchor_before((start + delta + char_count) as usize)
- .unwrap();
- let deleted_count = end - start;
- delta += char_count - deleted_count;
- Selection {
- start: anchor.clone(),
- end: anchor,
- reversed: false,
- goal_column: None,
- }
- })
- .collect();
-
+ self.update_selections(new_selections, ctx);
self.pause_cursor_blinking(ctx);
*self.autoscroll_requested.lock() = true;
}
@@ -419,22 +421,27 @@ impl BufferView {
}
pub fn backspace(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
- let buffer = self.buffer.as_ref(ctx);
- let map = self.display_map.as_ref(ctx);
- for selection in &mut self.selections {
- if selection.range(buffer).is_empty() {
- let head = selection.head().to_display_point(map, ctx.app()).unwrap();
- let cursor = map
- .anchor_before(
- movement::left(map, head, ctx.app()).unwrap(),
- Bias::Left,
- ctx.app(),
- )
- .unwrap();
- selection.set_head(&buffer, cursor);
- selection.goal_column = None;
+ let mut selections = self.selections(ctx.app()).to_vec();
+ {
+ let buffer = self.buffer.as_ref(ctx);
+ let map = self.display_map.as_ref(ctx);
+ for selection in &mut selections {
+ if selection.range(buffer).is_empty() {
+ let head = selection.head().to_display_point(map, ctx.app()).unwrap();
+ let cursor = map
+ .anchor_before(
+ movement::left(map, head, ctx.app()).unwrap(),
+ Bias::Left,
+ ctx.app(),
+ )
+ .unwrap();
+ selection.set_head(&buffer, cursor);
+ selection.goal_column = None;
+ }
}
}
+
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
self.insert(&String::new(), ctx);
}
@@ -450,10 +457,11 @@ impl BufferView {
}
pub fn move_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
+ let mut selections = self.selections(ctx.app()).to_vec();
{
let app = ctx.app();
- let map = self.display_map.as_ref(ctx);
- for selection in &mut self.selections {
+ let map = self.display_map.as_ref(app);
+ for selection in &mut selections {
let start = selection.start.to_display_point(map, app).unwrap();
let end = selection.end.to_display_point(map, app).unwrap();
@@ -470,14 +478,16 @@ impl BufferView {
selection.goal_column = None;
}
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
pub fn select_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
+ let mut selections = self.selections(ctx.app()).to_vec();
{
let buffer = self.buffer.as_ref(ctx);
let map = self.display_map.as_ref(ctx);
- for selection in &mut self.selections {
+ for selection in &mut selections {
let head = selection.head().to_display_point(map, ctx.app()).unwrap();
let cursor = map
.anchor_before(
@@ -490,14 +500,16 @@ impl BufferView {
selection.goal_column = None;
}
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
pub fn move_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
+ let mut selections = self.selections(ctx.app()).to_vec();
{
let app = ctx.app();
let map = self.display_map.as_ref(app);
- for selection in &mut self.selections {
+ for selection in &mut selections {
let start = selection.start.to_display_point(map, app).unwrap();
let end = selection.end.to_display_point(map, app).unwrap();
@@ -514,15 +526,17 @@ impl BufferView {
selection.goal_column = None;
}
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
pub fn select_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
+ let mut selections = self.selections(ctx.app()).to_vec();
{
- let buffer = self.buffer.as_ref(ctx);
let app = ctx.app();
+ let buffer = self.buffer.as_ref(app);
let map = self.display_map.as_ref(app);
- for selection in &mut self.selections {
+ for selection in &mut selections {
let head = selection.head().to_display_point(map, ctx.app()).unwrap();
let cursor = map
.anchor_before(movement::right(map, head, app).unwrap(), Bias::Right, app)
@@ -531,6 +545,7 @@ impl BufferView {
selection.goal_column = None;
}
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
@@ -538,23 +553,27 @@ impl BufferView {
if self.single_line {
ctx.propagate_action();
} else {
- let app = ctx.app();
- let map = self.display_map.as_ref(app);
- for selection in &mut self.selections {
- let start = selection.start.to_display_point(map, app).unwrap();
- let end = selection.end.to_display_point(map, app).unwrap();
- if start != end {
- selection.goal_column = None;
- }
+ let mut selections = self.selections(ctx.app()).to_vec();
+ {
+ let app = ctx.app();
+ let map = self.display_map.as_ref(app);
+ for selection in &mut selections {
+ let start = selection.start.to_display_point(map, app).unwrap();
+ let end = selection.end.to_display_point(map, app).unwrap();
+ if start != end {
+ selection.goal_column = None;
+ }
- let (start, goal_column) =
- movement::up(map, start, selection.goal_column, app).unwrap();
- let cursor = map.anchor_before(start, Bias::Left, app).unwrap();
- selection.start = cursor.clone();
- selection.end = cursor;
- selection.goal_column = goal_column;
- selection.reversed = false;
+ let (start, goal_column) =
+ movement::up(map, start, selection.goal_column, app).unwrap();
+ let cursor = map.anchor_before(start, Bias::Left, app).unwrap();
+ selection.start = cursor.clone();
+ selection.end = cursor;
+ selection.goal_column = goal_column;
+ selection.reversed = false;
+ }
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
}
@@ -563,16 +582,20 @@ impl BufferView {
if self.single_line {
ctx.propagate_action();
} else {
- let app = ctx.app();
- let buffer = self.buffer.as_ref(app);
- let map = self.display_map.as_ref(app);
- for selection in &mut self.selections {
- let head = selection.head().to_display_point(map, app).unwrap();
- let (head, goal_column) =
- movement::up(map, head, selection.goal_column, app).unwrap();
- selection.set_head(&buffer, map.anchor_before(head, Bias::Left, app).unwrap());
- selection.goal_column = goal_column;
+ let mut selections = self.selections(ctx.app()).to_vec();
+ {
+ let app = ctx.app();
+ let buffer = self.buffer.as_ref(app);
+ let map = self.display_map.as_ref(app);
+ for selection in &mut selections {
+ let head = selection.head().to_display_point(map, app).unwrap();
+ let (head, goal_column) =
+ movement::up(map, head, selection.goal_column, app).unwrap();
+ selection.set_head(&buffer, map.anchor_before(head, Bias::Left, app).unwrap());
+ selection.goal_column = goal_column;
+ }
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
}
@@ -581,23 +604,27 @@ impl BufferView {
if self.single_line {
ctx.propagate_action();
} else {
- let app = ctx.app();
- let map = self.display_map.as_ref(app);
- for selection in &mut self.selections {
- let start = selection.start.to_display_point(map, app).unwrap();
- let end = selection.end.to_display_point(map, app).unwrap();
- if start != end {
- selection.goal_column = None;
- }
+ let mut selections = self.selections(ctx.app()).to_vec();
+ {
+ let app = ctx.app();
+ let map = self.display_map.as_ref(app);
+ for selection in &mut selections {
+ let start = selection.start.to_display_point(map, app).unwrap();
+ let end = selection.end.to_display_point(map, app).unwrap();
+ if start != end {
+ selection.goal_column = None;
+ }
- let (start, goal_column) =
- movement::down(map, end, selection.goal_column, app).unwrap();
- let cursor = map.anchor_before(start, Bias::Right, app).unwrap();
- selection.start = cursor.clone();
- selection.end = cursor;
- selection.goal_column = goal_column;
- selection.reversed = false;
+ let (start, goal_column) =
+ movement::down(map, end, selection.goal_column, app).unwrap();
+ let cursor = map.anchor_before(start, Bias::Right, app).unwrap();
+ selection.start = cursor.clone();
+ selection.end = cursor;
+ selection.goal_column = goal_column;
+ selection.reversed = false;
+ }
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
}
@@ -606,69 +633,39 @@ impl BufferView {
if self.single_line {
ctx.propagate_action();
} else {
- let app = ctx.app();
- let buffer = self.buffer.as_ref(ctx);
- let map = self.display_map.as_ref(ctx);
- for selection in &mut self.selections {
- let head = selection.head().to_display_point(map, app).unwrap();
- let (head, goal_column) =
- movement::down(map, head, selection.goal_column, app).unwrap();
- selection.set_head(&buffer, map.anchor_before(head, Bias::Right, app).unwrap());
- selection.goal_column = goal_column;
+ let mut selections = self.selections(ctx.app()).to_vec();
+ {
+ let app = ctx.app();
+ let buffer = self.buffer.as_ref(app);
+ let map = self.display_map.as_ref(app);
+ for selection in &mut selections {
+ let head = selection.head().to_display_point(map, app).unwrap();
+ let (head, goal_column) =
+ movement::down(map, head, selection.goal_column, app).unwrap();
+ selection.set_head(&buffer, map.anchor_before(head, Bias::Right, app).unwrap());
+ selection.goal_column = goal_column;
+ }
}
+ self.update_selections(selections, ctx);
self.changed_selections(ctx);
}
}
pub fn changed_selections(&mut self, ctx: &mut ViewContext<Self>) {
- self.merge_selections(ctx.app());
self.pause_cursor_blinking(ctx);
*self.autoscroll_requested.lock() = true;
ctx.notify();
}
- fn merge_selections(&mut self, ctx: &AppContext) {
- let buffer = self.buffer.as_ref(ctx);
- let mut i = 1;
- while i < self.selections.len() {
- if self.selections[i - 1]
- .end
- .cmp(&self.selections[i].start, buffer)
- .unwrap()
- >= Ordering::Equal
- {
- let removed = self.selections.remove(i);
- if removed
- .start
- .cmp(&self.selections[i - 1].start, buffer)
- .unwrap()
- < Ordering::Equal
- {
- self.selections[i - 1].start = removed.start;
- }
- if removed
- .end
- .cmp(&self.selections[i - 1].end, buffer)
- .unwrap()
- > Ordering::Equal
- {
- self.selections[i - 1].end = removed.end;
- }
- } else {
- i += 1;
- }
- }
- }
-
pub fn first_selection(&self, app: &AppContext) -> Range<DisplayPoint> {
- self.selections
+ self.selections(app)
.first()
.unwrap()
.display_range(self.display_map.as_ref(app), app)
}
pub fn last_selection(&self, app: &AppContext) -> Range<DisplayPoint> {
- self.selections
+ self.selections(app)
.last()
.unwrap()
.display_range(self.display_map.as_ref(app), app)
@@ -691,7 +688,7 @@ impl BufferView {
None
}
});
- self.selections[start_index..]
+ self.selections(app)[start_index..]
.iter()
.map(move |s| s.display_range(map, app))
.take_while(move |r| r.start <= range.end || r.end <= range.end)
@@ -700,16 +697,12 @@ impl BufferView {
fn selection_insertion_index(&self, start: &Anchor, app: &AppContext) -> usize {
let buffer = self.buffer.as_ref(app);
-
- match self
- .selections
- .binary_search_by(|probe| probe.start.cmp(&start, buffer).unwrap())
- {
+ let selections = self.selections(app);
+ match selections.binary_search_by(|probe| probe.start.cmp(&start, buffer).unwrap()) {
Ok(index) => index,
Err(index) => {
if index > 0
- && self.selections[index - 1].end.cmp(&start, buffer).unwrap()
- == Ordering::Greater
+ && selections[index - 1].end.cmp(&start, buffer).unwrap() == Ordering::Greater
{
index - 1
} else {
@@ -719,6 +712,21 @@ impl BufferView {
}
}
+ fn selections<'a>(&self, app: &'a AppContext) -> &'a [Selection] {
+ self.buffer
+ .as_ref(app)
+ .selections(self.selection_set_id)
+ .unwrap()
+ }
+
+ fn update_selections<'a>(&self, selections: Vec<Selection>, ctx: &mut ViewContext<Self>) {
+ let op = self.buffer.update(ctx, |buffer, ctx| {
+ buffer
+ .update_selection_set(self.selection_set_id, selections, Some(ctx))
+ .unwrap()
+ });
+ }
+
pub fn page_up(&mut self, _: &(), _: &mut ViewContext<Self>) {
log::info!("BufferView::page_up");
}
@@ -734,7 +742,7 @@ impl BufferView {
let app = ctx.app();
let map = self.display_map.as_ref(app);
- for selection in &self.selections {
+ for selection in self.selections(app) {
let (start, end) = selection.display_range(map, app).sorted();
let buffer_start_row = start.to_buffer_point(map, Bias::Left, app).unwrap().row;
@@ -766,7 +774,7 @@ impl BufferView {
let map = self.display_map.as_ref(app);
let buffer = self.buffer.as_ref(app);
let ranges = self
- .selections
+ .selections(app)
.iter()
.map(|s| {
let (start, end) = s.display_range(map, app).sorted();
@@ -846,7 +854,7 @@ impl BufferView {
self.display_map.update(ctx, |map, ctx| {
let buffer = self.buffer.as_ref(ctx);
let ranges = self
- .selections
+ .selections(ctx.app())
.iter()
.map(|s| s.range(buffer))
.collect::<Vec<_>>();
@@ -1099,13 +1107,6 @@ impl BufferView {
}
}
-struct Selection {
- start: Anchor,
- end: Anchor,
- reversed: bool,
- goal_column: Option<u32>,
-}
-
pub enum Event {
Activate,
Edited,
@@ -1194,60 +1195,6 @@ impl workspace::ItemView for BufferView {
}
}
-impl Selection {
- fn head(&self) -> &Anchor {
- if self.reversed {
- &self.start
- } else {
- &self.end
- }
- }
-
- fn set_head(&mut self, buffer: &Buffer, cursor: Anchor) {
- if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal {
- if !self.reversed {
- mem::swap(&mut self.start, &mut self.end);
- self.reversed = true;
- }
- self.start = cursor;
- } else {
- if self.reversed {
- mem::swap(&mut self.start, &mut self.end);
- self.reversed = false;
- }
- self.end = cursor;
- }
- }
-
- fn tail(&self) -> &Anchor {
- if self.reversed {
- &self.end
- } else {
- &self.start
- }
- }
-
- fn range(&self, buffer: &Buffer) -> Range<Point> {
- let start = self.start.to_point(buffer).unwrap();
- let end = self.end.to_point(buffer).unwrap();
- if self.reversed {
- end..start
- } else {
- start..end
- }
- }
-
- fn display_range(&self, map: &DisplayMap, app: &AppContext) -> Range<DisplayPoint> {
- let start = self.start.to_display_point(map, app).unwrap();
- let end = self.end.to_display_point(map, app).unwrap();
- if self.reversed {
- end..start
- } else {
- start..end
- }
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
@@ -1492,12 +1439,12 @@ mod tests {
view.update(&mut app, |view, ctx| {
view.move_down(&(), ctx);
assert_eq!(
- view.selections(ctx.app()),
+ view.selection_ranges(ctx.app()),
&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
);
view.move_right(&(), ctx);
assert_eq!(
- view.selections(ctx.app()),
+ view.selection_ranges(ctx.app()),
&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
);
Ok::<(), Error>(())
@@ -1543,7 +1490,7 @@ mod tests {
}
impl BufferView {
- fn selections(&self, app: &AppContext) -> Vec<Range<DisplayPoint>> {
+ fn selection_ranges(&self, app: &AppContext) -> Vec<Range<DisplayPoint>> {
self.selections_in_range(DisplayPoint::zero()..self.max_point(app), app)
.collect::<Vec<_>>()
}