Skip to content

Commit f7ad067

Browse files
author
David Kutugata
authored
Davidkutu/ds interactive window focus fix (#9895)
* Fixed the focus on the interactive window when pressing ctrl +2 * the new prop 'focusPending' needs to change in order to give focus * added functional test * In test: force focus to buttons to take it away from * finished the functional test * updated changelog * deleted bug#.md
1 parent a08b501 commit f7ad067

File tree

10 files changed

+75
-13
lines changed

10 files changed

+75
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747

4848
### Fixes
4949

50+
1. Fixed the focus on the interactive window when pressing ctrl + 1/ ctrl + 2
51+
([#9693](https://github.com/microsoft/vscode-python/issues/9693))
5052
1. Fix variable explorer in Interactive and Notebook editors from interfering with execution.
5153
([#5980](https://github.com/Microsoft/vscode-python/issues/5980))
5254
1. Fix a crash when using pytest to discover doctests with unknown line number.

src/datascience-ui/history-react/interactiveCell.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ interface IInteractiveCellBaseProps {
4040
editorMeasureClassName?: string;
4141
font: IFont;
4242
settings: IDataScienceExtraSettings;
43+
focusPending: number;
4344
}
4445

4546
type IInteractiveCellProps = IInteractiveCellBaseProps & typeof actionCreators;
@@ -266,6 +267,7 @@ export class InteractiveCell extends React.Component<IInteractiveCellProps> {
266267
keyDown={this.isEditCell() ? this.onEditCellKeyDown : undefined}
267268
showLineNumbers={this.props.cellVM.showLineNumbers}
268269
font={this.props.font}
270+
focusPending={this.props.focusPending}
269271
/>
270272
);
271273
}

src/datascience-ui/history-react/interactivePanel.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export class InteractivePanel extends React.Component<IInteractivePanelProps> {
216216
monacoTheme={this.props.monacoTheme}
217217
font={this.props.font}
218218
settings={this.props.settings}
219+
focusPending={this.props.activateCount}
219220
/>
220221
</ErrorBoundary>
221222
</div>
@@ -279,6 +280,7 @@ export class InteractivePanel extends React.Component<IInteractivePanelProps> {
279280
monacoTheme={this.props.monacoTheme}
280281
font={this.props.font}
281282
settings={this.props.settings}
283+
focusPending={this.props.activateCount}
282284
/>
283285
</ErrorBoundary>
284286
</div>

src/datascience-ui/interactive-common/cellInput.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ interface ICellInputProps {
2626
editorMeasureClassName?: string;
2727
showLineNumbers?: boolean;
2828
font: IFont;
29+
focusPending: number;
2930
onCodeChange(changes: monacoEditor.editor.IModelContentChange[], cellId: string, modelId: string): void;
3031
onCodeCreated(code: string, file: string, cellId: string, modelId: string): void;
3132
openLink(uri: monacoEditor.Uri): void;
@@ -110,6 +111,7 @@ export class CellInput extends React.Component<ICellInputProps> {
110111
showLineNumbers={this.props.showLineNumbers}
111112
useQuickEdit={this.props.cellVM.useQuickEdit}
112113
font={this.props.font}
114+
focusPending={this.props.focusPending}
113115
/>
114116
</div>
115117
);

src/datascience-ui/interactive-common/code.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface ICodeProps {
2626
font: IFont;
2727
hasFocus: boolean;
2828
cursorPos: CursorPos;
29+
focusPending: number;
2930
onCreated(code: string, modelId: string): void;
3031
onChange(changes: monacoEditor.editor.IModelContentChange[], modelId: string): void;
3132
openLink(uri: monacoEditor.Uri): void;
@@ -46,6 +47,12 @@ export class Code extends React.Component<ICodeProps, ICodeState> {
4647
this.state = { allowWatermark: true };
4748
}
4849

50+
public componentDidUpdate(prevProps: ICodeProps) {
51+
if (prevProps.focusPending !== this.props.focusPending) {
52+
this.giveFocus(CursorPos.Current);
53+
}
54+
}
55+
4956
public render() {
5057
const readOnly = this.props.readOnly;
5158
const waterMarkClass = this.props.showWatermark && this.state.allowWatermark && !readOnly ? 'code-watermark' : 'hide';

src/datascience-ui/native-editor/nativeCell.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ interface INativeCellBaseProps {
4242
enableGather: boolean | undefined;
4343
editorOptions: monacoEditor.editor.IEditorOptions;
4444
themeMatplotlibPlots: boolean | undefined;
45+
focusPending: number;
4546
}
4647

4748
type INativeCellProps = INativeCellBaseProps & typeof actionCreators;
@@ -597,6 +598,7 @@ export class NativeCell extends React.Component<INativeCellProps> {
597598
keyDown={this.keyDownInput}
598599
showLineNumbers={this.props.cellVM.showLineNumbers}
599600
font={this.props.font}
601+
focusPending={this.props.focusPending}
600602
/>
601603
</div>
602604
);

src/datascience-ui/native-editor/nativeEditor.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ export class NativeEditor extends React.Component<INativeEditorProps> {
396396
editorOptions={this.props.editorOptions}
397397
enableGather={this.props.settings.enableGather}
398398
themeMatplotlibPlots={this.props.settings.themeMatplotlibPlots}
399+
focusPending={this.props.activateCount}
399400
/>
400401
</ErrorBoundary>
401402
{lastLine}

src/test/datascience/dataScienceIocContainer.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -898,17 +898,7 @@ export class DataScienceIocContainer extends UnitTestIocContainer {
898898
}
899899
}
900900

901-
private findPythonPath(): string {
902-
try {
903-
// Give preference to the CI test python (could also be set in launch.json for debugging).
904-
const output = child_process.execFileSync(process.env.CI_PYTHON_PATH || 'python', ['-c', 'import sys;print(sys.executable)'], { encoding: 'utf8' });
905-
return output.replace(/\r?\n/g, '');
906-
} catch (ex) {
907-
return 'python';
908-
}
909-
}
910-
911-
private postMessageToWebPanel(msg: any) {
901+
public postMessageToWebPanel(msg: any) {
912902
if (this.webPanelListener) {
913903
this.webPanelListener.onMessage(msg.type, msg.payload);
914904
} else {
@@ -923,6 +913,16 @@ export class DataScienceIocContainer extends UnitTestIocContainer {
923913
}
924914
}
925915

916+
private findPythonPath(): string {
917+
try {
918+
// Give preference to the CI test python (could also be set in launch.json for debugging).
919+
const output = child_process.execFileSync(process.env.CI_PYTHON_PATH || 'python', ['-c', 'import sys;print(sys.executable)'], { encoding: 'utf8' });
920+
return output.replace(/\r?\n/g, '');
921+
} catch (ex) {
922+
return 'python';
923+
}
924+
}
925+
926926
private mountReactControl(mount: () => ReactWrapper<any, Readonly<{}>, React.Component>) {
927927
// This is a remount (or first time). Clear out messages that were sent
928928
// by the last mount

src/test/datascience/interactiveWindow.functional.test.tsx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { defaultDataScienceSettings } from './helpers';
2626
import { addCode, getInteractiveCellResults, getOrCreateInteractiveWindow, runMountedTest } from './interactiveWindowTestHelpers';
2727
import { MockDocumentManager } from './mockDocumentManager';
2828
import { MockEditor } from './mockTextEditor';
29-
import { waitForUpdate } from './reactHelpers';
29+
import { createMessageEvent, waitForUpdate } from './reactHelpers';
3030
import {
3131
addContinuousMockData,
3232
addInputMockData,
@@ -36,9 +36,12 @@ import {
3636
enterInput,
3737
escapePath,
3838
findButton,
39+
getInteractiveEditor,
3940
getLastOutputCell,
4041
srcDirectory,
42+
submitInput,
4143
toggleCellExpansion,
44+
typeCode,
4245
verifyHtmlOnCell,
4346
verifyLastCellInputState,
4447
waitForMessage,
@@ -143,6 +146,47 @@ suite('DataScience Interactive Window output tests', () => {
143146
}
144147
);
145148

149+
runMountedTest(
150+
'Ctrl + 1/Ctrl + 2',
151+
async wrapper => {
152+
// Create an interactive window so that it listens to the results.
153+
const interactiveWindow = await getOrCreateInteractiveWindow(ioc);
154+
await interactiveWindow.show();
155+
156+
// Type in the input box
157+
const editor = getInteractiveEditor(wrapper);
158+
typeCode(editor, 'a=1\na');
159+
160+
// Give focus to a random div
161+
const reactDiv = wrapper
162+
.find('div')
163+
.first()
164+
.getDOMNode();
165+
166+
const domDiv = reactDiv.querySelector('div');
167+
168+
if (domDiv && ioc.postMessage) {
169+
domDiv.tabIndex = -1;
170+
domDiv.focus();
171+
172+
// send the ctrl + 1/2 message, this should put focus back on the input box
173+
const message = createMessageEvent({ type: InteractiveWindowMessages.Activate, payload: undefined });
174+
ioc.postMessage(message);
175+
176+
// Then enter press shift + enter on the active element
177+
const activeElement = document.activeElement;
178+
if (activeElement) {
179+
await submitInput(ioc, activeElement as HTMLTextAreaElement);
180+
}
181+
}
182+
183+
verifyHtmlOnCell(wrapper, 'InteractiveCell', '<span>1</span>', CellPosition.Last);
184+
},
185+
() => {
186+
return ioc;
187+
}
188+
);
189+
146190
runMountedTest(
147191
'Collapse / expand cell',
148192
async wrapper => {

src/test/datascience/testHelpers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ export function simulateKey(domNode: HTMLTextAreaElement, key: string, shiftDown
471471
}
472472
}
473473

474-
async function submitInput(ioc: DataScienceIocContainer, textArea: HTMLTextAreaElement): Promise<void> {
474+
export async function submitInput(ioc: DataScienceIocContainer, textArea: HTMLTextAreaElement): Promise<void> {
475475
// Get a render promise with the expected number of renders (how many updates a the shift + enter will cause)
476476
// Should be 6 - 1 for the shift+enter and 5 for the new cell.
477477
const renderPromise = waitForMessage(ioc, InteractiveWindowMessages.ExecutionRendered);

0 commit comments

Comments
 (0)