feat: support formulas in org table
This commit is contained in:
parent
3c2c8b28fd
commit
f8fd1306e2
3 changed files with 129 additions and 24 deletions
|
|
@ -8,10 +8,9 @@ use nom::{
|
|||
sequence::tuple,
|
||||
IResult, InputLength, InputTake,
|
||||
};
|
||||
use rowan::GreenNode;
|
||||
|
||||
use super::{
|
||||
combinator::{blank_lines, hash_plus_token, trim_line_end, GreenElement},
|
||||
combinator::{blank_lines, hash_plus_token, node, trim_line_end, GreenElement},
|
||||
input::Input,
|
||||
SyntaxKind,
|
||||
};
|
||||
|
|
@ -19,18 +18,19 @@ use super::{
|
|||
#[tracing::instrument(level = "debug", skip(input), fields(input = input.s))]
|
||||
pub fn keyword_node(input: Input) -> IResult<Input, GreenElement, ()> {
|
||||
fn f(input: Input) -> IResult<Input, GreenElement, ()> {
|
||||
let (input, (key, mut nodes, post_blank)) = keyword_node_base(input)?;
|
||||
let (input, (key, mut nodes)) = keyword_node_base(input)?;
|
||||
let (input, post_blank) = blank_lines(input)?;
|
||||
nodes.extend(post_blank);
|
||||
Ok((
|
||||
input,
|
||||
GreenElement::Node(GreenNode::new(
|
||||
node(
|
||||
if key == "CALL" {
|
||||
SyntaxKind::BABEL_CALL.into()
|
||||
SyntaxKind::BABEL_CALL
|
||||
} else {
|
||||
SyntaxKind::KEYWORD.into()
|
||||
SyntaxKind::KEYWORD
|
||||
},
|
||||
nodes,
|
||||
)),
|
||||
),
|
||||
))
|
||||
}
|
||||
crate::lossless_parser!(f, input)
|
||||
|
|
@ -44,10 +44,12 @@ pub fn affiliated_keyword_nodes(input: Input) -> IResult<Input, Vec<GreenElement
|
|||
let mut i = input;
|
||||
|
||||
while !i.is_empty() {
|
||||
let Ok((input_, (key, nodes, post_blank))) = keyword_node_base(i) else {
|
||||
let Ok((input_, (key, nodes))) = keyword_node_base(i) else {
|
||||
break;
|
||||
};
|
||||
|
||||
let (input_, post_blank) = blank_lines(input_)?;
|
||||
|
||||
// affiliated keyword can not followed by blank lines or eof
|
||||
if !post_blank.is_empty() || input_.is_empty() {
|
||||
return Ok((input, vec![]));
|
||||
|
|
@ -64,24 +66,44 @@ pub fn affiliated_keyword_nodes(input: Input) -> IResult<Input, Vec<GreenElement
|
|||
input_.input_len()
|
||||
);
|
||||
i = input_;
|
||||
children.push(GreenElement::Node(GreenNode::new(
|
||||
SyntaxKind::AFFILIATED_KEYWORD.into(),
|
||||
nodes,
|
||||
)));
|
||||
children.push(node(SyntaxKind::AFFILIATED_KEYWORD, nodes));
|
||||
}
|
||||
|
||||
Ok((i, children))
|
||||
}
|
||||
|
||||
fn keyword_node_base(
|
||||
input: Input,
|
||||
) -> IResult<Input, (&str, Vec<GreenElement>, Vec<GreenElement>), ()> {
|
||||
pub fn tblfm_keyword_nodes(input: Input) -> IResult<Input, Vec<GreenElement>, ()> {
|
||||
let mut children = vec![];
|
||||
let mut i = input;
|
||||
|
||||
while !i.is_empty() {
|
||||
let Ok((input, (key, nodes))) = keyword_node_base(i) else {
|
||||
break;
|
||||
};
|
||||
|
||||
if !key.eq_ignore_ascii_case("TBLFM") {
|
||||
break;
|
||||
}
|
||||
|
||||
debug_assert!(
|
||||
i.input_len() > input.input_len(),
|
||||
"{} > {}",
|
||||
i.input_len(),
|
||||
input.input_len()
|
||||
);
|
||||
i = input;
|
||||
children.push(node(SyntaxKind::KEYWORD, nodes));
|
||||
}
|
||||
|
||||
Ok((i, children))
|
||||
}
|
||||
|
||||
fn keyword_node_base(input: Input) -> IResult<Input, (&str, Vec<GreenElement>), ()> {
|
||||
let (input, (ws, hash_plus)) = tuple((space0, hash_plus_token))(input)?;
|
||||
|
||||
let (input, (key, optional, colon)) = alt((key_with_optional, key))(input)?;
|
||||
|
||||
let (input, (value, ws_, nl)) = trim_line_end(input)?;
|
||||
let (input, post_blank) = blank_lines(input)?;
|
||||
|
||||
let mut children = vec![];
|
||||
if !ws.is_empty() {
|
||||
|
|
@ -103,7 +125,7 @@ fn keyword_node_base(
|
|||
children.push(nl.nl_token());
|
||||
}
|
||||
|
||||
Ok((input, (key.s, children, post_blank)))
|
||||
Ok((input, (key.s, children)))
|
||||
}
|
||||
|
||||
fn key(input: Input) -> IResult<Input, (Input, Option<(Input, Input, Input)>, Input), ()> {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use nom::{
|
|||
use super::{
|
||||
combinator::{blank_lines, line_ends_iter, node, pipe_token, GreenElement, NodeBuilder},
|
||||
input::Input,
|
||||
keyword::tblfm_keyword_nodes,
|
||||
object::standard_object_nodes,
|
||||
SyntaxKind::*,
|
||||
};
|
||||
|
|
@ -23,11 +24,7 @@ fn org_table_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
|
||||
// Org tables end at the first line not starting with a vertical bar.
|
||||
if !trimmed.starts_with('|') {
|
||||
if start == 0 {
|
||||
return Err(nom::Err::Error(()));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if trimmed.starts_with("|-") {
|
||||
|
|
@ -39,8 +36,17 @@ fn org_table_node_base(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
start = i;
|
||||
}
|
||||
|
||||
let (input, post_blank) = blank_lines(input.slice(start..))?;
|
||||
if start == 0 {
|
||||
return Err(nom::Err::Error(()));
|
||||
}
|
||||
|
||||
let input = input.slice(start..);
|
||||
|
||||
let (input, tblfm) = tblfm_keyword_nodes(input)?;
|
||||
|
||||
let (input, post_blank) = blank_lines(input)?;
|
||||
|
||||
children.extend(tblfm);
|
||||
children.extend(post_blank);
|
||||
|
||||
Ok((input, node(ORG_TABLE, children)))
|
||||
|
|
@ -176,6 +182,52 @@ r#"|
|
|||
WHITESPACE@19..20 "\n"
|
||||
"###
|
||||
);
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
to_org_table("| a |\n#+tblfm: test").syntax,
|
||||
@r###"
|
||||
ORG_TABLE@0..19
|
||||
ORG_TABLE_STANDARD_ROW@0..6
|
||||
PIPE@0..1 "|"
|
||||
WHITESPACE@1..2 " "
|
||||
ORG_TABLE_CELL@2..3
|
||||
TEXT@2..3 "a"
|
||||
WHITESPACE@3..4 " "
|
||||
PIPE@4..5 "|"
|
||||
WHITESPACE@5..6 "\n"
|
||||
KEYWORD@6..19
|
||||
HASH_PLUS@6..8 "#+"
|
||||
TEXT@8..13 "tblfm"
|
||||
COLON@13..14 ":"
|
||||
TEXT@14..19 " test"
|
||||
"###
|
||||
);
|
||||
|
||||
insta::assert_debug_snapshot!(
|
||||
to_org_table("| a |\n#+TBLFM: test1\n#+TBLFM: test2").syntax,
|
||||
@r###"
|
||||
ORG_TABLE@0..35
|
||||
ORG_TABLE_STANDARD_ROW@0..6
|
||||
PIPE@0..1 "|"
|
||||
WHITESPACE@1..2 " "
|
||||
ORG_TABLE_CELL@2..3
|
||||
TEXT@2..3 "a"
|
||||
WHITESPACE@3..4 " "
|
||||
PIPE@4..5 "|"
|
||||
WHITESPACE@5..6 "\n"
|
||||
KEYWORD@6..21
|
||||
HASH_PLUS@6..8 "#+"
|
||||
TEXT@8..13 "TBLFM"
|
||||
COLON@13..14 ":"
|
||||
TEXT@14..20 " test1"
|
||||
NEW_LINE@20..21 "\n"
|
||||
KEYWORD@21..35
|
||||
HASH_PLUS@21..23 "#+"
|
||||
TEXT@23..28 "TBLFM"
|
||||
COLON@28..29 ":"
|
||||
TEXT@29..35 " test2"
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue