Repository navigation
Support scrolling in vscode notebooks #3380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,22 @@ | ||
| import vscode from "vscode"; | ||
| import { RevealLineAt } from "@cursorless/lib-common"; | ||
| import { | ||
| getCellIndex, | ||
| getNotebookFromCellEditor, | ||
| isDocumentNotebookCell, | ||
| } from "@cursorless/lib-vscode-common"; | ||
| import type { VscodeTextEditor } from "./VscodeTextEditor"; | ||
|
|
||
| export async function vscodeRevealLine( | ||
| editor: VscodeTextEditor, | ||
| lineNumber: number, | ||
| at: RevealLineAt, | ||
| ): Promise<void> { | ||
| if (isDocumentNotebookCell(editor.vscodeEditor.document)) { | ||
| revealNotebookCell(editor, at); | ||
| return; | ||
| } | ||
|
|
||
| // For reveal line to the work we have to have the correct editor focused | ||
| if (!editor.isActive) { | ||
| await editor.focus(); | ||
|
|
@@ -17,3 +27,36 @@ export async function vscodeRevealLine( | |
| at, | ||
| }); | ||
| } | ||
|
|
||
| function revealNotebookCell(editor: VscodeTextEditor, at: RevealLineAt) { | ||
| const notebookEditor = getNotebookFromCellEditor(editor.vscodeEditor); | ||
|
|
||
| const cellIndex = getCellIndex( | ||
| notebookEditor.notebook, | ||
| editor.vscodeEditor.document, | ||
| ); | ||
|
|
||
| notebookEditor.revealRange( | ||
| new vscode.NotebookRange(cellIndex, cellIndex), | ||
| getNotebookRevealType(at), | ||
| ); | ||
| } | ||
|
|
||
| function getNotebookRevealType( | ||
| at: RevealLineAt, | ||
| ): vscode.NotebookEditorRevealType { | ||
| switch (at) { | ||
| case RevealLineAt.top: | ||
| return vscode.NotebookEditorRevealType.AtTop; | ||
| case RevealLineAt.center: | ||
| return vscode.NotebookEditorRevealType.InCenter; | ||
| case RevealLineAt.bottom: | ||
| throw new Error( | ||
| "VS Code's notebook API doesn't support bottom alignment.", | ||
| ); | ||
|
Comment on lines
+53
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Whenever AGENTS.md reference: AGENTS.md:L32-L32 Useful? React with 👍 / 👎.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no way to make a fall back for this as far as I know |
||
| default: { | ||
| const _exhaustiveCheck: never = at; | ||
| throw new Error(`Unhandled case: ${_exhaustiveCheck}`); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import assert from "node:assert/strict"; | ||
| import { createSandbox } from "sinon"; | ||
| import type { NotebookEditor, TextDocument, TextEditor } from "vscode"; | ||
| import { Uri, ViewColumn, window } from "vscode"; | ||
| import { getNotebookFromCellEditor } from "@cursorless/lib-vscode-common"; | ||
|
|
||
| suite("Notebook editor lookup", () => { | ||
| const sandbox = createSandbox(); | ||
| const document = { | ||
| uri: Uri.parse("vscode-notebook-cell:/test.ipynb#cell1"), | ||
| } as TextDocument; | ||
| let first: NotebookEditor; | ||
| let second: NotebookEditor; | ||
| let cellEditor: TextEditor; | ||
| let visibleNotebookEditors: NotebookEditor[]; | ||
| let activeTextEditor: TextEditor | undefined; | ||
| let activeNotebookEditor: NotebookEditor | undefined; | ||
|
|
||
| setup(() => { | ||
| first = createNotebookEditor(ViewColumn.One); | ||
| second = createNotebookEditor(ViewColumn.Two); | ||
| cellEditor = { document } as TextEditor; | ||
| visibleNotebookEditors = [first, second]; | ||
| activeTextEditor = undefined; | ||
| activeNotebookEditor = undefined; | ||
| sandbox | ||
| .stub(window, "visibleNotebookEditors") | ||
| .get(() => visibleNotebookEditors); | ||
| sandbox.stub(window, "activeTextEditor").get(() => activeTextEditor); | ||
| sandbox | ||
| .stub(window, "activeNotebookEditor") | ||
| .get(() => activeNotebookEditor); | ||
| }); | ||
|
|
||
| teardown(() => sandbox.restore()); | ||
|
|
||
| test("resolves a notebook visible in only one group", () => { | ||
| visibleNotebookEditors = [second]; | ||
|
|
||
| assert.equal(getNotebookFromCellEditor(cellEditor), second); | ||
| }); | ||
|
|
||
| test("uses the target editor's group rather than the active notebook", () => { | ||
| cellEditor = { document, viewColumn: ViewColumn.Two } as TextEditor; | ||
| activeNotebookEditor = first; | ||
|
|
||
| assert.equal(getNotebookFromCellEditor(cellEditor), second); | ||
| }); | ||
|
|
||
| test("resolves the active cell editor in the second split", () => { | ||
| activeTextEditor = cellEditor; | ||
| activeNotebookEditor = second; | ||
|
|
||
| assert.equal(getNotebookFromCellEditor(cellEditor), second); | ||
| }); | ||
|
|
||
| test("rejects an inactive target even when its document is active", () => { | ||
| activeTextEditor = { document } as TextEditor; | ||
| activeNotebookEditor = second; | ||
|
|
||
| assert.throws( | ||
| () => getNotebookFromCellEditor(cellEditor), | ||
| /split notebook is unsupported/u, | ||
| ); | ||
| }); | ||
|
|
||
| test("rejects an active notebook that doesn't contain the target", () => { | ||
| activeTextEditor = cellEditor; | ||
| activeNotebookEditor = createNotebookEditor(ViewColumn.Three, { | ||
| uri: Uri.parse("vscode-notebook-cell:/other.ipynb#cell1"), | ||
| } as TextDocument); | ||
|
|
||
| assert.throws( | ||
| () => getNotebookFromCellEditor(cellEditor), | ||
| /split notebook is unsupported/u, | ||
| ); | ||
| }); | ||
|
|
||
| test("reports when the notebook is no longer visible", () => { | ||
| visibleNotebookEditors = []; | ||
|
|
||
| assert.throws( | ||
| () => getNotebookFromCellEditor(cellEditor), | ||
| /Couldn't find notebook editor/u, | ||
| ); | ||
| }); | ||
|
|
||
| function createNotebookEditor( | ||
| viewColumn: ViewColumn, | ||
| cellDocument = document, | ||
| ): NotebookEditor { | ||
| return { | ||
| notebook: { getCells: () => [{ document: cellDocument }] }, | ||
| viewColumn, | ||
| } as NotebookEditor; | ||
| } | ||
| }); |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the target is inside a notebook cell taller than the viewport, this branch discards
lineNumberand aligns the entire cell instead. SinceScroll.getLineNumbercomputes the specific line occupied by the target, crown/center on a token near the bottom of a long cell can leave that token off-screen or at the wrong position; pass the line through and reveal the position within the cell rather than only the cell range.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not supported by the vscode notebook api as far as I can tell