From ae1c06bd22146ac5e38bc513faffe83eaa39096c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20F=C3=B6rster?= Date: Sat, 22 Dec 2018 21:18:04 +0100 Subject: [PATCH] Parse LaTeX sections --- src/main/kotlin/texlab/latex/LatexSection.kt | 26 ++++++++++++++ .../kotlin/texlab/latex/LatexSyntaxTree.kt | 2 ++ .../kotlin/texlab/latex/LatexSectionTests.kt | 35 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/main/kotlin/texlab/latex/LatexSection.kt create mode 100644 src/test/kotlin/texlab/latex/LatexSectionTests.kt diff --git a/src/main/kotlin/texlab/latex/LatexSection.kt b/src/main/kotlin/texlab/latex/LatexSection.kt new file mode 100644 index 00000000..51e880af --- /dev/null +++ b/src/main/kotlin/texlab/latex/LatexSection.kt @@ -0,0 +1,26 @@ +package texlab.latex + +data class LatexSection(val command: LatexCommandSyntax, val text: String, val level: Int) { + companion object { + private val COMMAND_NAMES = arrayOf( + "\\chapter", "\\chapter*", + "\\section", "\\section*", + "\\subsection", "\\subsection*", + "\\subsubsection", "\\subsubsection*", + "\\paragraph", "\\paragraph*", + "\\subparagraph", "\\subparagraph*") + + fun analyze(root: LatexSyntaxNode): List { + return root.descendants() + .filterIsInstance() + .filter { COMMAND_NAMES.contains(it.name.text) } + .mapNotNull { analyze(it) } + } + + private fun analyze(command: LatexCommandSyntax): LatexSection? { + val text = command.extractText(0) ?: return null + val level = COMMAND_NAMES.indexOf(command.name.text) / 2 + return LatexSection(command, text.words.joinToString(" ") { it.text }, level) + } + } +} diff --git a/src/main/kotlin/texlab/latex/LatexSyntaxTree.kt b/src/main/kotlin/texlab/latex/LatexSyntaxTree.kt index d666b88f..0c31960f 100644 --- a/src/main/kotlin/texlab/latex/LatexSyntaxTree.kt +++ b/src/main/kotlin/texlab/latex/LatexSyntaxTree.kt @@ -7,4 +7,6 @@ class LatexSyntaxTree(text: String) { val includes: List = LatexInclude.analyze(root) val environments: List = LatexEnvironment.analyze(root) + + val sections: List = LatexSection.analyze(root) } diff --git a/src/test/kotlin/texlab/latex/LatexSectionTests.kt b/src/test/kotlin/texlab/latex/LatexSectionTests.kt new file mode 100644 index 00000000..d0f67f39 --- /dev/null +++ b/src/test/kotlin/texlab/latex/LatexSectionTests.kt @@ -0,0 +1,35 @@ +package texlab.latex + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class LatexSectionTests { + + @Test + fun `it should find numbered sections`() { + val text = "\\section{Foo Bar Baz}" + val tree = LatexParser.parse(text) + val expected = LatexSection(tree.children[0] as LatexCommandSyntax, "Foo Bar Baz", 1) + val actual = LatexSection.analyze(tree) + assertEquals(1, actual.size) + assertEquals(expected, actual[0]) + } + + @Test + fun `it should find unnumbered paragraphs`() { + val text = "\\paragraph*{Foo}" + val tree = LatexParser.parse(text) + val expected = LatexSection(tree.children[0] as LatexCommandSyntax, "Foo", 4) + val actual = LatexSection.analyze(tree) + assertEquals(1, actual.size) + assertEquals(expected, actual[0]) + } + + @Test + fun `it should ignore invalid chapters`() { + val text = "\\chapter*" + val tree = LatexParser.parse(text) + val actual = LatexSection.analyze(tree) + assertEquals(0, actual.size) + } +}