More messy progress towards selections in editors

This commit is contained in:
Nathan Sobo 2021-12-11 00:29:34 -07:00
parent 0639c8331c
commit 4dd0752e80
11 changed files with 298 additions and 479 deletions

View file

@ -30,7 +30,8 @@ use std::{
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
vec,
};
use text::operation_queue::OperationQueue;
use sum_tree::TreeMap;
use text::{operation_queue::OperationQueue, rope::TextDimension};
pub use text::{Buffer as TextBuffer, Operation as _, *};
use theme::SyntaxTheme;
use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
@ -64,6 +65,7 @@ pub struct Buffer {
syntax_tree: Mutex<Option<SyntaxTree>>,
parsing_in_background: bool,
parse_count: usize,
remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
diagnostics: DiagnosticSet,
diagnostics_update_count: usize,
language_server: Option<LanguageServerState>,
@ -76,6 +78,7 @@ pub struct BufferSnapshot {
text: text::BufferSnapshot,
tree: Option<Tree>,
diagnostics: DiagnosticSet,
remote_selections: TreeMap<ReplicaId, Arc<[Selection<Anchor>]>>,
diagnostics_update_count: usize,
is_parsing: bool,
language: Option<Arc<Language>>,
@ -112,6 +115,15 @@ pub enum Operation {
diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
lamport_timestamp: clock::Lamport,
},
UpdateSelections {
replica_id: ReplicaId,
selections: Arc<[Selection<Anchor>]>,
lamport_timestamp: clock::Lamport,
},
RemoveSelections {
replica_id: ReplicaId,
lamport_timestamp: clock::Lamport,
},
}
#[derive(Clone, Debug, Eq, PartialEq)]
@ -329,6 +341,7 @@ impl Buffer {
autoindent_requests: Default::default(),
pending_autoindent: Default::default(),
language: None,
remote_selections: Default::default(),
diagnostics: Default::default(),
diagnostics_update_count: 0,
language_server: None,
@ -342,6 +355,7 @@ impl Buffer {
BufferSnapshot {
text: self.text.snapshot(),
tree: self.syntax_tree(),
remote_selections: self.remote_selections.clone(),
diagnostics: self.diagnostics.clone(),
diagnostics_update_count: self.diagnostics_update_count,
is_parsing: self.parsing_in_background,
@ -1286,6 +1300,10 @@ impl Buffer {
&& self.text.can_resolve(&diagnostic.range.end)
})
}
Operation::UpdateSelections { selections, .. } => selections
.iter()
.all(|s| self.can_resolve(&s.start) && self.can_resolve(&s.end)),
Operation::RemoveSelections { .. } => true,
}
}
@ -1297,6 +1315,21 @@ impl Buffer {
Operation::UpdateDiagnostics { diagnostics, .. } => {
self.apply_diagnostic_update(diagnostics, cx);
}
Operation::UpdateSelections {
replica_id,
selections,
lamport_timestamp,
} => {
self.remote_selections.insert(replica_id, selections);
self.text.observe_lamport_timestamp(lamport_timestamp);
}
Operation::RemoveSelections {
replica_id: set_id,
lamport_timestamp,
} => {
self.remote_selections.remove(&set_id);
self.text.observe_lamport_timestamp(lamport_timestamp);
}
}
}
@ -1323,7 +1356,7 @@ impl Buffer {
}
pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
self.text.remove_peer(replica_id);
self.remote_selections.remove(&replica_id);
cx.notify();
}
@ -1615,6 +1648,43 @@ impl BufferSnapshot {
.min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
}
pub fn remote_selections_in_range<'a, I, O>(
&'a self,
range: Range<I>,
) -> impl 'a + Iterator<Item = (ReplicaId, impl 'a + Iterator<Item = Selection<O>>)>
where
I: ToOffset,
O: TextDimension,
{
let range = self.anchor_before(range.start)..self.anchor_after(range.end);
self.remote_selections
.iter()
.map(move |(replica_id, selections)| {
let start_ix = match selections
.binary_search_by(|probe| probe.end.cmp(&range.start, self).unwrap())
{
Ok(ix) | Err(ix) => ix,
};
let end_ix = match selections
.binary_search_by(|probe| probe.start.cmp(&range.end, self).unwrap())
{
Ok(ix) | Err(ix) => ix,
};
let selections = &selections[start_ix..end_ix];
let mut summaries =
self.summaries_for_anchors(selections.iter().flat_map(|s| [&s.start, &s.end]));
let resolved = selections.iter().map(move |s| Selection {
id: s.id,
start: summaries.next().unwrap(),
end: summaries.next().unwrap(),
reversed: s.reversed,
goal: s.goal,
});
(*replica_id, resolved)
})
}
pub fn diagnostics_in_range<'a, T, O>(
&'a self,
search_range: Range<T>,
@ -1650,6 +1720,7 @@ impl Clone for BufferSnapshot {
Self {
text: self.text.clone(),
tree: self.tree.clone(),
remote_selections: self.remote_selections.clone(),
diagnostics: self.diagnostics.clone(),
diagnostics_update_count: self.diagnostics_update_count,
is_parsing: self.is_parsing,
@ -1889,6 +1960,12 @@ impl operation_queue::Operation for Operation {
}
Operation::UpdateDiagnostics {
lamport_timestamp, ..
}
| Operation::UpdateSelections {
lamport_timestamp, ..
}
| Operation::RemoveSelections {
lamport_timestamp, ..
} => *lamport_timestamp,
}
}

View file

@ -41,13 +41,12 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
.collect(),
version: From::from(&undo.version),
}),
Operation::Buffer(text::Operation::UpdateSelections {
set_id,
Operation::UpdateSelections {
replica_id,
selections,
lamport_timestamp,
}) => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
replica_id: set_id.replica_id as u32,
local_timestamp: set_id.value,
} => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
replica_id: *replica_id as u32,
lamport_timestamp: lamport_timestamp.value,
selections: selections
.iter()
@ -59,24 +58,13 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
})
.collect(),
}),
Operation::Buffer(text::Operation::RemoveSelections {
set_id,
Operation::RemoveSelections {
replica_id,
lamport_timestamp,
}) => proto::operation::Variant::RemoveSelections(proto::operation::RemoveSelections {
replica_id: set_id.replica_id as u32,
local_timestamp: set_id.value,
} => proto::operation::Variant::RemoveSelections(proto::operation::RemoveSelections {
replica_id: *replica_id as u32,
lamport_timestamp: lamport_timestamp.value,
}),
Operation::Buffer(text::Operation::SetActiveSelections {
set_id,
lamport_timestamp,
}) => proto::operation::Variant::SetActiveSelections(
proto::operation::SetActiveSelections {
replica_id: lamport_timestamp.replica_id as u32,
local_timestamp: set_id.map(|set_id| set_id.value),
lamport_timestamp: lamport_timestamp.value,
},
),
Operation::UpdateDiagnostics {
diagnostics,
lamport_timestamp,
@ -108,22 +96,16 @@ pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::
}
}
pub fn serialize_selection_set(set: &SelectionSet) -> proto::SelectionSet {
proto::SelectionSet {
replica_id: set.id.replica_id as u32,
lamport_timestamp: set.id.value as u32,
is_active: set.active,
selections: set
.selections
.iter()
.map(|selection| proto::Selection {
id: selection.id as u64,
start: Some(serialize_anchor(&selection.start)),
end: Some(serialize_anchor(&selection.end)),
reversed: selection.reversed,
})
.collect(),
}
pub fn serialize_selections(selections: &Arc<[Selection<Anchor>]>) -> Vec<proto::Selection> {
selections
.iter()
.map(|selection| proto::Selection {
id: selection.id as u64,
start: Some(serialize_anchor(&selection.start)),
end: Some(serialize_anchor(&selection.end)),
reversed: selection.reversed,
})
.collect()
}
pub fn serialize_diagnostics<'a>(
@ -215,42 +197,22 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<Operation> {
})
.collect::<Vec<_>>();
Operation::Buffer(text::Operation::UpdateSelections {
set_id: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.local_timestamp,
},
Operation::UpdateSelections {
replica_id: message.replica_id as ReplicaId,
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
},
selections: Arc::from(selections),
})
}
proto::operation::Variant::RemoveSelections(message) => {
Operation::Buffer(text::Operation::RemoveSelections {
set_id: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.local_timestamp,
},
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
},
})
}
proto::operation::Variant::SetActiveSelections(message) => {
Operation::Buffer(text::Operation::SetActiveSelections {
set_id: message.local_timestamp.map(|value| clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value,
}),
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
},
})
}
}
proto::operation::Variant::RemoveSelections(message) => Operation::RemoveSelections {
replica_id: message.replica_id as ReplicaId,
lamport_timestamp: clock::Lamport {
replica_id: message.replica_id as ReplicaId,
value: message.lamport_timestamp,
},
},
proto::operation::Variant::UpdateDiagnostics(message) => Operation::UpdateDiagnostics {
diagnostics: Arc::from(deserialize_diagnostics(message.diagnostics)),
lamport_timestamp: clock::Lamport {
@ -280,28 +242,21 @@ pub fn deserialize_edit_operation(edit: proto::operation::Edit) -> EditOperation
}
}
pub fn deserialize_selection_set(set: proto::SelectionSet) -> SelectionSet {
SelectionSet {
id: clock::Lamport {
replica_id: set.replica_id as u16,
value: set.lamport_timestamp,
},
active: set.is_active,
selections: Arc::from(
set.selections
.into_iter()
.filter_map(|selection| {
Some(Selection {
id: selection.id as usize,
start: deserialize_anchor(selection.start?)?,
end: deserialize_anchor(selection.end?)?,
reversed: selection.reversed,
goal: SelectionGoal::None,
})
pub fn deserialize_selections(selections: Vec<proto::Selection>) -> Arc<[Selection<Anchor>]> {
Arc::from(
selections
.into_iter()
.filter_map(|selection| {
Some(Selection {
id: selection.id as usize,
start: deserialize_anchor(selection.start?)?,
end: deserialize_anchor(selection.end?)?,
reversed: selection.reversed,
goal: SelectionGoal::None,
})
.collect::<Vec<_>>(),
),
}
})
.collect::<Vec<_>>(),
)
}
pub fn deserialize_diagnostics(