Skip to content

Commit

Permalink
Optionally focus
Browse files Browse the repository at this point in the history
  • Loading branch information
sourishkrout committed Dec 15, 2024
1 parent 8101361 commit 996a273
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 32 deletions.
3 changes: 2 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1129,8 +1129,9 @@ export enum WebViews {
NotebookEnvStore = 'runme.notebook.envStore',
}
export const CATEGORY_SEPARATOR = ','
export const FOCUS_CELL_STORAGE_KEY = 'focusCell'
export const EXECUTION_CELL_STORAGE_KEY = 'executionCell'
export const EXECUTION_CELL_CREATION_DATE_STORAGE_KEY = 'executionCellCreationDate'
export const CELL_CREATION_DATE_STORAGE_KEY = 'cellCreationDate'
export const SAVE_CELL_LOGIN_CONSENT_STORAGE_KEY = 'loginConsent'
export const GITHUB_USER_SIGNED_IN = 'userSignedIn'
export const PLATFORM_USER_SIGNED_IN = 'platformUserSignedIn'
Expand Down
6 changes: 3 additions & 3 deletions src/extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import GrpcRunner, { IRunner } from './runner'
import * as survey from './survey'
import { RunmeCodeLensProvider } from './provider/codelens'
import CloudPanel from './panels/cloud'
import { createDemoFileRunnerForActiveNotebook, createDemoFileRunnerWatcher } from './handler/utils'
import { createBootFileRunnerForActiveNotebook, createBootFileRunnerWatcher } from './handler/utils'
import { GithubAuthProvider } from './provider/githubAuth'
import { StatefulAuthProvider } from './provider/statefulAuth'
import { IPanel } from './panels/base'
Expand Down Expand Up @@ -346,8 +346,8 @@ export class RunmeExtension {
RunmeExtension.registerCommand('runme.addToRecommendedExtensions', () =>
addToRecommendedExtension(context),
),
createDemoFileRunnerForActiveNotebook(context, kernel),
createDemoFileRunnerWatcher(context, kernel),
createBootFileRunnerForActiveNotebook(context, kernel),
createBootFileRunnerWatcher(context, kernel),
RunmeExtension.registerCommand(
'runme.notebookOutputsMasked',
this.handleMasking(kernel, true).bind(this),
Expand Down
4 changes: 2 additions & 2 deletions src/extension/handler/uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
parseParams,
writeDemoBootstrapFile,
executeActiveNotebookCell,
setCurrentCellExecutionDemo,
setCurrentCellForBootFile,
} from './utils'

const REGEX_WEB_RESOURCE = /^https?:\/\//
Expand Down Expand Up @@ -115,7 +115,7 @@ export class RunmeUriHandler implements UriHandler, Disposable {
const isProjectOpened =
workspace.workspaceFolders?.length &&
workspace.workspaceFolders.some((w) => w.uri.path === projectPath.path)
await setCurrentCellExecutionDemo(this.context, cell)
await setCurrentCellForBootFile(this.context, { cell, focus: true, execute: true })
if (!isProjectOpened) {
await writeDemoBootstrapFile(projectPath, fileToOpen, cell)
await commands.executeCommand('vscode.openFolder', projectPath, {
Expand Down
89 changes: 71 additions & 18 deletions src/extension/handler/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { BOOTFILE, BOOTFILE_DEMO } from '../constants'
import { Kernel } from '../kernel'
import getLogger from '../logger'
import {
EXECUTION_CELL_CREATION_DATE_STORAGE_KEY,
CELL_CREATION_DATE_STORAGE_KEY,
EXECUTION_CELL_STORAGE_KEY,
FOCUS_CELL_STORAGE_KEY,
} from '../../constants'

const config = workspace.getConfiguration('runme.checkout')
Expand Down Expand Up @@ -199,17 +200,57 @@ export async function executeActiveNotebookCell({
}
}

export async function setCurrentCellExecutionDemo(context: ExtensionContext, cell: number) {
if (isNaN(cell)) {
export async function focusActiveNotebookCell({ cell, kernel }: { cell: number; kernel: Kernel }) {
const notebookDocument = window.activeNotebookEditor?.notebook
if (!notebookDocument || notebookDocument.notebookType !== Kernel.type) {
return
}
await context.globalState.update(EXECUTION_CELL_STORAGE_KEY, cell)
await context.globalState.update(EXECUTION_CELL_CREATION_DATE_STORAGE_KEY, new Date())
if (notebookDocument) {
const cells = notebookDocument.getCells().filter((cell) => cell.kind === NotebookCellKind.Code)

if (!cells.length || Number.isNaN(cell)) {
return window.showErrorMessage('Could not find a valid code cell to focus')
}

const cellToFocus = cells[cell]
if (!cellToFocus) {
throw new Error(`Could not find cell at index ${cell}`)
}
return kernel.focusNotebookCell(cellToFocus)
}
}

export function shouldExecuteDemo(context: ExtensionContext): boolean {
export async function setCurrentCellForBootFile(
context: ExtensionContext,
{ cell, focus = true, execute = false }: { cell: number; focus: boolean; execute: boolean },
) {
if (!Number.isFinite(cell)) {
return
}
if (focus) {
await context.globalState.update(FOCUS_CELL_STORAGE_KEY, cell)
}
if (execute) {
await context.globalState.update(EXECUTION_CELL_STORAGE_KEY, cell)
}
await context.globalState.update(CELL_CREATION_DATE_STORAGE_KEY, new Date())
}

export function shouldFocusCell(context: ExtensionContext): boolean {
const cell = context.globalState.get<number>(FOCUS_CELL_STORAGE_KEY)
const creationDate = context.globalState.get<string>(CELL_CREATION_DATE_STORAGE_KEY)
if (typeof cell === 'number' && cell >= 0 && creationDate) {
const timeStampDiff =
Math.abs(new Date().getTime() - new Date(creationDate).getTime()) / (1000 * 60)
// Max diff of 5 minutes to focus a cell
return timeStampDiff <= 5
}
return false
}

export function shouldExecuteCell(context: ExtensionContext): boolean {
const cell = context.globalState.get<number>(EXECUTION_CELL_STORAGE_KEY)
const creationDate = context.globalState.get<string>(EXECUTION_CELL_CREATION_DATE_STORAGE_KEY)
const creationDate = context.globalState.get<string>(CELL_CREATION_DATE_STORAGE_KEY)
if (typeof cell === 'number' && cell >= 0 && creationDate) {
const timeStampDiff =
Math.abs(new Date().getTime() - new Date(creationDate).getTime()) / (1000 * 60)
Expand All @@ -219,12 +260,13 @@ export function shouldExecuteDemo(context: ExtensionContext): boolean {
return false
}

export async function cleanExecutionDemo(context: ExtensionContext) {
export async function cleanExecutionForBootFile(context: ExtensionContext) {
await context.globalState.update(FOCUS_CELL_STORAGE_KEY, undefined)
await context.globalState.update(EXECUTION_CELL_STORAGE_KEY, undefined)
await context.globalState.update(EXECUTION_CELL_CREATION_DATE_STORAGE_KEY, undefined)
await context.globalState.update(CELL_CREATION_DATE_STORAGE_KEY, undefined)
}

export function createDemoFileRunnerWatcher(context: ExtensionContext, kernel: Kernel) {
export function createBootFileRunnerWatcher(context: ExtensionContext, kernel: Kernel) {
const fileWatcher = workspace.createFileSystemWatcher(`**/*${BOOTFILE_DEMO}`)
return fileWatcher.onDidCreate(async (uri: Uri) => {
for (let i = 0; i < 50; i++) {
Expand All @@ -246,22 +288,33 @@ export function createDemoFileRunnerWatcher(context: ExtensionContext, kernel: K
kernel,
})
} else {
await setCurrentCellExecutionDemo(context, Number(cell))
await setCurrentCellForBootFile(context, { cell: Number(cell), focus: true, execute: true })
await commands.executeCommand('vscode.openWith', notebookUri, Kernel.type)
}
})
}

export function createDemoFileRunnerForActiveNotebook(context: ExtensionContext, kernel: Kernel) {
export function createBootFileRunnerForActiveNotebook(context: ExtensionContext, kernel: Kernel) {
return window.onDidChangeActiveNotebookEditor(async () => {
if (shouldExecuteDemo(context)) {
const cell = context.globalState.get<number>(EXECUTION_CELL_STORAGE_KEY)
// Remove the execution cell from the storage
await cleanExecutionDemo(context)
await executeActiveNotebookCell({
cell: cell!,
if (shouldFocusCell(context)) {
const focusCell = context.globalState.get<number>(FOCUS_CELL_STORAGE_KEY)
await focusActiveNotebookCell({
cell: focusCell!,
kernel,
})
await cleanExecutionForBootFile(context)
return
}

if (!shouldExecuteCell(context)) {
return
}
const execCell = context.globalState.get<number>(EXECUTION_CELL_STORAGE_KEY)
await executeActiveNotebookCell({
cell: execCell!,
kernel,
})

await cleanExecutionForBootFile(context)
})
}
22 changes: 14 additions & 8 deletions src/extension/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import getLogger from './logger'
import { Kernel } from './kernel'
import { BOOTFILE, BOOTFILE_DEMO } from './constants'
import { IRunnerEnvironment } from './runner/environment'
import { setCurrentCellExecutionDemo } from './handler/utils'
import { setCurrentCellForBootFile as setCurrentCellForBootFile } from './handler/utils'
import ContextState from './contextState'
import { GCPResolver } from './resolvers/gcpResolver'
import { AWSResolver } from './resolvers/awsResolver'
Expand Down Expand Up @@ -485,27 +485,33 @@ export async function bootFile(context: ExtensionContext) {
}

const startupFileUri = Uri.joinPath(workspace.workspaceFolders[0].uri, BOOTFILE)
const runnableFileUri = Uri.joinPath(workspace.workspaceFolders[0].uri, BOOTFILE_DEMO)
const demoFileUri = Uri.joinPath(workspace.workspaceFolders[0].uri, BOOTFILE_DEMO)
const hasStartupFile = await workspace.fs.stat(startupFileUri).then(
() => true,
() => false,
)

const hasRunnableFile = await workspace.fs.stat(runnableFileUri).then(
const hasDemoFile = await workspace.fs.stat(demoFileUri).then(
() => true,
() => false,
)

const fileUri = hasRunnableFile ? runnableFileUri : startupFileUri
const fileUri = hasDemoFile ? demoFileUri : startupFileUri

if (hasStartupFile || hasRunnableFile) {
if (hasStartupFile || hasDemoFile) {
let bootFile = new TextDecoder().decode(await workspace.fs.readFile(fileUri))
if (hasRunnableFile) {
const [fileName, cell] = bootFile.split('#')
const [fileName, cell] = bootFile.trim().split('#')

if (fileName) {
bootFile = fileName
await setCurrentCellExecutionDemo(context, Number(cell))
}

await setCurrentCellForBootFile(context, {
cell: Number(cell),
focus: true,
execute: hasDemoFile,
})

const bootFileUri = Uri.joinPath(workspace.workspaceFolders[0].uri, bootFile)
await workspace.fs.delete(fileUri)
log.info(`Open file defined in "${BOOTFILE}" file: ${bootFileUri.fsPath}`)
Expand Down

0 comments on commit 996a273

Please sign in to comment.