From ff4df63764c0cf60f7e4cbdf8381fb2c4dbbaf60 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Feb 2026 15:27:10 +0000 Subject: [PATCH 1/2] fix(lexer): handle backslash-newline line continuation between tokens Closes #289 --- crates/bashkit/src/parser/lexer.rs | 10 ++++++++++ crates/bashkit/tests/issue_289_test.rs | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 crates/bashkit/tests/issue_289_test.rs 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..57321e1e --- /dev/null +++ b/crates/bashkit/tests/issue_289_test.rs @@ -0,0 +1,20 @@ +//! 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"); +} From 12910e3570bda57f5fb3b1c3c719cbea7b23ed3c Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Feb 2026 15:34:40 +0000 Subject: [PATCH 2/2] chore: fix formatting --- crates/bashkit/tests/issue_289_test.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bashkit/tests/issue_289_test.rs b/crates/bashkit/tests/issue_289_test.rs index 57321e1e..39da8649 100644 --- a/crates/bashkit/tests/issue_289_test.rs +++ b/crates/bashkit/tests/issue_289_test.rs @@ -6,7 +6,9 @@ use bashkit::Bash; 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") + .exec( + "A=\"\"\nB=\"\"\nif [ -z \"$A\" ] || \\\n [ -z \"$B\" ]; then\n echo missing\nfi", + ) .await .unwrap(); assert_eq!(r.stdout.trim(), "missing");