diff --git a/crates/bashkit/src/parser/lexer.rs b/crates/bashkit/src/parser/lexer.rs index ee1ce750..7c54c779 100644 --- a/crates/bashkit/src/parser/lexer.rs +++ b/crates/bashkit/src/parser/lexer.rs @@ -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; } diff --git a/crates/bashkit/tests/issue_289_test.rs b/crates/bashkit/tests/issue_289_test.rs new file mode 100644 index 00000000..39da8649 --- /dev/null +++ b/crates/bashkit/tests/issue_289_test.rs @@ -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"); +}