Adding keyboard shortcuts for move cell up and move cell down - ipython

I am trying to add the Cntl+K and Cntl+J shortcuts to move cells up and down quickly. I viewed the issue on Github here for adding the shortcuts and found what looked to be a workable answer:
"For those (like me) who liked this shortcut, add this to your ~/.ipython/profile_default/static/custom/custom.js:
$([IPython.events]).on("app_initialized.NotebookApp", function () {
IPython.keyboard_manager.command_shortcuts.add_shortcut('ctrl-k', function (event) {
IPython.notebook.move_cell_up();
return false;
});
IPython.keyboard_manager.command_shortcuts.add_shortcut('ctrl-j', function (event) {
IPython.notebook.move_cell_down();
return false;
});
});
"
But my users/{my name}/.ipython/profile_default directory did not have a static folder. I tried adding the missing folders and custom.js file, and reopened Anaconda prompt, but this did not add the missing shortcuts.
Another answer had the same issue:
"Use the following:
$ cat ~/.jupyter/custom/custom.js
define(["base/js/namespace"], function(Jupyter){
console.info('Binding Ctrl-J/K to move cell up/down');
Jupyter.keyboard_manager.command_shortcuts.add_shortcut('Ctrl-k','jupyter-notebook:move-cell-up');
Jupyter.keyboard_manager.command_shortcuts.add_shortcut('Ctrl-j','jupyter-notebook:move-cell-down');
});
"
This answer also did not work (adding the missing folder and custom.js file did not work).

As proposed in the official doc (got with the "Help>Notebook" menu action),
you could try first in a live notebook. The browser javascript console helps too.
I tried:
%%javascript
IPython.keyboard_manager.command_shortcuts.add_shortcut('Ctrl-k','jupyter-notebook:move-cell-up');
// replacing IPython with Jupyter should work as well:
Jupyterkeyboard_manager.command_shortcuts.add_shortcut('Ctrl-j','jupyter-notebook:move-cell-down');
It works but, just as when clicking on the corresponding toolbar button, the console warns about deprecation
in favor of IPython.notebook.move_selection_up() .
The string "jupyter-notebook:move-cell-up" refers to the same action.
So I suppose a reasonnable thing to do is to redefine it from scratch:
IPython.keyboard_manager.command_shortcuts.add_shortcut('Ctrl-k', {
help : 'move up selected cells',
help_index : 'jupyter-notebook:move-selection-up',
handler : function (event) {
IPython.notebook.move_selection_up();
return false;
}}
);
IPython.keyboard_manager.command_shortcuts.add_shortcut('Ctrl-j', {
help : 'move down selected cells',
help_index : 'jupyter-notebook:move-selection-down',
handler : function (event) {
IPython.notebook.move_selection_down();
return false;
}}
);
After executing the notbook cell (or the code in your browser console), it should
be active and you can experiment with it.
Once happy, check the path of your jupyter profile with !jupyter --config, and from there
you'd know where to copy your code : <profile>/static/custom/custom.js
so that it would be active in next jupyter sessions.

Related

Make Upload tab the default in Insert/Edit Image dialog

Using TinyMCE 5.7.0
Is there a way to make the "Upload" tab the default tab displayed in the Insert/Edit Image dialog?
I'm looking for a configuration option or programmatic way to do this so we can continue to easily update TinyMCE when new versions come out.
In TinyMCE (5.7.0 in my case, not the minified version), open plugins/image/plugin.js.
Search for these lines (1462 to 1466):
tabs: flatten([
[MainTab.makeTab(info)],
info.hasAdvTab ? [AdvTab.makeTab(info)] : [],
info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : []
])
Reorder the lines like this:
tabs: flatten([
info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : [],
[MainTab.makeTab(info)],
info.hasAdvTab ? [AdvTab.makeTab(info)] : []
])
We had the same requirement and this is how we did it.
Instead of adding the "Upload Image" option to toolbar, create a keyboard shortcut for opening the image upload modal using addShortcut method. Something like this in reactjs:
editor.addShortcut('ctrl+shift+i', 'Open image upload window', function () {
editor.execCommand('mceImage')
});
Now that we have a code block that runs when pressing the shortcut keys, we can add logic inside that block to initiate a click action on the "Upload" button within the modal like this:
setTimeout(() => {
let element = document.querySelectorAll('.tox-dialog__body-nav-item')[1];
if (element) { element.click() }
}, 0)
The setTimeout is added to make sure that the modal is added to DOM before run the querySelectorAll method on the document object is executed. Timeout even with 0 will make sure the code block only executes after all the synchronous tasks are done, which includes the DOM update.
In the end, the final codeblock will look like this:
editor.addShortcut('ctrl+shift+i', 'Open image upload window', function () {
editor.execCommand('mceImage')
setTimeout(() => {
let element = document.querySelectorAll('.tox-dialog__body-nav-item')[1];
if (element) { element.click() }
}, 0)
});
Edit:
If you notice other elements in the DOM with the same class as "tox-dialog__body-nav-item", you can change the querySelectorAll method to make it more well defined and make sure it only selects the class within image upload modal if found. I haven't yet ran into this issue, so this was enough for my case.

Maintain screen position always centered on cursor

I'm trying to write an extension for VSCode where the editor screen is always centered on the cursor. There are other extensions that add a command to center the screen onto the cursor, but you have to press the command to activate it.
Currently the only way I've found to implement this is to rewrite the cursorUp, cursorDown, enter, pageUp, pageDown -- any command that moves the cursor up and down basically, and then use the "revealLine" command with the cursor line position and with the "at" attribute as "center".
Is there a better way? Reimplementing the default editor commands seems very inefficient.
Here's what I've got currently:
"use strict";
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
let disposable1 = vscode.commands.registerCommand("cursorUp",() => {
centralizar();
vscode.commands.executeCommand("cursorMove", {
to: "up",
});
}
);
let disposable2 = vscode.commands.registerCommand("cursorDown",() => {
centralizar();
vscode.commands.executeCommand("cursorMove", {
to: "down",
});
}
);
context.subscriptions.push(disposable1);
context.subscriptions.push(disposable2);
}
function centralizar() {
let currentLineNumber = vscode.window.activeTextEditor.selection.start.line;
vscode.commands.executeCommand("revealLine", {
lineNumber: currentLineNumber,
at: "center"
});
}
export function deactivate() {}
Perhaps you can utilize the new (v1.38) command editor.cursorSurroundingLines. See scrollOff release notes.
It takes a number, but if you can get the number of visible lines in an editor window, then set editor.cursorSurroundingLines to the appropriate midpoint that may work. It seems you would not have to listen for scroll events. But would have to update the value if the editor window was resized.
The Scrolloff extension implements this functionality when its "alwaysCenter" option is enabled. It works by listening to window.onDidChangeTextEditorSelection, which fires when the cursor moves.

Add another insertText command inside Atom init script

Inside Atom I am able to run a simple text-editor insert with:
atom.commands.add 'atom-text-editor',
'custom:react-class': ->
atom.workspace.getActiveTextEditor()?.insertText('text to be inserted')
I'd like to setup another keyboard shortcut to insert a different snippet of text, but I cant seem to get it. Can I run multiple insertText in the same script file? Should these all be in the same command?
The following can serve as a template (it's in JavaScript, but you can either translate to CoffeeScript or rename init.coffee to init.js)
atom.
commands.add("atom-text-editor", {
"custom:f1": () => {
atom.workspace.getActiveTextEditor().insertText('executing f1');
},
"custom:66": () => {
atom.workspace.getActiveTextEditor().insertText('executing order 66');
},
"custom:f2": () => {
atom.notifications.addSuccess("Executed f2", { dismissable: true });
}
});
The actual functions can be as complex as you like. Anything NodeJS can do, Atom can do, and NodeJS can do anything.
The commands can then be linked to a keyboard shortcut like so
"atom-text-editor":
"cmd-shift-a": "custom:f1"
"cmd-shift-b": "custom:66"
"cmd-shift-c": "custom:f2"

How to add keyboard shortcuts permanently to Jupyter (ipython) notebook?

I have the following configuration for shortcuts, that works after running it in the cell of Jupiter notebook:
%%javascript
IPython.keyboard_manager.command_shortcuts.add_shortcut('ctrl-q', {
help: 'Clear all output', // This text will show up on the help page (CTRL-M h or ESC h)
handler: function (event) { // Function that gets invoked
if (IPython.notebook.mode == 'command') {
IPython.notebook.clear_all_output();
return false;
}
return true;
}
});
How can I setup Jupiter notebook to make this initialization automatically on startup?
I tried adding the same code (without %%javascript) to C:\Users\<username>\.ipython\profile_default\static\custom\custom.js but it didn't work.
I have only one profile, created with ipython profile create, Python 3.3, Windows 7.
Thanks in advance.
In the new version of Jupyter notebook (update it either with pip install --upgrade notebook or if you use conda conda upgrade notebook), you can customize them from the notebook itself.
To do this Help -> Edit keyboard shortcuts
custom.js is the correct place for this code. Try wrapping it as follows (don't forget the return true before the end of the block):
$([IPython.events]).on("app_initialized.NotebookApp", function () {
<your code>
return true;
});
1. For changing command mode shortcuts: refer Salvador's answer
2. For changing edit mode shortcuts:
Edit the file, ~/.jupyter/nbconfig/notebook.json as explained on https://jupyter-notebook.readthedocs.io/en/stable/extending/keymaps.html
For example, after replacing the control-enter shortcut to execute code, with command-enter on macOS, the file looks like this:
{
"Notebook": {
"Toolbar": true,
"Header": true
},
"Cell": {
"cm_config": {
"lineNumbers": true
}
},
"keys": {
"command": {
"unbind": [
"ctrl-enter"
],
"bind": {
"cmdtrl-enter": "jupyter-notebook:run-cell"
}
},
"edit": {
"unbind": [
"ctrl-enter"
],
"bind": {
"cmdtrl-enter": "jupyter-notebook:run-cell"
}
}
}
}
Adding hotkeys the easy way with nbextensions
Install nbextensions.
pip install jupyter_contrib_nbextensions
Then launch jupyter notebook.
The the intro page will have a new tab called nbextensions click it and enable Keyboard Shortcut Editor.
Now open any notebook click help>keyboard shortcuts
Each shortcut will have a pencil icon next to it if you click on it then you can set the shortcut to whatever you want.

Change content before preview in TinyMCE 4

In TinyMCE 4, I want to change displayed contents before they are showed on preview popup windows. This change must not affect current contents in editor. Can we do that?
If it can't, I want to catch close event of preview windows. How to do that?
TinyMCE allows us to register callbacks via the property init_instance_callback
By using the BeforeExecCommand event, oddly not in current documentation, you can make changes prior to a command being executed. We can similarly use the ExecCommand event to make changes after the command is executed. The Preview Plugin triggers the mcePreview command. You can view the Editor command Identifiers here.
Putting that together you can add the following when initializing your TinyMCE. This will show "changed content" in the preview without making visible changes to the content within TinyMCE.
var preProssesInnerHtml;
tinymce.init({
//other things...
init_instance_callback: function (editor) {
editor.on('BeforeExecCommand', function (e) {
if (e.command == "mcePreview") {
//store content prior to changing.
preProssesInnerHtml = editor.getContent();
editor.setContent("changed content");
}
});
editor.on("ExecCommand", function (e) {
if (e.command == "mcePreview") {
//Restore initial content.
editor.setContent(preProssesInnerHtml);
}
});
}
}