Loading repository data…
Loading repository data…
moble / repository
Adds a customizable menu item to Jupyter (IPython) notebooks to insert boilerplate snippets of code
Adds a customizable menu item to Jupyter notebooks to insert snippets, boilerplate, and examples of code.
This notebook extension adds a menu item (or multiple menu items, if
desired) after the Help menu in Jupyter notebooks. This new menu
contains little snippets of code that we all forget from time to time
but don't want to google, or are just too lazy to type, or simply
didn't know about. It can also be helpful for people just starting
out with a programming language, who need some ideas for what to do
next — like importing a module, defining variables, or calling
functions.
The new menu comes with a default value relevant for python
programming — especially scientific computing — though this is fully
user-configurable as detailed below. The default menu is named
Snippets, and contains sub-menus with snippets for a few popular
python packages, as well as python itself, and some notebook markdown.
(Note that some of the menus are so large that it is necessary to move
the first-level menus to the left so that lower-level menus will fit
on the screen. This behavior is also user-configurable, as discussed
in detail below.)
So, for example, if you are editing a code cell and want to import
matplotlib for use in the notebook, you can just click the Snippets
menu, then mouse over "Matplotlib". This will open up a new sub-menu,
with an item "Setup for notebook". Clicking on that item will insert
the code snippet at the point where your cursor was just before you
clicked on the menu. In particular, for this matplotlib example,
the following code gets inserted:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
The inserted text will be selected, so that you can delete it by pressing backspace or delete, or you can just select another snippet to replace it -- and just to highlight what was inserted.
Note that many of the snippets involve variable names prefixed with
bp_. For example, a new numpy array is created as bp_new_array.
These are intentionally dumb names that you really should replace.
Failing to do so could lead to ugly bugs in your code if you use
multiple boilerplate snippets with clashing variable names.
Similarly, some strings are intended to be replaced, such as the axis labels in plots. These are there to show you what can be done, and to remind you to put informative labels in your plots. If you don't want, e.g., a title on your plot, just remove that line.
To install this extension alone (without the main collection of nbextensions), run the following from the command line:
git clone https://github.com/moble/jupyter_boilerplate
jupyter nbextension install jupyter_boilerplate
jupyter nbextension enable jupyter_boilerplate/main
You can then disable the extension if you want with
jupyter nbextension disable jupyter_boilerplate/main
The default menu might have too many irrelevant items for you, or may not have something you would find useful. You can easily customize it in the jupyter_nbextensions_configurator, which you almost certainly have if you installed this extension the normal way, through jupyter_contrib_nbextensions. Usually, you can get to the configurator by pointing your browser to http://127.0.0.1:8888/nbextensions, though you may have to modify the URL if you use a more complicated jupyter server.
On the configurator page, you will see a number of options (as well as this README) that should be fairly self-explanatory, allowing you to remove any of the default menu items, or add a custom menu within the "Snippets" menu. The custom menu is written in JSON, and a simple (and useless) example is given that should be easy to modify as needed.
It is also possible to extensively customize the menus in far more
complex ways using your custom.js file. For example, you can change
the order of menu items, add more custom sub-menus under the
"Snippets" menu, and custom menus alongside "Snippets" in the menu
bar, or even add menus in other places, like inside the "Insert" menu.
You can find the path to custom.js by running the command
echo $(jupyter --config-dir)/custom/custom.js
For Mac and linux users, the result is probably
~/.jupyter/custom/custom.js. If this file or the directory
containing it do not exist, you can simply create them.
The customization process is best explained through examples, which
are available in the examples_for_custom.js file in this directory.
Note that there's a lot of explanation here, but it's all actually
pretty simple. Give it a try, and you'll pick it up quickly. Note
that using this method can make it so that options selected in the
configurator are ignored.
The theory behind this customization is that the menu is represented by a nested JavaScript array (which is just like a python list). So to change the menu, you just need to change that array. And each menu item inside this array is represented by a JavaScript "object" (which is just like a python dictionary). So to change a menu item, you just have to change that object.
Again, this makes more sense when looking at example, as follows.
Suppose you want to make a new sub-menu with your favorite snippets at
the bottom of Snippets. You create a new object for the menu item,
and then just "push" it onto the default menu. Do this by inserting
some lines into your custom.js, so that it looks like this:
require(["nbextensions/snippets_menu/main"], function (snippets_menu) {
console.log('Loading `snippets_menu` customizations from `custom.js`');
var horizontal_line = '---';
var my_favorites = {
'name' : 'My favorites',
'sub-menu' : [
{
'name' : 'Menu item text',
'snippet' : ['new_command(3.14)',],
},
{
'name' : 'Another menu item',
'snippet' : ['another_new_command(2.78)',],
},
],
};
snippets_menu.options['menus'] = snippets_menu.default_menus;
snippets_menu.options['menus'][0]['sub-menu'].push(horizontal_line);
snippets_menu.options['menus'][0]['sub-menu'].push(my_favorites);
console.log('Loaded `snippets_menu` customizations from `custom.js`');
});
Now, if you refresh your notebook, you'll see a new menu item named "My
favorites". Hover over it, and it will pop up a sub-menu with two more
options. Click the first one, and it will insert new_command(3.14) into
your notebook wherever the cursor was.
We discuss how all this works below. But first, we need to slightly generalize the example above to work with more complicated snippets.
The example above inserted simple one-line snippets of code. Those snippets didn't have any quotation marks (single or double), backslashes, or newlines, which made everything easy. Unfortunately, JavaScript doesn't deal too well with strings. (There are no raw triple-quoted strings, like in python.) So there are just three things to remember when writing snippets.
Quotation marks can be a tiny bit tricky. There are a few options:
1. The obvious option is to enclose your snippets in single quotation marks
('), and use only double quotation marks (") within the snippet
itself.
2. Just as easy is to enclose your snippets in double quotation marks
("), and use only single quotation marks (') within the snippet
itself.
3. You can also escape single quotation marks inside single quotation marks
as \'.
Newlines are even trickier, but the extension takes care of this for you
as long as you put separate lines of code as separate elements of the
snippet array. Generally, there's no reason to put a literal newline in
your snippets.
JavaScript will treat backslashes as if they're trying to escape whatever comes after them. So if you want one backslash in your output code, you'll need to put two backslashes in.
This is all best described with another example. Let's change the first function above, to give it some more lines and some quotes:
require(["nbextensions/snippets_menu/main"], function (snippets_menu) {
console.log('Loading `snippets_menu` customizations from `custom.js`');
var horizontal_line = '---';
var my_favorites = {
'name' : 'My $\\nu$ favorites',
'sub-menu' : [
{
'name' : 'Multi-line snippet',
'snippet' : ['new_command(3.14)',
'other_new_code_on_new_line("with a string!")',
'stringy(\'escape single quotes once\')',
"stringy2('or use single quotes inside of double quotes')",
'backslashy("This \\ appears as just one backslash in the output")',
'backslashy2("Here are \\\\ two backslashes")',],
},
{
'name' : 'TeX appears correctly $\\alpha_W e\\int_0 \\mu \\epsilon$',
'snippet' : ['another_new_command(2.78)',],
},
],
};
snippets_menu.options['menus'].push(snippets_menu.default_menus[0]);
snippets_menu.options['menus'][0]['sub-menu'].push(horizontal_line);
snippets_menu.options['menus'][0]['sub-menu'].push(my_favorites);
console.log('Loaded `snippets_menu` customizations from `custom.js`');
});
Note the code output by the first item contains all sorts of interesting
strings. Also, the menu title of the second item contains TeX, which will
display correctly, and is used in some of the default menus to show the
standard symbols for physical constants. For more examples, look at the
default menus stored in the snippets_menu directory -- mostly under python.
Each of the menu items above is a JavaScript object (like a python dict),
with some attributes -- name and sub-menu for the main menu item, and
name and snippet for the sub-menu items. In general, any menu object can
have any of the following properties:
name: Text that appears in the menu. Note that this can include latex,
as the menus are processed by MathJax after being loaded.sub-menu: An array of more menu itemssnippet: An array of strings turned into code when the menu item is
clickedinternal-link: Link to some place on the present page. For example,
this could be #References, to link to the References section of any
notebook you're in.external-link: This just a link to some external web page, which will be
identified with a little icon, just like in the standard notebook "Help"
menu. When clicked, the link will open in a new window/tab.menu-direction: If the value of this property is left, this menu's
sub-menus open on the left. This is useful when the top-level menu is
inserted as an item within other menu items. See
below for examples.sub-menu-direction: If the value of this property is left, sub-menus
within this menu's sub-menus open on the left. This is used by default
for items under the Snippets menu to help ensure that nested menus
don't become too large to fit on the screen. See