T17 round 2 fixes: merge keeps the newest caret in the lead by where it was given, and a composition cleared to nothing ends
This commit is contained in:
1 parent
8ea952c6dc
commit
40bce9b945
4 files changed
+46
-21
No files matched your search
@@ -61,9 +61,9 @@ Per-component lines live in `tasks/`. Tags there:
|
||||
- [x] T16d Finance · Trading
|
||||
- [x] T16e Finance · Markets & assets
|
||||
- [ ] T17a Editor · Core
|
||||
- [ ] T17b Editor · Intelligence
|
||||
- [ ] T17c Editor · Search
|
||||
- [ ] T17d Editor · Panels
|
||||
- [x] T17b Editor · Intelligence
|
||||
- [x] T17c Editor · Search
|
||||
- [x] T17d Editor · Panels
|
||||
- [x] T17e Editor · Status items
|
||||
- [ ] T18 Terminal
|
||||
- [ ] T19 Git
|
||||
@@ -230,11 +230,12 @@ Per-component lines live in `tasks/`. Tags there:
|
||||
| T16e | 1 | FAIL | a smaller loss than expected read as a miss |
|
||||
| T16e | 2 | PASS | |
|
||||
| T17a | 1 | FAIL | hidden numbers crashed the gutter; an edit with nothing to change tripped an assert; a read-only editor moved its caret and undid; a hint past a multi-line ghost fell off its row; the newest cursor lost the lead on merge; a slow composition left its pinyin in undo; gpui tests broke a featureless test build |
|
||||
| T17a | 2 | — | pending review |
|
||||
| T17a | 2 | FAIL | a selection touching the newest caret took the lead; a composition cleared to nothing stayed open and kept later edits out of undo |
|
||||
| T17a | 3 | — | pending review |
|
||||
| T17b | 1 | FAIL | two calls of one name shared a tree key; references counted lines, not matches |
|
||||
| T17b | 2 | — | pending review |
|
||||
| T17b | 2 | PASS | |
|
||||
| T17c | 1 | FAIL | a match on trailing spaces ran past its trimmed line; `**/` needed a folder |
|
||||
| T17c | 2 | — | pending review |
|
||||
| T17c | 2 | PASS | |
|
||||
| T17d | 1 | FAIL | a path match marked a project name mid-character; pin and remove also opened the row; number settings showed no places |
|
||||
| T17d | 2 | — | pending review |
|
||||
| T17d | 2 | PASS | |
|
||||
| T17e | 1 | PASS | |
|
||||
+23
-14
@@ -38,14 +38,14 @@ impl Selection {
|
||||
}
|
||||
|
||||
/// Sorted by where they start, overlapping selections joined into one; the last given, the primary, stays last.
|
||||
pub(crate) fn merged(mut all: Vec<Selection>) -> Vec<Selection> {
|
||||
let primary = all
|
||||
.last()
|
||||
.expect("an editor keeps at least one cursor")
|
||||
.range();
|
||||
all.sort_by_key(|selection| selection.range().start);
|
||||
pub(crate) fn merged(all: Vec<Selection>) -> Vec<Selection> {
|
||||
assert!(!all.is_empty(), "an editor keeps at least one cursor");
|
||||
let primary = all.len() - 1;
|
||||
let mut all: Vec<(usize, Selection)> = all.into_iter().enumerate().collect();
|
||||
all.sort_by_key(|(_, selection)| selection.range().start);
|
||||
let mut out: Vec<Selection> = Vec::with_capacity(all.len());
|
||||
for next in all {
|
||||
let mut lead = 0;
|
||||
for (given, next) in all {
|
||||
match out.last_mut() {
|
||||
Some(last)
|
||||
if next.range().start < last.range().end
|
||||
@@ -61,14 +61,10 @@ pub(crate) fn merged(mut all: Vec<Selection>) -> Vec<Selection> {
|
||||
}
|
||||
_ => out.push(next),
|
||||
}
|
||||
if given == primary {
|
||||
lead = out.len() - 1;
|
||||
}
|
||||
}
|
||||
let lead = out
|
||||
.iter()
|
||||
.position(|selection| {
|
||||
let range = selection.range();
|
||||
range.start <= primary.start && primary.end <= range.end
|
||||
})
|
||||
.expect("a merge keeps every cursor inside one");
|
||||
let lead = out.remove(lead);
|
||||
out.push(lead);
|
||||
out
|
||||
@@ -174,6 +170,19 @@ pub(crate) fn replace_each(
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn the_last_cursor_given_leads_even_beside_a_touching_selection() {
|
||||
let all = merged(vec![
|
||||
Selection {
|
||||
anchor: 0,
|
||||
head: 1,
|
||||
goal: None,
|
||||
},
|
||||
Selection::caret(1),
|
||||
]);
|
||||
assert_eq!(all.last(), Some(&Selection::caret(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overlapping_selections_join_and_carets_on_one_spot_become_one() {
|
||||
let joined = merged(vec![
|
||||
|
||||
@@ -182,6 +182,9 @@ impl EntityInputHandler for CodeEditor {
|
||||
}
|
||||
self.apply(vec![(range.clone(), text.to_string())], true, cx);
|
||||
self.marked = (!text.is_empty()).then(|| range.start..range.start + text.len());
|
||||
if self.marked.is_none() {
|
||||
self.end_composition();
|
||||
}
|
||||
let caret = match selected_utf16 {
|
||||
Some(inner) => range.start + from_utf16(text, inner.end),
|
||||
None => range.start + text.len(),
|
||||
|
||||
@@ -194,6 +194,18 @@ fn a_slow_composition_undoes_in_one_step(cx: &mut TestAppContext) {
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_composition_cleared_to_nothing_ends(cx: &mut TestAppContext) {
|
||||
let (editor, cx) = editor("", cx);
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.replace_and_mark_text_in_range(None, "n", None, window, cx);
|
||||
editor.replace_and_mark_text_in_range(None, "", None, window, cx);
|
||||
editor.type_text("x", cx);
|
||||
editor.undo(cx);
|
||||
assert_eq!(editor.text(), "", "typing after the cleared mark undoes");
|
||||
});
|
||||
}
|
||||
|
||||
impl CodeEditor {
|
||||
/// Whether line `line` has a row now.
|
||||
fn frame_shows(&self, line: usize) -> bool {
|
||||
|
||||
Reference in new issue
Block a user