Skip to content
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

Added a shortcut to go to the last run or current running cell #7551

Merged
merged 4 commits into from Nov 27, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 16 additions & 5 deletions packages/notebook-extension/src/index.ts
Expand Up @@ -214,6 +214,8 @@ namespace CommandIDs {
export const enableOutputScrolling = 'notebook:enable-output-scrolling';

export const disableOutputScrolling = 'notebook:disable-output-scrolling';

export const selectLastRunCell = 'notebook:select-last-run-cell';
}

/**
Expand Down Expand Up @@ -1702,11 +1704,9 @@ function addCommands(
return;
}

return Private.createConsole(
commands,
current,
args['activate'] as boolean
);
return Private.createConsole(commands, current, args[
'activate'
] as boolean);
mlucool marked this conversation as resolved.
Show resolved Hide resolved
},
isEnabled
});
Expand Down Expand Up @@ -1886,6 +1886,17 @@ function addCommands(
},
isEnabled
});
commands.addCommand(CommandIDs.selectLastRunCell, {
label: 'Select current running or last run cell',
execute: args => {
const current = getCurrent(args);

if (current) {
return NotebookActions.selectLastRunCell(current.content);
}
},
isEnabled
});
}

/**
Expand Down
37 changes: 37 additions & 0 deletions packages/notebook/src/actions.tsx
Expand Up @@ -1288,6 +1288,43 @@ export namespace NotebookActions {
Private.handleState(notebook, state);
}

/**
* Go to the last cell that is run or current if it is running.
*
* Note: This requires execution timing to be toggled on or this will have
* no effect.
*
* @param notebook - The target notebook widget.
*/
export function selectLastRunCell(notebook: Notebook): void {
let latestTime: Date = null;
let latestCellIdx: number = null;
notebook.widgets.forEach((cell, cellIndx) => {
if (cell.model.type === 'code') {
const execution = (cell as CodeCell).model.metadata.get('execution');
if (
execution &&
typeof execution === 'object' &&
'iopub.status.busy' in execution
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Could these two lines be replaced by execution['iopub.status.busy'] !== undefined ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was done. I will note that I had to cast it to a JSONObject before which is slightly less safe. If execution was set to 3 this will now throw.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think that using @phosphor/coreutils/JSONExt.isObject() will likely be the most robust method here (both in JS and for typings).

For reference, typeof null === 'object' 😕

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Note: I'm not implying that the previous code was wrong, just that typeof X === 'object' is so counter-intuitive most of the time that I've made it a rule of thumb to simply avoid it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this anyway. Sadly, isObject fails to return a falsy value with JSONExt.isObject(undefined)

) {
// The busy status is used as soon as a request is received:
// https://jupyter-client.readthedocs.io/en/stable/messaging.html
const timestamp = execution['iopub.status.busy'].toString();
if (timestamp) {
const startTime = new Date(timestamp);
if (!latestTime || startTime >= latestTime) {
latestTime = startTime;
latestCellIdx = cellIndx;
}
}
}
}
});
if (latestCellIdx) {
mlucool marked this conversation as resolved.
Show resolved Hide resolved
notebook.activeCellIndex = latestCellIdx;
}
}

/**
* Set the markdown header level.
*
Expand Down