Allow escaping double braces with {{{{
(#765)
This commit is contained in:
parent
7cbce4374f
commit
d3b277c04c
11
README.adoc
11
README.adoc
@ -446,11 +446,11 @@ publish:
|
|||||||
|
|
||||||
==== Escaping `{{`
|
==== Escaping `{{`
|
||||||
|
|
||||||
To write a recipe containing `{{`, use `{{ "{{" }}`:
|
To write a recipe containing `{{`, use `{{{{`:
|
||||||
|
|
||||||
```make
|
```make
|
||||||
braces:
|
braces:
|
||||||
echo 'I {{ "{{" }}LOVE}} curly braces!'
|
echo 'I {{{{LOVE}} curly braces!'
|
||||||
```
|
```
|
||||||
|
|
||||||
(An unmatched `}}` is ignored, so it doesn't need to be escaped.)
|
(An unmatched `}}` is ignored, so it doesn't need to be escaped.)
|
||||||
@ -462,6 +462,13 @@ braces:
|
|||||||
echo '{{'I {{LOVE}} curly braces!'}}'
|
echo '{{'I {{LOVE}} curly braces!'}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Yet another option is to use `{{ "{{" }}`:
|
||||||
|
|
||||||
|
```make
|
||||||
|
braces:
|
||||||
|
echo 'I {{ "{{" }}LOVE}} curly braces!'
|
||||||
|
```
|
||||||
|
|
||||||
=== Strings
|
=== Strings
|
||||||
|
|
||||||
Double-quoted strings support escape sequences:
|
Double-quoted strings support escape sequences:
|
||||||
|
@ -169,12 +169,15 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
let mut evaluated = String::new();
|
let mut evaluated = String::new();
|
||||||
for (i, fragment) in line.fragments.iter().enumerate() {
|
for (i, fragment) in line.fragments.iter().enumerate() {
|
||||||
match fragment {
|
match fragment {
|
||||||
Fragment::Text { token } =>
|
Fragment::Text { token } => {
|
||||||
|
let lexeme = token.lexeme().replace("{{{{", "{{");
|
||||||
|
|
||||||
if i == 0 && continued {
|
if i == 0 && continued {
|
||||||
evaluated += token.lexeme().trim_start();
|
evaluated += lexeme.trim_start();
|
||||||
} else {
|
} else {
|
||||||
evaluated += token.lexeme();
|
evaluated += &lexeme;
|
||||||
},
|
}
|
||||||
|
},
|
||||||
Fragment::Interpolation { expression } => {
|
Fragment::Interpolation { expression } => {
|
||||||
evaluated += &self.evaluate_expression(expression)?;
|
evaluated += &self.evaluate_expression(expression)?;
|
||||||
},
|
},
|
||||||
|
31
src/lexer.rs
31
src/lexer.rs
@ -91,6 +91,15 @@ impl<'src> Lexer<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Advance over N characters.
|
||||||
|
fn skip(&mut self, n: usize) -> CompilationResult<'src, ()> {
|
||||||
|
for _ in 0..n {
|
||||||
|
self.advance()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Lexeme of in-progress token
|
/// Lexeme of in-progress token
|
||||||
fn lexeme(&self) -> &'src str {
|
fn lexeme(&self) -> &'src str {
|
||||||
&self.src[self.token_start.offset..self.token_end.offset]
|
&self.src[self.token_start.offset..self.token_end.offset]
|
||||||
@ -515,6 +524,11 @@ impl<'src> Lexer<'src> {
|
|||||||
use Terminator::*;
|
use Terminator::*;
|
||||||
|
|
||||||
let terminator = loop {
|
let terminator = loop {
|
||||||
|
if self.rest_starts_with("{{{{") {
|
||||||
|
self.skip(4)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some('\n') = self.next {
|
if let Some('\n') = self.next {
|
||||||
break Newline;
|
break Newline;
|
||||||
}
|
}
|
||||||
@ -1239,6 +1253,23 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: brace_escape,
|
||||||
|
text: "
|
||||||
|
foo:
|
||||||
|
{{{{
|
||||||
|
",
|
||||||
|
tokens: (
|
||||||
|
Identifier:"foo",
|
||||||
|
Colon,
|
||||||
|
Eol,
|
||||||
|
Indent,
|
||||||
|
Text:"{{{{",
|
||||||
|
Eol,
|
||||||
|
Dedent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: indented_block_followed_by_item,
|
name: indented_block_followed_by_item,
|
||||||
text: "
|
text: "
|
||||||
|
@ -2600,6 +2600,30 @@ test! {
|
|||||||
shell: false,
|
shell: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: brace_escape,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
echo '{{{{'
|
||||||
|
",
|
||||||
|
stdout: "{{\n",
|
||||||
|
stderr: "
|
||||||
|
echo '{{'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: brace_escape_extra,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
echo '{{{{{'
|
||||||
|
",
|
||||||
|
stdout: "{{{\n",
|
||||||
|
stderr: "
|
||||||
|
echo '{{{'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
test! {
|
test! {
|
||||||
name: windows_interpreter_path_no_base,
|
name: windows_interpreter_path_no_base,
|
||||||
|
Loading…
Reference in New Issue
Block a user