jupyterlab-toc
jupyterlab-toc copied to clipboard
features
Hi, as one of the authors and maintainers of the toc2 nbextension, I really appreciate this port to jupyterlab!
I would like to share some thoughts and experience on this
- automatic section numbering is a very useful feature. In toc2 we have a parameter to enable it and fix the depth of numbering. In an early version we had a link in the toc header to toggle on/off numbering; (the depth of sections to show in the toc is also a parameter).
- though it might seem redundant, lot of users like the possibility to insert a "toc cell" at the beginning of the notebook
- the toc2 cooperates with the collapsible headings nbextension. (Un)Collapsing a section in the toc/notebook (un)collapses it the notebook/toc. We simply have an event triggered and processed by the other nbextension.
- it is very useful to have the toc exported when exporting to html. Currently we add the toc2 javascript logic as a script into the exported html document. This is done via a dedicated exporter. In principle this could survive to the lab transition (?).
- some users like to have the sections with cells currently executed to be be highlighted in the toc, to follow the processing of their notebook
- it is useful to have a mark displayed in the toc pointing the current section while scrolling into the notebook. Thanks for your work on that!
I don't know (yet) typescript and haven't digged into the source to understand the new API, so unfortunately I can't really help for now...
Hi @jfbercher, thanks for the information! Yep, toc2 was definitely the model for this port, thanks for all the hard work! I would love to have more help/input in bringing this up to speed with your extension.
To your specific points:
- Yep, automatic section numbering would be nice. Is there reason you removed the button to toggle it?
- Interesting, a "generate TOC cell" button should be doable.
- Collapsable sections is a really neat fature. I haven't really touched it in this initial implementation since the story on cell collapsing in JupyterLab is kind of a moving target. There is an early implementation of individual cell collapsing, but no concept of sections and collapsing those.
- I don't really understand the exporter in toc2. Is it done using nbconvert on the server side? It would indeed be nice to port that as well.
- It should be possible to add some sort of active/executing badge to individual sections.
The API I have started to design here is perhaps a tad overcomplicated: I have tried to make it so that different document types could register a "TOC generator", which knows how to parse them and make a TOC that can then be rendered into the pane. Other extensions could then rely on this one for TOC rendering. As a proof of concept, this currently works for notebooks and markdown files.
Typescript is really nice. It has helped me a lot in taming JS, and hopefully it's not too tough to read for a JS developer.
Hi,
All of TOC2 features are very nice to have. For me though, TOC2 itself is still not perfect when it comes to tools aiming to make navigation in long notebook easy. I would like to suggest two more killer features for navigation:
- A switch section button/keyboard shortcut that will enable you to jump back and forth between two last visited sections.
- A link while hovering over a variable or a function that upon click takes you to the last definition/assignment/import
- A back button to allow you to go back by sections
Based on my experience, a lot of times you define a variable/function in one section, and use it many times during the notebook. Altering/examining those variables/ functions is usually what force you to travel to earlier sections. You then usually want to take a look or edit the var/func run it, and go back to where you were. The features suggested above should make very easy to do.
Using the TOC, on the contrary, requires you to remember in which section the function/var was defined, which you rarely do. So you read the sections descriptions to understand where it might be and go to search in that area. Another option is to use the browser search which requires cmdC + cmdF + cmd V to start scrolling through the usages and it also shows you all appearances and not the assignments/definitions.
If my use case is the common one, which I believe it is than those features above would be killer features..
WDYT?
Hi @ian-r-rose
- the toc numbering toggle button was not removed but moved to a dialog designed by @jcb91 to present and change the nbextension parameters. All parameters have a default value. Some of them can be changed systemwide (and applied to any notebook) and some can be changed per notebook. The per-notebook parameters can be changed using the dialog and their state/value stored in the notebook metadata. In the lab, perhaps that the parameters can be altered via a json file (I saw that there is a json editor for config files), and may be some other in metadata.
- the exporter is indeed based on nbconvert. It essentially serves to call the correct template which includes
toc2.js
as a script and render the toc when the document is ready. Having the exporter enables to define an entry point for nbconvert and to add an entry in the "download as" menu (as html with toc)
@idoDavid I think that a go back button or something to go through the history of visited sections is feasible. It would require to implement a stack collecting the visited sections each time a user scroll into the notebbok (requires recognizing which is the nearest section to the current viewport -- implemented in the current toc2) or jump to a section via the toc. I think the other item (jumping to function/variable/definition) is a really interesting feature to have, but perhaps a different project...
@ian-r-rose Another point you should consider is whether you should render the headings in the toc. Eg, a heading like that
## The **real** importance of the $x_k$ in the result
can be displayed in plain text or rendered in html, including the maths.
LaTeX parsing is now in master, but not in the released package at the moment.
I'm currently not sure what the best way to handle emphasis, underlining, etc, is. I currently have a React component that takes plain text for headers, and I am thinking that it would be time to bring a markdown renderer into the mix.
@jfbercher
I think a stack holding the scrolled through sections might be a good starting point. But.. if the scrolling pattern was (sec5, sec5.1 sec5.2 sec2(due to a jump from toc) sec 2.1, sec 5 (another jump), sec5.1, sec5.2) do we really want the back button to replay all those actions?
I would suggest that a user know the context he is in. He would like to use to back button to jump to the last place out of context. so in the example, a back press at sec5.2 will take you back to sec 2.1 (and not sec5.1)
This is a more delicate implementation, but also more usable. WDYT?
This stack of sections sounds very much like the window history, which can already store #
entries, which only tracks ones you've explicitly clicked, and where, (in modern browsers at least), you can already programmatically push and pop entries. Sounds like the simplest solution would be, when you click a toc entry, to push the current section onto the stack before adding the new one...
window.histiory
also has the added bonus of playing nicely with browser forward/back buttons if done well.
@jcb91 that could be nice - using my mouse back button to scroll through the notebook :)
I think that for perfect usage we might need a little more - consider the scenario in which you are working on advanced sections, then need to change a method in an earlier section. you use the TOC to jump to more-or-less the location you need, then you scroll down a bit until you find the method to edit. ideally, the switching between notebook locations should be between your section before the link and the section after the link and after the scrolling.
The solution is somewhat algorithmic. let's define a session succession as the registration of normal scrolling through sections, i.e. [sec5, sec5.1, sec5.2, sec 5.3 etc] and section disruption as link click event, then:
- every link click starts a session succession
- session succession can be initialized by a link, or by first opening of the notebook
- upon a switch event, you would want to jump to the edge of the last session succession.
For example:
- I have naturally scrolled through my notebook till sec5. my current session edge is at sec5, my last session edge is at sec5.
- I clicked a link to sec 2. my current session edge is at sec 2, my last session edge is at sec 5.
- I scrolled to sec 2.2 - my current session edge is at sec 2.2, my last session edge is at sec 5
- I press the switch button/keyboard sc, I jump back to sec 5. my current session edge is at sec 5, my last is at sec 2.2
- I scroll to 5.5. my current edge is at 5.5, my last is at 2.2.
- I press the switch button/keyboard sc and I move to sec 2.2
- etc
Also - we can have keys/buttons to scroll through a session (i.e. from 5.5 back to 5.4, 5.3 etc) so combined with the key/button above you can switch to the last session edge and then back down the last session.
WDYT?
@idoDavid @jcb91 Tentative implementation and proof of concept for toc2 here. Thanks for the remark @jcb91!
What @idoDavid is talking about makes me think of all the navigation options in vim. I'm a bit rusty, but there is a jump list and CTRL+o that takes you back through your jump history, and marks that you set and recall, etc. Since the notebook already has a bit of vim in its command mode (which includes i and j for navigating, dd for delete, etc), perhaps some further inspiration from vim would help to implement a sane means of jumping around combined with some keystrokes that at least some folks are already accustomed to.
I worry a bit about writing to window.history
. That's a global namespace, as far as I know. We have talked about adding filebrowser navigation to that (though have not done anything like that so far). It could mess with the encapsulation of the plugin and make it play badly with others.
Yes of course -- and with several opened tabs with notebooks, it will be difficult to sort the history per notebook. So it is probably better to implement an history stack for each notebook and add a couple of keyboard shortcuts; and perhaps two buttons in the header of the toc.
Hey devs, thanks for creating such a useful extension.
My suggestion for a new 'killer feature' for the TOC extension is to allow users to move groups of cells in their notebook by dragging the corresponding heading (or sub-heading) of the cells displayed in the Contents panel on the left.
Hi, just wanted to +1
this feature:
- some users like to have the sections with cells currently executed to be be highlighted in the toc, to follow the processing of their notebook
This is coming from a user who recently switched from the classic Jupyter Notebook (with toc2). Thank you.
Hello! Do you guys have in mind implementing the "create TOC cell" feature mentioned in OP? Or alternatively, a way to export TOCs to HTML versions of the notebook? Thanks a lot for the hard work.
I would just like to echo the comment immediately above: the table of contents in Jupyter lab is substantially less useful than toc2 in Jupyter notebook because you cannot create a TOC cell at the top of the notebook that is exported to HTML. Therefore, unlike toc2 in Jupyter notebook, the table of contents in Jupyter lab isn't useful for exports.
Hi,
If you have the jupyter_contrib_nbextensions
installed; and you are able to use toc2 in the classical notebook, then you have a toc2.tpl
template and an entry point for a nbconvert exporter. Ths means that in principle
jupyter nbconvert FILE.ipynb --template toc
or even
jupyter nbconvert --to html_toc FILE.ipynb
should work, and add to your exported html the very same toc2 sidebar as in the livenotebook (but not the toc2 cell though).
If in addition you use the jupyter_latex_envs
, you have an entry point for including both latex_envs and toc2, through
jupyter nbconvert --to html_with_toclenvs FILE.ipynb
(continued)
This works by incorporating into the exported html a call to the toc2.js
library in the jupyter_contrib_nbextensions
repo, and launching it with the parameters stored in the notebook itself plus some other default values.
In principle, this should work inchanged for files edited or created with jupyterlab. I just mention that I do not use jupyterlab myself because I am very dependent of the jupyter_latex_envs nbextension with a large base of existing files. and I have not time to port it in a predictible future.
I had not realized from glancing over this issue, that installing the jupyter_contrib_nbextensions will also add export entries to the jupyterlab export menu which allow inclusion of the toc. That's very helpful for me. Is this something that will continue working in the foreseeable future?