diff --git a/crates/ui-egui/src/control.rs b/crates/ui-egui/src/control.rs index 32d680b549..c1e6b7d0db 100644 --- a/crates/ui-egui/src/control.rs +++ b/crates/ui-egui/src/control.rs @@ -650,7 +650,10 @@ fn occurrences(text: &str, needle: &str, fold: bool) -> Vec { /// changed. fn replace_text(s: &str, r: &Rewrite) -> Option { let decoded = if has_percent_escape(s) { decoded_with_spans(s).filter(|(decoded, _)| decoded != s) } else { None }; - let mut found = Found::default(); + let mut found = Found { kept: readable_ids_in(s, None, r), ..Found::default() }; + if let Some((text, spans)) = &decoded { + found.kept.extend(readable_ids_in(text, Some(spans.as_slice()), r)); + } for group in &r.pairs { for fold in [false, true].into_iter().take(if r.fold { 2 } else { 1 }) { for (from, to) in group { @@ -677,24 +680,28 @@ fn replace_text(s: &str, r: &Rewrite) -> Option { Some(out) } -/// The spans of a text that [`replace_text`] replaces, each with its replacement, and every span it has -/// taken: the ones it replaces and the loaded library ids it keeps. +/// The spans of a text that [`replace_text`] replaces, each with its replacement, every span it has +/// taken (the ones it replaces and the loaded library ids it keeps), and the whole readable library ids +/// the text holds ([`readable_ids_in`]). #[derive(Default)] struct Found<'a> { cuts: Vec<(usize, usize, &'a str)>, taken: Vec<(usize, usize)>, + kept: Vec<(usize, usize)>, } impl<'a> Found<'a> { - /// Takes each occurrence of `from` in `text` that overlaps no span taken: as a span to write as `to`, - /// or, where it begins a loaded library's id ([`begins_known_id`]), that id's span, kept. `spans` - /// gives the range of the original text each byte of a decoded `text` was read from. + /// Takes each occurrence of `from` in `text` that overlaps no span taken and lies inside no whole + /// readable library id: as a span to write as `to`, or, where it begins a loaded library's id + /// ([`begins_known_id`]), that id's span, kept. `spans` gives the range of the original text each + /// byte of a decoded `text` was read from. fn claim(&mut self, text: &str, spans: Option<&[(usize, usize)]>, from: &str, to: &'a str, fold: bool, r: &Rewrite) { let span = |at: usize, end: usize| spans.map_or((at, end), |s| (s[at].0, s[end - 1].1)); for at in occurrences(text, from, fold) { let end = at + from.len(); let (start, stop) = span(at, end); - if self.taken.iter().any(|&(a, b)| start < b && a < stop) || ends_a_longer_path(text, at, from) { + let inside_readable = self.kept.iter().any(|&(a, b)| a <= start && stop <= b); + if inside_readable || self.taken.iter().any(|&(a, b)| start < b && a < stop) || ends_a_longer_path(text, at, from) { continue; } match begins_known_id(text, at, end, r) { @@ -823,6 +830,40 @@ fn begins_known_id(text: &str, at: usize, end: usize, r: &Rewrite) -> Option