[DEV] Escapable curly braces (#955)
This commit is contained in:
parent
598c574b8a
commit
c622cf68b5
3 changed files with 30 additions and 3 deletions
|
|
@ -88,6 +88,12 @@ triple-quotes can be used to avoid *closing* the String.
|
|||
%string("""This has both " and ' in it.""")
|
||||
}
|
||||
|
||||
If you want a plain string that contains literal curly braces, you can escape them like so:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
string_variable: "This contains \\{ literal curly braces \\}"
|
||||
|
||||
Integer
|
||||
~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ CUSTOM_FUNCTION_ARGUMENTS_ONLY_ARGS = InvalidSyntaxException(
|
|||
|
||||
FUNCTION_INVALID_CHAR = InvalidSyntaxException("Invalid value when parsing a function")
|
||||
|
||||
BRACKET_INVALID_CHAR = InvalidSyntaxException("Invalid value within brackets")
|
||||
|
||||
|
||||
def _UNEXPECTED_CHAR_ARGUMENT(arg_type: ParsedArgType):
|
||||
return InvalidSyntaxException(f"Unexpected character when parsing {arg_type.value} arguments")
|
||||
|
|
@ -505,6 +507,10 @@ class _Parser:
|
|||
raise UNREACHABLE
|
||||
|
||||
def _parse_main_loop(self, ch: str) -> bool:
|
||||
if ch == "\\" and self._read(increment_pos=False) in {"{", "}"}:
|
||||
# Escape brackets are \{ and \}, only add the second char
|
||||
self._literal_str += self._read()
|
||||
return True
|
||||
if ch == "}":
|
||||
if self._bracket_counter == 0:
|
||||
raise BRACKET_NOT_CLOSED
|
||||
|
|
@ -558,9 +564,9 @@ class _Parser:
|
|||
elif self._bracket_counter == 0:
|
||||
# Only accumulate literal str if not in brackets
|
||||
self._literal_str += ch
|
||||
else:
|
||||
# Should only be possible to get here if it's a space
|
||||
assert ch.isspace()
|
||||
elif not ch.isspace():
|
||||
self._set_highlight_position(pos=self._pos - 1)
|
||||
raise BRACKET_INVALID_CHAR
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from typing import Union
|
|||
import pytest
|
||||
|
||||
from ytdl_sub.script.parser import _UNEXPECTED_CHAR_ARGUMENT
|
||||
from ytdl_sub.script.parser import BRACKET_INVALID_CHAR
|
||||
from ytdl_sub.script.parser import BRACKET_NOT_CLOSED
|
||||
from ytdl_sub.script.parser import ParsedArgType
|
||||
from ytdl_sub.script.parser import parse
|
||||
|
|
@ -192,6 +193,15 @@ class TestParser:
|
|||
]
|
||||
)
|
||||
|
||||
def test_escaped_bracket(self):
|
||||
assert parse("\\{ This is escape {%string('{}')} and here \\}") == SyntaxTree(
|
||||
[
|
||||
String(value="{ This is escape "),
|
||||
BuiltInFunction(name="string", args=[String(value="{}")]),
|
||||
String(value=" and here }"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class TestParserBracketFailures:
|
||||
def test_bracket_open(self):
|
||||
|
|
@ -208,3 +218,8 @@ class TestParserBracketFailures:
|
|||
match=re.escape(str(_UNEXPECTED_CHAR_ARGUMENT(ParsedArgType.MAP_KEY))),
|
||||
):
|
||||
parse("hello {%capitalize({as_arg)}")
|
||||
|
||||
@pytest.mark.parametrize("char", [")", ",", "*", "]"])
|
||||
def test_extra_char_in_brackets(self, char: str):
|
||||
with pytest.raises(InvalidSyntaxException, match=re.escape(str(BRACKET_INVALID_CHAR))):
|
||||
parse(f"{{ %string('hi') {char} }}")
|
||||
|
|
|
|||
Loading…
Reference in a new issue