Skip to content

Commit 06d565d

Browse files
committed
Fix false positives in Typst
See #72
1 parent 1eb8c63 commit 06d565d

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

changelog.xml

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
<action type="add" issue="#55">
2424
Add support for Neorg (LSP language ID `neorg`)
2525
</action>
26+
<action type="fix" issue="#72">
27+
Fix false positives in Typst
28+
</action>
2629
</release>
2730
<release version="18.4.0" date="2024-12-23">
2831
<action type="add" issue="valentjn/ltex-ls#268" due-to="Benoît Pasquier">

src/main/kotlin/org/bsplines/ltexls/parsing/typst/TypstAnnotatedTextBuilder.kt

+27-2
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,31 @@ class TypstAnnotatedTextBuilder(
2020
private var codeModeString = false
2121
private var codeModeBracketsCounter = 0
2222
private var codeModeStringCounter = 0
23+
private var headingMode = false
2324

2425
override fun processCharacter() {
2526
processEscapeCharacter()
2627
addMarkupInternal(NO_TEXT_INLINE_MATH_REGEX, "", true)
2728
processMathBlock()
2829
processCodeMode()
30+
processHeading()
2931

3032
if (this.isStartOfLine) {
3133
addMarkupInternal(LIST_REGEX)
3234
addMarkupInternal(LEADING_WHITESPACE_REGEX)
33-
addMarkupInternal(HEADING_REGEX)
3435
}
3536

3637
addMarkupInternal(LET_CURLY_BRACKETS_REGEX)
3738
addMarkupInternal(LET_CODE_REGEX, "", false, true)
3839
addMarkupInternal(LET_REGEX)
40+
addMarkupInternal(CITE_REGEX)
3941
addMarkupInternal(CODE_REGEX, "", false, true)
4042
addMarkupInternal(CODE_SQUARE_BRACKETS_REGEX, "", true)
4143
addMarkupInternal(LINE_COMMENT_REGEX, "\n")
4244
addMarkupInternal(MULTILINELINE_COMMENT_REGEX, "\n")
4345
addMarkupInternal(MARKUP_REGEX)
4446
addMarkupInternal(IMPORT_REGEX, "\n")
47+
addMarkupInternal(SHOW_REGEX, "\n")
4548
addMarkupInternal(LABEL_REGEX, " ", true)
4649
addMarkupInternal(LABEL_REF_REGEX)
4750
addMarkupInternal(VARIABLE_REGEX, "", true)
@@ -152,20 +155,42 @@ class TypstAnnotatedTextBuilder(
152155
}
153156
}
154157

158+
private fun processHeading() {
159+
if (this.isStartOfLine && matchFromPosition(HEADING_REGEX) != null) {
160+
addMarkupInternal(HEADING_REGEX)
161+
headingMode = true
162+
}
163+
if (headingMode) {
164+
if (matchFromPosition(HEADING_END_REGEX) != null) {
165+
if (this.curString == "?") {
166+
addMarkupInternal(HEADING_END_REGEX, "?\n")
167+
} else if (curString == "!") {
168+
addMarkupInternal(HEADING_END_REGEX, "!\n")
169+
} else {
170+
addMarkupInternal(HEADING_END_REGEX, ".\n")
171+
}
172+
headingMode = false
173+
}
174+
}
175+
}
176+
155177
companion object {
156178
private val NO_TEXT_INLINE_MATH_REGEX = Regex("^\\$[^\"$\n]*\\$")
157179
private val LIST_REGEX = Regex("^\\s*[+|\\-|\\/]\\s")
158180
private val LEADING_WHITESPACE_REGEX = Regex("^\\s*")
159181
private val HEADING_REGEX = Regex("^=+\\s")
182+
private val HEADING_END_REGEX = Regex("^\\.?\\??\\!?\r?\n")
160183
private val LET_CURLY_BRACKETS_REGEX = Regex("^#let.*=\\s*\\{(.|\r?\n)*?\\}")
161184
private val LET_CODE_REGEX = Regex("^#let.*?=\\s*?\\w*?\\(")
162185
private val LET_REGEX = Regex("^#let.*=\\s*")
163-
private val CODE_REGEX = Regex("^#.*\\(")
186+
private val CITE_REGEX = Regex("^#cite\\(\\S+\\)")
187+
private val CODE_REGEX = Regex("^#.*?\\(")
164188
private val CODE_SQUARE_BRACKETS_REGEX = Regex("^#.*\\[(.|\r?\n)*?\\]")
165189
private val LINE_COMMENT_REGEX = Regex("^\\/\\/.*(\r?\n|$)")
166190
private val MULTILINELINE_COMMENT_REGEX = Regex("^\\/\\*(.|\r?\n)*?\\*\\/")
167191
private val MARKUP_REGEX = Regex("^(\\*|\\_)")
168192
private val IMPORT_REGEX = Regex("^(#import|#include).*\r?\n")
193+
private val SHOW_REGEX = Regex("^#show.*\r?\n")
169194
private val LABEL_REGEX = Regex("^\\s@[^\\s]*")
170195
private val LABEL_REF_REGEX = Regex("^<[^\\s]*>")
171196
private val VARIABLE_REGEX = Regex("^#\\S+")

src/test/kotlin/org/bsplines/ltexls/parsing/typst/TypstAnnotatedTextBuilderTest.kt

+34-7
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,25 @@ class TypstAnnotatedTextBuilderTest : CodeAnnotatedTextBuilderTest("typst") {
2929
fun testHeadings() {
3030
assertPlainText(
3131
"""
32-
== Heading in Typst
32+
= Heading in Typst
33+
More text
34+
== A question heading? Is it a problem?
35+
Even more text
36+
=== That is a bold statement!
37+
More text to read
38+
=== A heading with a dot.
39+
More text
40+
""".trimIndent(),
41+
"""
42+
Heading in Typst.
43+
More text
44+
A question heading? Is it a problem?
45+
Even more text
46+
That is a bold statement!
47+
More text to read
48+
A heading with a dot.
3349
More text
34-
3550
""".trimIndent(),
36-
"Heading in Typst\nMore text\n",
3751
)
3852
}
3953

@@ -146,10 +160,13 @@ class TypstAnnotatedTextBuilderTest : CodeAnnotatedTextBuilderTest("typst") {
146160
#show: resume.with(
147161
author: name,
148162
)
149-
More text
163+
More text.
164+
#show link: underline
165+
#show link: set text(rgb(0, 0, 255))
166+
More text.
150167
151168
""".trimIndent(),
152-
"\nMore text\n",
169+
"\nMore text.\n\n\nMore text.\n",
153170
)
154171
}
155172

@@ -182,15 +199,25 @@ class TypstAnnotatedTextBuilderTest : CodeAnnotatedTextBuilderTest("typst") {
182199
)
183200
}
184201

202+
@Test
203+
fun testCite() {
204+
assertPlainText(
205+
"""
206+
The sky is blue.#cite(label("DBLP:books/lib/Hoff2020")) More text.
207+
""".trimIndent(),
208+
"The sky is blue. More text.",
209+
)
210+
}
211+
185212
@Test
186213
fun testLabel() {
187214
assertPlainText(
188215
"""
189216
This is a @link to a label.
190-
= Heading 1 <link>
217+
= Heading 1<link>
191218
More text.
192219
""".trimIndent(),
193-
"This is a Dummy0 to a label.\nHeading 1 \nMore text.",
220+
"This is a Dummy0 to a label.\nHeading 1.\nMore text.",
194221
)
195222
}
196223
}

0 commit comments

Comments
 (0)