Skip to content

Commit 9ecf372

Browse files
authored
fix: "\%" early stop (#160)
Previously: - `%` is used to remove comments, which interfered with literal `\%` in LaTeX documents. Now: - Handle `%` properly. Tested for `%`, `\%` and `\\%`.
1 parent e84f708 commit 9ecf372

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

internal/libs/tex/latexpand.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,23 @@ import (
88
"paperdebugger/internal/libs/shared"
99
)
1010

11+
// commentRegex matches a LaTeX comment: an unescaped % and everything after it
12+
// until end of line. The leading group captures either start-of-line or a
13+
// non-backslash character, then consumes pairs of backslashes (\\) before %.
14+
// This generalizes to any run of N backslashes preceding %: if N is even
15+
// (including 0), every backslash pairs up as a literal-backslash escape and
16+
// the % is unescaped, so the comment is stripped; if N is odd, the final
17+
// backslash escapes the % itself, so the % (and the surrounding text) is
18+
// preserved.
19+
var commentRegex = regexp.MustCompile(`(^|[^\\])((?:\\\\)*)%.*$`)
20+
1121
func removeComments(text string) string {
1222
// Split into lines, trim each line and filter empty ones
1323
lines := strings.Split(text, "\n")
1424
var result []string
1525
for _, line := range lines {
1626
trimmed := strings.TrimSpace(line)
17-
commentRegex := regexp.MustCompile(`%.*$`)
18-
cleaned := commentRegex.ReplaceAllString(trimmed, "")
27+
cleaned := commentRegex.ReplaceAllString(trimmed, "$1$2")
1928
cleaned = strings.TrimSpace(cleaned)
2029
if len(cleaned) == 0 {
2130
continue

internal/libs/tex/latexpand_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,27 @@ Hello, world!
2020
\end{document}`, removeComments(input))
2121
}
2222

23+
func TestRemoveCommentsBackslashRunsBeforePercent(t *testing.T) {
24+
cases := []struct {
25+
name string
26+
input string
27+
want string
28+
}{
29+
{"1 backslash (odd) preserves %", `a\% keep`, `a\% keep`},
30+
{"2 backslashes (even) strips comment", `a\\% drop`, `a\\`},
31+
{"3 backslashes (odd) preserves %", `a\\\% keep`, `a\\\% keep`},
32+
{"4 backslashes (even) strips comment", `a\\\\% drop`, `a\\\\`},
33+
{"5 backslashes (odd) preserves %", `a\\\\\% keep`, `a\\\\\% keep`},
34+
{"3 backslashes at line start preserves %", `\\\% keep`, `\\\% keep`},
35+
{"4 backslashes at line start strips comment", `\\\\% drop`, `\\\\`},
36+
}
37+
for _, tc := range cases {
38+
t.Run(tc.name, func(t *testing.T) {
39+
assert.Equal(t, tc.want, removeComments(tc.input))
40+
})
41+
}
42+
}
43+
2344
func TestLatexpand(t *testing.T) {
2445
input := map[string]string{
2546
"main.tex": `

0 commit comments

Comments
 (0)