mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-26 03:16:53 -06:00
Merge #358: Replace every occurrence in edit.findReplace when replacement contains find (@Silvertree2010)
This commit is contained in:
@@ -1012,13 +1012,20 @@ fn find_replace(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
if let NodeKind::Text(t) = &mut n.kind {
|
||||
// Replace occurrence by occurrence so styles shift correctly.
|
||||
// The search resumes after each inserted replacement, so a replacement that
|
||||
// contains `find` neither loops forever nor stops the other occurrences.
|
||||
let mut guard = 0;
|
||||
while let Some(pos) = t.characters.find(find.as_str()) {
|
||||
let start = t.characters.get(..pos).map(|x| x.chars().count()).unwrap_or(0);
|
||||
let len = find.chars().count();
|
||||
let mut cursor = 0;
|
||||
let len = find.chars().count();
|
||||
let r_len = r.chars().count();
|
||||
loop {
|
||||
let from = t.characters.char_indices().nth(cursor).map_or(t.characters.len(), |(b, _)| b);
|
||||
let Some(pos) = t.characters.get(from..).and_then(|tail| tail.find(find.as_str())) else { break };
|
||||
let start = cursor + t.characters.get(from..from + pos).map_or(0, |x| x.chars().count());
|
||||
t.replace_range(start, start + len, r);
|
||||
cursor = start + r_len;
|
||||
guard += 1;
|
||||
if guard > 10_000 || r.contains(find.as_str()) {
|
||||
if guard > 10_000 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,28 @@ fn text_create_autosize_and_edit() {
|
||||
assert_eq!(s.doc().unwrap().node(t).unwrap().kind.text().unwrap().characters, "Hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_replace_replaces_every_occurrence_when_replacement_contains_find() {
|
||||
for (text, find, replace, want) in [
|
||||
("cat and cat", "cat", "cats", "cats and cats"),
|
||||
("cat and cat", "cat", "category", "category and category"),
|
||||
("banana", "a", "aa", "baanaanaa"),
|
||||
] {
|
||||
let mut s = sess();
|
||||
let t = id(&s.execute("text.create", &json!({"text": text, "x": 0, "y": 0})).unwrap());
|
||||
s.execute("edit.findReplace", &json!({"find": find, "replace": replace})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().node(t).unwrap().kind.text().unwrap().characters, want, "{text}: {find} -> {replace}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_replace_rejects_empty_find() {
|
||||
let mut s = sess();
|
||||
let t = id(&s.execute("text.create", &json!({"text": "cat", "x": 0, "y": 0})).unwrap());
|
||||
assert!(s.execute("edit.findReplace", &json!({"find": "", "replace": "x"})).is_err());
|
||||
assert_eq!(s.doc().unwrap().node(t).unwrap().kind.text().unwrap().characters, "cat");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn components_and_instances_sync() {
|
||||
let mut s = sess();
|
||||
|
||||
Reference in New Issue
Block a user