Skip to content

Commit

Permalink
Allow escaping newlines (#1551)
Browse files Browse the repository at this point in the history
  • Loading branch information
ids1024 authored Jul 25, 2023
1 parent f04de75 commit 30bcf28
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ impl<'src> Lexer<'src> {
',' => self.lex_single(Comma),
'/' => self.lex_single(Slash),
':' => self.lex_colon(),
'\\' => self.lex_escape(),
'=' => self.lex_choices('=', &[('=', EqualsEquals), ('~', EqualsTilde)], Equals),
'@' => self.lex_single(At),
'[' => self.lex_delimiter(BracketL),
Expand Down Expand Up @@ -709,6 +710,31 @@ impl<'src> Lexer<'src> {
Ok(())
}

/// Lex an token starting with '\' escape
fn lex_escape(&mut self) -> CompileResult<'src, ()> {
self.presume('\\')?;

// Treat newline escaped with \ as whitespace
if self.accepted('\n')? {
while self.next_is_whitespace() {
self.advance()?;
}
self.token(Whitespace);
} else if self.accepted('\r')? {
if !self.accepted('\n')? {
return Err(self.error(UnpairedCarriageReturn));
}
while self.next_is_whitespace() {
self.advance()?;
}
self.token(Whitespace);
} else if let Some(character) = self.next {
return Err(self.error(CompileErrorKind::InvalidEscapeSequence { character }));
}

Ok(())
}

/// Lex a carriage return and line feed
fn lex_eol(&mut self) -> CompileResult<'src, ()> {
if self.accepted('\r')? {
Expand Down
1 change: 1 addition & 0 deletions tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ mod json;
mod line_prefixes;
mod misc;
mod multibyte_char;
mod newline_escape;
mod no_cd;
mod no_exit_message;
mod os_attributes;
Expand Down
77 changes: 77 additions & 0 deletions tests/newline_escape.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use super::*;

#[test]
fn newline_escape_deps() {
Test::new()
.justfile(
"
default: a \\
b \\
c
a:
echo a
b:
echo b
c:
echo c
",
)
.stdout("a\nb\nc\n")
.stderr("echo a\necho b\necho c\n")
.run();
}

#[test]
fn newline_escape_deps_no_indent() {
Test::new()
.justfile(
"
default: a\\
b\\
c
a:
echo a
b:
echo b
c:
echo c
",
)
.stdout("a\nb\nc\n")
.stderr("echo a\necho b\necho c\n")
.run();
}

#[test]
fn newline_escape_deps_linefeed() {
Test::new()
.justfile(
"
default: a\\\r
b
a:
echo a
b:
echo b
",
)
.stdout("a\nb\n")
.stderr("echo a\necho b\n")
.run();
}

#[test]
fn newline_escape_deps_invalid_esc() {
Test::new()
.justfile(
"
default: a\\ b
",
)
.stdout("")
.stderr(
"error: `\\ ` is not a valid escape sequence\n |\n1 | default: a\\ b\n | ^\n",
)
.status(EXIT_FAILURE)
.run();
}

0 comments on commit 30bcf28

Please sign in to comment.