From 41f36220247c1b302166a3441fbb39a0f570afe2 Mon Sep 17 00:00:00 2001 From: PoiScript Date: Wed, 8 May 2024 19:18:40 +0800 Subject: [PATCH] fix: node property parsing --- src/syntax/combinator.rs | 2 +- src/syntax/drawer.rs | 113 +++++++++++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/syntax/combinator.rs b/src/syntax/combinator.rs index 557e12d..a06478d 100644 --- a/src/syntax/combinator.rs +++ b/src/syntax/combinator.rs @@ -58,7 +58,7 @@ token_parser!(percent2_token, "%%", PERCENT2); token_parser!(backslash_token, "\\", BACKSLASH); token_parser!(underscore_token, "_", UNDERSCORE); // token_parser!(star_token, "*", STAR); -token_parser!(plus_token, "+", PLUS); +// token_parser!(plus_token, "+", PLUS); token_parser!(minus_token, "-", MINUS); token_parser!(colon_token, ":", COLON); token_parser!(colon2_token, "::", COLON2); diff --git a/src/syntax/drawer.rs b/src/syntax/drawer.rs index 471571c..691df50 100644 --- a/src/syntax/drawer.rs +++ b/src/syntax/drawer.rs @@ -1,15 +1,15 @@ use nom::{ bytes::complete::{tag_no_case, take_while1}, character::complete::{space0, space1}, - combinator::{iterator, map, opt}, + combinator::{iterator, map, verify}, sequence::tuple, IResult, InputTake, }; use super::{ combinator::{ - blank_lines, colon_token, eol_or_eof, line_starts_iter, node, plus_token, trim_line_end, - GreenElement, NodeBuilder, + blank_lines, colon_token, eol_or_eof, line_starts_iter, node, trim_line_end, GreenElement, + NodeBuilder, }, element::element_nodes, input::Input, @@ -104,30 +104,37 @@ fn property_drawer_node_base(input: Input) -> IResult { } fn node_property_node(input: Input) -> IResult { - map( - tuple(( - space0, - colon_token, - take_while1(|c| c != ':' && c != '+'), - opt(plus_token), - colon_token, - space1, - trim_line_end, - )), - |(ws, colon, name, plus, colon_, ws_, (value, ws__, nl))| { - let mut b = NodeBuilder::new(); - b.ws(ws); - b.push(colon); - b.text(name); - b.push_opt(plus); - b.push(colon_); - b.ws(ws_); - b.text(value); - b.ws(ws__); - b.nl(nl); - b.finish(NODE_PROPERTY) - }, - )(input) + let (input, ws1) = space0(input)?; + let (input, colon1) = colon_token(input)?; + let (input, (colon2, name)) = map( + verify(take_while1(|c| c != ' ' && c != '\t'), |i: &Input| { + i.ends_with(':') + }), + |input: Input| input.take_split(input.len() - 1), + )(input)?; + let (input, ws2) = space1(input)?; + let (input, (value, ws3, nl)) = trim_line_end(input)?; + + let mut b = NodeBuilder::new(); + + b.ws(ws1); + b.push(colon1); + + if name.ends_with("+") { + let (plus, name) = name.take_split(name.len() - 1); + b.text(name); + b.token(PLUS, plus); + } else { + b.text(name); + } + + b.token(COLON, colon2); + b.ws(ws2); + b.text(value); + b.ws(ws3); + b.nl(nl); + + Ok((input, b.finish(NODE_PROPERTY))) } #[cfg_attr( @@ -149,9 +156,14 @@ pub fn drawer_node(input: Input) -> IResult { #[test] fn parse() { - use crate::{ast::Drawer, tests::to_ast, ParseConfig}; + use crate::{ + ast::{Drawer, PropertyDrawer}, + tests::to_ast, + ParseConfig, + }; let to_drawer = to_ast::(drawer_node); + let to_property_drawer = to_ast::(property_drawer_node); insta::assert_debug_snapshot!( to_drawer( @@ -208,8 +220,53 @@ fn parse() { "### ); + // https://github.com/PoiScript/orgize/issues/70#issuecomment-2099671563 + insta::assert_debug_snapshot!( + to_property_drawer(r#":PROPERTIES: +:header-args:clojure: :session *clojure-1* +:NAME: VALUE +:NAME+: VALUE +:END:"#).syntax, + @r###" + PROPERTY_DRAWER@0..91 + DRAWER_BEGIN@0..13 + COLON@0..1 ":" + TEXT@1..11 "PROPERTIES" + COLON@11..12 ":" + NEW_LINE@12..13 "\n" + NODE_PROPERTY@13..59 + COLON@13..14 ":" + TEXT@14..33 "header-args:clojure" + COLON@33..34 ":" + WHITESPACE@34..38 " " + TEXT@38..58 ":session *clojure-1*" + NEW_LINE@58..59 "\n" + NODE_PROPERTY@59..72 + COLON@59..60 ":" + TEXT@60..64 "NAME" + COLON@64..65 ":" + WHITESPACE@65..66 " " + TEXT@66..71 "VALUE" + NEW_LINE@71..72 "\n" + NODE_PROPERTY@72..86 + COLON@72..73 ":" + TEXT@73..77 "NAME" + PLUS@77..78 "+" + COLON@78..79 ":" + WHITESPACE@79..80 " " + TEXT@80..85 "VALUE" + NEW_LINE@85..86 "\n" + DRAWER_END@86..91 + COLON@86..87 ":" + TEXT@87..90 "END" + COLON@90..91 ":" + "### + ); + let config = &ParseConfig::default(); // https://github.com/PoiScript/orgize/issues/9 assert!(drawer_node((":SPAGHETTI:\n", config).into()).is_err()); + + assert!(property_drawer_node((":PROPERTIES:\n:NAME:VALUE\n:END:", config).into()).is_err()); }