diff --git a/org_mode_samples/greater_element/drawer/affiliated_keyword.org b/org_mode_samples/greater_element/drawer/affiliated_keyword.org new file mode 100644 index 0000000..b77f799 --- /dev/null +++ b/org_mode_samples/greater_element/drawer/affiliated_keyword.org @@ -0,0 +1,74 @@ +* Headline +before +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +:candle: +inside + +the drawer +:end: + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +:candle: +inside + +the drawer +:end: + +after diff --git a/org_mode_samples/greater_element/drawer/name.org b/org_mode_samples/greater_element/drawer/name.org deleted file mode 100644 index 41b7c3d..0000000 --- a/org_mode_samples/greater_element/drawer/name.org +++ /dev/null @@ -1,10 +0,0 @@ -* Headline -before -#+NAME: foo -:candle: -inside - -the drawer -:end: - -after diff --git a/org_mode_samples/greater_element/dynamic_block/affiliated_keyword.org b/org_mode_samples/greater_element/dynamic_block/affiliated_keyword.org new file mode 100644 index 0000000..3eba6cf --- /dev/null +++ b/org_mode_samples/greater_element/dynamic_block/affiliated_keyword.org @@ -0,0 +1,72 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+BEGIN: clocktable :scope file :maxlevel 2 +#+CAPTION: Clock summary at [2023-08-25 Fri 05:34] +| Headline | Time | +|--------------+--------| +| *Total time* | *0:00* | +#+END: + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+BEGIN: clocktable :scope file :maxlevel 2 +#+CAPTION: Clock summary at [2023-08-25 Fri 05:34] +| Headline | Time | +|--------------+--------| +| *Total time* | *0:00* | +#+END: diff --git a/org_mode_samples/greater_element/dynamic_block/name.org b/org_mode_samples/greater_element/dynamic_block/name.org deleted file mode 100644 index 4da2f79..0000000 --- a/org_mode_samples/greater_element/dynamic_block/name.org +++ /dev/null @@ -1,7 +0,0 @@ -#+NAME: foo -#+BEGIN: clocktable :scope file :maxlevel 2 -#+CAPTION: Clock summary at [2023-08-25 Fri 05:34] -| Headline | Time | -|--------------+--------| -| *Total time* | *0:00* | -#+END: diff --git a/org_mode_samples/greater_element/footnote_definition/affiliated_keyword.org b/org_mode_samples/greater_element/footnote_definition/affiliated_keyword.org new file mode 100644 index 0000000..bfe6f23 --- /dev/null +++ b/org_mode_samples/greater_element/footnote_definition/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +[fn:1] A footnote. + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +[fn:1] A footnote. diff --git a/org_mode_samples/greater_element/greater_block/center/affiliated_keyword.org b/org_mode_samples/greater_element/greater_block/center/affiliated_keyword.org new file mode 100644 index 0000000..eb3e829 --- /dev/null +++ b/org_mode_samples/greater_element/greater_block/center/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_center + +#+end_center + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_center + +#+end_center diff --git a/org_mode_samples/greater_element/greater_block/center/name.org b/org_mode_samples/greater_element/greater_block/center/name.org deleted file mode 100644 index e0f9c0c..0000000 --- a/org_mode_samples/greater_element/greater_block/center/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_center - -#+end_center diff --git a/org_mode_samples/greater_element/greater_block/quote/affiliated_keyword.org b/org_mode_samples/greater_element/greater_block/quote/affiliated_keyword.org new file mode 100644 index 0000000..a4cc540 --- /dev/null +++ b/org_mode_samples/greater_element/greater_block/quote/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_quote + +#+end_quote + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_quote + +#+end_quote diff --git a/org_mode_samples/greater_element/greater_block/quote/name.org b/org_mode_samples/greater_element/greater_block/quote/name.org deleted file mode 100644 index fe2fa3a..0000000 --- a/org_mode_samples/greater_element/greater_block/quote/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_quote - -#+end_quote diff --git a/org_mode_samples/greater_element/greater_block/special/affiliated_keyword.org b/org_mode_samples/greater_element/greater_block/special/affiliated_keyword.org new file mode 100644 index 0000000..71c12ce --- /dev/null +++ b/org_mode_samples/greater_element/greater_block/special/affiliated_keyword.org @@ -0,0 +1,71 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_defun +foo + +{{{bar(baz)}}} +#+end_defun + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_defun +foo + +{{{bar(baz)}}} +#+end_defun diff --git a/org_mode_samples/greater_element/greater_block/special/name.org b/org_mode_samples/greater_element/greater_block/special/name.org deleted file mode 100644 index 6b513b1..0000000 --- a/org_mode_samples/greater_element/greater_block/special/name.org +++ /dev/null @@ -1,6 +0,0 @@ -#+NAME: foo -#+begin_defun -foo - -{{{bar(baz)}}} -#+end_defun diff --git a/org_mode_samples/greater_element/plain_list/affiliated_keyword.org b/org_mode_samples/greater_element/plain_list/affiliated_keyword.org new file mode 100644 index 0000000..ddccf0a --- /dev/null +++ b/org_mode_samples/greater_element/plain_list/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +1. bar + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +1. BAR diff --git a/org_mode_samples/greater_element/plain_list/name.org b/org_mode_samples/greater_element/plain_list/name.org deleted file mode 100644 index d80b7ba..0000000 --- a/org_mode_samples/greater_element/plain_list/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -1. bar diff --git a/org_mode_samples/greater_element/table/affiliated_keyword.org b/org_mode_samples/greater_element/table/affiliated_keyword.org new file mode 100644 index 0000000..043d251 --- /dev/null +++ b/org_mode_samples/greater_element/table/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +| foo | bar | + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +| foo | bar | diff --git a/org_mode_samples/greater_element/table/name.org b/org_mode_samples/greater_element/table/name.org deleted file mode 100644 index b5d3a56..0000000 --- a/org_mode_samples/greater_element/table/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -| foo | bar | diff --git a/org_mode_samples/lesser_element/babel_call/affiliated_keyword.org b/org_mode_samples/lesser_element/babel_call/affiliated_keyword.org new file mode 100644 index 0000000..677e165 --- /dev/null +++ b/org_mode_samples/lesser_element/babel_call/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+call: foo(bar="baz") + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+call: foo(bar="baz") diff --git a/org_mode_samples/lesser_element/babel_call/name.org b/org_mode_samples/lesser_element/babel_call/name.org deleted file mode 100644 index da7aea9..0000000 --- a/org_mode_samples/lesser_element/babel_call/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -#+call: foo(bar="baz") diff --git a/org_mode_samples/lesser_element/diary_sexp/affiliated_keyword.org b/org_mode_samples/lesser_element/diary_sexp/affiliated_keyword.org new file mode 100644 index 0000000..e94349e --- /dev/null +++ b/org_mode_samples/lesser_element/diary_sexp/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +%%(foo) + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +%%(foo) diff --git a/org_mode_samples/lesser_element/diary_sexp/name.org b/org_mode_samples/lesser_element/diary_sexp/name.org deleted file mode 100644 index 34e6155..0000000 --- a/org_mode_samples/lesser_element/diary_sexp/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -%%(foo) diff --git a/org_mode_samples/lesser_element/fixed_width_area/affiliated_keyword.org b/org_mode_samples/lesser_element/fixed_width_area/affiliated_keyword.org new file mode 100644 index 0000000..5766401 --- /dev/null +++ b/org_mode_samples/lesser_element/fixed_width_area/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +: bar + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +: bar diff --git a/org_mode_samples/lesser_element/fixed_width_area/name.org b/org_mode_samples/lesser_element/fixed_width_area/name.org deleted file mode 100644 index 482c0d2..0000000 --- a/org_mode_samples/lesser_element/fixed_width_area/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -: bar diff --git a/org_mode_samples/lesser_element/horizontal_rule/affiliated_keyword.org b/org_mode_samples/lesser_element/horizontal_rule/affiliated_keyword.org new file mode 100644 index 0000000..88bbdf7 --- /dev/null +++ b/org_mode_samples/lesser_element/horizontal_rule/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +----- + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +----- diff --git a/org_mode_samples/lesser_element/horizontal_rule/name.org b/org_mode_samples/lesser_element/horizontal_rule/name.org deleted file mode 100644 index 252fc4f..0000000 --- a/org_mode_samples/lesser_element/horizontal_rule/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo ------ diff --git a/org_mode_samples/lesser_element/keyword/affiliated_keyword.org b/org_mode_samples/lesser_element/keyword/affiliated_keyword.org index 2323b99..c5b92a1 100644 --- a/org_mode_samples/lesser_element/keyword/affiliated_keyword.org +++ b/org_mode_samples/lesser_element/keyword/affiliated_keyword.org @@ -1,8 +1,63 @@ -#+name: foo -#+caption: bar -#+caption: baz -[[file:lorem/ipsum.png]] +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+foo: bar -#+name: cat -#+caption: dog -[[file:lorem/ipsum.png]] + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+foo: bar diff --git a/org_mode_samples/lesser_element/keyword/affiliated_keywords_short_version.org b/org_mode_samples/lesser_element/keyword/affiliated_keywords_short_version.org deleted file mode 100644 index 4de56be..0000000 --- a/org_mode_samples/lesser_element/keyword/affiliated_keywords_short_version.org +++ /dev/null @@ -1,7 +0,0 @@ -# This test is to prove that the parser works with affiliated keywords that have both a shorter and longer version. - -#+results: -#+result: -#+begin_latex -\foo -#+end_latex diff --git a/org_mode_samples/lesser_element/keyword/name.org b/org_mode_samples/lesser_element/keyword/name.org deleted file mode 100644 index 51bc2fa..0000000 --- a/org_mode_samples/lesser_element/keyword/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -#+FOO: BAR diff --git a/org_mode_samples/lesser_element/latex_environment/affiliated_keyword.org b/org_mode_samples/lesser_element/latex_environment/affiliated_keyword.org new file mode 100644 index 0000000..fea212d --- /dev/null +++ b/org_mode_samples/lesser_element/latex_environment/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +\begin{foo} +bar +\end{foo} + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +\begin{foo} +bar +\end{foo} diff --git a/org_mode_samples/lesser_element/latex_environment/name.org b/org_mode_samples/lesser_element/latex_environment/name.org deleted file mode 100644 index 51a6471..0000000 --- a/org_mode_samples/lesser_element/latex_environment/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -\begin{foo} -bar -\end{foo} diff --git a/org_mode_samples/lesser_element/lesser_block/comment/affiliated_keyword.org b/org_mode_samples/lesser_element/lesser_block/comment/affiliated_keyword.org new file mode 100644 index 0000000..b844b82 --- /dev/null +++ b/org_mode_samples/lesser_element/lesser_block/comment/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_comment text +bar +#+end_comment + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_comment text +bar +#+end_comment diff --git a/org_mode_samples/lesser_element/lesser_block/comment/name.org b/org_mode_samples/lesser_element/lesser_block/comment/name.org deleted file mode 100644 index ad25dbd..0000000 --- a/org_mode_samples/lesser_element/lesser_block/comment/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_comment text -bar -#+end_comment diff --git a/org_mode_samples/lesser_element/lesser_block/example/affiliated_keyword.org b/org_mode_samples/lesser_element/lesser_block/example/affiliated_keyword.org new file mode 100644 index 0000000..32de53c --- /dev/null +++ b/org_mode_samples/lesser_element/lesser_block/example/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_example text +bar +#+end_example + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_example text +bar +#+end_example diff --git a/org_mode_samples/lesser_element/lesser_block/example/name.org b/org_mode_samples/lesser_element/lesser_block/example/name.org deleted file mode 100644 index 84b09c5..0000000 --- a/org_mode_samples/lesser_element/lesser_block/example/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_example text -bar -#+end_example diff --git a/org_mode_samples/lesser_element/lesser_block/export/affiliated_keyword.org b/org_mode_samples/lesser_element/lesser_block/export/affiliated_keyword.org new file mode 100644 index 0000000..cce0eec --- /dev/null +++ b/org_mode_samples/lesser_element/lesser_block/export/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_export text +bar +#+end_export + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_export text +bar +#+end_export diff --git a/org_mode_samples/lesser_element/lesser_block/export/name.org b/org_mode_samples/lesser_element/lesser_block/export/name.org deleted file mode 100644 index cfba5df..0000000 --- a/org_mode_samples/lesser_element/lesser_block/export/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_export text -bar -#+end_export diff --git a/org_mode_samples/lesser_element/lesser_block/src/affiliated_keyword.org b/org_mode_samples/lesser_element/lesser_block/src/affiliated_keyword.org new file mode 100644 index 0000000..65871f9 --- /dev/null +++ b/org_mode_samples/lesser_element/lesser_block/src/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_src text +bar +#+end_src + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_src text +bar +#+end_src diff --git a/org_mode_samples/lesser_element/lesser_block/src/name.org b/org_mode_samples/lesser_element/lesser_block/src/name.org deleted file mode 100644 index 31af9eb..0000000 --- a/org_mode_samples/lesser_element/lesser_block/src/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_src text -bar -#+end_src diff --git a/org_mode_samples/lesser_element/lesser_block/verse/affiliated_keyword.org b/org_mode_samples/lesser_element/lesser_block/verse/affiliated_keyword.org new file mode 100644 index 0000000..14c600a --- /dev/null +++ b/org_mode_samples/lesser_element/lesser_block/verse/affiliated_keyword.org @@ -0,0 +1,67 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +#+begin_verse text +bar +#+end_verse + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +#+begin_verse text +bar +#+end_verse diff --git a/org_mode_samples/lesser_element/lesser_block/verse/name.org b/org_mode_samples/lesser_element/lesser_block/verse/name.org deleted file mode 100644 index 94e5877..0000000 --- a/org_mode_samples/lesser_element/lesser_block/verse/name.org +++ /dev/null @@ -1,4 +0,0 @@ -#+NAME: foo -#+begin_verse text -bar -#+end_verse diff --git a/org_mode_samples/lesser_element/paragraph/affiliated_keyword.org b/org_mode_samples/lesser_element/paragraph/affiliated_keyword.org new file mode 100644 index 0000000..2bb3278 --- /dev/null +++ b/org_mode_samples/lesser_element/paragraph/affiliated_keyword.org @@ -0,0 +1,63 @@ +#+NAME: a +#+caption: b *lorem* ipsum +#+results: c +#+headers: d +#+header: e +#+label: f +#+plot: g +#+resname: h +#+result: i +#+source: j +#+srcname: k +#+tblname: l +#+attr_latex: m +#+attr_html: n +#+NAME: aa +#+caption: bb *lorem* ipsum +#+results: cc +#+headers: dd +#+header: ee +#+label: ff +#+plot: gg +#+resname: hh +#+result: ii +#+source: jj +#+srcname: kk +#+tblname: ll +#+attr_latex: mm +#+attr_html: nn +bar + + + + + +#+NAME: A +#+CAPTION: B *LOREM* IPSUM +#+RESULTS: C +#+HEADERS: D +#+HEADER: E +#+LABEL: F +#+PLOT: G +#+RESNAME: H +#+RESULT: I +#+SOURCE: J +#+SRCNAME: K +#+TBLNAME: L +#+ATTR_LATEX: M +#+ATTR_HTML: N +#+NAME: AA +#+CAPTION: BB *LOREM* IPSUM +#+RESULTS: CC +#+HEADERS: DD +#+HEADER: EE +#+LABEL: FF +#+PLOT: GG +#+RESNAME: HH +#+RESULT: II +#+SOURCE: JJ +#+SRCNAME: KK +#+TBLNAME: LL +#+ATTR_LATEX: MM +#+ATTR_HTML: NN +bar diff --git a/org_mode_samples/lesser_element/paragraph/name.org b/org_mode_samples/lesser_element/paragraph/name.org deleted file mode 100644 index 5cc5a63..0000000 --- a/org_mode_samples/lesser_element/paragraph/name.org +++ /dev/null @@ -1,2 +0,0 @@ -#+NAME: foo -bar diff --git a/src/compare/compare_field.rs b/src/compare/compare_field.rs index 3d0daad..1fd82aa 100644 --- a/src/compare/compare_field.rs +++ b/src/compare/compare_field.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::str::FromStr; use super::diff::artificial_diff_scope; +use super::diff::artificial_owned_diff_scope; use super::diff::compare_ast_node; use super::diff::DiffEntry; use super::diff::DiffStatus; @@ -15,6 +16,7 @@ use super::util::get_property_unquoted_atom; use crate::types::AstNode; use crate::types::CharOffsetInLine; use crate::types::LineNumber; +use crate::types::Object; use crate::types::RetainLabels; use crate::types::SwitchNumberLines; @@ -410,6 +412,81 @@ where Ok(ComparePropertiesResult::NoChange) } +/// Special compare used for affiliate keywords that are parsed as objects. +/// +/// Org-mode seems to store these as a 3-deep list: +/// - Outer list with 1 element per #+caption keyword (or other parsed keyword). +/// - Middle list that seems to always have 1 element. +/// - Inner list of the objects from each #+caption keyword (or other parsed keyword). +pub(crate) fn compare_property_list_of_list_of_list_of_ast_nodes< + 'b, + 's, + 'x, + R, + RG: Fn(R) -> Option<&'b Vec>>>, +>( + source: &'s str, + emacs: &'b Token<'s>, + rust_node: R, + emacs_field: &'x str, + rust_value_getter: RG, +) -> Result, Box> { + // TODO: Replace Object<'s> with generics. I hard-coded Object in to make lifetimes easier. + let rust_value = rust_value_getter(rust_node); + let value = get_property(emacs, emacs_field)? + .map(Token::as_list) + .map_or(Ok(None), |r| r.map(Some))?; + let (value, rust_value) = match (value, rust_value) { + (None, None) => { + return Ok(ComparePropertiesResult::NoChange); + } + (None, Some(_)) | (Some(_), None) => { + let this_status = DiffStatus::Bad; + let message = Some(format!( + "{} mismatch (emacs != rust) {:?} != {:?}", + emacs_field, value, rust_value + )); + return Ok(ComparePropertiesResult::SelfChange(this_status, message)); + } + (Some(value), Some(rust_value)) if value.len() != rust_value.len() => { + let this_status = DiffStatus::Bad; + let message = Some(format!( + "{} mismatch (emacs != rust) {:?} != {:?}", + emacs_field, value, rust_value + )); + return Ok(ComparePropertiesResult::SelfChange(this_status, message)); + } + (Some(value), Some(rust_value)) => (value, rust_value), + }; + + // Iterate the outer lists + for (value, rust_value) in value.iter().zip(rust_value.iter()) { + // Assert the middle list is a length of 1 because I've never seen it any other way. + let value = value.as_list()?; + if value.len() != 1 { + let this_status = DiffStatus::Bad; + let message = Some(format!( + "{} mismatch (emacs != rust) {:?} != {:?}", + emacs_field, value, rust_value + )); + return Ok(ComparePropertiesResult::SelfChange(this_status, message)); + } + // Drill past the middle list to the inner list. + let value = value + .first() + .expect("The above if-statement asserts this exists."); + let value = value.as_list()?; + // Compare inner lists + let mut child_status: Vec> = Vec::with_capacity(rust_value.len()); + for (e, r) in value.iter().zip(rust_value) { + child_status.push(compare_ast_node(source, e, r.into())?); + } + let diff_scope = artificial_owned_diff_scope(emacs_field, child_status)?; + return Ok(ComparePropertiesResult::DiffEntry(diff_scope)); + } + Ok(ComparePropertiesResult::NoChange) +} + pub(crate) fn compare_property_number_lines< 'b, 's, diff --git a/src/compare/diff.rs b/src/compare/diff.rs index e1996a5..87a9bf3 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -20,12 +20,13 @@ use super::elisp_fact::ElispFact; use super::elisp_fact::GetElispFact; use super::sexp::unquote; use super::sexp::Token; +use super::util::affiliated_keywords_names; use super::util::assert_no_children; use super::util::compare_additional_properties; +use super::util::compare_affiliated_keywords; use super::util::compare_children; use super::util::compare_children_iter; use super::util::compare_standard_properties; -use super::util::get_property_quoted_string; use crate::compare::compare_field::ComparePropertiesResult; use crate::compare::compare_field::EmacsField; use crate::compare::macros::compare_properties; @@ -329,6 +330,17 @@ pub(crate) fn artificial_diff_scope<'b, 's>( .into()) } +pub(crate) fn artificial_owned_diff_scope<'b, 's, 'x>( + name: &'x str, + children: Vec>, +) -> Result, Box> { + Ok(DiffLayer { + name: name.to_string().into(), + children, + } + .into()) +} + pub(crate) fn compare_ast_node<'b, 's>( source: &'s str, emacs: &'b Token<'s>, @@ -701,21 +713,7 @@ fn compare_paragraph<'b, 's>( &mut message, )?; - for diff in compare_properties!( - source, - emacs, - rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ) - ) { + for diff in compare_properties!(source, emacs, rust, [],) { match diff { ComparePropertiesResult::NoChange => {} ComparePropertiesResult::SelfChange(new_status, new_message) => { @@ -759,16 +757,7 @@ fn compare_plain_list<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":type"), |r| Some(match r.list_type { @@ -886,24 +875,28 @@ fn compare_center_block<'b, 's>( emacs: &'b Token<'s>, rust: &'b CenterBlock<'s>, ) -> Result, Box> { - let children = emacs.as_list()?; - let mut child_status = Vec::new(); let mut this_status = DiffStatus::Good; + let mut child_status = Vec::new(); let mut message = None; - // TODO: Compare :caption - // Compare name - let name = get_property_quoted_string(emacs, ":name")?; - if name.as_ref().map(String::as_str) != rust.name { - this_status = DiffStatus::Bad; - message = Some(format!( - "Name mismatch (emacs != rust) {:?} != {:?}", - name, rust.name - )); - } + compare_children( + source, + emacs, + &rust.children, + &mut child_status, + &mut this_status, + &mut message, + )?; - for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { - child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); + for diff in compare_properties!(source, emacs, rust, [],) { + match diff { + ComparePropertiesResult::NoChange => {} + ComparePropertiesResult::SelfChange(new_status, new_message) => { + this_status = new_status; + message = new_message + } + ComparePropertiesResult::DiffEntry(diff_entry) => child_status.push(diff_entry), + } } Ok(DiffResult { @@ -935,21 +928,7 @@ fn compare_quote_block<'b, 's>( &mut message, )?; - for diff in compare_properties!( - source, - emacs, - rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ) - ) { + for diff in compare_properties!(source, emacs, rust, [],) { match diff { ComparePropertiesResult::NoChange => {} ComparePropertiesResult::SelfChange(new_status, new_message) => { @@ -993,16 +972,7 @@ fn compare_special_block<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":type"), |r| Some(r.block_type), @@ -1062,16 +1032,7 @@ fn compare_dynamic_block<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":block-name"), |r| Some(r.block_name), @@ -1126,16 +1087,7 @@ fn compare_footnote_definition<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":label"), |r| Some(r.label), @@ -1232,16 +1184,7 @@ fn compare_drawer<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":drawer-name"), |r| Some(r.drawer_name), @@ -1378,16 +1321,7 @@ fn compare_table<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":tblfm"), |r| if r.formulas.is_empty() { @@ -1539,21 +1473,7 @@ fn compare_verse_block<'b, 's>( &mut message, )?; - for diff in compare_properties!( - source, - emacs, - rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ) - ) { + for diff in compare_properties!(source, emacs, rust, [],) { match diff { ComparePropertiesResult::NoChange => {} ComparePropertiesResult::SelfChange(new_status, new_message) => { @@ -1590,16 +1510,7 @@ fn compare_comment_block<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":value"), |r| Some(r.contents), @@ -1642,16 +1553,7 @@ fn compare_example_block<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":value"), |r| Some(r.contents.as_str()), @@ -1724,16 +1626,7 @@ fn compare_export_block<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":type"), |r| r.get_export_type(), @@ -1781,16 +1674,7 @@ fn compare_src_block<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":language"), |r| r.language, @@ -1928,16 +1812,7 @@ fn compare_diary_sexp<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":value"), |r| Some(r.value), @@ -2032,16 +1907,7 @@ fn compare_fixed_width_area<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":value"), |r| Some(r.get_value()), @@ -2080,21 +1946,7 @@ fn compare_horizontal_rule<'b, 's>( assert_no_children(emacs, &mut this_status, &mut message)?; - for diff in compare_properties!( - source, - emacs, - rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ) - ) { + for diff in compare_properties!(source, emacs, rust, [],) { match diff { ComparePropertiesResult::NoChange => {} ComparePropertiesResult::SelfChange(new_status, new_message) => { @@ -2131,16 +1983,7 @@ fn compare_keyword<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":key"), |r| Some(r.key.to_uppercase()), @@ -2188,16 +2031,7 @@ fn compare_babel_call<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":value"), |r| Some(r.value), @@ -2260,16 +2094,7 @@ fn compare_latex_environment<'b, 's>( source, emacs, rust, - ( - EmacsField::Optional(":name"), - |r| r.name, - compare_property_quoted_string - ), - ( - EmacsField::Optional(":caption"), - compare_identity, - compare_noop - ), + [], ( EmacsField::Required(":value"), |r| Some(r.value), diff --git a/src/compare/macros.rs b/src/compare/macros.rs index ecfd0ab..7170eef 100644 --- a/src/compare/macros.rs +++ b/src/compare/macros.rs @@ -30,7 +30,7 @@ /// } /// ``` macro_rules! compare_properties { - ($source:expr, $emacs:expr, $rust:expr, $(($emacs_field:expr, $rust_value_getter:expr, $compare_fn: expr)),+) => { + ($source:expr, $emacs:expr, $rust:expr, $(($emacs_field:expr, $rust_value_getter:expr, $compare_fn: expr)),*) => { { let mut new_status = Vec::new(); let children = $emacs.as_list()?; @@ -63,7 +63,7 @@ macro_rules! compare_properties { }, EmacsField::Optional(_name) => {}, } - )+ + )* if !emacs_keys.is_empty() { let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect(); @@ -91,13 +91,102 @@ macro_rules! compare_properties { new_status.push(result); } } - )+ + )* + + new_status + } + }; + // For elements with affiliated keywords + ($source:expr, $emacs:expr, $rust:expr, [], $(($emacs_field:expr, $rust_value_getter:expr, $compare_fn: expr)),*) => { + { + let mut new_status = Vec::new(); + let children = $emacs.as_list()?; + let attributes_child = children + .iter() + .nth(1) + .ok_or("Should have an attributes child.")?; + let attributes_map = attributes_child.as_map()?; + let mut emacs_keys: BTreeSet<&str> = attributes_map.keys().map(|s| *s).collect(); + if emacs_keys.contains(":standard-properties") { + emacs_keys.remove(":standard-properties"); + } else { + new_status.push(ComparePropertiesResult::SelfChange(DiffStatus::Bad, Some(format!( + "Emacs token lacks :standard-properties field.", + )))); + } + let affiliated_keywords_names: Vec = affiliated_keywords_names($rust).collect(); + for additional_field in affiliated_keywords_names.iter().map(String::as_str).map(EmacsField::Required) { + match additional_field { + EmacsField::Required(name) if emacs_keys.contains(name) => { + emacs_keys.remove(name); + }, + EmacsField::Optional(name) if emacs_keys.contains(name) => { + emacs_keys.remove(name); + }, + EmacsField::Required(name) => { + new_status.push(ComparePropertiesResult::SelfChange(DiffStatus::Bad, Some(format!( + "Emacs token lacks required field: {}", + name + )))); + }, + EmacsField::Optional(_name) => {}, + } + } + $( + match $emacs_field { + EmacsField::Required(name) if emacs_keys.contains(name) => { + emacs_keys.remove(name); + }, + EmacsField::Optional(name) if emacs_keys.contains(name) => { + emacs_keys.remove(name); + }, + EmacsField::Required(name) => { + new_status.push(ComparePropertiesResult::SelfChange(DiffStatus::Bad, Some(format!( + "Emacs token lacks required field: {}", + name + )))); + }, + EmacsField::Optional(_name) => {}, + } + )* + + if !emacs_keys.is_empty() { + let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect(); + let unexpected_keys = unexpected_keys.join(", "); + new_status.push(ComparePropertiesResult::SelfChange(DiffStatus::Bad, Some(format!( + "Emacs token had extra field(s): {}", + unexpected_keys + )))); + } + + for diff in compare_affiliated_keywords($source, $emacs, $rust)? { + new_status.push(diff); + } + + $( + let emacs_name = match $emacs_field { + EmacsField::Required(name) => { + name + }, + EmacsField::Optional(name) => { + name + }, + }; + let result = $compare_fn($source, $emacs, $rust, emacs_name, $rust_value_getter)?; + match result { + ComparePropertiesResult::SelfChange(DiffStatus::Good, _) => unreachable!("No comparison functions should return SelfChange() when DiffStatus is good."), + ComparePropertiesResult::NoChange => {}, + result => { + new_status.push(result); + } + } + )* new_status } }; // Specifies additional properties - ($source:expr, $emacs:expr, $rust:expr, $additionalproperties: expr, $(($emacs_field:expr, $rust_value_getter:expr, $compare_fn: expr)),+) => { + ($source:expr, $emacs:expr, $rust:expr, $additionalproperties: expr, $(($emacs_field:expr, $rust_value_getter:expr, $compare_fn: expr)),*) => { { let mut new_status = Vec::new(); let children = $emacs.as_list()?; @@ -147,7 +236,7 @@ macro_rules! compare_properties { }, EmacsField::Optional(_name) => {}, } - )+ + )* if !emacs_keys.is_empty() { let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect(); @@ -175,7 +264,7 @@ macro_rules! compare_properties { new_status.push(result); } } - )+ + )* new_status } diff --git a/src/compare/util.rs b/src/compare/util.rs index 4a4e684..5dcc0ed 100644 --- a/src/compare/util.rs +++ b/src/compare/util.rs @@ -1,5 +1,8 @@ use std::str::FromStr; +use super::compare_field::compare_property_list_of_list_of_list_of_ast_nodes; +use super::compare_field::compare_property_list_of_quoted_string; +use super::compare_field::compare_property_quoted_string; use super::compare_field::ComparePropertiesResult; use super::diff::DiffEntry; use super::diff::DiffStatus; @@ -7,7 +10,9 @@ use super::elisp_fact::GetElispFact; use super::sexp::Token; use crate::compare::diff::compare_ast_node; use crate::compare::sexp::unquote; +use crate::types::AffiliatedKeywordValue; use crate::types::AstNode; +use crate::types::GetAffiliatedKeywords; use crate::types::GetStandardProperties; use crate::types::StandardProperties; @@ -337,3 +342,61 @@ where } Ok(ComparePropertiesResult::NoChange) } + +pub(crate) fn compare_affiliated_keywords<'b, 's, GAK>( + source: &'s str, + emacs: &'b Token<'s>, + rust: &'b GAK, +) -> Result>, Box> +where + GAK: GetAffiliatedKeywords<'s>, +{ + let mut ret = Vec::new(); + let affiliated_keywords = rust.get_affiliated_keywords(); + for (rust_name, rust_value) in affiliated_keywords.keywords.iter() { + let emacs_property_name = format!(":{}", rust_name); + match rust_value { + AffiliatedKeywordValue::SingleString(rust_value) => { + let diff = compare_property_quoted_string( + source, + emacs, + rust, + emacs_property_name.as_str(), + |_| Some(*rust_value), + )?; + ret.push(diff); + } + AffiliatedKeywordValue::ListOfStrings(rust_value) => { + let diff = compare_property_list_of_quoted_string( + source, + emacs, + rust, + emacs_property_name.as_str(), + |_| Some(rust_value.iter()), + )?; + ret.push(diff); + } + AffiliatedKeywordValue::ListOfListsOfObjects(rust_value) => { + let diff = compare_property_list_of_list_of_list_of_ast_nodes( + source, + emacs, + rust, + emacs_property_name.as_str(), + |_| Some(rust_value), + )?; + ret.push(diff); + } + }; + } + Ok(ret) +} + +pub(crate) fn affiliated_keywords_names<'s, GAK>(rust: &'s GAK) -> impl Iterator + 's +where + GAK: GetAffiliatedKeywords<'s>, +{ + rust.get_affiliated_keywords() + .keywords + .keys() + .map(|k| format!(":{}", k)) +} diff --git a/src/context/constants.rs b/src/context/constants.rs index 3b20084..011797b 100644 --- a/src/context/constants.rs +++ b/src/context/constants.rs @@ -1,5 +1,25 @@ use super::global_settings::EntityDefinition; +pub(crate) const DEFAULT_ORG_ELEMENT_PARSED_KEYWORDS: [&'static str; 1] = ["CAPTION"]; + +pub(crate) const DEFAULT_ORG_ELEMENT_DUAL_KEYWORDS: [&'static str; 2] = ["CAPTION", "RESULTS"]; + +pub(crate) const DEFAULT_ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [ + "CAPTION", "DATA", "HEADER", "HEADERS", "LABEL", "NAME", "PLOT", "RESNAME", "RESULT", + "RESULTS", "SOURCE", "SRCNAME", "TBLNAME", +]; + +pub(crate) const DEFAULT_ORG_ELEMENT_KEYWORD_TRANSLATION_ALIST: [(&'static str, &'static str); 8] = [ + ("DATA", "NAME"), + ("LABEL", "NAME"), + ("RESNAME", "NAME"), + ("SOURCE", "NAME"), + ("SRCNAME", "NAME"), + ("TBLNAME", "NAME"), + ("RESULT", "RESULTS"), + ("HEADERS", "HEADER"), +]; + pub(crate) const DEFAULT_ORG_LINK_PARAMETERS: [&'static str; 23] = [ "id", "eww", diff --git a/src/context/global_settings.rs b/src/context/global_settings.rs index e8ba3d8..e011bd7 100644 --- a/src/context/global_settings.rs +++ b/src/context/global_settings.rs @@ -5,6 +5,10 @@ use super::constants::DEFAULT_ORG_ENTITIES; use super::constants::DEFAULT_ORG_LINK_PARAMETERS; use super::FileAccessInterface; use super::LocalFileAccessInterface; +use crate::context::constants::DEFAULT_ORG_ELEMENT_AFFILIATED_KEYWORDS; +use crate::context::constants::DEFAULT_ORG_ELEMENT_DUAL_KEYWORDS; +use crate::context::constants::DEFAULT_ORG_ELEMENT_KEYWORD_TRANSLATION_ALIST; +use crate::context::constants::DEFAULT_ORG_ELEMENT_PARSED_KEYWORDS; use crate::types::IndentationLevel; use crate::types::Object; @@ -54,6 +58,26 @@ pub struct GlobalSettings<'g, 's> { /// /// Corresponds to org-entities elisp variable. pub entities: &'g [EntityDefinition<'s>], + + /// Keywords that contain the standard set of objects (excluding footnote references). + /// + /// Corresponds to org-element-parsed-keywords elisp variable. + pub element_parsed_keywords: &'g [&'s str], + + /// Keywords that can have a secondary value in square brackets. + /// + /// Corresponds to org-element-dual-keywords elisp variable. + pub element_dual_keywords: &'g [&'s str], + + /// Keywords that can be affiliated with an element. + /// + /// Corresponds to org-element-affiliated-keywords elisp variable. + pub element_affiliated_keywords: &'g [&'s str], + + /// Mapping of keyword names. + /// + /// Corresponds to org-element-keyword-translation-alist elisp variable. + pub element_keyword_translation_alist: &'g [(&'s str, &'s str)], } pub const DEFAULT_TAB_WIDTH: IndentationLevel = 8; @@ -71,6 +95,7 @@ pub struct EntityDefinition<'a> { impl<'g, 's> GlobalSettings<'g, 's> { fn new() -> GlobalSettings<'g, 's> { + debug_assert!(DEFAULT_ORG_ENTITIES.is_sorted_by(|a, b| b.name.len().partial_cmp(&a.name.len()))); GlobalSettings { radio_targets: Vec::new(), file_access: &LocalFileAccessInterface { @@ -85,6 +110,10 @@ impl<'g, 's> GlobalSettings<'g, 's> { link_parameters: &DEFAULT_ORG_LINK_PARAMETERS, link_templates: BTreeMap::new(), entities: &DEFAULT_ORG_ENTITIES, + element_parsed_keywords: &DEFAULT_ORG_ELEMENT_PARSED_KEYWORDS, + element_dual_keywords: &DEFAULT_ORG_ELEMENT_DUAL_KEYWORDS, + element_affiliated_keywords: &DEFAULT_ORG_ELEMENT_AFFILIATED_KEYWORDS, + element_keyword_translation_alist: &DEFAULT_ORG_ELEMENT_KEYWORD_TRANSLATION_ALIST, } } } diff --git a/src/lib.rs b/src/lib.rs index da35ff7..bb3a52c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![feature(exit_status_error)] #![feature(trait_alias)] #![feature(path_file_prefix)] +#![feature(is_sorted)] // TODO: #![warn(missing_docs)] #[cfg(feature = "compare")] diff --git a/src/parser/affiliated_keyword.rs b/src/parser/affiliated_keyword.rs new file mode 100644 index 0000000..0dc9cfa --- /dev/null +++ b/src/parser/affiliated_keyword.rs @@ -0,0 +1,122 @@ +use std::collections::BTreeMap; + +use nom::combinator::all_consuming; +use nom::multi::many0; + +use super::object_parser::standard_set_object; +use crate::context::parser_with_context; +use crate::context::Context; +use crate::context::ContextElement; +use crate::context::GlobalSettings; +use crate::context::List; +use crate::types::AffiliatedKeywordValue; +use crate::types::AffiliatedKeywords; +use crate::types::Keyword; + +pub(crate) fn parse_affiliated_keywords<'g, 's>( + global_settings: &'g GlobalSettings<'g, 's>, + input: Vec>, +) -> AffiliatedKeywords<'s> { + let mut ret = BTreeMap::new(); + for kw in input.into_iter() { + let translated_name = translate_name(global_settings, kw.key); + if is_single_string_keyword(global_settings, translated_name.as_str()) { + ret.insert( + translated_name, + AffiliatedKeywordValue::SingleString(kw.value), + ); + } else if is_list_of_single_string_keyword(global_settings, translated_name.as_str()) { + let list_of_strings = ret + .entry(translated_name) + .or_insert_with(|| AffiliatedKeywordValue::ListOfStrings(Vec::with_capacity(1))); + match list_of_strings { + AffiliatedKeywordValue::ListOfStrings(list_of_strings) + if list_of_strings.is_empty() => + { + list_of_strings.push(kw.value); + } + AffiliatedKeywordValue::ListOfStrings(list_of_strings) => { + list_of_strings.clear(); + list_of_strings.push(kw.value); + } + _ => panic!("Invalid AffiliatedKeywordValue type."), + } + } else if is_list_of_objects_keyword(global_settings, translated_name.as_str()) { + let initial_context = ContextElement::document_context(); + let initial_context = Context::new(global_settings, List::new(&initial_context)); + + // TODO: This should be omitting footnote references + let (_remaining, objects) = all_consuming(many0(parser_with_context!( + standard_set_object + )(&initial_context)))(kw.value.into()) + .expect("Object parser should always succeed."); + let list_of_lists = ret.entry(translated_name).or_insert_with(|| { + AffiliatedKeywordValue::ListOfListsOfObjects(Vec::with_capacity(1)) + }); + match list_of_lists { + AffiliatedKeywordValue::ListOfListsOfObjects(list_of_lists) => { + list_of_lists.push(objects); + } + _ => panic!("Invalid AffiliatedKeywordValue type."), + } + } else { + let list_of_strings = ret + .entry(translated_name) + .or_insert_with(|| AffiliatedKeywordValue::ListOfStrings(Vec::with_capacity(1))); + match list_of_strings { + AffiliatedKeywordValue::ListOfStrings(list_of_strings) => { + list_of_strings.push(kw.value); + } + _ => panic!("Invalid AffiliatedKeywordValue type."), + } + } + } + AffiliatedKeywords { keywords: ret } +} + +fn translate_name<'g, 's>(global_settings: &'g GlobalSettings<'g, 's>, name: &'s str) -> String { + for (src, dst) in global_settings.element_keyword_translation_alist { + if name.eq_ignore_ascii_case(src) { + return dst.to_lowercase(); + } + } + name.to_lowercase() +} + +fn is_single_string_keyword<'g, 's>( + _global_settings: &'g GlobalSettings<'g, 's>, + name: &'s str, +) -> bool { + // TODO: Is this defined by an elisp variable? + for single_string_name in ["plot", "name"] { + if name.eq_ignore_ascii_case(single_string_name) { + return true; + } + } + false +} + +fn is_list_of_single_string_keyword<'g, 's>( + _global_settings: &'g GlobalSettings<'g, 's>, + name: &'s str, +) -> bool { + // TODO: Is this defined by an elisp variable? + for single_string_name in ["results"] { + if name.eq_ignore_ascii_case(single_string_name) { + return true; + } + } + false +} + +fn is_list_of_objects_keyword<'g, 's>( + global_settings: &'g GlobalSettings<'g, 's>, + name: &'s str, +) -> bool { + for parsed_keyword in global_settings.element_parsed_keywords { + if name.eq_ignore_ascii_case(parsed_keyword) { + return true; + } + } + false +} diff --git a/src/parser/babel_call.rs b/src/parser/babel_call.rs index cafb83e..eaeae75 100644 --- a/src/parser/babel_call.rs +++ b/src/parser/babel_call.rs @@ -14,9 +14,9 @@ use nom::multi::many_till; use nom::sequence::tuple; use nom::InputTake; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::BracketDepth; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::start_of_line; use super::OrgSource; @@ -50,7 +50,10 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>( remaining, BabelCall { source: Into::<&str>::into(source), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), value: Into::<&str>::into(line_break.take(0)), call: None, inside_header: None, @@ -73,7 +76,10 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>( remaining, BabelCall { source: Into::<&str>::into(source), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), value: Into::<&str>::into(value).trim_end(), call: call.map(Into::<&str>::into), inside_header: inside_header.map(Into::<&str>::into), diff --git a/src/parser/diary_sexp.rs b/src/parser/diary_sexp.rs index 7b667ab..698b30f 100644 --- a/src/parser/diary_sexp.rs +++ b/src/parser/diary_sexp.rs @@ -4,9 +4,9 @@ use nom::combinator::recognize; use nom::multi::many0; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::org_line_ending; use crate::context::RefContext; @@ -35,7 +35,10 @@ pub(crate) fn diary_sexp<'b, 'g, 'r, 's>( remaining, DiarySexp { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), value: Into::<&str>::into(value), }, )) diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index 36fda09..438a007 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -11,9 +11,9 @@ use nom::multi::many0; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -100,7 +100,10 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>( remaining, Drawer { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), drawer_name: drawer_name.into(), children, }, diff --git a/src/parser/dynamic_block.rs b/src/parser/dynamic_block.rs index 8bd0739..6086176 100644 --- a/src/parser/dynamic_block.rs +++ b/src/parser/dynamic_block.rs @@ -17,9 +17,9 @@ use nom::multi::many_till; use nom::sequence::preceded; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -107,7 +107,10 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>( remaining, DynamicBlock { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), block_name: name.into(), parameters: parameters.map(|val| val.into()), children, diff --git a/src/parser/fixed_width_area.rs b/src/parser/fixed_width_area.rs index 4025c8e..0260784 100644 --- a/src/parser/fixed_width_area.rs +++ b/src/parser/fixed_width_area.rs @@ -9,9 +9,9 @@ use nom::multi::many_till; use nom::sequence::preceded; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::org_line_ending; use crate::context::parser_with_context; @@ -57,7 +57,10 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>( remaining, FixedWidthArea { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), value, }, )) diff --git a/src/parser/footnote_definition.rs b/src/parser/footnote_definition.rs index 3386c59..1ce9aef 100644 --- a/src/parser/footnote_definition.rs +++ b/src/parser/footnote_definition.rs @@ -11,9 +11,9 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::include_input; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::WORD_CONSTITUENT_CHARACTERS; @@ -94,7 +94,10 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>( remaining, FootnoteDefinition { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), label: lbl.into(), children: children.into_iter().map(|(_, item)| item).collect(), }, diff --git a/src/parser/greater_block.rs b/src/parser/greater_block.rs index 4d5e72d..17ba072 100644 --- a/src/parser/greater_block.rs +++ b/src/parser/greater_block.rs @@ -17,9 +17,9 @@ use nom::multi::many_till; use nom::sequence::preceded; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::in_section; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::parser_with_context; @@ -71,19 +71,19 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>( context, remaining, pre_affiliated_keywords_input, - &affiliated_keywords, + affiliated_keywords, )?, "quote" => quote_block( context, remaining, pre_affiliated_keywords_input, - &affiliated_keywords, + affiliated_keywords, )?, _ => special_block(name)( context, remaining, pre_affiliated_keywords_input, - &affiliated_keywords, + affiliated_keywords, )?, }; Ok((remaining, element)) @@ -97,7 +97,7 @@ fn center_block<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, pre_affiliated_keywords_input: OrgSource<'s>, - affiliated_keywords: &Vec>, + affiliated_keywords: Vec>, ) -> Res, Element<'s>> { let (remaining, (source, children)) = greater_block_body( context, @@ -110,7 +110,10 @@ fn center_block<'b, 'g, 'r, 's>( remaining, Element::CenterBlock(CenterBlock { source, - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), children, }), )) @@ -124,7 +127,7 @@ fn quote_block<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, pre_affiliated_keywords_input: OrgSource<'s>, - affiliated_keywords: &Vec>, + affiliated_keywords: Vec>, ) -> Res, Element<'s>> { let (remaining, (source, children)) = greater_block_body( context, @@ -137,7 +140,10 @@ fn quote_block<'b, 'g, 'r, 's>( remaining, Element::QuoteBlock(QuoteBlock { source, - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), children, }), )) @@ -149,7 +155,7 @@ fn special_block<'s>( RefContext<'b, 'g, 'r, 's>, OrgSource<'s>, OrgSource<'s>, - &Vec>, + Vec>, ) -> Res, Element<'s>> + 's { let context_name = format!("special block {}", name); @@ -175,7 +181,7 @@ fn _special_block<'c, 'b, 'g, 'r, 's>( pre_affiliated_keywords_input: OrgSource<'s>, name: &'s str, context_name: &'c str, - affiliated_keywords: &Vec>, + affiliated_keywords: Vec>, ) -> Res, Element<'s>> { let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?; let (remaining, (source, children)) = greater_block_body( @@ -189,7 +195,10 @@ fn _special_block<'c, 'b, 'g, 'r, 's>( remaining, Element::SpecialBlock(SpecialBlock { source, - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), children, block_type: name, parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)), diff --git a/src/parser/horizontal_rule.rs b/src/parser/horizontal_rule.rs index f6466df..d331f91 100644 --- a/src/parser/horizontal_rule.rs +++ b/src/parser/horizontal_rule.rs @@ -9,10 +9,10 @@ use nom::multi::many0; use nom::multi::many1_count; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::get_consumed; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::RefContext; use crate::error::Res; @@ -42,7 +42,10 @@ pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>( remaining, HorizontalRule { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), }, )) } diff --git a/src/parser/keyword.rs b/src/parser/keyword.rs index 70bf4ed..cb6ae15 100644 --- a/src/parser/keyword.rs +++ b/src/parser/keyword.rs @@ -17,10 +17,10 @@ use nom::multi::many0; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::org_source::BracketDepth; use super::org_source::OrgSource; use super::util::get_consumed; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::Matcher; use crate::context::RefContext; @@ -28,6 +28,7 @@ use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::parser::util::start_of_line; +use crate::types::AffiliatedKeywords; use crate::types::Keyword; const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [ @@ -64,7 +65,7 @@ fn _filtered_keyword<'s, F: Matcher>( remaining, Keyword { source: consumed_input.into(), - name: None, // To be populated by the caller if this keyword is in a context to support affiliated keywords. + affiliated_keywords: AffiliatedKeywords::default(), // To be populated by the caller if this keyword is in a context to support affiliated keywords. key: parsed_key.into(), value: "".into(), }, @@ -82,7 +83,7 @@ fn _filtered_keyword<'s, F: Matcher>( remaining, Keyword { source: consumed_input.into(), - name: None, // To be populated by the caller if this keyword is in a context to support affiliated keywords. + affiliated_keywords: AffiliatedKeywords::default(), // To be populated by the caller if this keyword is in a context to support affiliated keywords. key: parsed_key.into(), value: parsed_value.into(), }, @@ -102,7 +103,8 @@ pub(crate) fn keyword<'b, 'g, 'r, 's>( let (remaining, _trailing_ws) = maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; let source = get_consumed(input, remaining); - kw.name = get_name(&affiliated_keywords); + kw.affiliated_keywords = + parse_affiliated_keywords(context.get_global_settings(), affiliated_keywords); kw.source = Into::<&str>::into(source); Ok((remaining, kw)) } diff --git a/src/parser/latex_environment.rs b/src/parser/latex_environment.rs index 692d046..44002f5 100644 --- a/src/parser/latex_environment.rs +++ b/src/parser/latex_environment.rs @@ -12,10 +12,10 @@ use nom::multi::many0; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::get_consumed; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -67,7 +67,10 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>( remaining, LatexEnvironment { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), value: value.into(), }, )) diff --git a/src/parser/lesser_block.rs b/src/parser/lesser_block.rs index 06e5de9..2870c82 100644 --- a/src/parser/lesser_block.rs +++ b/src/parser/lesser_block.rs @@ -18,9 +18,9 @@ use nom::multi::many_till; use nom::sequence::tuple; use nom::InputTake; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -103,7 +103,10 @@ pub(crate) fn verse_block<'b, 'g, 'r, 's>( remaining, VerseBlock { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), data: parameters.map(|parameters| Into::<&str>::into(parameters)), children, }, @@ -145,7 +148,10 @@ pub(crate) fn comment_block<'b, 'g, 'r, 's>( remaining, CommentBlock { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), contents: contents.into(), }, )) @@ -213,7 +219,10 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>( remaining, ExampleBlock { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), switches, number_lines, preserve_indent, @@ -266,7 +275,10 @@ pub(crate) fn export_block<'b, 'g, 'r, 's>( remaining, ExportBlock { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), export_type: export_type.map(Into::<&str>::into), data: parameters.map(|parameters| Into::<&str>::into(parameters)), contents, @@ -332,7 +344,10 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>( remaining, SrcBlock { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), language: language.map(Into::<&str>::into), switches, parameters: parameters.map(Into::<&str>::into), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 02dabf6..c9c2e6e 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,3 +1,4 @@ +mod affiliated_keyword; mod angle_link; mod babel_call; mod citation; diff --git a/src/parser/paragraph.rs b/src/parser/paragraph.rs index 6848726..23dff72 100644 --- a/src/parser/paragraph.rs +++ b/src/parser/paragraph.rs @@ -7,13 +7,13 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::element_parser::detect_element; use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::blank_line; use super::util::get_consumed; use super::util::get_has_affiliated_keyword; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -68,7 +68,10 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>( remaining, Paragraph { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), children, }, )) diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 5bf1171..3035f6b 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -18,11 +18,11 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::element_parser::element; use super::keyword::affiliated_keyword; use super::object_parser::standard_set_object; use super::org_source::OrgSource; -use super::util::get_name; use super::util::include_input; use super::util::indentation_level; use super::util::non_whitespace_character; @@ -163,7 +163,10 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>( remaining, PlainList { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), list_type: first_item_list_type.expect("Plain lists require at least one element."), children: children.into_iter().map(|(_start, item)| item).collect(), }, diff --git a/src/parser/table.rs b/src/parser/table.rs index f3b5a33..857a55d 100644 --- a/src/parser/table.rs +++ b/src/parser/table.rs @@ -13,12 +13,12 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use super::affiliated_keyword::parse_affiliated_keywords; use super::keyword::affiliated_keyword; use super::keyword::table_formula_keyword; use super::object_parser::table_cell_set_object; use super::org_source::OrgSource; use super::util::exit_matcher_parser; -use super::util::get_name; use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::org_line_ending; use crate::context::parser_with_context; @@ -77,7 +77,10 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>( remaining, Table { source: source.into(), - name: get_name(&affiliated_keywords), + affiliated_keywords: parse_affiliated_keywords( + context.get_global_settings(), + affiliated_keywords, + ), formulas, children, }, diff --git a/src/parser/util.rs b/src/parser/util.rs index 14388ad..05a292e 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -23,7 +23,6 @@ use crate::error::CustomError; use crate::error::MyError; use crate::error::Res; use crate::types::IndentationLevel; -use crate::types::Keyword; pub(crate) const WORD_CONSTITUENT_CHARACTERS: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; @@ -272,21 +271,6 @@ pub(crate) fn indentation_level<'b, 'g, 'r, 's>( Ok((remaining, (indentation_level, leading_whitespace))) } -pub(crate) fn get_name<'s>(affiliated_keywords: &Vec>) -> Option<&'s str> { - let name_keyword = affiliated_keywords - .iter() - .filter(|kw| { - kw.key.eq_ignore_ascii_case("name") - || kw.key.eq_ignore_ascii_case("source") - || kw.key.eq_ignore_ascii_case("tblname") - || kw.key.eq_ignore_ascii_case("resname") - || kw.key.eq_ignore_ascii_case("srcname") - || kw.key.eq_ignore_ascii_case("label") - }) - .last(); - name_keyword.map(|kw| kw.value) -} - pub(crate) fn get_has_affiliated_keyword<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, ) -> Option> { diff --git a/src/types/affiliated_keyword.rs b/src/types/affiliated_keyword.rs new file mode 100644 index 0000000..f3dd94e --- /dev/null +++ b/src/types/affiliated_keyword.rs @@ -0,0 +1,33 @@ +use std::collections::BTreeMap; + +use super::Object; + +#[derive(Debug)] +pub enum AffiliatedKeywordValue<'s> { + SingleString(&'s str), + ListOfStrings(Vec<&'s str>), + ListOfListsOfObjects(Vec>>), +} + +#[derive(Debug)] +pub struct AffiliatedKeyword<'s> { + pub name: &'s str, + pub value: AffiliatedKeywordValue<'s>, +} + +#[derive(Debug)] +pub struct AffiliatedKeywords<'s> { + pub(crate) keywords: BTreeMap>, +} + +pub trait GetAffiliatedKeywords<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s>; +} + +impl<'s> Default for AffiliatedKeywords<'s> { + fn default() -> Self { + AffiliatedKeywords { + keywords: BTreeMap::new(), + } + } +} diff --git a/src/types/greater_element.rs b/src/types/greater_element.rs index 7f2bede..e058b42 100644 --- a/src/types/greater_element.rs +++ b/src/types/greater_element.rs @@ -1,5 +1,7 @@ +use super::affiliated_keyword::GetAffiliatedKeywords; use super::element::Element; use super::lesser_element::TableCell; +use super::AffiliatedKeywords; use super::Keyword; use super::Object; use super::StandardProperties; @@ -7,7 +9,7 @@ use super::StandardProperties; #[derive(Debug)] pub struct PlainList<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub list_type: PlainListType, pub children: Vec>, } @@ -47,21 +49,21 @@ pub enum CheckboxType { #[derive(Debug)] pub struct CenterBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub children: Vec>, } #[derive(Debug)] pub struct QuoteBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub children: Vec>, } #[derive(Debug)] pub struct SpecialBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub block_type: &'s str, pub parameters: Option<&'s str>, pub children: Vec>, @@ -70,7 +72,7 @@ pub struct SpecialBlock<'s> { #[derive(Debug)] pub struct DynamicBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub block_name: &'s str, pub parameters: Option<&'s str>, pub children: Vec>, @@ -79,7 +81,7 @@ pub struct DynamicBlock<'s> { #[derive(Debug)] pub struct FootnoteDefinition<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub label: &'s str, pub children: Vec>, } @@ -87,7 +89,7 @@ pub struct FootnoteDefinition<'s> { #[derive(Debug)] pub struct Drawer<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub drawer_name: &'s str, pub children: Vec>, } @@ -108,7 +110,7 @@ pub struct NodeProperty<'s> { #[derive(Debug)] pub struct Table<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub formulas: Vec>, pub children: Vec>, } @@ -218,3 +220,51 @@ impl<'s> TableRow<'s> { } } } + +impl<'s> GetAffiliatedKeywords<'s> for PlainList<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for Table<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for Drawer<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for FootnoteDefinition<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for DynamicBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for SpecialBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for CenterBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for QuoteBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} diff --git a/src/types/lesser_element.rs b/src/types/lesser_element.rs index bf2ac27..a005e84 100644 --- a/src/types/lesser_element.rs +++ b/src/types/lesser_element.rs @@ -1,4 +1,6 @@ use super::object::Object; +use super::AffiliatedKeywords; +use super::GetAffiliatedKeywords; use super::PlainText; use super::StandardProperties; use super::Timestamp; @@ -6,7 +8,7 @@ use super::Timestamp; #[derive(Debug)] pub struct Paragraph<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub children: Vec>, } @@ -25,7 +27,7 @@ pub struct TableCell<'s> { #[derive(Debug)] pub struct VerseBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub data: Option<&'s str>, pub children: Vec>, } @@ -33,7 +35,7 @@ pub struct VerseBlock<'s> { #[derive(Debug)] pub struct CommentBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub contents: &'s str, } @@ -50,7 +52,7 @@ pub enum RetainLabels { #[derive(Debug)] pub struct ExampleBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub switches: Option<&'s str>, pub number_lines: Option, pub preserve_indent: Option, @@ -63,7 +65,7 @@ pub struct ExampleBlock<'s> { #[derive(Debug)] pub struct ExportBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub export_type: Option<&'s str>, pub data: Option<&'s str>, pub contents: String, @@ -72,7 +74,7 @@ pub struct ExportBlock<'s> { #[derive(Debug)] pub struct SrcBlock<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub language: Option<&'s str>, pub switches: Option<&'s str>, pub parameters: Option<&'s str>, @@ -101,7 +103,7 @@ pub struct Clock<'s> { #[derive(Debug)] pub struct DiarySexp<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub value: &'s str, } @@ -116,20 +118,20 @@ pub struct Planning<'s> { #[derive(Debug)] pub struct FixedWidthArea<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub value: Vec<&'s str>, } #[derive(Debug)] pub struct HorizontalRule<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, } #[derive(Debug)] pub struct Keyword<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub key: &'s str, pub value: &'s str, } @@ -137,7 +139,7 @@ pub struct Keyword<'s> { #[derive(Debug)] pub struct BabelCall<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub value: &'s str, pub call: Option<&'s str>, pub inside_header: Option<&'s str>, @@ -148,7 +150,7 @@ pub struct BabelCall<'s> { #[derive(Debug)] pub struct LatexEnvironment<'s> { pub source: &'s str, - pub name: Option<&'s str>, + pub affiliated_keywords: AffiliatedKeywords<'s>, pub value: &'s str, } @@ -172,7 +174,7 @@ impl<'s> Paragraph<'s> { objects.push(Object::PlainText(PlainText { source: input })); Paragraph { source: input, - name: None, + affiliated_keywords: AffiliatedKeywords::default(), children: objects, } } @@ -302,3 +304,75 @@ impl<'s> ExportBlock<'s> { self.export_type.map(|s| s.to_uppercase()) } } + +impl<'s> GetAffiliatedKeywords<'s> for Paragraph<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for LatexEnvironment<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for BabelCall<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for Keyword<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for HorizontalRule<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for FixedWidthArea<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for DiarySexp<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for SrcBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for ExportBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for ExampleBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for CommentBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} + +impl<'s> GetAffiliatedKeywords<'s> for VerseBlock<'s> { + fn get_affiliated_keywords<'a>(&'a self) -> &'a AffiliatedKeywords<'s> { + &self.affiliated_keywords + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index fc93c5a..dbce299 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,3 +1,4 @@ +mod affiliated_keyword; mod ast_node; mod document; mod element; @@ -9,6 +10,10 @@ mod object; mod source; mod standard_properties; mod util; +pub use affiliated_keyword::AffiliatedKeyword; +pub use affiliated_keyword::AffiliatedKeywordValue; +pub use affiliated_keyword::AffiliatedKeywords; +pub use affiliated_keyword::GetAffiliatedKeywords; pub(crate) use ast_node::AstNode; pub use document::Document; pub use document::DocumentElement;