C14.9 r1: tables keep extra cells and quote marks; preview refuses edits; lists only in list items; replace moves past its text (library edc328a)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
d4a7d3ebd7
commit
2aa4a080bb
9 files changed
+120
-23
No files matched your search
@@ -140,17 +140,28 @@ impl Desk {
|
||||
if edits.is_empty() {
|
||||
return;
|
||||
}
|
||||
// The next match starts past the replaced text.
|
||||
let after = edits[0].0.start + edits[0].1.len();
|
||||
let document = view.read(cx).document().clone();
|
||||
document.update(cx, |document, cx| document.replace(edits, cx));
|
||||
self.count(cx);
|
||||
// The next match takes the replaced one's place.
|
||||
let next = self
|
||||
.finding
|
||||
.as_ref()
|
||||
.and_then(|find| find.current.and_then(|at| find.hits.get(at)).cloned());
|
||||
if let Some(range) = next.filter(|_| !every) {
|
||||
document.update(cx, |document, cx| document.show_match(range, window, cx));
|
||||
if !document.update(cx, |document, cx| document.replace(edits, cx)) {
|
||||
let said = text(cx, "mark.preview.read_only", &[]);
|
||||
return self.toast(said, Severity::Info, cx);
|
||||
}
|
||||
self.count(cx);
|
||||
if every {
|
||||
return;
|
||||
}
|
||||
let Some(find) = self.finding.as_mut() else {
|
||||
return;
|
||||
};
|
||||
let next = find.hits.iter().position(|hit| hit.start >= after);
|
||||
find.current = next.or((!find.hits.is_empty()).then_some(0));
|
||||
let Some(range) = find.current.map(|at| find.hits[at].clone()) else {
|
||||
return;
|
||||
};
|
||||
let hits = find.hits.clone();
|
||||
mark(&document, &hits, find.current, cx);
|
||||
document.update(cx, |document, cx| document.show_match(range, window, cx));
|
||||
}
|
||||
|
||||
fn close_find(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
|
||||
@@ -118,3 +118,60 @@ fn the_table_menu_inserts_and_edits_a_table(cx: &mut TestAppContext) {
|
||||
current_text(&desk, cx)
|
||||
);
|
||||
}
|
||||
|
||||
fn replace_one(desk: &Entity<Desk>, with: &str, cx: &mut VisualTestContext) {
|
||||
desk.update_in(cx, |desk, window, cx| {
|
||||
let field = cx.new(|cx| TextInput::new(window, cx));
|
||||
field.update(cx, |field, cx| field.set_text(with, cx));
|
||||
desk.finding.as_mut().expect("open").replace = Some(field);
|
||||
desk.replace(false, window, cx);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
}
|
||||
|
||||
fn current_hit(desk: &Entity<Desk>, cx: &mut VisualTestContext) -> Option<std::ops::Range<usize>> {
|
||||
desk.read_with(cx, |desk, _| {
|
||||
let find = desk.finding.as_ref()?;
|
||||
find.current.map(|at| find.hits[at].clone())
|
||||
})
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_replacement_that_still_matches_moves_on(cx: &mut TestAppContext) {
|
||||
let (desk, cx, _files) = opened("a a\n", cx);
|
||||
query(&desk, "a", cx);
|
||||
desk.update_in(cx, |desk, window, cx| desk.step(true, window, cx));
|
||||
replace_one(&desk, "aa", cx);
|
||||
assert_eq!(current_text(&desk, cx), "aa a\n");
|
||||
assert_eq!(
|
||||
current_hit(&desk, cx),
|
||||
Some(3..4),
|
||||
"the next original match"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn replacing_the_last_match_wraps_to_the_first(cx: &mut TestAppContext) {
|
||||
let (desk, cx, _files) = opened("a b a\n", cx);
|
||||
query(&desk, "a", cx);
|
||||
desk.update_in(cx, |desk, window, cx| desk.step(false, window, cx));
|
||||
replace_one(&desk, "x", cx);
|
||||
assert_eq!(current_text(&desk, cx), "a b x\n");
|
||||
assert_eq!(current_hit(&desk, cx), Some(0..1));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn preview_keeps_its_text_from_tables_and_replacement(cx: &mut TestAppContext) {
|
||||
let (desk, cx, _files) = opened("a\n", cx);
|
||||
let view = desk.read_with(cx, |desk, _| desk.active_view().expect("a tab"));
|
||||
view.update_in(cx, |view, window, cx| {
|
||||
view.switch(crate::view::Mode::Preview, window, cx)
|
||||
});
|
||||
let focus = desk.read_with(cx, |desk, _| desk.core.focus.clone());
|
||||
cx.update(|window, cx| window.focus(&focus, cx));
|
||||
cx.dispatch_action(crate::tools::InsertTable);
|
||||
query(&desk, "a", cx);
|
||||
desk.update_in(cx, |desk, window, cx| desk.step(true, window, cx));
|
||||
replace_one(&desk, "x", cx);
|
||||
assert_eq!(current_text(&desk, cx), "a\n");
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
//! The table menu's work on the shown file (MARK-06).
|
||||
|
||||
use ely_gpui_component::{documents::TableEdit, primitives::Severity};
|
||||
use ely_gpui_component::{
|
||||
documents::{TableEdit, TableRefusal},
|
||||
primitives::Severity,
|
||||
};
|
||||
use ely_office::prelude::*;
|
||||
use ely_ui::i18n::text;
|
||||
use gpui::{Context, InteractiveElement as _, actions};
|
||||
@@ -29,15 +32,20 @@ impl Desk {
|
||||
let document = view.read(cx).document().clone();
|
||||
let done = document.update(cx, |document, cx| match edit {
|
||||
Some(edit) => document.edit_table(edit, cx),
|
||||
None => {
|
||||
document.insert_table(cx);
|
||||
true
|
||||
}
|
||||
None => document.insert_table(cx),
|
||||
});
|
||||
if !done {
|
||||
let said = text(cx, "mark.table.none", &[]);
|
||||
self.toast(said, Severity::Info, cx);
|
||||
}
|
||||
let Err(refusal) = done else {
|
||||
return;
|
||||
};
|
||||
let key = match refusal {
|
||||
TableRefusal::Outside => "mark.table.none",
|
||||
TableRefusal::Kept => "mark.table.kept",
|
||||
TableRefusal::Beyond => "mark.table.beyond",
|
||||
TableRefusal::Mixed => "mark.table.mixed",
|
||||
TableRefusal::Preview => "mark.preview.read_only",
|
||||
};
|
||||
let said = text(cx, key, &[]);
|
||||
self.toast(said, Severity::Info, cx);
|
||||
}
|
||||
|
||||
pub fn table_actions(element: gpui::Div, cx: &mut Context<Self>) -> gpui::Div {
|
||||
|
||||
Reference in new issue
Block a user