diff --git a/news/1 Enhancements/10198.md b/news/1 Enhancements/10198.md new file mode 100644 index 000000000000..eed15c9b96ed --- /dev/null +++ b/news/1 Enhancements/10198.md @@ -0,0 +1 @@ +Support using 'esc' or 'ctrl+u' to clear the contents of the interactive window input box. \ No newline at end of file diff --git a/src/datascience-ui/history-react/interactiveCell.tsx b/src/datascience-ui/history-react/interactiveCell.tsx index c9b94a6e4b0f..75fd1065c6f9 100644 --- a/src/datascience-ui/history-react/interactiveCell.tsx +++ b/src/datascience-ui/history-react/interactiveCell.tsx @@ -349,12 +349,20 @@ export class InteractiveCell extends React.Component { }; private onEditCellKeyDown = (_cellId: string, e: IKeyboardEvent) => { - if (e.code === 'Escape') { - this.editCellEscape(e); + if (e.code === 'Tab' && e.shiftKey) { + this.editCellShiftTab(e); } else if (e.code === 'Enter' && e.shiftKey) { this.editCellSubmit(e); } else if (e.code === 'NumpadEnter' && e.shiftKey) { this.editCellSubmit(e); + } else if (e.code === 'KeyU' && e.ctrlKey && e.editorInfo && !e.editorInfo.isSuggesting) { + e.editorInfo.clear(); + e.stopPropagation(); + e.preventDefault(); + } else if (e.code === 'Escape' && e.editorInfo && !e.editorInfo.isSuggesting) { + e.editorInfo.clear(); + e.stopPropagation(); + e.preventDefault(); } }; @@ -395,11 +403,13 @@ export class InteractiveCell extends React.Component { } } - private editCellEscape = (e: IKeyboardEvent) => { + private editCellShiftTab = (e: IKeyboardEvent) => { const focusedElement = document.activeElement; if (focusedElement !== null && e.editorInfo && !e.editorInfo.isSuggesting) { const nextTabStop = this.findTabStop(1, focusedElement); if (nextTabStop) { + e.stopPropagation(); + e.preventDefault(); nextTabStop.focus(); } } diff --git a/src/test/datascience/interactiveWindow.functional.test.tsx b/src/test/datascience/interactiveWindow.functional.test.tsx index 611978139272..85a1754cce5a 100644 --- a/src/test/datascience/interactiveWindow.functional.test.tsx +++ b/src/test/datascience/interactiveWindow.functional.test.tsx @@ -9,6 +9,7 @@ import * as path from 'path'; import * as TypeMoq from 'typemoq'; import { Disposable, Selection, TextDocument, TextEditor, Uri } from 'vscode'; +import { ReactWrapper } from 'enzyme'; import { IApplicationShell, IDocumentManager } from '../../client/common/application/types'; import { IDataScienceSettings } from '../../client/common/types'; import { createDeferred, waitForPromise } from '../../client/common/utils/async'; @@ -19,7 +20,9 @@ import { InteractiveWindowMessages } from '../../client/datascience/interactive- import { InteractiveWindow } from '../../client/datascience/interactive-window/interactiveWindow'; import { concatMultilineStringInput } from '../../datascience-ui/common'; import { InteractivePanel } from '../../datascience-ui/history-react/interactivePanel'; +import { IKeyboardEvent } from '../../datascience-ui/react-common/event'; import { ImageButton } from '../../datascience-ui/react-common/imageButton'; +import { MonacoEditor } from '../../datascience-ui/react-common/monacoEditor'; import { DataScienceIocContainer } from './dataScienceIocContainer'; import { createDocument } from './editor-integration/helpers'; import { defaultDataScienceSettings } from './helpers'; @@ -38,6 +41,7 @@ import { addMockData, CellInputState, CellPosition, + enterEditorKey, enterInput, escapePath, findButton, @@ -87,6 +91,13 @@ suite('DataScience Interactive Window output tests', () => { return update; } + function simulateKeyPressOnEditor( + editorControl: ReactWrapper, React.Component> | undefined, + keyboardEvent: Partial & { code: string } + ) { + enterEditorKey(editorControl, keyboardEvent); + } + // Uncomment this to debug hangs on exit // suiteTeardown(() => { // asyncDump(); @@ -217,6 +228,36 @@ for i in range(10): } ); + runMountedTest( + 'Escape/Ctrl+U', + async wrapper => { + // Create an interactive window so that it listens to the results. + const interactiveWindow = await getOrCreateInteractiveWindow(ioc); + await interactiveWindow.show(); + + // Type in the input box + const editor = getInteractiveEditor(wrapper); + typeCode(editor, 'a=1\na'); + + // Check code is what we think it is + const reactEditor = editor.instance() as MonacoEditor; + assert.equal(reactEditor.state.model?.getValue().replace(/\r/g, ''), 'a=1\na'); + + // Send escape + simulateKeyPressOnEditor(editor, { code: 'Escape' }); + assert.equal(reactEditor.state.model?.getValue().replace(/\r/g, ''), ''); + + typeCode(editor, 'a=1\na'); + assert.equal(reactEditor.state.model?.getValue().replace(/\r/g, ''), 'a=1\na'); + + simulateKeyPressOnEditor(editor, { code: 'KeyU', ctrlKey: true }); + assert.equal(reactEditor.state.model?.getValue().replace(/\r/g, ''), ''); + }, + () => { + return ioc; + } + ); + runMountedTest( 'Click outside cells sets focus to input box', async wrapper => {