Repository: alvinwan/TexSoup

Issue:
Newlines after backslashes are not parsed correctly
For example:

```python
>>> import TexSoup
>>> text = 'a\\\nb'
>>> print(text)
a\
b
>>> soup = TexSoup.TexSoup(text)
>>> soup
a\b
```

The newline is gone, which has of course changed the meaning of the text, so running it through `TexSoup` again gives a different result:

```python
>>> TexSoup.TexSoup(soup)
a
```

Discussion:
MaicoTimmerman: @alvinwan I'd love to see the merged and released as it also fixes an warning:

```pytb
File /usr/local/lib/python3.10/site-packages/TexSoup/tex.py:1: in <module>
    from TexSoup.reader import read_expr, read_tex
File "/usr/local/lib/python3.10/site-packages/TexSoup/reader.py", line 97
    assert mode != MODE_MATH, 'Command \item invalid in math mode.'
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: invalid escape sequence '\i'
```

Patch:
diff --git a/TexSoup/reader.py b/TexSoup/reader.py
index fd53989..ba92aaa 100644
--- a/TexSoup/reader.py
+++ b/TexSoup/reader.py
@@ -31,7 +31,11 @@ SIGNATURES = {
     'textbf': (1, 0),
     'section': (1, 1),
     'label': (1, 0),
+    'cap': (0, 0),
     'cup': (0, 0),
+    'in': (0, 0),
+    'notin': (0, 0),
+    'infty': (0, 0),
     'noindent': (0, 0),
 }
 
@@ -278,7 +282,7 @@ def read_env(src, expr, skip_envs=(), tolerance=0, mode=MODE_NON_MATH):
     while src.hasNext():
         if src.peek().category == TC.Escape:
             name, args = make_read_peek(read_command)(
-                src, 1, skip=1, tolerance=tolerance, mode=mode)
+                src, skip=1, tolerance=tolerance, mode=mode)
             if name == 'end':
                 break
         contents.append(read_expr(src, skip_envs=skip_envs, tolerance=tolerance, mode=mode))
diff --git a/TexSoup/tokens.py b/TexSoup/tokens.py
index 492c50e..50e97e2 100644
--- a/TexSoup/tokens.py
+++ b/TexSoup/tokens.py
@@ -123,8 +123,8 @@ def tokenize_escaped_symbols(text, prev=None):
             and text.peek(1) \
             and text.peek(1).category in (
                 CC.Escape, CC.GroupBegin, CC.GroupEnd, CC.MathSwitch,
-                CC.Alignment, CC.Macro, CC.Superscript, CC.Subscript,
-                CC.Spacer, CC.Active, CC.Comment, CC.Other):
+                CC.Alignment, CC.EndOfLine, CC.Macro, CC.Superscript,
+                CC.Subscript, CC.Spacer, CC.Active, CC.Comment, CC.Other):
         result = text.forward(2)
         result.category = TC.EscapedComment
         return result


Test patch:
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 60ea596..e958c58 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -195,6 +195,13 @@ def test_escaped_characters():
     assert '\\$4-\\$5' in str(soup), 'Escaped characters not properly rendered.'
 
 
+def test_newline_after_backslash():
+    """Tests that newlines after backslashes are preserved."""
+    text = 'a\\\nb'
+    soup = TexSoup(text)
+    assert str(soup) == text
+
+
 def test_math_environment_weirdness():
     """Tests that math environment interacts correctly with other envs."""
     soup = TexSoup(r"""\begin{a} \end{a}$ b$""")
@@ -385,7 +392,7 @@ def test_def_item():
 
 
 def test_def_without_braces():
-    """Tests that def without braces around the new command parses correctly"""
+    """Tests that def without braces around the new command parses correctly."""
     soup = TexSoup(r"\def\acommandname{replacement text}")
     assert len(soup.find("def").args) == 2
     assert str(soup.find("def").args[0]) == r"\acommandname"
@@ -398,6 +405,19 @@ def test_grouping_optional_argument():
     assert len(soup.Theorem.args) == 1
 
 
+def test_zero_argument_signatures():
+    """Tests that specific commands that do not take arguments are parsed correctly."""
+    soup = TexSoup(r"$\cap[\cup[\in[\notin[\infty[$")
+    assert len(soup.find("cap").args) == 0
+    assert len(soup.find("cup").args) == 0
+    assert len(soup.find("in").args) == 0
+    assert len(soup.find("notin").args) == 0
+    assert len(soup.find("infty").args) == 0
+
+    soup = TexSoup(r"\begin{equation} \cup [0, \infty) \end{equation}")
+    assert len(soup.find("cup").args) == 0
+
+
 ##############
 # FORMATTING #
 ##############