Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/bashkit/src/parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,16 @@ impl<'a> Lexer<'a> {
while let Some(ch) = self.peek_char() {
if ch == ' ' || ch == '\t' {
self.advance();
} else if ch == '\\' {
// Check for backslash-newline (line continuation) between tokens
let mut lookahead = self.chars.clone();
lookahead.next(); // skip backslash
if lookahead.next() == Some('\n') {
self.advance(); // consume backslash
self.advance(); // consume newline
} else {
break;
}
} else {
break;
}
Expand Down
22 changes: 22 additions & 0 deletions crates/bashkit/tests/issue_289_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Regression test for #289: backslash line continuation fails in some contexts

use bashkit::Bash;

#[tokio::test]
async fn issue_289_backslash_continuation_if() {
let mut bash = Bash::new();
let r = bash
.exec(
"A=\"\"\nB=\"\"\nif [ -z \"$A\" ] || \\\n [ -z \"$B\" ]; then\n echo missing\nfi",
)
.await
.unwrap();
assert_eq!(r.stdout.trim(), "missing");
}

#[tokio::test]
async fn issue_289_backslash_continuation_command() {
let mut bash = Bash::new();
let r = bash.exec("echo hello \\\n world").await.unwrap();
assert_eq!(r.stdout.trim(), "hello world");
}
Loading