Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
534de31
Init new ManimShell wrapper
Splines Oct 25, 2024
7c86072
Include ManimShell as additional layer in other commands
Splines Oct 25, 2024
7436cb0
Wait until command in IPython Terminal is finished
Splines Oct 25, 2024
34046ab
Detect shell exit
Splines Oct 25, 2024
6411241
Open terminal upon error
Splines Oct 25, 2024
5511f5d
Improve docstrings & implement executeCommandEnsureActiveSession
Splines Oct 25, 2024
1a06808
Add docstrings for `exec` method
Splines Oct 25, 2024
1ed9546
Add docstrings to `retrieveOrInitActiveShell`
Splines Oct 25, 2024
70aabd5
Add docstrings for `initiateTerminalDataReading`
Splines Oct 25, 2024
ab096bd
Add docstrings for ANSI filtering
Splines Oct 25, 2024
8f8d254
Add docstrings to regular expressions
Splines Oct 25, 2024
d426004
Remove log line
Splines Oct 25, 2024
576d1a4
Fix wrong variable usage
Splines Oct 25, 2024
d1f30d8
Simplify overly complicated Promises/callbacks
Splines Oct 25, 2024
50181e9
Explain only divergence of notation
Splines Oct 25, 2024
75c519f
Don't carry optional parameter startLine around
Splines Oct 25, 2024
7c083c4
Simplify execute command waiting
Splines Oct 25, 2024
d75681a
Move resetActiveShell method down
Splines Oct 25, 2024
6c15e6e
Extract method hasActiveShell()
Splines Oct 25, 2024
e5d1576
Exit scene if start scene is invoked while scene is running
Splines Oct 25, 2024
6edb693
Make method private
Splines Oct 25, 2024
947dc7a
Import Terminal directly
Splines Oct 25, 2024
93f7560
Clarify what ManimShell is
Splines Oct 25, 2024
cc81d62
Add docstring for detectShellExecutionEnd
Splines Oct 25, 2024
5321eaa
Fix typos in docstrings
Splines Oct 25, 2024
d035d69
Lock new command execution during startup
Splines Oct 25, 2024
a5f86e9
Don't be stingy with empty lines
Splines Oct 25, 2024
835e8b6
Avoid orphan VSCode terminals upon scene start
Splines Oct 25, 2024
896cc5e
Merge branch 'main' into feature/manim-shell
Splines Oct 25, 2024
f6045be
Remove unnecessary statements
Splines Oct 25, 2024
bd40282
Listen to terminal data right from the beginning
Splines Oct 25, 2024
4d41027
Fix clipboard buffering
Splines Oct 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions src/executeTerminalCommand.ts

This file was deleted.

154 changes: 35 additions & 119 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import * as vscode from 'vscode';
import { window } from 'vscode';
import { ManimShell } from './manimShell';
import { ManimCell } from './manimCell';
import { ManimCellRanges } from './manimCellRanges';
import { previewCode } from './previewCode';
import { executeTerminalCommand } from './executeTerminalCommand';
import { startScene, exitScene } from './startStopScene';

export function activate(context: vscode.ExtensionContext) {

// Trigger the Manim shell to start listening to the terminal
ManimShell.instance;

const previewManimCellCommand = vscode.commands.registerCommand(
'manim-notebook.previewManimCell', (cellCode: string | undefined) => {
previewManimCell(cellCode);
'manim-notebook.previewManimCell', (cellCode?: string, startLine?: number) => {
previewManimCell(cellCode, startLine);
});

const previewSelectionCommand = vscode.commands.registerCommand(
Expand Down Expand Up @@ -52,12 +57,14 @@ export function deactivate() { }
* (when accessed via the command pallette) or the code of the cell where
* the codelens was clicked.
*/
function previewManimCell(cellCode: string | undefined) {
function previewManimCell(cellCode?: string, startLine?: number) {
let startLineFinal: number | undefined = startLine;

// User has executed the command via command pallette
if (cellCode === undefined) {
const editor = vscode.window.activeTextEditor;
const editor = window.activeTextEditor;
if (!editor) {
vscode.window.showErrorMessage(
window.showErrorMessage(
'No opened file found. Place your cursor in a Manim cell.');
return;
}
Expand All @@ -67,22 +74,28 @@ function previewManimCell(cellCode: string | undefined) {
const cursorLine = editor.selection.active.line;
const range = ManimCellRanges.getCellRangeAtLine(document, cursorLine);
if (!range) {
vscode.window.showErrorMessage('Place your cursor in a Manim cell.');
window.showErrorMessage('Place your cursor in a Manim cell.');
return;
}
cellCode = document.getText(range);
startLineFinal = range.start.line;
}

if (startLineFinal === undefined) {
window.showErrorMessage('Internal error: Line number not found in `previewManimCell()`.');
return;
}

previewCode(cellCode);
previewCode(cellCode, startLineFinal);
}

/**
* Previews the Manim code of the selected text.
*/
function previewSelection() {
const editor = vscode.window.activeTextEditor;
const editor = window.activeTextEditor;
if (!editor) {
vscode.window.showErrorMessage('Select some code to preview.');
window.showErrorMessage('Select some code to preview.');
return;
}

Expand All @@ -102,119 +115,22 @@ function previewSelection() {
}

if (!selectedText) {
vscode.window.showErrorMessage('Select some code to preview.');
window.showErrorMessage('Select some code to preview.');
return;
}

previewCode(selectedText);
}

/**
* Runs the `manimgl` command in the terminal, with the current cursor's line number:
* manimgl <file_name> <ClassName> [-se <lineNumber>]
*
* - Saves the active file.
* - Previews the scene at the cursor's line (end of line)
* - If the cursor is on a class definition line, then `-se <lineNumber>`
* is NOT added, i.e. the whole scene is previewed.
* - (3b1b's version also copies this command to the clipboard with additional
* args `--prerun --finder -w`. We don't do that here.)
*/
async function startScene() {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showErrorMessage(
'No opened file found. Please place your cursor at a line of code.'
);
return;
}

// Save active file
vscode.commands.executeCommand('workbench.action.files.save');

const languageId = editor.document.languageId;
if (languageId !== 'python') {
vscode.window.showErrorMessage("You don't have a Python file open.");
return;
}

const lines = editor.document.getText().split("\n");

// Find which lines define classes
// E.g. here, classLines = [{ line: "class FirstScene(Scene):", index: 3 }, ...]
const classLines = lines
.map((line, index) => ({ line, index }))
.filter(({ line }) => /^class (.+?)\((.+?)\):/.test(line));

const cursorLine = editor.selection.start.line;

// Find the first class defined before where the cursor is
// E.g. here, matchingClass = { line: "class SelectedScene(Scene):", index: 42 }
const matchingClass = classLines
.reverse()
.find(({ index }) => index <= cursorLine);
if (!matchingClass) {
vscode.window.showErrorMessage('Place your cursor in Manim code inside a class.');
return;
}
// E.g. here, sceneName = "SelectedScene"
const sceneName = matchingClass.line.slice("class ".length, matchingClass.line.indexOf("("));

// While line is empty - make it the previous line
// (because `manimgl -se <lineNumber>` doesn't work on empty lines)
let lineNumber = cursorLine;
while (lines[lineNumber].trim() === "") {
lineNumber--;
}

// Create the command
const filePath = editor.document.fileName; // absolute path
const cmds = ["manimgl", filePath, sceneName];
let enter = false;
if (cursorLine !== matchingClass.index) {
cmds.push(`-se ${lineNumber + 1}`);
enter = true;
}
const command = cmds.join(" ");

// // Commented out - in case someone would like it.
// // For us - we want to NOT overwrite our clipboard.
// // If one wants to run it in a different terminal,
// // it's often to write to a file
// await vscode.env.clipboard.writeText(command + " --prerun --finder -w");

// Run the command
executeTerminalCommand(command);

// // Commented out - in case someone would like it.
// // For us - it would require MacOS. Also - the effect is not desired.
// // Focus some windows (ONLY for MacOS because it uses `osascript`!)
// const terminal = vscode.window.activeTerminal || vscode.window.createTerminal();
// if (enter) {
// // Keep cursor where it started (in VSCode)
// const cmd_focus_vscode = 'osascript -e "tell application \\"Visual Studio Code\\" to activate"';
// // Execute the command in the shell after a delay (to give the animation window enough time to open)
// await new Promise(resolve => setTimeout(resolve, 2500));
// require('child_process').exec(cmd_focus_vscode);
// } else {
// terminal.show();
// }
}

/**
* Runs the `exit()` command in the terminal to close the animation window
* and the IPython terminal.
*/
function exitScene() {
executeTerminalCommand("exit()");
previewCode(selectedText, selection.start.line);
}

/**
* Runs the `clear()` command in the terminal to remove all objects from
* the scene.
*/
function clearScene() {
executeTerminalCommand("clear()");
async function clearScene() {
const success = await ManimShell.instance.executeCommandEnsureActiveSession("clear()");
if (!success) {
window.showErrorMessage('No active ManimGL scene found to remove objects from.');
}
}

/**
Expand All @@ -229,24 +145,24 @@ function registerManimCellProviders(context: vscode.ExtensionContext) {
{ language: 'python' }, manimCell);
context.subscriptions.push(codeLensProvider, foldingRangeProvider);

vscode.window.onDidChangeActiveTextEditor(editor => {
window.onDidChangeActiveTextEditor(editor => {
if (editor) {
manimCell.applyCellDecorations(editor);
}
}, null, context.subscriptions);

vscode.workspace.onDidChangeTextDocument(event => {
const editor = vscode.window.activeTextEditor;
const editor = window.activeTextEditor;
if (editor && event.document === editor.document) {
manimCell.applyCellDecorations(editor);
}
}, null, context.subscriptions);

vscode.window.onDidChangeTextEditorSelection(event => {
window.onDidChangeTextEditorSelection(event => {
manimCell.applyCellDecorations(event.textEditor);
}, null, context.subscriptions);

if (vscode.window.activeTextEditor) {
manimCell.applyCellDecorations(vscode.window.activeTextEditor);
if (window.activeTextEditor) {
manimCell.applyCellDecorations(window.activeTextEditor);
}
}
2 changes: 1 addition & 1 deletion src/manimCell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class ManimCell implements vscode.CodeLensProvider, vscode.FoldingRangePr
title: "▶ Preview Manim Cell",
command: "manim-notebook.previewManimCell",
tooltip: "Preview this Manim Cell inside an interactive Manim environment",
arguments: [cellCode]
arguments: [cellCode, codeLens.range.start.line]
};

return codeLens;
Expand Down
Loading