code-cells.el icon indicating copy to clipboard operation
code-cells.el copied to clipboard

Suggestion for additoinal functions: code-cell-eval-and-step, code-cell-eval-below, code-cell-eval-buffer, py process

Open mirbehroznoor opened this issue 2 years ago • 3 comments
trafficstars

Thanks for the package. It is amazingly lightweight and fantastic. I am glad to find it.

I felt it is missing functions like:

  1. Evaluate Current cell block and move to the next.
  2. Run all cells below.
  3. Run all cells in the buffer.
  4. Lastly, evaluate cell and ensure python shell is running.

Below are the functions for the particular purposes.

Code-cells-eval-and-step

Evaluate the current cell and move to the next block, just like in Jupyter notebook or Elpy (elpy-send-statement-and-step). I had simply added one-line (outline-next-heading) at the end of code-cells-eval.

(defun code-cells-eval-and-step (start end)
  "Evaluate code according to current modes.
The first suitable function from `code-cells-eval-region-commands'
is used to do the job.

Interactively, evaluate the region, if active, otherwise the
current code cell.  With a numeric prefix, evaluate that many
code cells.

Called from Lisp, evaluate region between START and END."
  (interactive (code-cells--bounds (prefix-numeric-value current-prefix-arg) t))
  (funcall
   (or (seq-some (pcase-lambda (`(,mode . ,fun))
                   (when (or (and (boundp mode) (symbol-value mode))
                             (derived-mode-p mode))
                     fun))
                 code-cells-eval-region-commands)
       (forward-line)
       (user-error
        "No entry for the current modes in `code-cells-eval-region-commands'."))
   start end)
  (pulse-momentary-highlight-region start end)

  ;; Go to next cell block, or outline heading
  (outline-next-heading)
  )

Run all cells below

It is almost the same code as code-cells-eval-above.

(defun code-cells-eval-below (arg)
  "Evaluate this and all cells below"
  (interactive "p")
  (code-cells-eval (point) (save-excursion
                                 (code-cells-forward-cell arg)
                                 (point-max))))

Run all cells in the Buffer: Beginning to End

As in org-src-execute-buffer or Run all in jupyter-notebook. Again, he same code as code-cells-eval-above.

(defun code-cells-eval-buffer (arg)
  "Evaluate all the cells in the buffer."
  (interactive "p")
  (elpy-shell--ensure-shell-running) ;; (require 'elpy)
  (code-cells-eval (point-min) (save-excursion
                                 (code-cells-forward-cell arg)
                                 (point-max))))

OR

(defun my-code-cells-eval-buffer (arg)
  "Evaluate all the cells in the buffer."
  (interactive "p")
  (elpy-shell--ensure-shell-running) ;; (require 'elpy)
  (code-cells-eval (point-min) (point-max)))

Evaluate cell and ensure python shell is running.

I have been using code-cells with Elpy functions. I use Elpy function (elpy-shell--ensure-shell-running) with code-cells-eval-and-step. Simply open the file and evaluate the code. Elpy automatically starts or switch to the running Python session. The only trouble with this code and code-cells-eval-buffer, is the Elpy dependency (although not necessary but saves the trouble of starting the inferior python process).

(defun code-cells-eval-and-step (start end)
  "Evaluate code according to current modes.
The first suitable function from `code-cells-eval-region-commands'
is used to do the job.

Interactively, evaluate the region, if active, otherwise the
current code cell.  With a numeric prefix, evaluate that many
code cells.

Called from Lisp, evaluate region between START and END."
  (interactive (code-cells--bounds (prefix-numeric-value current-prefix-arg) t))

   ;; starts python shell if not running already
  (elpy-shell--ensure-shell-running) ;; (require 'elpy)

  (funcall
   (or (seq-some (pcase-lambda (`(,mode . ,fun))
                   (when (or (and (boundp mode) (symbol-value mode))
                             (derived-mode-p mode))
                     fun))
                 code-cells-eval-region-commands)
       (forward-line)
       (user-error
        "No entry for the current modes in `code-cells-eval-region-commands'."))
   start end)
  (pulse-momentary-highlight-region start end)

  ;; Go to next cell block, or outline heading
  (outline-next-heading)
  )

I wanted to share these slight additions. Since, my Elisp knowledge is limited, I would be glad to know if there is another better way.

Thank you and have a nice day!

regards, Behroz

mirbehroznoor avatar Jun 01 '23 19:06 mirbehroznoor

Thanks for the suggestions. Here are some questions and comments:

  • Eval and step: makes sense, I should add this.
  • Run all cells below: Should it include the current cell (I feel it should not)? And do you think it's right that the "eval above" command does include the current cell?
  • Run all cells in the Buffer: This is normally covered by the upstream shell package. Why do you want this? Is it because of the multiple dispatch (see code-cells-eval-region-commands)?
  • Evaluate cell and ensure python shell is running: This is too specific. You can arrange for it in your configuration using advices.

astoff avatar Jul 08 '23 08:07 astoff

Since I am using code-cells, I have rarely opened the Jupyter Notebook for analysis.

To your questions:

Run all cells Below/ Above: Should it include the current cell There are two ways to reason it.

  • Follow the logic of Elisp and Emacs.
  • Follow Jupyter Notebook's default behavior. I rarely use both commands. I prefer code-cells-eval-buffer or run all cells in the buffer.

Run all Cells in the Buffer

  • It is an option in Jupyter Notebook.
  • Most of the time, I keep separate .ipynb files for graphs. There are always little tweaks to do. I simply edit the graph cell and evaluate the whole buffer.
  • I do not have to bother about the pointer position, open the file and evaluate the whole buffer.
  • Sometimes I had to kill the inferior python shell for some reason then rather than manually evaluating all the cells, I just evaluate the whole buffer. If everything goes smoothly, I just wrap everything up.
  • With the help of Elpy, inferior python pops up over the .ipynb file or in the side window. I can easily check the output if the whole file was smoothly evaluated or not.

I have no idea what is upstream shell package. If I understood it correctly, the multiple dispatch could be code-cells-eval-below or code-cells-eval-above. They would not be the same as code-cells-eval-buffer.

I also think there should be other commands such as:

  • Delete, Cut, Copy, Break cell, Insert cell below/above
  • Edit current cell in a temp buffer (replace-string replaces all the matches in the buffer instead of the one cell).

This is my hydra for code-cells which keeps away the Jupyter Notebook from annoying me:

^Insert^        ^Insert^    ^Evaluate^            ^Move Cell^     ^Actions
^Cell^          ^Markdown^
^^^^^^^^--------------------------------------------------------------------------
_a_: Above      _M_: Above  _w_: Whole Buffer     _<up>_:   Up    _D_: Delete
_b_: Below      _m_: Below  _A_: All Cells Above  _<down>_: Down  _c_: Comment
_i_: At Cursor  ^ ^         _B_: All Cells Below  ^ ^             _C_: Copy
^ ^             ^ ^         ^ ^                   ^ ^             _-_: Break Cell
^ ^             ^ ^         ^ ^                   ^ ^	          _d_: Cut

Thank you and have a nice day!

mirbehroznoor avatar Jul 29 '23 19:07 mirbehroznoor

Some of the cell manipulation commands would be really helpful, especially delete current cell. IIRC, break cell, insert cell below/above could just be built in terms of outline-minor-mode commands.

However, that last one, edit current cell in a temp buffer seems potentially quite useful.

swflint avatar Oct 20 '23 20:10 swflint