Merge pull request #672 from zed-industries/fix-unfollowing-on-edit
Automatically unfollow leader only for edits that originate from the follower editor
This commit is contained in:
commit
ccc276da7a
11 changed files with 563 additions and 463 deletions
|
@ -1744,22 +1744,22 @@ impl Editor {
|
||||||
pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
|
pub fn handle_input(&mut self, action: &Input, cx: &mut ViewContext<Self>) {
|
||||||
let text = action.0.as_ref();
|
let text = action.0.as_ref();
|
||||||
if !self.skip_autoclose_end(text, cx) {
|
if !self.skip_autoclose_end(text, cx) {
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
if !self.surround_with_bracket_pair(text, cx) {
|
if !this.surround_with_bracket_pair(text, cx) {
|
||||||
self.insert(text, cx);
|
this.insert(text, cx);
|
||||||
self.autoclose_bracket_pairs(cx);
|
this.autoclose_bracket_pairs(cx);
|
||||||
}
|
}
|
||||||
self.end_transaction(cx);
|
});
|
||||||
self.trigger_completion_on_input(text, cx);
|
self.trigger_completion_on_input(text, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
|
pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
let mut old_selections = SmallVec::<[_; 32]>::new();
|
let mut old_selections = SmallVec::<[_; 32]>::new();
|
||||||
{
|
{
|
||||||
let selections = self.local_selections::<usize>(cx);
|
let selections = this.local_selections::<usize>(cx);
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
let buffer = this.buffer.read(cx).snapshot(cx);
|
||||||
for selection in selections.iter() {
|
for selection in selections.iter() {
|
||||||
let start_point = selection.start.to_point(&buffer);
|
let start_point = selection.start.to_point(&buffer);
|
||||||
let indent = buffer
|
let indent = buffer
|
||||||
|
@ -1789,7 +1789,8 @@ impl Editor {
|
||||||
pair.newline
|
pair.newline
|
||||||
&& buffer.contains_str_at(end + trailing_whitespace_len, pair_end)
|
&& buffer.contains_str_at(end + trailing_whitespace_len, pair_end)
|
||||||
&& buffer.contains_str_at(
|
&& buffer.contains_str_at(
|
||||||
(start - leading_whitespace_len).saturating_sub(pair_start.len()),
|
(start - leading_whitespace_len)
|
||||||
|
.saturating_sub(pair_start.len()),
|
||||||
pair_start,
|
pair_start,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -1805,7 +1806,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
let mut delta = 0_isize;
|
let mut delta = 0_isize;
|
||||||
let mut pending_edit: Option<PendingEdit> = None;
|
let mut pending_edit: Option<PendingEdit> = None;
|
||||||
for (_, _, range, indent, insert_extra_newline) in &old_selections {
|
for (_, _, range, indent, insert_extra_newline) in &old_selections {
|
||||||
|
@ -1848,7 +1849,7 @@ impl Editor {
|
||||||
buffer.edit_with_autoindent(pending.ranges, new_text, cx);
|
buffer.edit_with_autoindent(pending.ranges, new_text, cx);
|
||||||
|
|
||||||
let buffer = buffer.read(cx);
|
let buffer = buffer.read(cx);
|
||||||
self.selections = self
|
this.selections = this
|
||||||
.selections
|
.selections
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -1869,8 +1870,8 @@ impl Editor {
|
||||||
.collect();
|
.collect();
|
||||||
});
|
});
|
||||||
|
|
||||||
self.request_autoscroll(Autoscroll::Fit, cx);
|
this.request_autoscroll(Autoscroll::Fit, cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PendingEdit {
|
struct PendingEdit {
|
||||||
|
@ -1882,10 +1883,9 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
|
let old_selections = this.local_selections::<usize>(cx);
|
||||||
let old_selections = self.local_selections::<usize>(cx);
|
let selection_anchors = this.buffer.update(cx, |buffer, cx| {
|
||||||
let selection_anchors = self.buffer.update(cx, |buffer, cx| {
|
|
||||||
let anchors = {
|
let anchors = {
|
||||||
let snapshot = buffer.read(cx);
|
let snapshot = buffer.read(cx);
|
||||||
old_selections
|
old_selections
|
||||||
|
@ -1899,7 +1899,7 @@ impl Editor {
|
||||||
});
|
});
|
||||||
|
|
||||||
let selections = {
|
let selections = {
|
||||||
let snapshot = self.buffer.read(cx).read(cx);
|
let snapshot = this.buffer.read(cx).read(cx);
|
||||||
selection_anchors
|
selection_anchors
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(id, goal, position)| {
|
.map(|(id, goal, position)| {
|
||||||
|
@ -1914,8 +1914,8 @@ impl Editor {
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
this.update_selections(selections, Some(Autoscroll::Fit), cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -2284,7 +2284,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
let text = &text[common_prefix_len..];
|
let text = &text[common_prefix_len..];
|
||||||
|
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
if let Some(mut snippet) = snippet {
|
if let Some(mut snippet) = snippet {
|
||||||
snippet.text = text.to_string();
|
snippet.text = text.to_string();
|
||||||
for tabstop in snippet.tabstops.iter_mut().flatten() {
|
for tabstop in snippet.tabstops.iter_mut().flatten() {
|
||||||
|
@ -2292,13 +2292,13 @@ impl Editor {
|
||||||
tabstop.end -= common_prefix_len as isize;
|
tabstop.end -= common_prefix_len as isize;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.insert_snippet(&ranges, snippet, cx).log_err();
|
this.insert_snippet(&ranges, snippet, cx).log_err();
|
||||||
} else {
|
} else {
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
buffer.edit_with_autoindent(ranges, text, cx);
|
buffer.edit_with_autoindent(ranges, text, cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.end_transaction(cx);
|
});
|
||||||
|
|
||||||
let project = self.project.clone()?;
|
let project = self.project.clone()?;
|
||||||
let apply_edits = project.update(cx, |project, cx| {
|
let apply_edits = project.update(cx, |project, cx| {
|
||||||
|
@ -2747,14 +2747,13 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
|
pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
self.select_all(&SelectAll, cx);
|
this.select_all(&SelectAll, cx);
|
||||||
self.insert("", cx);
|
this.insert("", cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
|
pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
|
||||||
let mut selections = self.local_selections::<Point>(cx);
|
let mut selections = self.local_selections::<Point>(cx);
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
for selection in &mut selections {
|
for selection in &mut selections {
|
||||||
|
@ -2780,9 +2779,11 @@ impl Editor {
|
||||||
selection.set_head(new_head, SelectionGoal::None);
|
selection.set_head(new_head, SelectionGoal::None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
|
||||||
self.insert("", cx);
|
self.transact(cx, |this, cx| {
|
||||||
self.end_transaction(cx);
|
this.update_selections(selections, Some(Autoscroll::Fit), cx);
|
||||||
|
this.insert("", cx);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
|
pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -2802,11 +2803,11 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start_transaction(cx);
|
|
||||||
let tab_size = cx.global::<Settings>().tab_size;
|
let tab_size = cx.global::<Settings>().tab_size;
|
||||||
let mut selections = self.local_selections::<Point>(cx);
|
let mut selections = self.local_selections::<Point>(cx);
|
||||||
|
self.transact(cx, |this, cx| {
|
||||||
let mut last_indent = None;
|
let mut last_indent = None;
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
for selection in &mut selections {
|
for selection in &mut selections {
|
||||||
if selection.is_empty() {
|
if selection.is_empty() {
|
||||||
let char_column = buffer
|
let char_column = buffer
|
||||||
|
@ -2846,7 +2847,8 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
for row in start_row..end_row {
|
for row in start_row..end_row {
|
||||||
let indent_column = buffer.read(cx).indent_column_for_line(row) as usize;
|
let indent_column =
|
||||||
|
buffer.read(cx).indent_column_for_line(row) as usize;
|
||||||
let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
|
let columns_to_next_tab_stop = tab_size - (indent_column % tab_size);
|
||||||
let row_start = Point::new(row, 0);
|
let row_start = Point::new(row, 0);
|
||||||
buffer.edit(
|
buffer.edit(
|
||||||
|
@ -2869,8 +2871,8 @@ impl Editor {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
this.update_selections(selections, Some(Autoscroll::Fit), cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
|
pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -2879,7 +2881,6 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start_transaction(cx);
|
|
||||||
let tab_size = cx.global::<Settings>().tab_size;
|
let tab_size = cx.global::<Settings>().tab_size;
|
||||||
let selections = self.local_selections::<Point>(cx);
|
let selections = self.local_selections::<Point>(cx);
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
|
@ -2911,21 +2912,20 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
|
||||||
|
self.transact(cx, |this, cx| {
|
||||||
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
buffer.edit(deletion_ranges, "", cx);
|
buffer.edit(deletion_ranges, "", cx);
|
||||||
});
|
});
|
||||||
|
this.update_selections(
|
||||||
self.update_selections(
|
this.local_selections::<usize>(cx),
|
||||||
self.local_selections::<usize>(cx),
|
|
||||||
Some(Autoscroll::Fit),
|
Some(Autoscroll::Fit),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
|
pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
|
||||||
|
|
||||||
let selections = self.local_selections::<Point>(cx);
|
let selections = self.local_selections::<Point>(cx);
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let buffer = self.buffer.read(cx).snapshot(cx);
|
let buffer = self.buffer.read(cx).snapshot(cx);
|
||||||
|
@ -2975,7 +2975,8 @@ impl Editor {
|
||||||
edit_ranges.push(edit_start..edit_end);
|
edit_ranges.push(edit_start..edit_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
let buffer = self.buffer.update(cx, |buffer, cx| {
|
self.transact(cx, |this, cx| {
|
||||||
|
let buffer = this.buffer.update(cx, |buffer, cx| {
|
||||||
buffer.edit(edit_ranges, "", cx);
|
buffer.edit(edit_ranges, "", cx);
|
||||||
buffer.snapshot(cx)
|
buffer.snapshot(cx)
|
||||||
});
|
});
|
||||||
|
@ -2992,13 +2993,11 @@ impl Editor {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
|
pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
|
||||||
|
|
||||||
let selections = self.local_selections::<Point>(cx);
|
let selections = self.local_selections::<Point>(cx);
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let buffer = &display_map.buffer_snapshot;
|
let buffer = &display_map.buffer_snapshot;
|
||||||
|
@ -3029,14 +3028,15 @@ impl Editor {
|
||||||
edits.push((start, text, rows.len() as u32));
|
edits.push((start, text, rows.len() as u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
self.transact(cx, |this, cx| {
|
||||||
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
for (point, text, _) in edits.into_iter().rev() {
|
for (point, text, _) in edits.into_iter().rev() {
|
||||||
buffer.edit(Some(point..point), text, cx);
|
buffer.edit(Some(point..point), text, cx);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.request_autoscroll(Autoscroll::Fit, cx);
|
this.request_autoscroll(Autoscroll::Fit, cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
|
pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -3137,16 +3137,16 @@ impl Editor {
|
||||||
new_selections.extend(contiguous_row_selections.drain(..));
|
new_selections.extend(contiguous_row_selections.drain(..));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
self.unfold_ranges(unfold_ranges, cx);
|
this.unfold_ranges(unfold_ranges, cx);
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
for (range, text) in edits {
|
for (range, text) in edits {
|
||||||
buffer.edit([range], text, cx);
|
buffer.edit([range], text, cx);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.fold_ranges(refold_ranges, cx);
|
this.fold_ranges(refold_ranges, cx);
|
||||||
self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
|
pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -3240,20 +3240,19 @@ impl Editor {
|
||||||
new_selections.extend(contiguous_row_selections.drain(..));
|
new_selections.extend(contiguous_row_selections.drain(..));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
self.unfold_ranges(unfold_ranges, cx);
|
this.unfold_ranges(unfold_ranges, cx);
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
for (range, text) in edits {
|
for (range, text) in edits {
|
||||||
buffer.edit([range], text, cx);
|
buffer.edit([range], text, cx);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.fold_ranges(refold_ranges, cx);
|
this.fold_ranges(refold_ranges, cx);
|
||||||
self.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
this.update_selections(new_selections, Some(Autoscroll::Fit), cx);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
|
pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
|
||||||
self.start_transaction(cx);
|
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
let mut selections = self.local_selections::<Point>(cx);
|
let mut selections = self.local_selections::<Point>(cx);
|
||||||
let mut clipboard_selections = Vec::with_capacity(selections.len());
|
let mut clipboard_selections = Vec::with_capacity(selections.len());
|
||||||
|
@ -3278,12 +3277,12 @@ impl Editor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
|
||||||
self.insert("", cx);
|
|
||||||
self.end_transaction(cx);
|
|
||||||
|
|
||||||
cx.as_mut()
|
self.transact(cx, |this, cx| {
|
||||||
.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
|
this.update_selections(selections, Some(Autoscroll::Fit), cx);
|
||||||
|
this.insert("", cx);
|
||||||
|
cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
|
pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -3313,15 +3312,15 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.as_mut()
|
cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
|
||||||
.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
|
pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
|
||||||
|
self.transact(cx, |this, cx| {
|
||||||
if let Some(item) = cx.as_mut().read_from_clipboard() {
|
if let Some(item) = cx.as_mut().read_from_clipboard() {
|
||||||
let clipboard_text = item.text();
|
let clipboard_text = item.text();
|
||||||
if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
|
if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
|
||||||
let mut selections = self.local_selections::<usize>(cx);
|
let mut selections = this.local_selections::<usize>(cx);
|
||||||
let all_selections_were_entire_line =
|
let all_selections_were_entire_line =
|
||||||
clipboard_selections.iter().all(|s| s.is_entire_line);
|
clipboard_selections.iter().all(|s| s.is_entire_line);
|
||||||
if clipboard_selections.len() != selections.len() {
|
if clipboard_selections.len() != selections.len() {
|
||||||
|
@ -3346,13 +3345,14 @@ impl Editor {
|
||||||
selection.start = (selection.start as isize + delta) as usize;
|
selection.start = (selection.start as isize + delta) as usize;
|
||||||
selection.end = (selection.end as isize + delta) as usize;
|
selection.end = (selection.end as isize + delta) as usize;
|
||||||
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
// If the corresponding selection was empty when this slice of the
|
// If the corresponding selection was empty when this slice of the
|
||||||
// clipboard text was written, then the entire line containing the
|
// clipboard text was written, then the entire line containing the
|
||||||
// selection was copied. If this selection is also currently empty,
|
// selection was copied. If this selection is also currently empty,
|
||||||
// then paste the line before the current line of the buffer.
|
// then paste the line before the current line of the buffer.
|
||||||
let range = if selection.is_empty() && entire_line {
|
let range = if selection.is_empty() && entire_line {
|
||||||
let column = selection.start.to_point(&buffer.read(cx)).column as usize;
|
let column =
|
||||||
|
selection.start.to_point(&buffer.read(cx)).column as usize;
|
||||||
let line_start = selection.start - column;
|
let line_start = selection.start - column;
|
||||||
line_start..line_start
|
line_start..line_start
|
||||||
} else {
|
} else {
|
||||||
|
@ -3365,11 +3365,12 @@ impl Editor {
|
||||||
selection.end = selection.start;
|
selection.end = selection.start;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.update_selections(selections, Some(Autoscroll::Fit), cx);
|
this.update_selections(selections, Some(Autoscroll::Fit), cx);
|
||||||
} else {
|
} else {
|
||||||
self.insert(clipboard_text, cx);
|
this.insert(clipboard_text, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
|
pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -3378,6 +3379,7 @@ impl Editor {
|
||||||
self.set_selections(selections, None, true, cx);
|
self.set_selections(selections, None, true, cx);
|
||||||
}
|
}
|
||||||
self.request_autoscroll(Autoscroll::Fit, cx);
|
self.request_autoscroll(Autoscroll::Fit, cx);
|
||||||
|
cx.emit(Event::Edited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,6 +3389,7 @@ impl Editor {
|
||||||
self.set_selections(selections, None, true, cx);
|
self.set_selections(selections, None, true, cx);
|
||||||
}
|
}
|
||||||
self.request_autoscroll(Autoscroll::Fit, cx);
|
self.request_autoscroll(Autoscroll::Fit, cx);
|
||||||
|
cx.emit(Event::Edited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3977,12 +3980,12 @@ impl Editor {
|
||||||
let comment_prefix = full_comment_prefix.trim_end_matches(' ');
|
let comment_prefix = full_comment_prefix.trim_end_matches(' ');
|
||||||
let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
|
let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
|
||||||
|
|
||||||
self.start_transaction(cx);
|
self.transact(cx, |this, cx| {
|
||||||
let mut selections = self.local_selections::<Point>(cx);
|
let mut selections = this.local_selections::<Point>(cx);
|
||||||
let mut all_selection_lines_are_comments = true;
|
let mut all_selection_lines_are_comments = true;
|
||||||
let mut edit_ranges = Vec::new();
|
let mut edit_ranges = Vec::new();
|
||||||
let mut last_toggled_row = None;
|
let mut last_toggled_row = None;
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
this.buffer.update(cx, |buffer, cx| {
|
||||||
for selection in &mut selections {
|
for selection in &mut selections {
|
||||||
edit_ranges.clear();
|
edit_ranges.clear();
|
||||||
let snapshot = buffer.snapshot(cx);
|
let snapshot = buffer.snapshot(cx);
|
||||||
|
@ -4025,10 +4028,13 @@ impl Editor {
|
||||||
let matching_whitespace_len = line_bytes
|
let matching_whitespace_len = line_bytes
|
||||||
.zip(comment_prefix_whitespace.bytes())
|
.zip(comment_prefix_whitespace.bytes())
|
||||||
.take_while(|(a, b)| a == b)
|
.take_while(|(a, b)| a == b)
|
||||||
.count() as u32;
|
.count()
|
||||||
|
as u32;
|
||||||
let end = Point::new(
|
let end = Point::new(
|
||||||
row,
|
row,
|
||||||
start.column + comment_prefix.len() as u32 + matching_whitespace_len,
|
start.column
|
||||||
|
+ comment_prefix.len() as u32
|
||||||
|
+ matching_whitespace_len,
|
||||||
);
|
);
|
||||||
edit_ranges.push(start..end);
|
edit_ranges.push(start..end);
|
||||||
}
|
}
|
||||||
|
@ -4044,7 +4050,8 @@ impl Editor {
|
||||||
if all_selection_lines_are_comments {
|
if all_selection_lines_are_comments {
|
||||||
buffer.edit(edit_ranges.iter().cloned(), "", cx);
|
buffer.edit(edit_ranges.iter().cloned(), "", cx);
|
||||||
} else {
|
} else {
|
||||||
let min_column = edit_ranges.iter().map(|r| r.start.column).min().unwrap();
|
let min_column =
|
||||||
|
edit_ranges.iter().map(|r| r.start.column).min().unwrap();
|
||||||
let edit_ranges = edit_ranges.iter().map(|range| {
|
let edit_ranges = edit_ranges.iter().map(|range| {
|
||||||
let position = Point::new(range.start.row, min_column);
|
let position = Point::new(range.start.row, min_column);
|
||||||
position..position
|
position..position
|
||||||
|
@ -4055,12 +4062,12 @@ impl Editor {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.update_selections(
|
this.update_selections(
|
||||||
self.local_selections::<usize>(cx),
|
this.local_selections::<usize>(cx),
|
||||||
Some(Autoscroll::Fit),
|
Some(Autoscroll::Fit),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
self.end_transaction(cx);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_larger_syntax_node(
|
pub fn select_larger_syntax_node(
|
||||||
|
@ -5125,13 +5132,9 @@ impl Editor {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
|
update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
|
||||||
) {
|
) {
|
||||||
self.start_transaction(cx);
|
|
||||||
update(self, cx);
|
|
||||||
self.end_transaction(cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn start_transaction(&mut self, cx: &mut ViewContext<Self>) {
|
|
||||||
self.start_transaction_at(Instant::now(), cx);
|
self.start_transaction_at(Instant::now(), cx);
|
||||||
|
update(self, cx);
|
||||||
|
self.end_transaction_at(Instant::now(), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
|
fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -5145,10 +5148,6 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_transaction(&mut self, cx: &mut ViewContext<Self>) {
|
|
||||||
self.end_transaction_at(Instant::now(), cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
|
fn end_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(tx_id) = self
|
if let Some(tx_id) = self
|
||||||
.buffer
|
.buffer
|
||||||
|
@ -5159,6 +5158,8 @@ impl Editor {
|
||||||
} else {
|
} else {
|
||||||
log::error!("unexpectedly ended a transaction that wasn't started by this editor");
|
log::error!("unexpectedly ended a transaction that wasn't started by this editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cx.emit(Event::Edited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5328,11 +5329,13 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
|
pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
|
||||||
self.buffer
|
self.transact(cx, |this, cx| {
|
||||||
|
this.buffer
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.as_singleton()
|
.as_singleton()
|
||||||
.expect("you can only call set_text on editors for singleton buffers")
|
.expect("you can only call set_text on editors for singleton buffers")
|
||||||
.update(cx, |buffer, cx| buffer.set_text(text, cx));
|
.update(cx, |buffer, cx| buffer.set_text(text, cx));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
|
pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
|
||||||
|
@ -5535,10 +5538,10 @@ impl Editor {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
language::Event::Edited { local } => {
|
language::Event::Edited => {
|
||||||
self.refresh_active_diagnostics(cx);
|
self.refresh_active_diagnostics(cx);
|
||||||
self.refresh_code_actions(cx);
|
self.refresh_code_actions(cx);
|
||||||
cx.emit(Event::Edited { local: *local });
|
cx.emit(Event::BufferEdited);
|
||||||
}
|
}
|
||||||
language::Event::Dirtied => cx.emit(Event::Dirtied),
|
language::Event::Dirtied => cx.emit(Event::Dirtied),
|
||||||
language::Event::Saved => cx.emit(Event::Saved),
|
language::Event::Saved => cx.emit(Event::Saved),
|
||||||
|
@ -5662,10 +5665,11 @@ fn compute_scroll_position(
|
||||||
scroll_position
|
scroll_position
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Activate,
|
Activate,
|
||||||
Edited { local: bool },
|
BufferEdited,
|
||||||
|
Edited,
|
||||||
Blurred,
|
Blurred,
|
||||||
Dirtied,
|
Dirtied,
|
||||||
Saved,
|
Saved,
|
||||||
|
@ -6144,6 +6148,114 @@ mod tests {
|
||||||
use util::test::sample_text;
|
use util::test::sample_text;
|
||||||
use workspace::FollowableItem;
|
use workspace::FollowableItem;
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_edit_events(cx: &mut MutableAppContext) {
|
||||||
|
populate_settings(cx);
|
||||||
|
let buffer = cx.add_model(|cx| language::Buffer::new(0, "123456", cx));
|
||||||
|
|
||||||
|
let events = Rc::new(RefCell::new(Vec::new()));
|
||||||
|
let (_, editor1) = cx.add_window(Default::default(), {
|
||||||
|
let events = events.clone();
|
||||||
|
|cx| {
|
||||||
|
cx.subscribe(&cx.handle(), move |_, _, event, _| {
|
||||||
|
if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
|
||||||
|
events.borrow_mut().push(("editor1", *event));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
Editor::for_buffer(buffer.clone(), None, cx)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let (_, editor2) = cx.add_window(Default::default(), {
|
||||||
|
let events = events.clone();
|
||||||
|
|cx| {
|
||||||
|
cx.subscribe(&cx.handle(), move |_, _, event, _| {
|
||||||
|
if matches!(event, Event::Edited | Event::BufferEdited | Event::Dirtied) {
|
||||||
|
events.borrow_mut().push(("editor2", *event));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
Editor::for_buffer(buffer.clone(), None, cx)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
|
||||||
|
|
||||||
|
// Mutating editor 1 will emit an `Edited` event only for that editor.
|
||||||
|
editor1.update(cx, |editor, cx| editor.insert("X", cx));
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *events.borrow_mut()),
|
||||||
|
[
|
||||||
|
("editor1", Event::Edited),
|
||||||
|
("editor1", Event::BufferEdited),
|
||||||
|
("editor2", Event::BufferEdited),
|
||||||
|
("editor1", Event::Dirtied),
|
||||||
|
("editor2", Event::Dirtied)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mutating editor 2 will emit an `Edited` event only for that editor.
|
||||||
|
editor2.update(cx, |editor, cx| editor.delete(&Delete, cx));
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *events.borrow_mut()),
|
||||||
|
[
|
||||||
|
("editor2", Event::Edited),
|
||||||
|
("editor1", Event::BufferEdited),
|
||||||
|
("editor2", Event::BufferEdited),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Undoing on editor 1 will emit an `Edited` event only for that editor.
|
||||||
|
editor1.update(cx, |editor, cx| editor.undo(&Undo, cx));
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *events.borrow_mut()),
|
||||||
|
[
|
||||||
|
("editor1", Event::Edited),
|
||||||
|
("editor1", Event::BufferEdited),
|
||||||
|
("editor2", Event::BufferEdited),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Redoing on editor 1 will emit an `Edited` event only for that editor.
|
||||||
|
editor1.update(cx, |editor, cx| editor.redo(&Redo, cx));
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *events.borrow_mut()),
|
||||||
|
[
|
||||||
|
("editor1", Event::Edited),
|
||||||
|
("editor1", Event::BufferEdited),
|
||||||
|
("editor2", Event::BufferEdited),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Undoing on editor 2 will emit an `Edited` event only for that editor.
|
||||||
|
editor2.update(cx, |editor, cx| editor.undo(&Undo, cx));
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *events.borrow_mut()),
|
||||||
|
[
|
||||||
|
("editor2", Event::Edited),
|
||||||
|
("editor1", Event::BufferEdited),
|
||||||
|
("editor2", Event::BufferEdited),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Redoing on editor 2 will emit an `Edited` event only for that editor.
|
||||||
|
editor2.update(cx, |editor, cx| editor.redo(&Redo, cx));
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *events.borrow_mut()),
|
||||||
|
[
|
||||||
|
("editor2", Event::Edited),
|
||||||
|
("editor1", Event::BufferEdited),
|
||||||
|
("editor2", Event::BufferEdited),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// No event is emitted when the mutation is a no-op.
|
||||||
|
editor2.update(cx, |editor, cx| {
|
||||||
|
editor.select_ranges([0..0], None, cx);
|
||||||
|
editor.backspace(&Backspace, cx);
|
||||||
|
});
|
||||||
|
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
|
fn test_undo_redo_with_selection_restoration(cx: &mut MutableAppContext) {
|
||||||
populate_settings(cx);
|
populate_settings(cx);
|
||||||
|
|
|
@ -198,7 +198,7 @@ impl FollowableItem for Editor {
|
||||||
|
|
||||||
fn should_unfollow_on_event(event: &Self::Event, _: &AppContext) -> bool {
|
fn should_unfollow_on_event(event: &Self::Event, _: &AppContext) -> bool {
|
||||||
match event {
|
match event {
|
||||||
Event::Edited { local } => *local,
|
Event::Edited => true,
|
||||||
Event::SelectionsChanged { local } => *local,
|
Event::SelectionsChanged { local } => *local,
|
||||||
Event::ScrollPositionChanged { local } => *local,
|
Event::ScrollPositionChanged { local } => *local,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -291,7 +291,7 @@ impl FileFinder {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Edited { .. } => {
|
editor::Event::BufferEdited { .. } => {
|
||||||
let query = self.query_editor.update(cx, |buffer, cx| buffer.text(cx));
|
let query = self.query_editor.update(cx, |buffer, cx| buffer.text(cx));
|
||||||
if query.is_empty() {
|
if query.is_empty() {
|
||||||
self.latest_search_id = post_inc(&mut self.search_count);
|
self.latest_search_id = post_inc(&mut self.search_count);
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl GoToLine {
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
||||||
editor::Event::Edited { .. } => {
|
editor::Event::BufferEdited { .. } => {
|
||||||
let line_editor = self.line_editor.read(cx).buffer().read(cx).read(cx).text();
|
let line_editor = self.line_editor.read(cx).buffer().read(cx).read(cx).text();
|
||||||
let mut components = line_editor.trim().split(&[',', ':'][..]);
|
let mut components = line_editor.trim().split(&[',', ':'][..]);
|
||||||
let row = components.next().and_then(|row| row.parse::<u32>().ok());
|
let row = components.next().and_then(|row| row.parse::<u32>().ok());
|
||||||
|
|
|
@ -142,7 +142,7 @@ pub enum Operation {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Operation(Operation),
|
Operation(Operation),
|
||||||
Edited { local: bool },
|
Edited,
|
||||||
Dirtied,
|
Dirtied,
|
||||||
Saved,
|
Saved,
|
||||||
FileHandleChanged,
|
FileHandleChanged,
|
||||||
|
@ -967,7 +967,7 @@ impl Buffer {
|
||||||
) -> Option<TransactionId> {
|
) -> Option<TransactionId> {
|
||||||
if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
|
if let Some((transaction_id, start_version)) = self.text.end_transaction_at(now) {
|
||||||
let was_dirty = start_version != self.saved_version;
|
let was_dirty = start_version != self.saved_version;
|
||||||
self.did_edit(&start_version, was_dirty, true, cx);
|
self.did_edit(&start_version, was_dirty, cx);
|
||||||
Some(transaction_id)
|
Some(transaction_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1160,7 +1160,6 @@ impl Buffer {
|
||||||
&mut self,
|
&mut self,
|
||||||
old_version: &clock::Global,
|
old_version: &clock::Global,
|
||||||
was_dirty: bool,
|
was_dirty: bool,
|
||||||
local: bool,
|
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
if self.edits_since::<usize>(old_version).next().is_none() {
|
if self.edits_since::<usize>(old_version).next().is_none() {
|
||||||
|
@ -1169,7 +1168,7 @@ impl Buffer {
|
||||||
|
|
||||||
self.reparse(cx);
|
self.reparse(cx);
|
||||||
|
|
||||||
cx.emit(Event::Edited { local });
|
cx.emit(Event::Edited);
|
||||||
if !was_dirty {
|
if !was_dirty {
|
||||||
cx.emit(Event::Dirtied);
|
cx.emit(Event::Dirtied);
|
||||||
}
|
}
|
||||||
|
@ -1206,7 +1205,7 @@ impl Buffer {
|
||||||
self.text.apply_ops(buffer_ops)?;
|
self.text.apply_ops(buffer_ops)?;
|
||||||
self.deferred_ops.insert(deferred_ops);
|
self.deferred_ops.insert(deferred_ops);
|
||||||
self.flush_deferred_ops(cx);
|
self.flush_deferred_ops(cx);
|
||||||
self.did_edit(&old_version, was_dirty, false, cx);
|
self.did_edit(&old_version, was_dirty, cx);
|
||||||
// Notify independently of whether the buffer was edited as the operations could include a
|
// Notify independently of whether the buffer was edited as the operations could include a
|
||||||
// selection update.
|
// selection update.
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -1321,7 +1320,7 @@ impl Buffer {
|
||||||
|
|
||||||
if let Some((transaction_id, operation)) = self.text.undo() {
|
if let Some((transaction_id, operation)) = self.text.undo() {
|
||||||
self.send_operation(Operation::Buffer(operation), cx);
|
self.send_operation(Operation::Buffer(operation), cx);
|
||||||
self.did_edit(&old_version, was_dirty, true, cx);
|
self.did_edit(&old_version, was_dirty, cx);
|
||||||
Some(transaction_id)
|
Some(transaction_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1342,7 +1341,7 @@ impl Buffer {
|
||||||
self.send_operation(Operation::Buffer(operation), cx);
|
self.send_operation(Operation::Buffer(operation), cx);
|
||||||
}
|
}
|
||||||
if undone {
|
if undone {
|
||||||
self.did_edit(&old_version, was_dirty, true, cx)
|
self.did_edit(&old_version, was_dirty, cx)
|
||||||
}
|
}
|
||||||
undone
|
undone
|
||||||
}
|
}
|
||||||
|
@ -1353,7 +1352,7 @@ impl Buffer {
|
||||||
|
|
||||||
if let Some((transaction_id, operation)) = self.text.redo() {
|
if let Some((transaction_id, operation)) = self.text.redo() {
|
||||||
self.send_operation(Operation::Buffer(operation), cx);
|
self.send_operation(Operation::Buffer(operation), cx);
|
||||||
self.did_edit(&old_version, was_dirty, true, cx);
|
self.did_edit(&old_version, was_dirty, cx);
|
||||||
Some(transaction_id)
|
Some(transaction_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1374,7 +1373,7 @@ impl Buffer {
|
||||||
self.send_operation(Operation::Buffer(operation), cx);
|
self.send_operation(Operation::Buffer(operation), cx);
|
||||||
}
|
}
|
||||||
if redone {
|
if redone {
|
||||||
self.did_edit(&old_version, was_dirty, true, cx)
|
self.did_edit(&old_version, was_dirty, cx)
|
||||||
}
|
}
|
||||||
redone
|
redone
|
||||||
}
|
}
|
||||||
|
@ -1440,7 +1439,7 @@ impl Buffer {
|
||||||
if !ops.is_empty() {
|
if !ops.is_empty() {
|
||||||
for op in ops {
|
for op in ops {
|
||||||
self.send_operation(Operation::Buffer(op), cx);
|
self.send_operation(Operation::Buffer(op), cx);
|
||||||
self.did_edit(&old_version, was_dirty, true, cx);
|
self.did_edit(&old_version, was_dirty, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,19 +122,11 @@ fn test_edit_events(cx: &mut gpui::MutableAppContext) {
|
||||||
let buffer_1_events = buffer_1_events.borrow();
|
let buffer_1_events = buffer_1_events.borrow();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*buffer_1_events,
|
*buffer_1_events,
|
||||||
vec![
|
vec![Event::Edited, Event::Dirtied, Event::Edited, Event::Edited]
|
||||||
Event::Edited { local: true },
|
|
||||||
Event::Dirtied,
|
|
||||||
Event::Edited { local: true },
|
|
||||||
Event::Edited { local: true }
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let buffer_2_events = buffer_2_events.borrow();
|
let buffer_2_events = buffer_2_events.borrow();
|
||||||
assert_eq!(
|
assert_eq!(*buffer_2_events, vec![Event::Edited, Event::Dirtied]);
|
||||||
*buffer_2_events,
|
|
||||||
vec![Event::Edited { local: false }, Event::Dirtied]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
|
|
@ -224,7 +224,7 @@ impl OutlineView {
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
||||||
editor::Event::Edited { .. } => self.update_matches(cx),
|
editor::Event::BufferEdited { .. } => self.update_matches(cx),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6229,10 +6229,7 @@ mod tests {
|
||||||
assert!(buffer.is_dirty());
|
assert!(buffer.is_dirty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*events.borrow(),
|
*events.borrow(),
|
||||||
&[
|
&[language::Event::Edited, language::Event::Dirtied]
|
||||||
language::Event::Edited { local: true },
|
|
||||||
language::Event::Dirtied
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
events.borrow_mut().clear();
|
events.borrow_mut().clear();
|
||||||
buffer.did_save(buffer.version(), buffer.file().unwrap().mtime(), None, cx);
|
buffer.did_save(buffer.version(), buffer.file().unwrap().mtime(), None, cx);
|
||||||
|
@ -6255,9 +6252,9 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*events.borrow(),
|
*events.borrow(),
|
||||||
&[
|
&[
|
||||||
language::Event::Edited { local: true },
|
language::Event::Edited,
|
||||||
language::Event::Dirtied,
|
language::Event::Dirtied,
|
||||||
language::Event::Edited { local: true },
|
language::Event::Edited,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
events.borrow_mut().clear();
|
events.borrow_mut().clear();
|
||||||
|
@ -6269,7 +6266,7 @@ mod tests {
|
||||||
assert!(buffer.is_dirty());
|
assert!(buffer.is_dirty());
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(*events.borrow(), &[language::Event::Edited { local: true }]);
|
assert_eq!(*events.borrow(), &[language::Event::Edited]);
|
||||||
|
|
||||||
// When a file is deleted, the buffer is considered dirty.
|
// When a file is deleted, the buffer is considered dirty.
|
||||||
let events = Rc::new(RefCell::new(Vec::new()));
|
let events = Rc::new(RefCell::new(Vec::new()));
|
||||||
|
|
|
@ -328,7 +328,7 @@ impl ProjectSymbolsView {
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
editor::Event::Blurred => cx.emit(Event::Dismissed),
|
||||||
editor::Event::Edited { .. } => self.update_matches(cx),
|
editor::Event::BufferEdited { .. } => self.update_matches(cx),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,7 +360,7 @@ impl SearchBar {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Edited { .. } => {
|
editor::Event::BufferEdited { .. } => {
|
||||||
self.query_contains_error = false;
|
self.query_contains_error = false;
|
||||||
self.clear_matches(cx);
|
self.clear_matches(cx);
|
||||||
self.update_matches(true, cx);
|
self.update_matches(true, cx);
|
||||||
|
@ -377,7 +377,7 @@ impl SearchBar {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Edited { .. } => self.update_matches(false, cx),
|
editor::Event::BufferEdited { .. } => self.update_matches(false, cx),
|
||||||
editor::Event::SelectionsChanged { .. } => self.update_match_index(cx),
|
editor::Event::SelectionsChanged { .. } => self.update_match_index(cx),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ impl ThemeSelector {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::Edited { .. } => {
|
editor::Event::BufferEdited { .. } => {
|
||||||
self.update_matches(cx);
|
self.update_matches(cx);
|
||||||
self.select_if_matching(&cx.global::<Settings>().theme.name);
|
self.select_if_matching(&cx.global::<Settings>().theme.name);
|
||||||
self.show_selected_theme(cx);
|
self.show_selected_theme(cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue