Merge branch 'affiliated_keywords_properties'
Some checks failed
rustfmt Build rustfmt has failed
rust-build Build rust-build has failed
rust-test Build rust-test has failed
rust-foreign-document-test Build rust-foreign-document-test has failed

This commit is contained in:
Tom Alexander 2023-10-11 15:31:23 -04:00
commit 68fac7cfe8
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
68 changed files with 2066 additions and 397 deletions

View File

@ -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

View File

@ -1,10 +0,0 @@
* Headline
before
#+NAME: foo
:candle:
inside
the drawer
:end:
after

View File

@ -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:

View File

@ -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:

View File

@ -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.

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_center
#+end_center

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_quote
#+end_quote

View File

@ -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

View File

@ -1,6 +0,0 @@
#+NAME: foo
#+begin_defun
foo
{{{bar(baz)}}}
#+end_defun

View File

@ -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

View File

@ -1,2 +0,0 @@
#+NAME: foo
1. bar

View File

@ -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 |

View File

@ -1,2 +0,0 @@
#+NAME: foo
| foo | bar |

View File

@ -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")

View File

@ -1,2 +0,0 @@
#+NAME: foo
#+call: foo(bar="baz")

View File

@ -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)

View File

@ -1,2 +0,0 @@
#+NAME: foo
%%(foo)

View File

@ -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

View File

@ -1,2 +0,0 @@
#+NAME: foo
: bar

View File

@ -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
-----

View File

@ -1,2 +0,0 @@
#+NAME: foo
-----

View File

@ -1,8 +1,63 @@
#+name: foo #+NAME: a
#+caption: bar #+caption: b *lorem* ipsum
#+caption: baz #+results: c
[[file:lorem/ipsum.png]] #+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

View File

@ -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

View File

@ -1,2 +0,0 @@
#+NAME: foo
#+FOO: BAR

View File

@ -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}

View File

@ -1,4 +0,0 @@
#+NAME: foo
\begin{foo}
bar
\end{foo}

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_comment text
bar
#+end_comment

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_example text
bar
#+end_example

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_export text
bar
#+end_export

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_src text
bar
#+end_src

View File

@ -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

View File

@ -1,4 +0,0 @@
#+NAME: foo
#+begin_verse text
bar
#+end_verse

View File

@ -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

View File

@ -1,2 +0,0 @@
#+NAME: foo
bar

View File

@ -3,6 +3,7 @@ use std::fmt::Debug;
use std::str::FromStr; use std::str::FromStr;
use super::diff::artificial_diff_scope; use super::diff::artificial_diff_scope;
use super::diff::artificial_owned_diff_scope;
use super::diff::compare_ast_node; use super::diff::compare_ast_node;
use super::diff::DiffEntry; use super::diff::DiffEntry;
use super::diff::DiffStatus; use super::diff::DiffStatus;
@ -15,6 +16,7 @@ use super::util::get_property_unquoted_atom;
use crate::types::AstNode; use crate::types::AstNode;
use crate::types::CharOffsetInLine; use crate::types::CharOffsetInLine;
use crate::types::LineNumber; use crate::types::LineNumber;
use crate::types::Object;
use crate::types::RetainLabels; use crate::types::RetainLabels;
use crate::types::SwitchNumberLines; use crate::types::SwitchNumberLines;
@ -410,6 +412,81 @@ where
Ok(ComparePropertiesResult::NoChange) 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<Vec<Object<'s>>>>,
>(
source: &'s str,
emacs: &'b Token<'s>,
rust_node: R,
emacs_field: &'x str,
rust_value_getter: RG,
) -> Result<ComparePropertiesResult<'b, 's>, Box<dyn std::error::Error>> {
// 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<DiffEntry<'b, 's>> = 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< pub(crate) fn compare_property_number_lines<
'b, 'b,
's, 's,

View File

@ -20,12 +20,13 @@ use super::elisp_fact::ElispFact;
use super::elisp_fact::GetElispFact; use super::elisp_fact::GetElispFact;
use super::sexp::unquote; use super::sexp::unquote;
use super::sexp::Token; use super::sexp::Token;
use super::util::affiliated_keywords_names;
use super::util::assert_no_children; use super::util::assert_no_children;
use super::util::compare_additional_properties; use super::util::compare_additional_properties;
use super::util::compare_affiliated_keywords;
use super::util::compare_children; use super::util::compare_children;
use super::util::compare_children_iter; use super::util::compare_children_iter;
use super::util::compare_standard_properties; use super::util::compare_standard_properties;
use super::util::get_property_quoted_string;
use crate::compare::compare_field::ComparePropertiesResult; use crate::compare::compare_field::ComparePropertiesResult;
use crate::compare::compare_field::EmacsField; use crate::compare::compare_field::EmacsField;
use crate::compare::macros::compare_properties; use crate::compare::macros::compare_properties;
@ -329,6 +330,17 @@ pub(crate) fn artificial_diff_scope<'b, 's>(
.into()) .into())
} }
pub(crate) fn artificial_owned_diff_scope<'b, 's, 'x>(
name: &'x str,
children: Vec<DiffEntry<'b, 's>>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
Ok(DiffLayer {
name: name.to_string().into(),
children,
}
.into())
}
pub(crate) fn compare_ast_node<'b, 's>( pub(crate) fn compare_ast_node<'b, 's>(
source: &'s str, source: &'s str,
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
@ -701,21 +713,7 @@ fn compare_paragraph<'b, 's>(
&mut message, &mut message,
)?; )?;
for diff in compare_properties!( for diff in compare_properties!(source, emacs, rust, [],) {
source,
emacs,
rust,
(
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
)
) {
match diff { match diff {
ComparePropertiesResult::NoChange => {} ComparePropertiesResult::NoChange => {}
ComparePropertiesResult::SelfChange(new_status, new_message) => { ComparePropertiesResult::SelfChange(new_status, new_message) => {
@ -759,16 +757,7 @@ fn compare_plain_list<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":type"), EmacsField::Required(":type"),
|r| Some(match r.list_type { |r| Some(match r.list_type {
@ -886,24 +875,28 @@ fn compare_center_block<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b CenterBlock<'s>, rust: &'b CenterBlock<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new();
let mut message = None; let mut message = None;
// TODO: Compare :caption compare_children(
// Compare name source,
let name = get_property_quoted_string(emacs, ":name")?; emacs,
if name.as_ref().map(String::as_str) != rust.name { &rust.children,
this_status = DiffStatus::Bad; &mut child_status,
message = Some(format!( &mut this_status,
"Name mismatch (emacs != rust) {:?} != {:?}", &mut message,
name, rust.name )?;
));
}
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { for diff in compare_properties!(source, emacs, rust, [],) {
child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); 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 { Ok(DiffResult {
@ -935,21 +928,7 @@ fn compare_quote_block<'b, 's>(
&mut message, &mut message,
)?; )?;
for diff in compare_properties!( for diff in compare_properties!(source, emacs, rust, [],) {
source,
emacs,
rust,
(
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
)
) {
match diff { match diff {
ComparePropertiesResult::NoChange => {} ComparePropertiesResult::NoChange => {}
ComparePropertiesResult::SelfChange(new_status, new_message) => { ComparePropertiesResult::SelfChange(new_status, new_message) => {
@ -993,16 +972,7 @@ fn compare_special_block<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":type"), EmacsField::Required(":type"),
|r| Some(r.block_type), |r| Some(r.block_type),
@ -1062,16 +1032,7 @@ fn compare_dynamic_block<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":block-name"), EmacsField::Required(":block-name"),
|r| Some(r.block_name), |r| Some(r.block_name),
@ -1126,16 +1087,7 @@ fn compare_footnote_definition<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":label"), EmacsField::Required(":label"),
|r| Some(r.label), |r| Some(r.label),
@ -1232,16 +1184,7 @@ fn compare_drawer<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":drawer-name"), EmacsField::Required(":drawer-name"),
|r| Some(r.drawer_name), |r| Some(r.drawer_name),
@ -1378,16 +1321,7 @@ fn compare_table<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":tblfm"), EmacsField::Required(":tblfm"),
|r| if r.formulas.is_empty() { |r| if r.formulas.is_empty() {
@ -1539,21 +1473,7 @@ fn compare_verse_block<'b, 's>(
&mut message, &mut message,
)?; )?;
for diff in compare_properties!( for diff in compare_properties!(source, emacs, rust, [],) {
source,
emacs,
rust,
(
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
)
) {
match diff { match diff {
ComparePropertiesResult::NoChange => {} ComparePropertiesResult::NoChange => {}
ComparePropertiesResult::SelfChange(new_status, new_message) => { ComparePropertiesResult::SelfChange(new_status, new_message) => {
@ -1590,16 +1510,7 @@ fn compare_comment_block<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":value"), EmacsField::Required(":value"),
|r| Some(r.contents), |r| Some(r.contents),
@ -1642,16 +1553,7 @@ fn compare_example_block<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":value"), EmacsField::Required(":value"),
|r| Some(r.contents.as_str()), |r| Some(r.contents.as_str()),
@ -1724,16 +1626,7 @@ fn compare_export_block<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":type"), EmacsField::Required(":type"),
|r| r.get_export_type(), |r| r.get_export_type(),
@ -1781,16 +1674,7 @@ fn compare_src_block<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":language"), EmacsField::Required(":language"),
|r| r.language, |r| r.language,
@ -1928,16 +1812,7 @@ fn compare_diary_sexp<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":value"), EmacsField::Required(":value"),
|r| Some(r.value), |r| Some(r.value),
@ -2032,16 +1907,7 @@ fn compare_fixed_width_area<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":value"), EmacsField::Required(":value"),
|r| Some(r.get_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)?; assert_no_children(emacs, &mut this_status, &mut message)?;
for diff in compare_properties!( for diff in compare_properties!(source, emacs, rust, [],) {
source,
emacs,
rust,
(
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
)
) {
match diff { match diff {
ComparePropertiesResult::NoChange => {} ComparePropertiesResult::NoChange => {}
ComparePropertiesResult::SelfChange(new_status, new_message) => { ComparePropertiesResult::SelfChange(new_status, new_message) => {
@ -2131,16 +1983,7 @@ fn compare_keyword<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":key"), EmacsField::Required(":key"),
|r| Some(r.key.to_uppercase()), |r| Some(r.key.to_uppercase()),
@ -2188,16 +2031,7 @@ fn compare_babel_call<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":value"), EmacsField::Required(":value"),
|r| Some(r.value), |r| Some(r.value),
@ -2260,16 +2094,7 @@ fn compare_latex_environment<'b, 's>(
source, source,
emacs, emacs,
rust, rust,
( [],
EmacsField::Optional(":name"),
|r| r.name,
compare_property_quoted_string
),
(
EmacsField::Optional(":caption"),
compare_identity,
compare_noop
),
( (
EmacsField::Required(":value"), EmacsField::Required(":value"),
|r| Some(r.value), |r| Some(r.value),

View File

@ -30,7 +30,7 @@
/// } /// }
/// ``` /// ```
macro_rules! compare_properties { 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 mut new_status = Vec::new();
let children = $emacs.as_list()?; let children = $emacs.as_list()?;
@ -63,7 +63,7 @@ macro_rules! compare_properties {
}, },
EmacsField::Optional(_name) => {}, EmacsField::Optional(_name) => {},
} }
)+ )*
if !emacs_keys.is_empty() { if !emacs_keys.is_empty() {
let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect(); let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect();
@ -91,13 +91,102 @@ macro_rules! compare_properties {
new_status.push(result); 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<String> = 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 new_status
} }
}; };
// Specifies additional properties // 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 mut new_status = Vec::new();
let children = $emacs.as_list()?; let children = $emacs.as_list()?;
@ -147,7 +236,7 @@ macro_rules! compare_properties {
}, },
EmacsField::Optional(_name) => {}, EmacsField::Optional(_name) => {},
} }
)+ )*
if !emacs_keys.is_empty() { if !emacs_keys.is_empty() {
let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect(); let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect();
@ -175,7 +264,7 @@ macro_rules! compare_properties {
new_status.push(result); new_status.push(result);
} }
} }
)+ )*
new_status new_status
} }

View File

@ -1,5 +1,8 @@
use std::str::FromStr; 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::compare_field::ComparePropertiesResult;
use super::diff::DiffEntry; use super::diff::DiffEntry;
use super::diff::DiffStatus; use super::diff::DiffStatus;
@ -7,7 +10,9 @@ use super::elisp_fact::GetElispFact;
use super::sexp::Token; use super::sexp::Token;
use crate::compare::diff::compare_ast_node; use crate::compare::diff::compare_ast_node;
use crate::compare::sexp::unquote; use crate::compare::sexp::unquote;
use crate::types::AffiliatedKeywordValue;
use crate::types::AstNode; use crate::types::AstNode;
use crate::types::GetAffiliatedKeywords;
use crate::types::GetStandardProperties; use crate::types::GetStandardProperties;
use crate::types::StandardProperties; use crate::types::StandardProperties;
@ -337,3 +342,61 @@ where
} }
Ok(ComparePropertiesResult::NoChange) Ok(ComparePropertiesResult::NoChange)
} }
pub(crate) fn compare_affiliated_keywords<'b, 's, GAK>(
source: &'s str,
emacs: &'b Token<'s>,
rust: &'b GAK,
) -> Result<Vec<ComparePropertiesResult<'b, 's>>, Box<dyn std::error::Error>>
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<Item = String> + 's
where
GAK: GetAffiliatedKeywords<'s>,
{
rust.get_affiliated_keywords()
.keywords
.keys()
.map(|k| format!(":{}", k))
}

View File

@ -1,5 +1,25 @@
use super::global_settings::EntityDefinition; 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] = [ pub(crate) const DEFAULT_ORG_LINK_PARAMETERS: [&'static str; 23] = [
"id", "id",
"eww", "eww",

View File

@ -5,6 +5,10 @@ use super::constants::DEFAULT_ORG_ENTITIES;
use super::constants::DEFAULT_ORG_LINK_PARAMETERS; use super::constants::DEFAULT_ORG_LINK_PARAMETERS;
use super::FileAccessInterface; use super::FileAccessInterface;
use super::LocalFileAccessInterface; 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::IndentationLevel;
use crate::types::Object; use crate::types::Object;
@ -54,6 +58,26 @@ pub struct GlobalSettings<'g, 's> {
/// ///
/// Corresponds to org-entities elisp variable. /// Corresponds to org-entities elisp variable.
pub entities: &'g [EntityDefinition<'s>], 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; pub const DEFAULT_TAB_WIDTH: IndentationLevel = 8;
@ -71,6 +95,7 @@ pub struct EntityDefinition<'a> {
impl<'g, 's> GlobalSettings<'g, 's> { impl<'g, 's> GlobalSettings<'g, 's> {
fn new() -> 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 { GlobalSettings {
radio_targets: Vec::new(), radio_targets: Vec::new(),
file_access: &LocalFileAccessInterface { file_access: &LocalFileAccessInterface {
@ -85,6 +110,10 @@ impl<'g, 's> GlobalSettings<'g, 's> {
link_parameters: &DEFAULT_ORG_LINK_PARAMETERS, link_parameters: &DEFAULT_ORG_LINK_PARAMETERS,
link_templates: BTreeMap::new(), link_templates: BTreeMap::new(),
entities: &DEFAULT_ORG_ENTITIES, 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,
} }
} }
} }

View File

@ -1,6 +1,7 @@
#![feature(exit_status_error)] #![feature(exit_status_error)]
#![feature(trait_alias)] #![feature(trait_alias)]
#![feature(path_file_prefix)] #![feature(path_file_prefix)]
#![feature(is_sorted)]
// TODO: #![warn(missing_docs)] // TODO: #![warn(missing_docs)]
#[cfg(feature = "compare")] #[cfg(feature = "compare")]

View File

@ -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<Keyword<'s>>,
) -> 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
}

View File

@ -14,9 +14,9 @@ use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use nom::InputTake; use nom::InputTake;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::start_of_line; use super::util::start_of_line;
use super::OrgSource; use super::OrgSource;
@ -50,7 +50,10 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>(
remaining, remaining,
BabelCall { BabelCall {
source: Into::<&str>::into(source), 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)), value: Into::<&str>::into(line_break.take(0)),
call: None, call: None,
inside_header: None, inside_header: None,
@ -73,7 +76,10 @@ pub(crate) fn babel_call<'b, 'g, 'r, 's>(
remaining, remaining,
BabelCall { BabelCall {
source: Into::<&str>::into(source), 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(), value: Into::<&str>::into(value).trim_end(),
call: call.map(Into::<&str>::into), call: call.map(Into::<&str>::into),
inside_header: inside_header.map(Into::<&str>::into), inside_header: inside_header.map(Into::<&str>::into),

View File

@ -4,9 +4,9 @@ use nom::combinator::recognize;
use nom::multi::many0; use nom::multi::many0;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending; use super::util::org_line_ending;
use crate::context::RefContext; use crate::context::RefContext;
@ -35,7 +35,10 @@ pub(crate) fn diary_sexp<'b, 'g, 'r, 's>(
remaining, remaining,
DiarySexp { DiarySexp {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
value: Into::<&str>::into(value), value: Into::<&str>::into(value),
}, },
)) ))

View File

@ -11,9 +11,9 @@ use nom::multi::many0;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
@ -100,7 +100,10 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>(
remaining, remaining,
Drawer { Drawer {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
drawer_name: drawer_name.into(), drawer_name: drawer_name.into(),
children, children,
}, },

View File

@ -17,9 +17,9 @@ use nom::multi::many_till;
use nom::sequence::preceded; use nom::sequence::preceded;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
@ -107,7 +107,10 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>(
remaining, remaining,
DynamicBlock { DynamicBlock {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
block_name: name.into(), block_name: name.into(),
parameters: parameters.map(|val| val.into()), parameters: parameters.map(|val| val.into()),
children, children,

View File

@ -9,9 +9,9 @@ use nom::multi::many_till;
use nom::sequence::preceded; use nom::sequence::preceded;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending; use super::util::org_line_ending;
use crate::context::parser_with_context; use crate::context::parser_with_context;
@ -57,7 +57,10 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>(
remaining, remaining,
FixedWidthArea { FixedWidthArea {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
value, value,
}, },
)) ))

View File

@ -11,9 +11,9 @@ use nom::multi::many1;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::include_input; use super::util::include_input;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::WORD_CONSTITUENT_CHARACTERS; use super::util::WORD_CONSTITUENT_CHARACTERS;
@ -94,7 +94,10 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>(
remaining, remaining,
FootnoteDefinition { FootnoteDefinition {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
label: lbl.into(), label: lbl.into(),
children: children.into_iter().map(|(_, item)| item).collect(), children: children.into_iter().map(|(_, item)| item).collect(),
}, },

View File

@ -17,9 +17,9 @@ use nom::multi::many_till;
use nom::sequence::preceded; use nom::sequence::preceded;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::in_section; use super::util::in_section;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
@ -71,19 +71,19 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
context, context,
remaining, remaining,
pre_affiliated_keywords_input, pre_affiliated_keywords_input,
&affiliated_keywords, affiliated_keywords,
)?, )?,
"quote" => quote_block( "quote" => quote_block(
context, context,
remaining, remaining,
pre_affiliated_keywords_input, pre_affiliated_keywords_input,
&affiliated_keywords, affiliated_keywords,
)?, )?,
_ => special_block(name)( _ => special_block(name)(
context, context,
remaining, remaining,
pre_affiliated_keywords_input, pre_affiliated_keywords_input,
&affiliated_keywords, affiliated_keywords,
)?, )?,
}; };
Ok((remaining, element)) Ok((remaining, element))
@ -97,7 +97,7 @@ fn center_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
pre_affiliated_keywords_input: OrgSource<'s>, pre_affiliated_keywords_input: OrgSource<'s>,
affiliated_keywords: &Vec<Keyword<'s>>, affiliated_keywords: Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> { ) -> Res<OrgSource<'s>, Element<'s>> {
let (remaining, (source, children)) = greater_block_body( let (remaining, (source, children)) = greater_block_body(
context, context,
@ -110,7 +110,10 @@ fn center_block<'b, 'g, 'r, 's>(
remaining, remaining,
Element::CenterBlock(CenterBlock { Element::CenterBlock(CenterBlock {
source, source,
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
children, children,
}), }),
)) ))
@ -124,7 +127,7 @@ fn quote_block<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
pre_affiliated_keywords_input: OrgSource<'s>, pre_affiliated_keywords_input: OrgSource<'s>,
affiliated_keywords: &Vec<Keyword<'s>>, affiliated_keywords: Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> { ) -> Res<OrgSource<'s>, Element<'s>> {
let (remaining, (source, children)) = greater_block_body( let (remaining, (source, children)) = greater_block_body(
context, context,
@ -137,7 +140,10 @@ fn quote_block<'b, 'g, 'r, 's>(
remaining, remaining,
Element::QuoteBlock(QuoteBlock { Element::QuoteBlock(QuoteBlock {
source, source,
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
children, children,
}), }),
)) ))
@ -149,7 +155,7 @@ fn special_block<'s>(
RefContext<'b, 'g, 'r, 's>, RefContext<'b, 'g, 'r, 's>,
OrgSource<'s>, OrgSource<'s>,
OrgSource<'s>, OrgSource<'s>,
&Vec<Keyword<'s>>, Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> ) -> Res<OrgSource<'s>, Element<'s>>
+ 's { + 's {
let context_name = format!("special block {}", name); 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>, pre_affiliated_keywords_input: OrgSource<'s>,
name: &'s str, name: &'s str,
context_name: &'c str, context_name: &'c str,
affiliated_keywords: &Vec<Keyword<'s>>, affiliated_keywords: Vec<Keyword<'s>>,
) -> Res<OrgSource<'s>, Element<'s>> { ) -> Res<OrgSource<'s>, Element<'s>> {
let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?; let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?;
let (remaining, (source, children)) = greater_block_body( let (remaining, (source, children)) = greater_block_body(
@ -189,7 +195,10 @@ fn _special_block<'c, 'b, 'g, 'r, 's>(
remaining, remaining,
Element::SpecialBlock(SpecialBlock { Element::SpecialBlock(SpecialBlock {
source, source,
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
children, children,
block_type: name, block_type: name,
parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)), parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)),

View File

@ -9,10 +9,10 @@ use nom::multi::many0;
use nom::multi::many1_count; use nom::multi::many1_count;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_consumed; use super::util::get_consumed;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::RefContext; use crate::context::RefContext;
use crate::error::Res; use crate::error::Res;
@ -42,7 +42,10 @@ pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>(
remaining, remaining,
HorizontalRule { HorizontalRule {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
}, },
)) ))
} }

View File

@ -17,10 +17,10 @@ use nom::multi::many0;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_consumed; use super::util::get_consumed;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::Matcher; use crate::context::Matcher;
use crate::context::RefContext; use crate::context::RefContext;
@ -28,6 +28,7 @@ use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
use crate::error::Res; use crate::error::Res;
use crate::parser::util::start_of_line; use crate::parser::util::start_of_line;
use crate::types::AffiliatedKeywords;
use crate::types::Keyword; use crate::types::Keyword;
const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [ const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [
@ -64,7 +65,7 @@ fn _filtered_keyword<'s, F: Matcher>(
remaining, remaining,
Keyword { Keyword {
source: consumed_input.into(), 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(), key: parsed_key.into(),
value: "".into(), value: "".into(),
}, },
@ -82,7 +83,7 @@ fn _filtered_keyword<'s, F: Matcher>(
remaining, remaining,
Keyword { Keyword {
source: consumed_input.into(), 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(), key: parsed_key.into(),
value: parsed_value.into(), value: parsed_value.into(),
}, },
@ -102,7 +103,8 @@ pub(crate) fn keyword<'b, 'g, 'r, 's>(
let (remaining, _trailing_ws) = let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, 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); kw.source = Into::<&str>::into(source);
Ok((remaining, kw)) Ok((remaining, kw))
} }

View File

@ -12,10 +12,10 @@ use nom::multi::many0;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_consumed; use super::util::get_consumed;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
@ -67,7 +67,10 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>(
remaining, remaining,
LatexEnvironment { LatexEnvironment {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
value: value.into(), value: value.into(),
}, },
)) ))

View File

@ -18,9 +18,9 @@ use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use nom::InputTake; use nom::InputTake;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
@ -103,7 +103,10 @@ pub(crate) fn verse_block<'b, 'g, 'r, 's>(
remaining, remaining,
VerseBlock { VerseBlock {
source: source.into(), 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)), data: parameters.map(|parameters| Into::<&str>::into(parameters)),
children, children,
}, },
@ -145,7 +148,10 @@ pub(crate) fn comment_block<'b, 'g, 'r, 's>(
remaining, remaining,
CommentBlock { CommentBlock {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
contents: contents.into(), contents: contents.into(),
}, },
)) ))
@ -213,7 +219,10 @@ pub(crate) fn example_block<'b, 'g, 'r, 's>(
remaining, remaining,
ExampleBlock { ExampleBlock {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
switches, switches,
number_lines, number_lines,
preserve_indent, preserve_indent,
@ -266,7 +275,10 @@ pub(crate) fn export_block<'b, 'g, 'r, 's>(
remaining, remaining,
ExportBlock { ExportBlock {
source: source.into(), 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), export_type: export_type.map(Into::<&str>::into),
data: parameters.map(|parameters| Into::<&str>::into(parameters)), data: parameters.map(|parameters| Into::<&str>::into(parameters)),
contents, contents,
@ -332,7 +344,10 @@ pub(crate) fn src_block<'b, 'g, 'r, 's>(
remaining, remaining,
SrcBlock { SrcBlock {
source: source.into(), 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), language: language.map(Into::<&str>::into),
switches, switches,
parameters: parameters.map(Into::<&str>::into), parameters: parameters.map(Into::<&str>::into),

View File

@ -1,3 +1,4 @@
mod affiliated_keyword;
mod angle_link; mod angle_link;
mod babel_call; mod babel_call;
mod citation; mod citation;

View File

@ -7,13 +7,13 @@ use nom::multi::many1;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::element_parser::detect_element; use super::element_parser::detect_element;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::blank_line; use super::util::blank_line;
use super::util::get_consumed; use super::util::get_consumed;
use super::util::get_has_affiliated_keyword; use super::util::get_has_affiliated_keyword;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context; use crate::context::parser_with_context;
use crate::context::ContextElement; use crate::context::ContextElement;
@ -68,7 +68,10 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>(
remaining, remaining,
Paragraph { Paragraph {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
children, children,
}, },
)) ))

View File

@ -18,11 +18,11 @@ use nom::multi::many1;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::element_parser::element; use super::element_parser::element;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::object_parser::standard_set_object; use super::object_parser::standard_set_object;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::get_name;
use super::util::include_input; use super::util::include_input;
use super::util::indentation_level; use super::util::indentation_level;
use super::util::non_whitespace_character; use super::util::non_whitespace_character;
@ -163,7 +163,10 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>(
remaining, remaining,
PlainList { PlainList {
source: source.into(), 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."), list_type: first_item_list_type.expect("Plain lists require at least one element."),
children: children.into_iter().map(|(_start, item)| item).collect(), children: children.into_iter().map(|(_start, item)| item).collect(),
}, },

View File

@ -13,12 +13,12 @@ use nom::multi::many1;
use nom::multi::many_till; use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::affiliated_keyword::parse_affiliated_keywords;
use super::keyword::affiliated_keyword; use super::keyword::affiliated_keyword;
use super::keyword::table_formula_keyword; use super::keyword::table_formula_keyword;
use super::object_parser::table_cell_set_object; use super::object_parser::table_cell_set_object;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::exit_matcher_parser; use super::util::exit_matcher_parser;
use super::util::get_name;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting; use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::util::org_line_ending; use super::util::org_line_ending;
use crate::context::parser_with_context; use crate::context::parser_with_context;
@ -77,7 +77,10 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>(
remaining, remaining,
Table { Table {
source: source.into(), source: source.into(),
name: get_name(&affiliated_keywords), affiliated_keywords: parse_affiliated_keywords(
context.get_global_settings(),
affiliated_keywords,
),
formulas, formulas,
children, children,
}, },

View File

@ -23,7 +23,6 @@ use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
use crate::error::Res; use crate::error::Res;
use crate::types::IndentationLevel; use crate::types::IndentationLevel;
use crate::types::Keyword;
pub(crate) const WORD_CONSTITUENT_CHARACTERS: &str = pub(crate) const WORD_CONSTITUENT_CHARACTERS: &str =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@ -272,21 +271,6 @@ pub(crate) fn indentation_level<'b, 'g, 'r, 's>(
Ok((remaining, (indentation_level, leading_whitespace))) Ok((remaining, (indentation_level, leading_whitespace)))
} }
pub(crate) fn get_name<'s>(affiliated_keywords: &Vec<Keyword<'s>>) -> 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>( pub(crate) fn get_has_affiliated_keyword<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
) -> Option<OrgSource<'s>> { ) -> Option<OrgSource<'s>> {

View File

@ -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<Vec<Object<'s>>>),
}
#[derive(Debug)]
pub struct AffiliatedKeyword<'s> {
pub name: &'s str,
pub value: AffiliatedKeywordValue<'s>,
}
#[derive(Debug)]
pub struct AffiliatedKeywords<'s> {
pub(crate) keywords: BTreeMap<String, AffiliatedKeywordValue<'s>>,
}
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(),
}
}
}

View File

@ -1,5 +1,7 @@
use super::affiliated_keyword::GetAffiliatedKeywords;
use super::element::Element; use super::element::Element;
use super::lesser_element::TableCell; use super::lesser_element::TableCell;
use super::AffiliatedKeywords;
use super::Keyword; use super::Keyword;
use super::Object; use super::Object;
use super::StandardProperties; use super::StandardProperties;
@ -7,7 +9,7 @@ use super::StandardProperties;
#[derive(Debug)] #[derive(Debug)]
pub struct PlainList<'s> { pub struct PlainList<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub list_type: PlainListType, pub list_type: PlainListType,
pub children: Vec<PlainListItem<'s>>, pub children: Vec<PlainListItem<'s>>,
} }
@ -47,21 +49,21 @@ pub enum CheckboxType {
#[derive(Debug)] #[derive(Debug)]
pub struct CenterBlock<'s> { pub struct CenterBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct QuoteBlock<'s> { pub struct QuoteBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct SpecialBlock<'s> { pub struct SpecialBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub block_type: &'s str, pub block_type: &'s str,
pub parameters: Option<&'s str>, pub parameters: Option<&'s str>,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
@ -70,7 +72,7 @@ pub struct SpecialBlock<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct DynamicBlock<'s> { pub struct DynamicBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub block_name: &'s str, pub block_name: &'s str,
pub parameters: Option<&'s str>, pub parameters: Option<&'s str>,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
@ -79,7 +81,7 @@ pub struct DynamicBlock<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct FootnoteDefinition<'s> { pub struct FootnoteDefinition<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub label: &'s str, pub label: &'s str,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
} }
@ -87,7 +89,7 @@ pub struct FootnoteDefinition<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct Drawer<'s> { pub struct Drawer<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub drawer_name: &'s str, pub drawer_name: &'s str,
pub children: Vec<Element<'s>>, pub children: Vec<Element<'s>>,
} }
@ -108,7 +110,7 @@ pub struct NodeProperty<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct Table<'s> { pub struct Table<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub formulas: Vec<Keyword<'s>>, pub formulas: Vec<Keyword<'s>>,
pub children: Vec<TableRow<'s>>, pub children: Vec<TableRow<'s>>,
} }
@ -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
}
}

View File

@ -1,4 +1,6 @@
use super::object::Object; use super::object::Object;
use super::AffiliatedKeywords;
use super::GetAffiliatedKeywords;
use super::PlainText; use super::PlainText;
use super::StandardProperties; use super::StandardProperties;
use super::Timestamp; use super::Timestamp;
@ -6,7 +8,7 @@ use super::Timestamp;
#[derive(Debug)] #[derive(Debug)]
pub struct Paragraph<'s> { pub struct Paragraph<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub children: Vec<Object<'s>>, pub children: Vec<Object<'s>>,
} }
@ -25,7 +27,7 @@ pub struct TableCell<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct VerseBlock<'s> { pub struct VerseBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub data: Option<&'s str>, pub data: Option<&'s str>,
pub children: Vec<Object<'s>>, pub children: Vec<Object<'s>>,
} }
@ -33,7 +35,7 @@ pub struct VerseBlock<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct CommentBlock<'s> { pub struct CommentBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub contents: &'s str, pub contents: &'s str,
} }
@ -50,7 +52,7 @@ pub enum RetainLabels {
#[derive(Debug)] #[derive(Debug)]
pub struct ExampleBlock<'s> { pub struct ExampleBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub switches: Option<&'s str>, pub switches: Option<&'s str>,
pub number_lines: Option<SwitchNumberLines>, pub number_lines: Option<SwitchNumberLines>,
pub preserve_indent: Option<CharOffsetInLine>, pub preserve_indent: Option<CharOffsetInLine>,
@ -63,7 +65,7 @@ pub struct ExampleBlock<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct ExportBlock<'s> { pub struct ExportBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub export_type: Option<&'s str>, pub export_type: Option<&'s str>,
pub data: Option<&'s str>, pub data: Option<&'s str>,
pub contents: String, pub contents: String,
@ -72,7 +74,7 @@ pub struct ExportBlock<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct SrcBlock<'s> { pub struct SrcBlock<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub language: Option<&'s str>, pub language: Option<&'s str>,
pub switches: Option<&'s str>, pub switches: Option<&'s str>,
pub parameters: Option<&'s str>, pub parameters: Option<&'s str>,
@ -101,7 +103,7 @@ pub struct Clock<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct DiarySexp<'s> { pub struct DiarySexp<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub value: &'s str, pub value: &'s str,
} }
@ -116,20 +118,20 @@ pub struct Planning<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct FixedWidthArea<'s> { pub struct FixedWidthArea<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub value: Vec<&'s str>, pub value: Vec<&'s str>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct HorizontalRule<'s> { pub struct HorizontalRule<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Keyword<'s> { pub struct Keyword<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub key: &'s str, pub key: &'s str,
pub value: &'s str, pub value: &'s str,
} }
@ -137,7 +139,7 @@ pub struct Keyword<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct BabelCall<'s> { pub struct BabelCall<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub value: &'s str, pub value: &'s str,
pub call: Option<&'s str>, pub call: Option<&'s str>,
pub inside_header: Option<&'s str>, pub inside_header: Option<&'s str>,
@ -148,7 +150,7 @@ pub struct BabelCall<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct LatexEnvironment<'s> { pub struct LatexEnvironment<'s> {
pub source: &'s str, pub source: &'s str,
pub name: Option<&'s str>, pub affiliated_keywords: AffiliatedKeywords<'s>,
pub value: &'s str, pub value: &'s str,
} }
@ -172,7 +174,7 @@ impl<'s> Paragraph<'s> {
objects.push(Object::PlainText(PlainText { source: input })); objects.push(Object::PlainText(PlainText { source: input }));
Paragraph { Paragraph {
source: input, source: input,
name: None, affiliated_keywords: AffiliatedKeywords::default(),
children: objects, children: objects,
} }
} }
@ -302,3 +304,75 @@ impl<'s> ExportBlock<'s> {
self.export_type.map(|s| s.to_uppercase()) 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
}
}

View File

@ -1,3 +1,4 @@
mod affiliated_keyword;
mod ast_node; mod ast_node;
mod document; mod document;
mod element; mod element;
@ -9,6 +10,10 @@ mod object;
mod source; mod source;
mod standard_properties; mod standard_properties;
mod util; 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(crate) use ast_node::AstNode;
pub use document::Document; pub use document::Document;
pub use document::DocumentElement; pub use document::DocumentElement;