QuantEcon / sphinxcontrib-jupyter

A Sphinx Extension for Generating Jupyter Notebooks
BSD 3-Clause "New" or "Revised" License
76 stars 23 forks source link

ENH: added exercises directive #164

Closed sglyon closed 5 years ago

sglyon commented 5 years ago

Hey @mmcky here is my first pass at making an .. exercise directive.

It seems to work pretty well for me, but isn't a totally clean/optimal implementation.

One place where I really had to do something I'm not proud of is in JupyterTranslator.depart_literal_block

Let me explain what I wanted, then I'll try to defend myself...

I wanted the ability to do something like

.. exercise::
   :class: cfu

   This is a check for understanding exercise

   This is a note that has some *italic* and **bold** embedded

   - list
   - in
   - exercise

   .. code-block:: python

      def foobar(x, y, z):
         print(x, y, z)

   And text after the code block

and have the entire exercise block -- code section and everything -- in a single markdown cell inside a <blockquote> element (html name for >).

The issue is that the literal_block handling caused a cell break to happen on either side of each .. code-block. To get around that I do the following:

This will cause the .. code-block to be written out to markdown, but then merged with the cell containing the prose for the .. exercise

I don't love the pop part and it seems like it might be fragile, but in my tests is does what I want 🤷‍♂️

mmcky commented 5 years ago

hey @sglyon. Thanks -- this will be a great addition.

I'm not sure I fully follow. If we are in_exercise=True could we not just write code-blocks or more accurately literal_blocks as a syntax highlighted markdown? and skipping the inserted breaks? I will use your test to trace the state and look a bit more closely. Thanks!

sglyon commented 5 years ago

Hey @mmcky that's a good point and something I wanted to do.

I found it a bit difficult because the (visit|depart)_literal_block methods are in a different class that don't know anything about the exercise node type, so it was hard to convey that state.

My workaround was to let the other class do its thing and then patch it up in the class that did know about exercises.

One other complication is that sometimes I want to just displayed highlighted code in markdown cells, but other times I actually do want a code cell. Right now I'm differentiating between the two cases by passing different language names for the .. code-block:: (b/c my conf.py has python3 associated with a kernel, that one generates the code cells while python generates markdown highlighted code)

mmcky commented 5 years ago

ah -- right. thanks for the update @sglyon. That makes sense - the dual class operations are difficult and probably a poor design in some respects - but was done to reduce duplication.

I have run this branch over the quantecon lectures site and doesn't interact with it in any way so I'm happy to merge this as is and we can improve over time.

thanks!