mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Multiple replacements, escapes
This commit is contained in:
parent
7a631d8b09
commit
91f2f97572
@ -500,6 +500,8 @@ mod tests {
|
|||||||
|
|
||||||
// Test simple replacements.
|
// Test simple replacements.
|
||||||
test("hello world", 6 .. 11, "wankers", true);
|
test("hello world", 6 .. 11, "wankers", true);
|
||||||
|
test("a d e", 1 .. 3, " b c d", true);
|
||||||
|
test("a #f() e", 1 .. 6, " b c d", false);
|
||||||
test("{(0, 1, 2)}", 5 .. 6, "11pt", true);
|
test("{(0, 1, 2)}", 5 .. 6, "11pt", true);
|
||||||
test("= A heading", 3 .. 3, "n evocative", true);
|
test("= A heading", 3 .. 3, "n evocative", true);
|
||||||
test(
|
test(
|
||||||
@ -546,6 +548,8 @@ mod tests {
|
|||||||
test("x = y", 2 .. 2, "+ y \n ", false);
|
test("x = y", 2 .. 2, "+ y \n ", false);
|
||||||
test("abc\n= a heading", 3 .. 4, "\nsome more test\n\n", true);
|
test("abc\n= a heading", 3 .. 4, "\nsome more test\n\n", true);
|
||||||
test("abc\n= a heading", 3 .. 4, "\nnot ", false);
|
test("abc\n= a heading", 3 .. 4, "\nnot ", false);
|
||||||
|
test("hey #myfriend", 4 .. 4, "\\", false);
|
||||||
|
test("hey #myfriend", 4 .. 4, "\\", true);
|
||||||
|
|
||||||
// Test type invariants.
|
// Test type invariants.
|
||||||
test("#for x in array {x}", 16 .. 19, "[#x]", true);
|
test("#for x in array {x}", 16 .. 19, "[#x]", true);
|
||||||
|
@ -240,6 +240,7 @@ impl GreenNode {
|
|||||||
let mut loop_result = None;
|
let mut loop_result = None;
|
||||||
let mut child_at_start = true;
|
let mut child_at_start = true;
|
||||||
let last = self.children.len() - 1;
|
let last = self.children.len() - 1;
|
||||||
|
let mut start = None;
|
||||||
for (i, child) in self.children.iter_mut().enumerate() {
|
for (i, child) in self.children.iter_mut().enumerate() {
|
||||||
let child_span = Span::new(replace.source, offset, offset + child.len());
|
let child_span = Span::new(replace.source, offset, offset + child.len());
|
||||||
if child_span.surrounds(replace) {
|
if child_span.surrounds(replace) {
|
||||||
@ -271,8 +272,45 @@ impl GreenNode {
|
|||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
loop_result =
|
loop_result = Some((
|
||||||
Some((i, child_span, i == last && outermost, function, policy));
|
i .. i + 1,
|
||||||
|
child_span,
|
||||||
|
i == last && outermost,
|
||||||
|
function,
|
||||||
|
policy,
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
} else if child_span.contains(replace.start)
|
||||||
|
&& mode == TokenMode::Markup
|
||||||
|
&& child.kind().incremental_safety().markup_safe()
|
||||||
|
{
|
||||||
|
eprintln!("found safe start");
|
||||||
|
start = Some((i, offset));
|
||||||
|
} else if child_span.contains(replace.end)
|
||||||
|
&& mode == TokenMode::Markup
|
||||||
|
&& child.kind().incremental_safety().markup_safe()
|
||||||
|
{
|
||||||
|
eprintln!("found safe end");
|
||||||
|
if let Some((start, start_offset)) = start {
|
||||||
|
let (function, policy) =
|
||||||
|
match child.kind().reparsing_function(kind.mode().child_mode()) {
|
||||||
|
Ok(p) => p,
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
loop_result = Some((
|
||||||
|
start .. i + 1,
|
||||||
|
Span::new(replace.source, start_offset, offset + child.len()),
|
||||||
|
i == last && outermost,
|
||||||
|
function,
|
||||||
|
policy,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if start.is_some()
|
||||||
|
&& (mode != TokenMode::Markup
|
||||||
|
|| !child.kind().incremental_safety().markup_safe())
|
||||||
|
{
|
||||||
|
eprintln!("unsafe inbetweeen {:?}", child.kind());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +321,7 @@ impl GreenNode {
|
|||||||
|
|
||||||
// We now have a child that we can replace and a function to do so if
|
// We now have a child that we can replace and a function to do so if
|
||||||
// the loop found any results at all.
|
// the loop found any results at all.
|
||||||
let (child_idx, child_span, child_outermost, func, policy) =
|
let (child_idx_range, child_span, child_outermost, func, policy) =
|
||||||
if let Some(loop_result) = loop_result {
|
if let Some(loop_result) = loop_result {
|
||||||
loop_result
|
loop_result
|
||||||
} else {
|
} else {
|
||||||
@ -316,7 +354,7 @@ impl GreenNode {
|
|||||||
eprintln!("function failed");
|
eprintln!("function failed");
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let child_mode = self.children[child_idx].kind().mode().child_mode();
|
let child_mode = self.children[child_idx_range.start].kind().mode().child_mode();
|
||||||
eprintln!("child mode {:?}", child_mode);
|
eprintln!("child mode {:?}", child_mode);
|
||||||
|
|
||||||
// Check if the children / child has the right type.
|
// Check if the children / child has the right type.
|
||||||
@ -340,7 +378,7 @@ impl GreenNode {
|
|||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
} {
|
} {
|
||||||
if self.children[child_idx].kind() != new_children[0].kind() {
|
if self.children[child_idx_range.start].kind() != new_children[0].kind() {
|
||||||
eprintln!("not the same kind");
|
eprintln!("not the same kind");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -361,8 +399,8 @@ impl GreenNode {
|
|||||||
|
|
||||||
// Check if the neighbor invariants are still true.
|
// Check if the neighbor invariants are still true.
|
||||||
if mode == TokenMode::Markup {
|
if mode == TokenMode::Markup {
|
||||||
if child_idx > 0 {
|
if child_idx_range.start > 0 {
|
||||||
if self.children[child_idx - 1].kind().incremental_safety()
|
if self.children[child_idx_range.start - 1].kind().incremental_safety()
|
||||||
== IncrementalSafety::EnsureRightWhitespace
|
== IncrementalSafety::EnsureRightWhitespace
|
||||||
&& !new_children[0].kind().is_whitespace()
|
&& !new_children[0].kind().is_whitespace()
|
||||||
{
|
{
|
||||||
@ -376,7 +414,7 @@ impl GreenNode {
|
|||||||
new_at_start = child.kind().is_at_start(new_at_start);
|
new_at_start = child.kind().is_at_start(new_at_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
for child in &self.children[child_idx + 1 ..] {
|
for child in &self.children[child_idx_range.end ..] {
|
||||||
if child.kind().is_trivia() {
|
if child.kind().is_trivia() {
|
||||||
new_at_start = child.kind().is_at_start(new_at_start);
|
new_at_start = child.kind().is_at_start(new_at_start);
|
||||||
continue;
|
continue;
|
||||||
@ -393,14 +431,25 @@ impl GreenNode {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if new_children.last().map(|x| x.kind().incremental_safety())
|
||||||
|
== Some(IncrementalSafety::EnsureRightWhitespace)
|
||||||
|
&& self.children.len() > child_idx_range.end
|
||||||
|
{
|
||||||
|
if !self.children[child_idx_range.end].kind().is_whitespace() {
|
||||||
|
eprintln!("right whitespace missing");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("... replacing");
|
eprintln!("... replacing");
|
||||||
|
|
||||||
let old_len = self.children[child_idx].len();
|
let old_len: usize =
|
||||||
|
self.children[child_idx_range.clone()].iter().map(Green::len).sum();
|
||||||
let new_len: usize = new_children.iter().map(Green::len).sum();
|
let new_len: usize = new_children.iter().map(Green::len).sum();
|
||||||
|
|
||||||
self.children.splice(child_idx .. child_idx + 1, new_children);
|
self.children.splice(child_idx_range, new_children);
|
||||||
self.erroneous = self.children.iter().any(|x| x.erroneous());
|
self.erroneous = self.children.iter().any(|x| x.erroneous());
|
||||||
self.data.set_len(self.data.len + new_len - old_len);
|
self.data.set_len(self.data.len + new_len - old_len);
|
||||||
true
|
true
|
||||||
@ -1379,6 +1428,16 @@ impl IncrementalSafety {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn markup_safe(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Safe
|
||||||
|
| Self::SameKindInCode
|
||||||
|
| Self::EnsureAtStart
|
||||||
|
| Self::UnsafeLayer => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This enum describes which mode a token of [`NodeKind`] can appear in.
|
/// This enum describes which mode a token of [`NodeKind`] can appear in.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user