Restore all active selections when undoing/redoing autoindent
In the unlikely event that we're handling autoindent requests from multiple editors, we undo/redo selections from both editors. This is somewhat imperfect but probably good enough and easier than performing auto-indents on a per-editor basis.
This commit is contained in:
parent
47372e7342
commit
561857fdf2
1 changed files with 59 additions and 45 deletions
|
@ -201,7 +201,7 @@ struct SyntaxTree {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AutoindentRequest {
|
struct AutoindentRequest {
|
||||||
selection_set_id: Option<SelectionSetId>,
|
selection_set_ids: HashSet<SelectionSetId>,
|
||||||
before_edit: Snapshot,
|
before_edit: Snapshot,
|
||||||
edited: AnchorSet,
|
edited: AnchorSet,
|
||||||
inserted: Option<AnchorRangeSet>,
|
inserted: Option<AnchorRangeSet>,
|
||||||
|
@ -214,8 +214,8 @@ struct Transaction {
|
||||||
buffer_was_dirty: bool,
|
buffer_was_dirty: bool,
|
||||||
edits: Vec<clock::Local>,
|
edits: Vec<clock::Local>,
|
||||||
ranges: Vec<Range<usize>>,
|
ranges: Vec<Range<usize>>,
|
||||||
selections_before: Option<(SelectionSetId, Arc<[Selection]>)>,
|
selections_before: HashMap<SelectionSetId, Arc<[Selection]>>,
|
||||||
selections_after: Option<(SelectionSetId, Arc<[Selection]>)>,
|
selections_after: HashMap<SelectionSetId, Arc<[Selection]>>,
|
||||||
first_edit_at: Instant,
|
first_edit_at: Instant,
|
||||||
last_edit_at: Instant,
|
last_edit_at: Instant,
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ impl History {
|
||||||
&mut self,
|
&mut self,
|
||||||
start: clock::Global,
|
start: clock::Global,
|
||||||
buffer_was_dirty: bool,
|
buffer_was_dirty: bool,
|
||||||
selections: Option<(SelectionSetId, Arc<[Selection]>)>,
|
selections_before: HashMap<SelectionSetId, Arc<[Selection]>>,
|
||||||
now: Instant,
|
now: Instant,
|
||||||
) {
|
) {
|
||||||
self.transaction_depth += 1;
|
self.transaction_depth += 1;
|
||||||
|
@ -310,8 +310,8 @@ impl History {
|
||||||
buffer_was_dirty,
|
buffer_was_dirty,
|
||||||
edits: Vec::new(),
|
edits: Vec::new(),
|
||||||
ranges: Vec::new(),
|
ranges: Vec::new(),
|
||||||
selections_before: selections,
|
selections_before,
|
||||||
selections_after: None,
|
selections_after: Default::default(),
|
||||||
first_edit_at: now,
|
first_edit_at: now,
|
||||||
last_edit_at: now,
|
last_edit_at: now,
|
||||||
});
|
});
|
||||||
|
@ -320,7 +320,7 @@ impl History {
|
||||||
|
|
||||||
fn end_transaction(
|
fn end_transaction(
|
||||||
&mut self,
|
&mut self,
|
||||||
selections: Option<(SelectionSetId, Arc<[Selection]>)>,
|
selections_after: HashMap<SelectionSetId, Arc<[Selection]>>,
|
||||||
now: Instant,
|
now: Instant,
|
||||||
) -> Option<&Transaction> {
|
) -> Option<&Transaction> {
|
||||||
assert_ne!(self.transaction_depth, 0);
|
assert_ne!(self.transaction_depth, 0);
|
||||||
|
@ -331,7 +331,7 @@ impl History {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let transaction = self.undo_stack.last_mut().unwrap();
|
let transaction = self.undo_stack.last_mut().unwrap();
|
||||||
transaction.selections_after = selections;
|
transaction.selections_after = selections_after;
|
||||||
transaction.last_edit_at = now;
|
transaction.last_edit_at = now;
|
||||||
Some(transaction)
|
Some(transaction)
|
||||||
}
|
}
|
||||||
|
@ -367,7 +367,9 @@ impl History {
|
||||||
|
|
||||||
if let Some(transaction) = transactions_to_merge.last_mut() {
|
if let Some(transaction) = transactions_to_merge.last_mut() {
|
||||||
last_transaction.last_edit_at = transaction.last_edit_at;
|
last_transaction.last_edit_at = transaction.last_edit_at;
|
||||||
last_transaction.selections_after = transaction.selections_after.take();
|
last_transaction
|
||||||
|
.selections_after
|
||||||
|
.extend(transaction.selections_after.drain());
|
||||||
last_transaction.end = transaction.end.clone();
|
last_transaction.end = transaction.end.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,16 +1116,17 @@ impl Buffer {
|
||||||
let selection_set_ids = self
|
let selection_set_ids = self
|
||||||
.autoindent_requests
|
.autoindent_requests
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.filter_map(|req| req.selection_set_id)
|
.flat_map(|req| req.selection_set_ids.clone())
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
self.start_transaction(None).unwrap();
|
self.start_transaction(selection_set_ids.iter().copied())
|
||||||
|
.unwrap();
|
||||||
for (row, indent_column) in &indent_columns {
|
for (row, indent_column) in &indent_columns {
|
||||||
self.set_indent_column_for_line(*row, *indent_column, cx);
|
self.set_indent_column_for_line(*row, *indent_column, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for selection_set_id in selection_set_ids {
|
for selection_set_id in &selection_set_ids {
|
||||||
if let Some(set) = self.selections.get(&selection_set_id) {
|
if let Some(set) = self.selections.get(selection_set_id) {
|
||||||
let new_selections = set
|
let new_selections = set
|
||||||
.selections
|
.selections
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1149,12 +1152,13 @@ impl Buffer {
|
||||||
selection.clone()
|
selection.clone()
|
||||||
})
|
})
|
||||||
.collect::<Arc<[_]>>();
|
.collect::<Arc<[_]>>();
|
||||||
self.update_selection_set(selection_set_id, new_selections, cx)
|
self.update_selection_set(*selection_set_id, new_selections, cx)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.end_transaction(None, cx).unwrap();
|
self.end_transaction(selection_set_ids.iter().copied(), cx)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indent_column_for_line(&self, row: u32) -> u32 {
|
pub fn indent_column_for_line(&self, row: u32) -> u32 {
|
||||||
|
@ -1382,20 +1386,28 @@ impl Buffer {
|
||||||
self.deferred_ops.len()
|
self.deferred_ops.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_transaction(&mut self, set_id: Option<SelectionSetId>) -> Result<()> {
|
pub fn start_transaction(
|
||||||
self.start_transaction_at(set_id, Instant::now())
|
&mut self,
|
||||||
|
selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.start_transaction_at(selection_set_ids, Instant::now())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_transaction_at(&mut self, set_id: Option<SelectionSetId>, now: Instant) -> Result<()> {
|
fn start_transaction_at(
|
||||||
let selections = if let Some(set_id) = set_id {
|
&mut self,
|
||||||
|
selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
|
||||||
|
now: Instant,
|
||||||
|
) -> Result<()> {
|
||||||
|
let selections = selection_set_ids
|
||||||
|
.into_iter()
|
||||||
|
.map(|set_id| {
|
||||||
let set = self
|
let set = self
|
||||||
.selections
|
.selections
|
||||||
.get(&set_id)
|
.get(&set_id)
|
||||||
.ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
|
.expect("invalid selection set id");
|
||||||
Some((set_id, set.selections.clone()))
|
(set_id, set.selections.clone())
|
||||||
} else {
|
})
|
||||||
None
|
.collect();
|
||||||
};
|
|
||||||
self.history
|
self.history
|
||||||
.start_transaction(self.version.clone(), self.is_dirty(), selections, now);
|
.start_transaction(self.version.clone(), self.is_dirty(), selections, now);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1403,27 +1415,28 @@ impl Buffer {
|
||||||
|
|
||||||
pub fn end_transaction(
|
pub fn end_transaction(
|
||||||
&mut self,
|
&mut self,
|
||||||
set_id: Option<SelectionSetId>,
|
selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.end_transaction_at(set_id, Instant::now(), cx)
|
self.end_transaction_at(selection_set_ids, Instant::now(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_transaction_at(
|
fn end_transaction_at(
|
||||||
&mut self,
|
&mut self,
|
||||||
set_id: Option<SelectionSetId>,
|
selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
|
||||||
now: Instant,
|
now: Instant,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let selections = if let Some(set_id) = set_id {
|
let selections = selection_set_ids
|
||||||
|
.into_iter()
|
||||||
|
.map(|set_id| {
|
||||||
let set = self
|
let set = self
|
||||||
.selections
|
.selections
|
||||||
.get(&set_id)
|
.get(&set_id)
|
||||||
.ok_or_else(|| anyhow!("invalid selection set {:?}", set_id))?;
|
.expect("invalid selection set id");
|
||||||
Some((set_id, set.selections.clone()))
|
(set_id, set.selections.clone())
|
||||||
} else {
|
})
|
||||||
None
|
.collect();
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(transaction) = self.history.end_transaction(selections, now) {
|
if let Some(transaction) = self.history.end_transaction(selections, now) {
|
||||||
let since = transaction.start.clone();
|
let since = transaction.start.clone();
|
||||||
|
@ -1544,16 +1557,17 @@ impl Buffer {
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
let selection_set_id = self
|
let selection_set_ids = self
|
||||||
.history
|
.history
|
||||||
.undo_stack
|
.undo_stack
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.selections_before
|
.selections_before
|
||||||
.as_ref()
|
.keys()
|
||||||
.map(|(set_id, _)| *set_id);
|
.copied()
|
||||||
|
.collect();
|
||||||
self.autoindent_requests.push(Arc::new(AutoindentRequest {
|
self.autoindent_requests.push(Arc::new(AutoindentRequest {
|
||||||
selection_set_id,
|
selection_set_ids,
|
||||||
before_edit,
|
before_edit,
|
||||||
edited,
|
edited,
|
||||||
inserted,
|
inserted,
|
||||||
|
@ -1953,7 +1967,7 @@ impl Buffer {
|
||||||
if let Some(transaction) = self.history.pop_undo().cloned() {
|
if let Some(transaction) = self.history.pop_undo().cloned() {
|
||||||
let selections = transaction.selections_before.clone();
|
let selections = transaction.selections_before.clone();
|
||||||
self.undo_or_redo(transaction, cx).unwrap();
|
self.undo_or_redo(transaction, cx).unwrap();
|
||||||
if let Some((set_id, selections)) = selections {
|
for (set_id, selections) in selections {
|
||||||
let _ = self.update_selection_set(set_id, selections, cx);
|
let _ = self.update_selection_set(set_id, selections, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1972,7 +1986,7 @@ impl Buffer {
|
||||||
if let Some(transaction) = self.history.pop_redo().cloned() {
|
if let Some(transaction) = self.history.pop_redo().cloned() {
|
||||||
let selections = transaction.selections_after.clone();
|
let selections = transaction.selections_after.clone();
|
||||||
self.undo_or_redo(transaction, cx).unwrap();
|
self.undo_or_redo(transaction, cx).unwrap();
|
||||||
if let Some((set_id, selections)) = selections {
|
for (set_id, selections) in selections {
|
||||||
let _ = self.update_selection_set(set_id, selections, cx);
|
let _ = self.update_selection_set(set_id, selections, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue