Skip to content

Commit b216b43

Browse files
authored
Shift+PageUp/Down to select NB output contents (#207962)
1 parent 8c7cf6a commit b216b43

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

src/vs/workbench/contrib/notebook/browser/contrib/navigation/arrow.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ registerAction2(class extends NotebookCellAction {
358358
NOTEBOOK_EDITOR_FOCUSED,
359359
ContextKeyExpr.has(InputFocusedContextKey),
360360
EditorContextKeys.editorTextFocus,
361+
NOTEBOOK_OUTPUT_FOCUSED.negate(), // Webview handles Shift+PageUp for selection of output contents
361362
),
362363
primary: KeyMod.Shift | KeyCode.PageUp,
363364
weight: NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT
@@ -406,6 +407,7 @@ registerAction2(class extends NotebookCellAction {
406407
NOTEBOOK_EDITOR_FOCUSED,
407408
ContextKeyExpr.has(InputFocusedContextKey),
408409
EditorContextKeys.editorTextFocus,
410+
NOTEBOOK_OUTPUT_FOCUSED.negate(), // Webview handles Shift+PageDown for selection of output contents
409411
),
410412
primary: KeyMod.Shift | KeyCode.PageDown,
411413
weight: NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT

src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,38 @@ async function webviewPreloads(ctx: PreloadContext) {
286286

287287
};
288288

289+
const onPageUpDownSelectionHandler = (e: KeyboardEvent) => {
290+
if (!lastFocusedOutput?.id || !e.shiftKey) {
291+
return;
292+
}
293+
// We want to handle just `Shift + PageUp/PageDown` & `Shift + Cmd + ArrowUp/ArrowDown` (for mac)
294+
if (!(e.code === 'PageUp' || e.code === 'PageDown') && !(e.metaKey && (e.code === 'ArrowDown' || e.code === 'ArrowUp'))) {
295+
return;
296+
}
297+
const outputContainer = window.document.getElementById(lastFocusedOutput.id);
298+
const selection = window.getSelection();
299+
if (!outputContainer || !selection?.anchorNode) {
300+
return;
301+
}
302+
303+
// These should change the scroll position, not adjust the selected cell in the notebook
304+
e.stopPropagation(); // We don't want the notebook to handle this.
305+
e.preventDefault(); // We will handle selection.
306+
307+
const { anchorNode, anchorOffset } = selection;
308+
const range = document.createRange();
309+
if (e.code === 'PageDown' || e.code === 'ArrowDown') {
310+
range.setStart(anchorNode, anchorOffset);
311+
range.setEnd(outputContainer, 1);
312+
}
313+
else {
314+
range.setStart(outputContainer, 0);
315+
range.setEnd(anchorNode, anchorOffset);
316+
}
317+
selection.removeAllRanges();
318+
selection.addRange(range);
319+
};
320+
289321
const handleDataUrl = async (data: string | ArrayBuffer | null, downloadName: string) => {
290322
postNotebookMessage<webviewMessages.IClickedDataUrlMessage>('clicked-data-url', {
291323
data,
@@ -310,6 +342,7 @@ async function webviewPreloads(ctx: PreloadContext) {
310342
window.document.body.addEventListener('click', handleInnerClick);
311343
window.document.body.addEventListener('focusin', checkOutputInputFocus);
312344
window.document.body.addEventListener('focusout', handleOutputFocusOut);
345+
window.document.body.addEventListener('keydown', onPageUpDownSelectionHandler);
313346

314347
interface RendererContext extends rendererApi.RendererContext<unknown> {
315348
readonly onDidChangeSettings: Event<RenderOptions>;

0 commit comments

Comments
 (0)