Change:
Type: <bBug</bSince i newly installed vs code version 1.84.2 I have an issue where, every time i paste a command into the termnal it executes immediately without my having pressed enter. So far I have read that this "feature" was removed from VS code but apparently it persists. VS Code version: Code 1.84.2 (, 2023-11-09T10:51:52.184Z) OS version: WindowsNT x64 10.0. Modes: Remote OS version: Linux x64 5.10.16.3-microsoft-standard-WSL2 <details<summarySystem Info</summary </details<details<summaryExtensions (7)</summaryExtensionVersion ------ remote-ssh0.107.1 remote-ssh-edit0.86.0 remote-wsl0.81.8 vscode-remote-extensionpack0.25.0 material-icon-theme4.32.0 ayu1.0.5 material-theme3.16.2 (1 theme extensions excluded) </details<details<summaryA/B Experiments</summary</details<!-- generated by issue reporter --
Thanks for creating this issue! To help narrow it down, please take the time to follow below steps. Thanks a lot and happy coding Stop VS Code and from the command line (NOT the integrated terminal in Code), execute: and try your steps again to see if it reproduces. If it still reproduces, jump to the next chapter. If you see it is an issue with the extension, please run the command and follow the instructions to find the extension that is causing this issue. <img width="631" alt="image" src="https://user-"Please report the issue to the extension causing this. If the issue is not caused by an extension, it is maybe caused by your configuration. Try to run where is an empty folder. This will ensure Code is starting with a fresh data directory, e.g. no specific settings and without any extensions running. If it still reproduces, it was maybe fixed already in our nightly release. Please download from and see if you can reproduce the issue. Finally, to help us narrow down what change caused the issue, please run the following command to find the build. It will start previous releases of VS Code insiders to see where the regression was introduced: follow the instructions until you found the offending build report back the commit range in this issue Thanks! /label info-needed
Hi, I think I've observed that the newline is automatically entered only when the pasted text was copied from a "copy button" on a website. It seems that when I click and drag-select text that there is no problem. which would indicate that the automatic newline is perhaps an artifact of the copy button feature on some websites, and is carried through the clipboard.
this sounds like it's working as designed. reopen if I'm misunderstanding.
Yes this is by design, we do have a warning alert that pops up when pasting which is enabled by default , but this is ignored if the shell has enabled bracketed paste mode. Some shells like pwsh uses bracketed paste mode to ensure it's all treated as a single input, as if shift+enter was being used instead of enter.
I am using bash shell wsl Ubuntu. I get no warnings, just immediate execution. Seems like something that should not be turned on by default
I actually rely on this behavior almost every day, we also have an explicit check here that bypasses the warning even when bracketed paste mode is off when it's followed by a single new line: I get your point that some might not like the behavior. Since we already have , instead of just we could expand it to be something like where is the current "smart" default and "always" ignores the single new line and bracketed paste mode checks.
I'm thinking we may not actually be talking about the same issue. My issue is that, when I copy code from any website that features a "copy" button, and then paste that code into my terminal, the command is executed immediately, not just put on a new line
would the new warning when is used better for you? It would still execute immediately after you say ok, but at least you'll know that your text has a copied line
auto does not seem to work for me with pwsh: ! Powershell recognizes the multi line input (see ), but I still get the warning when configuring "auto"
For pwsh the multi-line paste warning should never be getting hit since there is a custom keybinding which sends it to PSReadLine to be handled by that. That's this built-in keybinding: This is called out here: ! If that is disabled I don't think pwsh turns on bracketed paste mode so that would be working as intended. can you check why that keybinding is not being used? You might have unbound it? Since this was a feature request done for Dec/Jan I'll close this. Please open a new bug if there is indeed a new problem.
I just verified this on my laptop, there it works as expected!

Discussion:
import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; <del> import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; </del> import { CodeDataTransfers, containsDragType } from 'vs/platform/dnd/browser/dnd'; import { FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';

import type { IMarker, Terminal as XTermTerminal } from '@xterm/xterm'; import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; <ins> import { shouldPasteTerminalText } from 'vs/workbench/contrib/terminal/common/terminalClipboard'; </ins> const enum Constants { /**

@IThemeService private readonly _themeService: IThemeService, @IConfigurationService private readonly _configurationService: IConfigurationService, @ITerminalLogService private readonly _logService: ITerminalLogService, <del> @IDialogService private readonly _dialogService: IDialogService, </del> @IStorageService private readonly _storageService: IStorageService, @IAccessibilityService private readonly _accessibilityService: IAccessibilityService, @IProductService private readonly _productService: IProductService,

this._terminalAltBufferActiveContextKey.set(!!(this.xterm && this.xterm.raw.buffer.active === this.xterm.raw.buffer.alternate)); } <del> private async _shouldPasteText(text: string): Promise<boolean> { // Ignore check if the shell is in bracketed paste mode (ie. the shell can handle multi-line // text). if (this.xterm?.raw.modes.bracketedPasteMode) { return true; } const textForLines = text.split(/r?n/); // Ignore check when a command is copied with a trailing new line if (textForLines.length === 2 && textForLines[1].trim().length === 0) { return true; } // If the clipboard has only one line, no prompt will be triggered if (textForLines.length === 1 || !this._configurationService.getValue<boolean>(TerminalSettingId.EnableMultiLinePasteWarning)) { return true; } const displayItemsCount = 3; const maxPreviewLineLength = 30; let detail = nls.localize('preview', "Preview:"); for (let i = 0; i < Math.min(textForLines.length, displayItemsCount); i++) { const line = textForLines[i]; const cleanedLine = line.length > maxPreviewLineLength ? `${line.slice(0, maxPreviewLineLength)}…` : line; detail += `n${cleanedLine}`; } if (textForLines.length > displayItemsCount) { detail += `n…`; } const { confirmed, checkboxChecked } = await this._dialogService.confirm({ message: nls.localize('confirmMoveTrashMessageFilesAndDirectories', "Are you sure you want to paste {0} lines of text into the terminal?", textForLines.length), detail, primaryButton: nls.localize({ key: 'multiLinePasteButton', comment: ['&& denotes a mnemonic'] }, "&&Paste"), checkbox: { label: nls.localize('doNotAskAgain', "Do not ask me again") } }); if (confirmed && checkboxChecked) { await this._configurationService.updateValue(TerminalSettingId.EnableMultiLinePasteWarning, false); } return confirmed; } </del> override dispose(reason?: TerminalExitReason): void { if (this.isDisposed) { return;

} async paste(): Promise<void> { <del> if (!this.xterm) { return; } const currentText: string = await this._clipboardService.readText(); if (!await this._shouldPasteText(currentText)) { return; } this.focus(); this.xterm.raw.paste(currentText); </del> <ins> await this._paste(await this._clipboardService.readText()); </ins> } async pasteSelection(): Promise<void> { <ins> await this._paste(await this._clipboardService.readText('selection')); } private async _paste(value: string): Promise<void> { </ins> if (!this.xterm) { return; } <del> const currentText: string = await this._clipboardService.readText('selection'); if (!await this._shouldPasteText(currentText)) { </del> <ins> const currentText: string = value; const shouldPasteText = await this._scopedInstantiationService.invokeFunction(shouldPasteTerminalText, currentText, this.xterm?.raw.modes.bracketedPasteMode); if (!shouldPasteText) { </ins> return; }

<ins> /*--------------------------------------------------------------------------------------------- *  Copyright (c) Microsoft Corporation. All rights reserved. *  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; export async function shouldPasteTerminalText(accessor: ServicesAccessor, text: string, bracketedPasteMode: boolean | undefined): Promise<boolean> { const configurationService = accessor.get(IConfigurationService); const dialogService = accessor.get(IDialogService); // If the clipboard has only one line, a warning should never show const textForLines = text.split(/r?n/); if (textForLines.length === 1) { return true; } // Get config value function parseConfigValue(value: unknown): 'auto' | 'always' | 'never' { // Valid value if (typeof value === 'string') { if (value === 'auto' || value === 'always' || value === 'never') { return value; } } // Legacy backwards compatibility if (typeof value === 'boolean') { return value ? 'auto' : 'never'; } // Invalid value fallback return 'auto'; } const configValue = parseConfigValue(configurationService.getValue(TerminalSettingId.EnableMultiLinePasteWarning)); // Never show it if (configValue === 'never') { return true; } // Special edge cases to not show for auto if (configValue === 'auto') { // Ignore check if the shell is in bracketed paste mode (ie. the shell can handle multi-line // text). if (bracketedPasteMode) { return true; } const textForLines = text.split(/r?n/); // Ignore check when a command is copied with a trailing new line if (textForLines.length === 2 && textForLines[1].trim().length === 0) { return true; } } const displayItemsCount = 3; const maxPreviewLineLength = 30; let detail = localize('preview', "Preview:"); for (let i = 0; i < Math.min(textForLines.length, displayItemsCount); i++) { const line = textForLines[i]; const cleanedLine = line.length > maxPreviewLineLength ? `${line.slice(0, maxPreviewLineLength)}…` : line; detail += `n${cleanedLine}`; } if (textForLines.length > displayItemsCount) { detail += `n…`; } const { confirmed, checkboxChecked } = await dialogService.confirm({ message: localize('confirmMoveTrashMessageFilesAndDirectories', "Are you sure you want to paste {0} lines of text into the terminal?", textForLines.length), detail, primaryButton: localize({ key: 'multiLinePasteButton', comment: ['&& denotes a mnemonic'] }, "&&Paste"), checkbox: { label: localize('doNotAskAgain', "Do not ask me again") } }); if (confirmed && checkboxChecked) { await configurationService.updateValue(TerminalSettingId.EnableMultiLinePasteWarning, false); } return confirmed; } </ins>

default: false }, [TerminalSettingId.EnableMultiLinePasteWarning]: { <del> markdownDescription: localize('terminal.integrated.enableMultiLinePasteWarning', "Show a warning dialog when pasting multiple lines into the terminal. The dialog does not show when:nn- Bracketed paste mode is enabled (the shell supports multi-line paste natively)n- The paste is handled by the shell's readline (in the case of pwsh)"), type: 'boolean', default: true </del> <ins> markdownDescription: localize('terminal.integrated.enableMultiLinePasteWarning', "Controls whether to show a warning dialog when pasting multiple lines into the terminal."), type: 'string', enum: ['auto', 'always', 'never'], markdownEnumDescriptions: [ localize('terminal.integrated.enableMultiLinePasteWarning.auto', "Enable the warning but do not show it when:nn- Bracketed paste mode is enabled (the shell supports multi-line paste natively)n- The paste is handled by the shell's readline (in the case of pwsh)"), localize('terminal.integrated.enableMultiLinePasteWarning.always', "Always show the warning if the text contains a new line."), localize('terminal.integrated.enableMultiLinePasteWarning.never', "Never show the warning.") ], default: 'auto' </ins> }, [TerminalSettingId.DrawBoldTextInBrightColors]: { description: localize('terminal.integrated.drawBoldTextInBrightColors', "Controls whether bold text in the terminal will always use the "bright" ANSI color variant."),

<ins> /*--------------------------------------------------------------------------------------------- *  Copyright (c) Microsoft Corporation. All rights reserved. *  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { strictEqual } from 'assert'; import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { shouldPasteTerminalText } from 'vs/workbench/contrib/terminal/common/terminalClipboard'; suite('TerminalClipboard', function () { suite('shouldPasteTerminalText', () => { let instantiationService: TestInstantiationService; let configurationService: TestConfigurationService; let dialogService: TestDialogService; setup(async () => { instantiationService = new TestInstantiationService(); configurationService = new TestConfigurationService({ [TerminalSettingId.EnableMultiLinePasteWarning]: 'auto' }); dialogService = new TestDialogService({ confirmed: false }); instantiationService.stub(IConfigurationService, configurationService); instantiationService.stub(IDialogService, dialogService); }); ensureNoDisposablesAreLeakedInTestSuite(); function setConfigValue(value: unknown) { configurationService = new TestConfigurationService({ [TerminalSettingId.EnableMultiLinePasteWarning]: value }); instantiationService.stub(IConfigurationService, configurationService); } test('Single line string', async () => { strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foo', undefined), true); setConfigValue('always'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foo', undefined), true); setConfigValue('never'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foo', undefined), true); }); test('Single line string with trailing new line', async () => { strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foon', undefined), true); setConfigValue('always'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foon', undefined), false); setConfigValue('never'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foon', undefined), true); }); test('Multi-line string', async () => { strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', undefined), false); setConfigValue('always'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', undefined), false); setConfigValue('never'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', undefined), true); }); test('Bracketed paste mode', async () => { strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', true), true); setConfigValue('always'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', true), false); setConfigValue('never'); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', true), true); }); test('Legacy config', async () => { setConfigValue(true); // 'auto' strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', undefined), false); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', true), true); setConfigValue(false); // 'never' strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', true), true); }); test('Invalid config', async () => { setConfigValue(123); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', undefined), false); strictEqual(await instantiationService.invokeFunction(shouldPasteTerminalText, 'foonbar', true), true); }); }); }); </ins>