feat: support use_sub_superscript config
This commit is contained in:
parent
9b8aec02a4
commit
eab9eb68ec
3 changed files with 91 additions and 38 deletions
|
|
@ -1,6 +1,27 @@
|
|||
use crate::syntax::document::document_node;
|
||||
use crate::Org;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UseSubSuperscript {
|
||||
Nil,
|
||||
Brace,
|
||||
True,
|
||||
}
|
||||
|
||||
impl UseSubSuperscript {
|
||||
pub fn is_nil(&self) -> bool {
|
||||
matches!(self, UseSubSuperscript::Nil)
|
||||
}
|
||||
|
||||
pub fn is_true(&self) -> bool {
|
||||
matches!(self, UseSubSuperscript::True)
|
||||
}
|
||||
|
||||
pub fn is_brace(&self) -> bool {
|
||||
matches!(self, UseSubSuperscript::Brace)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse configuration
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParseConfig {
|
||||
|
|
@ -11,6 +32,15 @@ pub struct ParseConfig {
|
|||
|
||||
pub parsed_keywords: Vec<String>,
|
||||
|
||||
/// Control sub/superscript parsing
|
||||
///
|
||||
/// Equivalent to `org-use-sub-superscripts`
|
||||
///
|
||||
/// - `UseSubSuperscript::Nil`: disable parsing
|
||||
/// - `UseSubSuperscript::True`: enable parsing
|
||||
/// - `UseSubSuperscript::Brace`: enable parsing, but braces are required
|
||||
pub use_sub_superscript: UseSubSuperscript,
|
||||
|
||||
/// Affiliated keywords
|
||||
///
|
||||
/// Equivalent to [`org-element-affiliated-keywords`](https://git.sr.ht/~bzg/org-mode/tree/6f960f3c6a4dfe137fbd33fef9f7dadfd229600c/item/lisp/org-element.el#L331)
|
||||
|
|
@ -36,6 +66,7 @@ impl Default for ParseConfig {
|
|||
todo_keywords: (vec!["TODO".into()], vec!["DONE".into()]),
|
||||
dual_keywords: vec!["CAPTION".into(), "RESULTS".into()],
|
||||
parsed_keywords: vec!["CAPTION".into()],
|
||||
use_sub_superscript: UseSubSuperscript::True,
|
||||
affiliated_keywords: vec![
|
||||
"CAPTION".into(),
|
||||
"DATA".into(),
|
||||
|
|
|
|||
|
|
@ -128,8 +128,16 @@ pub fn minimal_object_nodes(input: Input) -> Vec<GreenElement> {
|
|||
b'~' if emphasis::verify_pre(pre.s) => code_node(i),
|
||||
b'$' => latex_fragment_node(i),
|
||||
b'\\' => entity_node(i).or_else(|_| latex_fragment_node(i)),
|
||||
b'^' if subscript_superscript::verify_pre(pre.s) => superscript_node(i),
|
||||
b'_' if subscript_superscript::verify_pre(pre.s) => subscript_node(i),
|
||||
b'^' if !input.c.use_sub_superscript.is_nil()
|
||||
&& subscript_superscript::verify_pre(pre.s) =>
|
||||
{
|
||||
superscript_node(i)
|
||||
}
|
||||
b'_' if !input.c.use_sub_superscript.is_nil()
|
||||
&& subscript_superscript::verify_pre(pre.s) =>
|
||||
{
|
||||
subscript_node(i)
|
||||
}
|
||||
_ => Err(nom::Err::Error(())),
|
||||
},
|
||||
input,
|
||||
|
|
|
|||
|
|
@ -24,23 +24,16 @@ pub fn superscript_node(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
|
||||
let mut children = vec![caret];
|
||||
|
||||
if let Ok((input, star)) = tag::<&str, Input, ()>("*")(input) {
|
||||
children.push(star.text_token());
|
||||
Ok((input, node(SyntaxKind::SUPERSCRIPT, children)))
|
||||
} else if let Ok((input, (l, contents, r))) = template1(input) {
|
||||
children.push(l);
|
||||
children.extend(standard_object_nodes(contents));
|
||||
children.push(r);
|
||||
Ok((input, node(SyntaxKind::SUPERSCRIPT, children)))
|
||||
} else if let Ok((input, (sign, contents))) = template2(input) {
|
||||
if let Some(s) = sign {
|
||||
children.push(s)
|
||||
}
|
||||
children.push(contents);
|
||||
Ok((input, node(SyntaxKind::SUPERSCRIPT, children)))
|
||||
} else {
|
||||
Err(nom::Err::Error(()))
|
||||
if input.c.use_sub_superscript.is_brace() {
|
||||
let (input, rest) = template1(input)?;
|
||||
children.extend(rest);
|
||||
return Ok((input, node(SyntaxKind::SUPERSCRIPT, children)));
|
||||
}
|
||||
|
||||
let (input, rest) = alt((template0, template1, template2))(input)?;
|
||||
children.extend(rest);
|
||||
|
||||
Ok((input, node(SyntaxKind::SUPERSCRIPT, children)))
|
||||
}
|
||||
|
||||
pub fn subscript_node(input: Input) -> IResult<Input, GreenElement, ()> {
|
||||
|
|
@ -48,33 +41,35 @@ pub fn subscript_node(input: Input) -> IResult<Input, GreenElement, ()> {
|
|||
|
||||
let mut children = vec![underscore];
|
||||
|
||||
if let Ok((input, star)) = tag::<&str, Input, ()>("*")(input) {
|
||||
children.push(star.text_token());
|
||||
Ok((input, node(SyntaxKind::SUBSCRIPT, children)))
|
||||
} else if let Ok((input, (l, contents, r))) = template1(input) {
|
||||
children.push(l);
|
||||
children.extend(standard_object_nodes(contents));
|
||||
children.push(r);
|
||||
Ok((input, node(SyntaxKind::SUBSCRIPT, children)))
|
||||
} else if let Ok((input, (sign, contents))) = template2(input) {
|
||||
if let Some(s) = sign {
|
||||
children.push(s)
|
||||
}
|
||||
children.push(contents);
|
||||
Ok((input, node(SyntaxKind::SUBSCRIPT, children)))
|
||||
} else {
|
||||
Err(nom::Err::Error(()))
|
||||
if input.c.use_sub_superscript.is_brace() {
|
||||
let (input, rest) = template1(input)?;
|
||||
children.extend(rest);
|
||||
return Ok((input, node(SyntaxKind::SUBSCRIPT, children)));
|
||||
}
|
||||
|
||||
let (input, rest) = alt((template0, template1, template2))(input)?;
|
||||
children.extend(rest);
|
||||
|
||||
Ok((input, node(SyntaxKind::SUBSCRIPT, children)))
|
||||
}
|
||||
|
||||
fn template1(input: Input) -> IResult<Input, (GreenElement, Input, GreenElement), ()> {
|
||||
fn template0(input: Input) -> IResult<Input, Vec<GreenElement>, ()> {
|
||||
let (input, star) = tag("*")(input)?;
|
||||
Ok((input, vec![star.text_token()]))
|
||||
}
|
||||
|
||||
fn template1(input: Input) -> IResult<Input, Vec<GreenElement>, ()> {
|
||||
let (input, l) = l_curly_token(input)?;
|
||||
let (input, contents) = balanced_brackets(input)?;
|
||||
let (input, r) = r_curly_token(input)?;
|
||||
Ok((input, (l, contents, r)))
|
||||
let mut children = vec![];
|
||||
children.push(l);
|
||||
children.extend(standard_object_nodes(contents));
|
||||
children.push(r);
|
||||
Ok((input, children))
|
||||
}
|
||||
|
||||
fn template2(input: Input) -> IResult<Input, (Option<GreenElement>, GreenElement), ()> {
|
||||
fn template2(input: Input) -> IResult<Input, Vec<GreenElement>, ()> {
|
||||
let (input, sign) = opt(alt((tag("+"), tag("-"))))(input)?;
|
||||
|
||||
let (input, contents) =
|
||||
|
|
@ -84,7 +79,15 @@ fn template2(input: Input) -> IResult<Input, (Option<GreenElement>, GreenElement
|
|||
return Err(nom::Err::Error(()));
|
||||
}
|
||||
|
||||
Ok((input, (sign.map(|x| x.text_token()), contents.text_token())))
|
||||
let mut children = vec![];
|
||||
|
||||
if let Some(s) = sign {
|
||||
children.push(s.text_token())
|
||||
}
|
||||
|
||||
children.push(contents.text_token());
|
||||
|
||||
Ok((input, children))
|
||||
}
|
||||
|
||||
fn balanced_brackets(input: Input) -> IResult<Input, Input, ()> {
|
||||
|
|
@ -113,6 +116,7 @@ pub fn verify_pre(s: &str) -> bool {
|
|||
#[test]
|
||||
fn parse() {
|
||||
use crate::ast::Subscript;
|
||||
use crate::config::{ParseConfig, UseSubSuperscript};
|
||||
use crate::tests::to_ast;
|
||||
|
||||
let to_subscript = to_ast::<Subscript>(subscript_node);
|
||||
|
|
@ -158,4 +162,14 @@ fn parse() {
|
|||
TEXT@1..4 "abc"
|
||||
"###
|
||||
);
|
||||
|
||||
let with_brace = ParseConfig {
|
||||
use_sub_superscript: UseSubSuperscript::Brace,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
debug_assert!(subscript_node(("_*", &with_brace).into()).is_err());
|
||||
debug_assert!(subscript_node(("_abc", &with_brace).into()).is_err());
|
||||
debug_assert!(subscript_node(("_+123", &with_brace).into()).is_err());
|
||||
debug_assert!(subscript_node(("_{*bo\nld*}", &with_brace).into()).is_ok());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue