diff --git a/src/tmux-manager.ts b/src/tmux-manager.ts index 4a3ab1fa..523c4260 100644 --- a/src/tmux-manager.ts +++ b/src/tmux-manager.ts @@ -479,9 +479,11 @@ export interface PasteTextCommands { /** * Escape a final `;` for tmux. tmux splits commands on an argument that ENDS in - * `;` (`set-buffer -- 'a;'` stores `a`, `send-keys -l 'a;'` types `a`, a lone `;` + * `;` (`set-buffer -- 'a;'` stores `a`, `send-keys -l -- 'a;'` types `a`, a lone `;` * is no argument at all); a final `\;` is its escape for a literal `;`. A `;` - * anywhere else in the argument is literal already. Exported for unit testing. + * anywhere else in the argument is literal already. Every `send-keys -l` passes + * `--` before the text, like `set-buffer`, or tmux parses a text that starts with + * `-` as its own options. Exported for unit testing. */ export function escapeTmuxTrailingSemicolon(text: string): string { return text.endsWith(';') ? `${text.slice(0, -1)}\\;` : text; diff --git a/test/tmux-submit-paste.test.ts b/test/tmux-submit-paste.test.ts index 9af06c40..7cc04b7f 100644 --- a/test/tmux-submit-paste.test.ts +++ b/test/tmux-submit-paste.test.ts @@ -181,7 +181,7 @@ describe('sendInput wiring', () => { it('escapes a trailing ";" on every send-keys -l in sendInput and sendInputToPane', async () => { const src = await source(); - const typed = src.match(/send-keys[^`\n]*-l -- \$\{[^`\n]*\}/g) ?? []; + const typed = src.match(/send-keys[^`\n]*-l (?:-- )?\$\{[^`\n]*\}/g) ?? []; const inSend = [await sendInputBody(), src.slice(src.indexOf('sendInputToPane(muxName'))] .map((b) => b.slice(0, b.indexOf('\n }\n'))) .join('\n'); @@ -279,7 +279,7 @@ describe('sendInput line breaks', () => { // Without an Enter, what is left is one line, so it is typed like any other. const typed = managerWithSession(); await typed.sendInput('s1', '\n\njust type'); - expect(typed.ran).toEqual([expect.stringMatching(/ send-keys -t "codeman-abc12345" -l 'just type'$/)]); + expect(typed.ran).toEqual([expect.stringMatching(/ send-keys -t "codeman-abc12345" -l -- 'just type'$/)]); }); it('leaves single-line input as it was: pasted with Enter, typed without', async () => { @@ -291,6 +291,6 @@ describe('sendInput line breaks', () => { const typed = managerWithSession(); await typed.sendInput('s1', 'just type'); expect(typed.ran).toHaveLength(1); - expect(typed.ran[0]).toMatch(/ send-keys -t "codeman-abc12345" -l 'just type'$/); + expect(typed.ran[0]).toMatch(/ send-keys -t "codeman-abc12345" -l -- 'just type'$/); }); });