mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-24 10:37:03 -06:00
Merge pull request #1002 from Silvertree2010/fix/h2821-find-replace-ignores-line-breaks
This commit is contained in:
@@ -105,7 +105,7 @@ impl Opts {
|
||||
}
|
||||
|
||||
fn para_chars(p: &Paragraph) -> Vec<char> {
|
||||
p.runs.iter().flat_map(|r| r.text.chars()).collect()
|
||||
p.runs.iter().flat_map(|r| r.content().chars()).collect()
|
||||
}
|
||||
|
||||
/// Matches that lie wholly in plain text runs (never inside a field, equation or break).
|
||||
@@ -113,7 +113,7 @@ fn para_matches(p: &Paragraph, o: &Opts) -> Vec<(usize, usize)> {
|
||||
let mut spans = vec![];
|
||||
let mut off = 0;
|
||||
for r in &p.runs {
|
||||
let n = r.text.chars().count();
|
||||
let n = r.char_len();
|
||||
spans.push((off, off + n, matches!(r.kind, RunKind::Text)));
|
||||
off += n;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ fn splice(p: &mut Paragraph, a: usize, b: usize, with: &str) {
|
||||
let mut off = 0;
|
||||
let mut placed = false;
|
||||
for r in &mut p.runs {
|
||||
let chars: Vec<char> = r.text.chars().collect();
|
||||
let chars: Vec<char> = r.content().chars().collect();
|
||||
let (s, e) = (off, off + chars.len());
|
||||
off = e;
|
||||
if e <= a || s >= b {
|
||||
@@ -222,6 +222,34 @@ mod tests {
|
||||
assert_eq!(opts("cat", false, true).matches(&t), vec![(0, 3), (4, 7)]);
|
||||
}
|
||||
|
||||
fn text_run(t: &str) -> Run {
|
||||
Run { text: t.into(), props: RunProps::default(), kind: RunKind::Text }
|
||||
}
|
||||
|
||||
fn br() -> Run {
|
||||
Run { text: String::new(), props: RunProps::default(), kind: RunKind::Break }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_match_never_spans_a_line_break() {
|
||||
let p = Paragraph { runs: vec![text_run("a"), br(), text_run("b")], ..Default::default() };
|
||||
assert!(para_matches(&p, &opts("ab", true, false)).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offsets_count_a_line_break_as_one_char() {
|
||||
let p = Paragraph { runs: vec![text_run("ab"), br(), text_run("cd")], ..Default::default() };
|
||||
assert_eq!(para_matches(&p, &opts("cd", true, false)), vec![(3, 5)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn splice_after_a_line_break_keeps_the_break() {
|
||||
let mut p = Paragraph { runs: vec![text_run("ab"), br(), text_run("cd")], ..Default::default() };
|
||||
splice(&mut p, 3, 5, "X");
|
||||
assert_eq!(p.text(), "ab\u{b}X");
|
||||
assert_eq!(p.runs[1].kind, RunKind::Break);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn splice_across_runs_keeps_the_first_runs_format() {
|
||||
let bold = RunProps { bold: Some(true), ..Default::default() };
|
||||
|
||||
@@ -3685,6 +3685,37 @@ fn find_and_replace_across_shapes_and_notes() {
|
||||
assert_eq!(s.execute("text.find", &q).unwrap().as_array().unwrap().len(), n - 1);
|
||||
}
|
||||
|
||||
/// Find and Replace count a line break as one character, so offsets agree with the editor and no
|
||||
/// match spans the break.
|
||||
#[test]
|
||||
fn find_and_replace_after_a_line_break() {
|
||||
let mut s = session();
|
||||
let id = s.execute("insert.textBox", &json!({"rect": [10, 10, 300, 80], "text": "ab"})).unwrap()["id"].as_u64().unwrap();
|
||||
s.execute("text.edit", &json!({"id": id, "end": true})).unwrap();
|
||||
s.execute("text.insert", &json!({"text": "\u{b}cd"})).unwrap();
|
||||
s.execute("text.exit", &json!({})).unwrap();
|
||||
let text = |s: &Session| {
|
||||
s.doc()
|
||||
.unwrap()
|
||||
.current_slide()
|
||||
.unwrap()
|
||||
.shapes
|
||||
.iter()
|
||||
.find(|x| u64::from(x.id.0) == id)
|
||||
.and_then(|x| x.text.as_ref())
|
||||
.map(|t| t.text())
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(text(&s), "ab\u{b}cd");
|
||||
assert!(s.execute("text.find", &json!({"text": "bc"})).unwrap().as_array().unwrap().is_empty(), "no match spans the break");
|
||||
let found = s.execute("text.find", &json!({"text": "cd"})).unwrap();
|
||||
assert_eq!((found[0]["start"].as_u64(), found[0]["end"].as_u64()), (Some(3), Some(5)), "{found}");
|
||||
s.execute("text.replace", &json!({"text": "cd", "with": "X"})).unwrap();
|
||||
assert_eq!(text(&s), "ab\u{b}X");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(text(&s), "ab\u{b}cd");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pen_pressure_is_kept_and_a_mouse_draws_at_full_width() {
|
||||
let mut s = session();
|
||||
|
||||
Reference in New Issue
Block a user