Skip to content

Commit

Permalink
Separate DocumentManager and CodeCellManager
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebutts committed Jul 16, 2024
1 parent 9560997 commit 720c125
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 263 deletions.
174 changes: 174 additions & 0 deletions extensions/positron-code-cells/src/codeCellManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*---------------------------------------------------------------------------------------------
* Copyright (C) 2023 Posit Software, PBC. All rights reserved.
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
*--------------------------------------------------------------------------------------------*/

import * as positron from 'positron';
import * as vscode from 'vscode';
import { type Cell, type CellParser, getParser } from './parser';
import { canHaveCells, getOrCreateDocumentManager } from './documentManager';

export interface ExecuteCode {
(language: string, code: string): Promise<void>;
}
const defaultExecuteCode: ExecuteCode = async (language, code) => {
await positron.runtime.executeCode(language, code, false, true);
};

// Handles execution of cells via editor
export class CodeCellManager {
private parser: CellParser | undefined;
constructor(
private editor: vscode.TextEditor,
private readonly executeCode: ExecuteCode = defaultExecuteCode,
) {
this.parser = getParser(this.editor.document.languageId);
}

private getCursor(line?: number): vscode.Position {
if (line !== undefined) {
return new vscode.Position(line, 0);
}
return this.editor.selection.active;
}

private getCells(): Cell[] | undefined {
return getOrCreateDocumentManager(this.editor.document)?.getCells();
}

private getCurrentCell(line?: number) {
const cursor = this.getCursor(line);
const cells = this.getCells();
if (!cells) { return; }

return cells.find(cell => {
return cell.range.contains(cursor);
});
}
private getNextCell(line?: number) {
const cursor = this.getCursor(line);
const cells = this.getCells();
if (!cells) { return; }

return cells.find(cell => {
return cell.range.end.isAfter(cursor) && !cell.range.contains(cursor);
});
}
private getPreviousCell(line?: number) {
const cursor = this.getCursor(line);
const cells = this.getCells();
if (!cells) { return; }

return cells.filter(cell => {
return cell.range.start.isBefore(cursor) && !cell.range.contains(cursor);
}).at(-1);
}

private goToCell(cell: Cell): void {
// Skip the cell marker line
const line = Math.min(cell.range.start.line + 1, cell.range.end.line);
const cursor = new vscode.Position(line, 0);
this.editor.selection = new vscode.Selection(cursor, cursor);
this.editor.revealRange(cell.range);
}

// Run cells
private runCell(cell: Cell): void {
if (!this.parser) { return; }
const text = this.parser.getCellText(cell, this.editor.document);
this.executeCode(this.editor.document.languageId, text);
}

// Public commands
public runCurrentCell(line?: number): void {
const cell = this.getCurrentCell(line);
if (cell) {
this.runCell(cell);
}
}

public runCurrentAdvance(line?: number): void {
this.runCurrentCell(line);
this.goToNextCell(line);
}

public runPreviousCell(line?: number): void {
const cell = this.getPreviousCell(line);
if (cell) {
this.runCell(cell);
this.goToCell(cell);
}
}

public runNextCell(line?: number): void {
const cell = this.getNextCell(line);
if (cell) {
this.runCell(cell);
this.goToCell(cell);
}
}

public runAllCells(): void {
const cells = this.getCells();
if (cells) {
cells.forEach((cell) => this.runCell(cell));
// for (let i = 0; i < cells.length; i++) {
// this.runCell(cells[i]);
// }
}
}

public runCellsAbove(line?: number): void {
const cursor = this.getCursor(line);
this.getCells()?.filter((cell) =>
cell.range.start.isBefore(cursor) && !cell.range.contains(cursor)
).forEach((cell) => this.runCell(cell));
}


public runCurrentAndBelow(line?: number): void {
const cursor = this.getCursor(line);
this.getCells()?.filter((cell) =>
cell.range.end.isAfter(cursor)
).forEach((cell) => this.runCell(cell));
}

public runCellsBelow(line?: number): void {
const cursor = this.getCursor(line);
this.getCells()?.filter((cell) =>
cell.range.end.isAfter(cursor) && !cell.range.contains(cursor)
).forEach((cell) => this.runCell(cell));
}

public goToPreviousCell(line?: number): void {
const cell = this.getPreviousCell(line);
if (cell) {
this.goToCell(cell);
}
}

public goToNextCell(line?: number): void {
const cell = this.getNextCell(line);
if (cell) {
this.goToCell(cell);
}
}

public async insertCodeCell(line?: number): Promise<void> {
const location = this.getCurrentCell(line)?.range.end ?? this.editor.selection.active;
await this.editor.edit(editBuilder => {
editBuilder.insert(location, this.parser?.newCell() ?? '');
});
this.goToNextCell(location.line);
}


}

export function getActiveCodeCellManager(): CodeCellManager | undefined {
const activeEditor = vscode.window?.activeTextEditor;
if (activeEditor && canHaveCells(activeEditor.document)) {
return new CodeCellManager(activeEditor);
}
return undefined;
}
8 changes: 4 additions & 4 deletions extensions/positron-code-cells/src/codeLenses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { canHaveCells, getEditorFromDocument, getOrCreateDocumentManager } from './documentManager';
import { getOrCreateDocumentManager } from './documentManager';

export function runCellCodeLens(range: vscode.Range): vscode.CodeLens {
return new vscode.CodeLens(range, {
Expand Down Expand Up @@ -32,12 +32,12 @@ export function runNextCodeLens(range: vscode.Range): vscode.CodeLens {

export class CellCodeLensProvider implements vscode.CodeLensProvider {
provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult<vscode.CodeLens[]> {
const editor = getEditorFromDocument(document);
if (!canHaveCells(document) || !editor) {
const docManager = getOrCreateDocumentManager(document);
if (!docManager) {
return [];
}

const cells = getOrCreateDocumentManager(editor).getCells();
const cells = docManager.getCells();
const codeLenses: vscode.CodeLens[] = [];
for (let i = 0; i < cells.length; i += 1) {
const cell = cells[i];
Expand Down
24 changes: 12 additions & 12 deletions extensions/positron-code-cells/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,55 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { getActiveDocumentManager } from './documentManager';
import { getActiveCodeCellManager } from './codeCellManager';

export function registerCommands(disposables: vscode.Disposable[]) {
disposables.push(
// Movement
vscode.commands.registerCommand('positron.goToPreviousCell', (line?: number) => {
getActiveDocumentManager()?.goToPreviousCell(line);
getActiveCodeCellManager()?.goToPreviousCell(line);
}),

vscode.commands.registerCommand('positron.goToNextCell', (line?: number) => {
getActiveDocumentManager()?.goToNextCell(line);
getActiveCodeCellManager()?.goToNextCell(line);
}),

// Insert cell
vscode.commands.registerCommand('positron.insertCodeCell', async (line?: number) => {
await getActiveDocumentManager()?.insertCodeCell(line);
await getActiveCodeCellManager()?.insertCodeCell(line);
}),

// Run cells
vscode.commands.registerCommand('positron.runAllCells', () => {
getActiveDocumentManager()?.runAllCells();
getActiveCodeCellManager()?.runAllCells();
}),

vscode.commands.registerCommand('positron.runCellsAbove', (line?: number) => {
getActiveDocumentManager()?.runCellsAbove(line);
getActiveCodeCellManager()?.runCellsAbove(line);
}),

vscode.commands.registerCommand('positron.runCurrentAndBelow', (line?: number) => {
getActiveDocumentManager()?.runCurrentAndBelow(line);
getActiveCodeCellManager()?.runCurrentAndBelow(line);
}),

vscode.commands.registerCommand('positron.runCellsBelow', (line?: number) => {
getActiveDocumentManager()?.runCellsBelow(line);
getActiveCodeCellManager()?.runCellsBelow(line);
}),

vscode.commands.registerCommand('positron.runCurrentAdvance', (line?: number) => {
getActiveDocumentManager()?.runCurrentAdvance(line);
getActiveCodeCellManager()?.runCurrentAdvance(line);
}),

vscode.commands.registerCommand('positron.runCurrentCell', (line?: number) => {
getActiveDocumentManager()?.runCurrentCell(line);
getActiveCodeCellManager()?.runCurrentCell(line);
}),

vscode.commands.registerCommand('positron.runNextCell', (line?: number) => {
getActiveDocumentManager()?.runNextCell(line);
getActiveCodeCellManager()?.runNextCell(line);
}),

vscode.commands.registerCommand('positron.runPreviousCell', (line?: number) => {
getActiveDocumentManager()?.runPreviousCell(line);
getActiveCodeCellManager()?.runPreviousCell(line);
}),

);
Expand Down
3 changes: 2 additions & 1 deletion extensions/positron-code-cells/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ function setSupportsCodeCellsContext(editor: vscode.TextEditor | undefined): voi
}

function setHasCodeCellsContext(editor: vscode.TextEditor | undefined): void {
const value = editor && canHaveCells(editor.document) && getOrCreateDocumentManager(editor).getCells().length > 0;
const docManager = editor && getOrCreateDocumentManager(editor.document);
const value = (docManager && docManager.getCells().length > 0) ?? false;
contexts.set(ContextKey.HasCodeCells, value);
vscode.commands.executeCommand(
'setContext',
Expand Down
9 changes: 4 additions & 5 deletions extensions/positron-code-cells/src/decorations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { canHaveCells, getOrCreateDocumentManager } from './documentManager';
import { getOrCreateDocumentManager } from './documentManager';

export interface SetDecorations {
(
Expand Down Expand Up @@ -37,16 +37,15 @@ export function activateDecorations(

// Update the active editor's cell decorations.
function updateDecorations() {
if (!activeEditor || !canHaveCells(activeEditor.document)) {
const docManager = activeEditor && getOrCreateDocumentManager(activeEditor.document);
if (!activeEditor || !docManager) {
return;
}
const cells = getOrCreateDocumentManager(activeEditor).getCells();

// Get the relevant decoration ranges.
const cells = docManager.getCells();
const activeCellRanges: vscode.Range[] = [];
const allCellRanges: vscode.Range[] = [];
for (const cell of cells) {
allCellRanges.push(cell.range);
if (cell.range.contains(activeEditor.selection.active)) {
activeCellRanges.push(cell.range);
}
Expand Down
Loading

0 comments on commit 720c125

Please sign in to comment.