Fix multiline detection for CRLF-terminated startup commands

Strip the entire CRLF terminator (or lone CR/LF) from startup commands
before checking if the body contains newline characters.

Previously, slicing off only the last character of a CRLF-terminated
command left a trailing CR in the body. This caused a single-line
command to be incorrectly categorized as multiline and wrapped in
bracketed paste.
This commit is contained in:
Jinjing
2026-07-05 21:48:27 -07:00
parent 9a8f2fd393
commit 8926cc9bb4
2 changed files with 11 additions and 2 deletions
@@ -17,6 +17,12 @@ describe('buildStartupCommandSubmission', () => {
).toBe('claude\n')
})
it('treats a CRLF-terminated single-line command as single-line', () => {
expect(
buildStartupCommandSubmission('claude\r\n', { submit: '\r', bracketedPasteSafe: true })
).toBe('claude\r\n')
})
it('wraps a multiline command in bracketed paste with a trailing submit byte', () => {
const command = "claude 'first\nsecond'"
expect(buildStartupCommandSubmission(command, { submit: '\n', bracketedPasteSafe: true })).toBe(
+5 -2
View File
@@ -32,8 +32,11 @@ export function buildStartupCommandSubmission(
command: string,
{ submit, bracketedPasteSafe }: StartupCommandSubmissionOptions
): string {
const endsWithSubmit = command.endsWith('\r') || command.endsWith('\n')
const body = endsWithSubmit ? command.slice(0, -1) : command
// Strip a full CRLF (or lone CR/LF) terminator so a single-line command ending
// in \r\n isn't misread as multiline by the \r/\n body check below.
const trailingTerminator = /\r\n$|\r$|\n$/.exec(command)?.[0] ?? ''
const endsWithSubmit = trailingTerminator.length > 0
const body = endsWithSubmit ? command.slice(0, -trailingTerminator.length) : command
if (bracketedPasteSafe && (body.includes('\n') || body.includes('\r'))) {
return `${BRACKETED_PASTE_START}${body}${BRACKETED_PASTE_END}${submit}`
}