mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Switch bounded condition, delete only_at_start
This commit is contained in:
parent
91bf1b7f65
commit
b905048d4b
@ -59,7 +59,7 @@ impl Reparser<'_> {
|
|||||||
let original_offset = offset;
|
let original_offset = offset;
|
||||||
|
|
||||||
let mut search = SearchState::default();
|
let mut search = SearchState::default();
|
||||||
let mut ahead_nontrivia = AheadKind::None;
|
let mut ahead: Option<Ahead> = None;
|
||||||
|
|
||||||
// Whether the first node that should be replaced is at start.
|
// Whether the first node that should be replaced is at start.
|
||||||
let mut at_start = true;
|
let mut at_start = true;
|
||||||
@ -95,9 +95,11 @@ impl Reparser<'_> {
|
|||||||
search = SearchState::SpanFound(pos, pos);
|
search = SearchState::SpanFound(pos, pos);
|
||||||
} else {
|
} else {
|
||||||
// Update compulsary state of `ahead_nontrivia`.
|
// Update compulsary state of `ahead_nontrivia`.
|
||||||
match child.kind() {
|
if let Some(ahead_nontrivia) = ahead.as_mut() {
|
||||||
NodeKind::Space(n) if n > &1 => ahead_nontrivia.newline(),
|
match child.kind() {
|
||||||
_ => {}
|
NodeKind::Space(n) if n > &0 => ahead_nontrivia.newline(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We look only for non spaces, non-semicolon and also
|
// We look only for non spaces, non-semicolon and also
|
||||||
@ -106,15 +108,14 @@ impl Reparser<'_> {
|
|||||||
if !child.kind().is_space()
|
if !child.kind().is_space()
|
||||||
&& child.kind() != &NodeKind::Semicolon
|
&& child.kind() != &NodeKind::Semicolon
|
||||||
&& child.kind() != &NodeKind::Text('/'.into())
|
&& child.kind() != &NodeKind::Text('/'.into())
|
||||||
&& (ahead_nontrivia.is_none()
|
&& (ahead.is_none() || self.replaced.start > child_span.end)
|
||||||
|| self.replaced.start > child_span.end)
|
&& !ahead.map_or(false, Ahead::is_compulsory)
|
||||||
&& !ahead_nontrivia.is_compulsory()
|
|
||||||
{
|
{
|
||||||
ahead_nontrivia = if child.kind().is_unbounded() {
|
ahead = Some(Ahead::new(
|
||||||
AheadKind::Unbounded(pos, at_start, true)
|
pos,
|
||||||
} else {
|
at_start,
|
||||||
AheadKind::Normal(pos, at_start)
|
child.kind().is_bounded(),
|
||||||
};
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
at_start = child.kind().is_at_start(at_start);
|
at_start = child.kind().is_at_start(at_start);
|
||||||
@ -154,13 +155,7 @@ impl Reparser<'_> {
|
|||||||
if let SearchState::Contained(pos) = search {
|
if let SearchState::Contained(pos) = search {
|
||||||
// Do not allow replacement of elements inside of constructs whose
|
// Do not allow replacement of elements inside of constructs whose
|
||||||
// opening and closing brackets look the same.
|
// opening and closing brackets look the same.
|
||||||
let safe_inside = match node.kind() {
|
let safe_inside = node.kind().is_bounded();
|
||||||
NodeKind::Emph
|
|
||||||
| NodeKind::Strong
|
|
||||||
| NodeKind::Raw(_)
|
|
||||||
| NodeKind::Math(_) => false,
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
let child = &mut node.children_mut()[pos.idx];
|
let child = &mut node.children_mut()[pos.idx];
|
||||||
let prev_len = child.len();
|
let prev_len = child.len();
|
||||||
@ -211,15 +206,10 @@ impl Reparser<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (mut start, end) = search.done()?;
|
let (mut start, end) = search.done()?;
|
||||||
if let Some((ahead, ahead_at_start)) = ahead_nontrivia.data() {
|
if let Some(ahead) = ahead {
|
||||||
let ahead_kind = node.children().as_slice()[ahead.idx].kind();
|
if start.offset == self.replaced.start || ahead.is_compulsory() {
|
||||||
|
start = ahead.pos;
|
||||||
if start.offset == self.replaced.start
|
at_start = ahead.at_start;
|
||||||
|| ahead_kind.only_at_start()
|
|
||||||
|| ahead_nontrivia.is_compulsory()
|
|
||||||
{
|
|
||||||
start = ahead;
|
|
||||||
at_start = ahead_at_start;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
start = NodePos { idx: 0, offset: original_offset };
|
start = NodePos { idx: 0, offset: original_offset };
|
||||||
@ -342,46 +332,46 @@ impl SearchState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What kind of ahead element is found at the moment, with an index and whether it is `at_start`
|
/// An ahead element with an index and whether it is `at_start`.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum AheadKind {
|
struct Ahead {
|
||||||
/// No non-trivia child has been found yet.
|
pos: NodePos,
|
||||||
None,
|
at_start: bool,
|
||||||
/// A normal non-trivia child has been found.
|
kind: AheadKind,
|
||||||
Normal(NodePos, bool),
|
|
||||||
/// An unbounded child has been found. The last bool indicates whether it was on
|
|
||||||
/// the current line, in which case adding it to the reparsing range is
|
|
||||||
/// compulsory.
|
|
||||||
Unbounded(NodePos, bool, bool),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AheadKind {
|
/// The kind of ahead element.
|
||||||
fn newline(&mut self) {
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
match self {
|
enum AheadKind {
|
||||||
Self::Unbounded(_, _, current_line) => {
|
/// A normal non-trivia child has been found.
|
||||||
*current_line = false;
|
Normal,
|
||||||
}
|
/// An unbounded child has been found. The boolean indicates whether it was
|
||||||
_ => {}
|
/// on the current line, in which case adding it to the reparsing range is
|
||||||
|
/// compulsory.
|
||||||
|
Unbounded(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ahead {
|
||||||
|
fn new(pos: NodePos, at_start: bool, bounded: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
pos,
|
||||||
|
at_start,
|
||||||
|
kind: if bounded {
|
||||||
|
AheadKind::Normal
|
||||||
|
} else {
|
||||||
|
AheadKind::Unbounded(true)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data(self) -> Option<(NodePos, bool)> {
|
fn newline(&mut self) {
|
||||||
match self {
|
if let AheadKind::Unbounded(current_line) = &mut self.kind {
|
||||||
Self::None => None,
|
*current_line = false;
|
||||||
Self::Normal(pos, at_start) => Some((pos, at_start)),
|
|
||||||
Self::Unbounded(pos, at_start, _) => Some((pos, at_start)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_compulsory(self) -> bool {
|
fn is_compulsory(self) -> bool {
|
||||||
match self {
|
matches!(self.kind, AheadKind::Unbounded(true))
|
||||||
Self::None | Self::Normal(_, _) => false,
|
|
||||||
Self::Unbounded(_, _, current_line) => current_line,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_none(self) -> bool {
|
|
||||||
matches!(self, Self::None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,6 +410,9 @@ mod tests {
|
|||||||
test("", 0..0, "do it", 0..5);
|
test("", 0..0, "do it", 0..5);
|
||||||
test("a d e", 1 .. 3, " b c d", 0 .. 9);
|
test("a d e", 1 .. 3, " b c d", 0 .. 9);
|
||||||
test("*~ *", 2..2, "*", 0..5);
|
test("*~ *", 2..2, "*", 0..5);
|
||||||
|
test("_1_\n2a\n3", 5..5, "4", 0..7);
|
||||||
|
test("_1_\n2a\n3~", 8..8, "4", 5..10);
|
||||||
|
test("_1_ 2 3a\n4", 7..7, "5", 0..9);
|
||||||
test("* {1+2} *", 5..6, "3", 2..7);
|
test("* {1+2} *", 5..6, "3", 2..7);
|
||||||
test("a #f() e", 1 .. 6, " b c d", 0 .. 9);
|
test("a #f() e", 1 .. 6, " b c d", 0 .. 9);
|
||||||
test("a\nb\nc\nd\ne\n", 5 .. 5, "c", 2 .. 7);
|
test("a\nb\nc\nd\ne\n", 5 .. 5, "c", 2 .. 7);
|
||||||
@ -427,7 +420,7 @@ mod tests {
|
|||||||
test("a\nb\nc *hel a b lo* d\nd\ne", 13..13, "c ", 6..20);
|
test("a\nb\nc *hel a b lo* d\nd\ne", 13..13, "c ", 6..20);
|
||||||
test("~~ {a} ~~", 4 .. 5, "b", 3 .. 6);
|
test("~~ {a} ~~", 4 .. 5, "b", 3 .. 6);
|
||||||
test("{(0, 1, 2)}", 5 .. 6, "11pt", 0..14);
|
test("{(0, 1, 2)}", 5 .. 6, "11pt", 0..14);
|
||||||
test("\n= A heading", 4 .. 4, "n evocative", 3 .. 23);
|
test("\n= A heading", 4 .. 4, "n evocative", 0 .. 23);
|
||||||
test("for~your~thing", 9 .. 9, "a", 4 .. 15);
|
test("for~your~thing", 9 .. 9, "a", 4 .. 15);
|
||||||
test("a your thing a", 6 .. 7, "a", 0 .. 14);
|
test("a your thing a", 6 .. 7, "a", 0 .. 14);
|
||||||
test("{call(); abc}", 7 .. 7, "[]", 0 .. 15);
|
test("{call(); abc}", 7 .. 7, "[]", 0 .. 15);
|
||||||
|
@ -841,25 +841,25 @@ impl NodeKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this is a node that is not clearly delimited by a character and
|
/// Whether this is a node that is clearly delimited by a character and may
|
||||||
/// may appear in markup.
|
/// appear in markup.
|
||||||
pub fn is_unbounded(&self) -> bool {
|
pub fn is_bounded(&self) -> bool {
|
||||||
matches!(
|
match self {
|
||||||
self,
|
Self::CodeBlock
|
||||||
Self::Strong
|
| Self::ContentBlock
|
||||||
| Self::Emph
|
| Self::Linebreak { .. }
|
||||||
| Self::Raw(_)
|
| Self::NonBreakingSpace
|
||||||
| Self::Math(_)
|
| Self::Shy
|
||||||
| Self::LetExpr
|
| Self::EnDash
|
||||||
| Self::SetExpr
|
| Self::EmDash
|
||||||
| Self::ShowExpr
|
| Self::Ellipsis
|
||||||
| Self::WrapExpr
|
| Self::Quote { .. }
|
||||||
| Self::IfExpr
|
| Self::BlockComment
|
||||||
| Self::WhileExpr
|
| Self::Space(_)
|
||||||
| Self::ForExpr
|
| Self::Escape(_) => true,
|
||||||
| Self::IncludeExpr
|
Self::Text(t) => t != "-" && !t.ends_with('.'),
|
||||||
| Self::ImportExpr
|
_ => false,
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A human-readable name for the kind.
|
/// A human-readable name for the kind.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user