2012-05-07 14:41:15 +02:00
|
|
|
|
;;; ein-notebook.el --- Notebook module
|
|
|
|
|
|
|
|
|
|
;; Copyright (C) 2012- Takafumi Arakaki
|
|
|
|
|
|
2012-07-01 20:18:05 +02:00
|
|
|
|
;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
|
|
|
|
;; This file is NOT part of GNU Emacs.
|
|
|
|
|
|
|
|
|
|
;; ein-notebook.el is free software: you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
;; ein-notebook.el is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;; along with ein-notebook.el. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
2012-05-25 22:58:01 +02:00
|
|
|
|
;; * Coding rule about current buffer.
|
|
|
|
|
;; A lot of notebook and cell functions touches to current buffer and
|
|
|
|
|
;; it is not ideal to wrap all these functions by `with-current-buffer'.
|
|
|
|
|
;; Therefore, when the function takes `notebook' to the first argument
|
|
|
|
|
;; ("method" function), it is always assumed that the current buffer
|
|
|
|
|
;; is the notebook buffer. **However**, functions called as callback
|
|
|
|
|
;; (via `url-retrieve', for example) must protect themselves by
|
|
|
|
|
;; calling from unknown buffer.
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(eval-when-compile (require 'cl))
|
|
|
|
|
(require 'ewoc)
|
2012-08-01 20:04:47 +02:00
|
|
|
|
(eval-when-compile (require 'auto-complete nil t))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-08-28 15:26:32 +02:00
|
|
|
|
(require 'ein-core)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(require 'ein-log)
|
|
|
|
|
(require 'ein-node)
|
2015-02-12 08:45:29 -06:00
|
|
|
|
(require 'ein-contents-api)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(require 'ein-kernel)
|
2012-08-26 15:14:59 +02:00
|
|
|
|
(require 'ein-kernelinfo)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(require 'ein-cell)
|
2015-12-22 12:32:21 -06:00
|
|
|
|
(require 'ein-cell-output)
|
2012-08-19 11:58:04 +02:00
|
|
|
|
(require 'ein-worksheet)
|
2012-08-27 00:32:40 +02:00
|
|
|
|
(require 'ein-scratchsheet)
|
2012-08-28 21:43:57 +02:00
|
|
|
|
(require 'ein-notification)
|
2012-05-15 21:46:17 +02:00
|
|
|
|
(require 'ein-completer)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(require 'ein-pager)
|
|
|
|
|
(require 'ein-events)
|
2012-05-25 02:02:31 +02:00
|
|
|
|
(require 'ein-notification)
|
2012-05-14 23:47:10 +02:00
|
|
|
|
(require 'ein-kill-ring)
|
2012-05-25 22:12:34 +02:00
|
|
|
|
(require 'ein-query)
|
2012-06-03 17:30:16 +02:00
|
|
|
|
(require 'ein-pytools)
|
2015-02-02 13:20:24 -06:00
|
|
|
|
(require 'ein-traceback)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-05-25 00:23:09 +02:00
|
|
|
|
|
|
|
|
|
;;; Configuration
|
|
|
|
|
|
2012-08-28 21:10:23 +02:00
|
|
|
|
(make-obsolete-variable 'ein:notebook-discard-output-on-save nil "0.2.0")
|
|
|
|
|
|
2012-05-25 00:23:09 +02:00
|
|
|
|
(defcustom ein:notebook-discard-output-on-save 'no
|
|
|
|
|
"Configure if the output part of the cell should be saved or not.
|
|
|
|
|
|
2012-08-28 21:10:23 +02:00
|
|
|
|
.. warning:: This configuration is obsolete now.
|
|
|
|
|
Use nbconvert (https://github.com/ipython/nbconvert) to
|
|
|
|
|
strip output.
|
|
|
|
|
|
2012-06-11 04:21:30 +02:00
|
|
|
|
`no' : symbol
|
|
|
|
|
Save output. This is the default.
|
|
|
|
|
`yes' : symbol
|
|
|
|
|
Always discard output.
|
|
|
|
|
a function
|
|
|
|
|
This function takes two arguments, notebook and cell. Return
|
|
|
|
|
`t' to discard output and return `nil' to save. For example,
|
|
|
|
|
if you don't want to save image output but other kind of
|
|
|
|
|
output, use `ein:notebook-cell-has-image-output-p'.
|
2012-08-28 21:10:23 +02:00
|
|
|
|
"
|
2012-05-25 00:23:09 +02:00
|
|
|
|
:type '(choice (const :tag "No" 'no)
|
|
|
|
|
(const :tag "Yes" 'yes)
|
|
|
|
|
)
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-06-10 04:04:31 +02:00
|
|
|
|
(defun ein:notebook-cell-has-image-output-p (-ignore- cell)
|
|
|
|
|
(ein:cell-has-image-ouput-p cell))
|
|
|
|
|
|
|
|
|
|
(defun ein:notebook-discard-output-p (notebook cell)
|
2012-05-25 00:23:09 +02:00
|
|
|
|
"Return non-`nil' if the output must be discarded, otherwise save."
|
|
|
|
|
(case ein:notebook-discard-output-on-save
|
|
|
|
|
(no nil)
|
|
|
|
|
(yes t)
|
2012-06-10 04:04:31 +02:00
|
|
|
|
(t (funcall ein:notebook-discard-output-on-save notebook cell))))
|
2012-05-25 00:23:09 +02:00
|
|
|
|
|
2012-06-21 00:01:23 +02:00
|
|
|
|
;; As opening/saving notebook treats possibly huge data, define these
|
|
|
|
|
;; timeouts separately:
|
|
|
|
|
|
2012-06-21 01:05:42 +02:00
|
|
|
|
(defcustom ein:notebook-querty-timeout-save (* 60 1000) ; 1 min
|
2012-06-21 00:38:15 +02:00
|
|
|
|
"Query timeout for saving notebook.
|
|
|
|
|
Similar to `ein:notebook-querty-timeout-open', but for saving
|
|
|
|
|
notebook. For global setting and more information, see
|
|
|
|
|
`ein:query-timeout'."
|
2012-06-21 00:01:23 +02:00
|
|
|
|
:type '(choice (integer :tag "Timeout [ms]" 5000)
|
2012-06-21 03:53:51 +02:00
|
|
|
|
(const :tag "Use global setting" nil))
|
2012-06-21 00:01:23 +02:00
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-09-05 23:27:17 +02:00
|
|
|
|
(defcustom ein:helm-kernel-history-search-key nil
|
|
|
|
|
"Bind `helm-ein-kernel-history' to this key in notebook mode.
|
|
|
|
|
|
|
|
|
|
Example::
|
|
|
|
|
|
|
|
|
|
(setq ein:helm-kernel-history-search-key \"\\M-r\")
|
|
|
|
|
|
|
|
|
|
This key will be installed in the `ein:notebook-mode-map'."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:anything-kernel-history-search-key nil
|
|
|
|
|
"Bind `anything-ein-kernel-history' to this key in notebook mode.
|
|
|
|
|
|
|
|
|
|
Example::
|
|
|
|
|
|
|
|
|
|
(setq ein:anything-kernel-history-search-key \"\\M-r\")
|
|
|
|
|
|
|
|
|
|
This key will be installed in the `ein:notebook-mode-map'."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-10-09 15:43:15 +02:00
|
|
|
|
(defcustom ein:notebook-set-buffer-file-name nil
|
2015-05-16 07:46:47 -05:00
|
|
|
|
"[DEPRECATED] Set `buffer-file-name' of notebook buffer. Currently does nothing."
|
2012-10-09 15:43:15 +02:00
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-06-26 17:03:36 +02:00
|
|
|
|
(defvar ein:notebook-after-rename-hook nil
|
|
|
|
|
"Hooks to run after notebook is renamed successfully.
|
|
|
|
|
Current buffer for these functions is set to the notebook buffer.")
|
|
|
|
|
|
2012-05-25 00:23:09 +02:00
|
|
|
|
|
|
|
|
|
;;; Class and variable
|
|
|
|
|
|
2014-04-14 12:48:55 -05:00
|
|
|
|
(defvar ein:base-kernel-url "/api/")
|
|
|
|
|
(defvar ein:create-session-url "/api/sessions")
|
|
|
|
|
;; Currently there is no way to know this setting. Maybe I should ask IPython
|
|
|
|
|
;; developers for an API to get this from notebook server.
|
|
|
|
|
;;
|
|
|
|
|
;; 10April2014 (JMM) - The most recent documentation for the RESTful interface
|
|
|
|
|
;; is at:
|
|
|
|
|
;; https://github.com/ipython/ipython/wiki/IPEP-16%3A-Notebook-multi-directory-dashboard-and-URL-mapping
|
|
|
|
|
|
2012-05-22 20:50:47 +02:00
|
|
|
|
|
2012-05-14 17:07:09 +02:00
|
|
|
|
(defvar ein:notebook-pager-buffer-name-template "*ein:pager %s/%s*")
|
2012-05-13 04:29:27 +02:00
|
|
|
|
(defvar ein:notebook-buffer-name-template "*ein: %s/%s*")
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-05-17 04:08:18 +02:00
|
|
|
|
(defvar ein:notebook-save-retry-max 1
|
|
|
|
|
"Maximum retries for notebook saving.")
|
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(defstruct ein:$notebook
|
2012-05-13 02:51:47 +02:00
|
|
|
|
"Hold notebook variables.
|
|
|
|
|
|
|
|
|
|
`ein:$notebook-url-or-port'
|
|
|
|
|
URL or port of IPython server.
|
|
|
|
|
|
2012-05-13 05:46:24 +02:00
|
|
|
|
`ein:$notebook-notebook-id' : string
|
2014-04-14 12:48:55 -05:00
|
|
|
|
uuid string (as of ipython 2.0 this is the same is notebook-name).
|
|
|
|
|
|
|
|
|
|
`ein:$notebook-notebook-path' : string
|
|
|
|
|
Path to notebook.
|
2012-05-13 05:46:24 +02:00
|
|
|
|
|
|
|
|
|
`ein:$notebook-kernel' : `ein:$kernel'
|
|
|
|
|
`ein:$kernel' instance.
|
|
|
|
|
|
2012-08-26 16:46:33 +02:00
|
|
|
|
`ein:$notebook-kernelinfo' : `ein:kernelinfo'
|
|
|
|
|
`ein:kernelinfo' instance.
|
2012-08-26 15:14:59 +02:00
|
|
|
|
|
2012-05-13 05:46:24 +02:00
|
|
|
|
`ein:$notebook-pager'
|
|
|
|
|
Variable for `ein:pager-*' functions. See ein-pager.el.
|
|
|
|
|
|
|
|
|
|
`ein:$notebook-dirty' : boolean
|
|
|
|
|
Set to `t' if notebook has unsaved changes. Otherwise `nil'.
|
|
|
|
|
|
|
|
|
|
`ein:$notebook-metadata' : plist
|
|
|
|
|
Notebook meta data (e.g., notebook name).
|
|
|
|
|
|
|
|
|
|
`ein:$notebook-name' : string
|
|
|
|
|
Notebook name.
|
|
|
|
|
|
|
|
|
|
`ein:$notebook-nbformat' : integer
|
2012-05-22 13:56:24 +02:00
|
|
|
|
Notebook file format version.
|
|
|
|
|
|
2012-08-12 19:43:39 +02:00
|
|
|
|
`ein:$notebook-nbformat-minor' : integer
|
|
|
|
|
Notebook file format version.
|
|
|
|
|
|
2012-05-22 13:56:24 +02:00
|
|
|
|
`ein:$notebook-events' : `ein:$events'
|
2012-05-25 02:02:31 +02:00
|
|
|
|
Event handler instance.
|
|
|
|
|
|
2012-08-19 11:58:04 +02:00
|
|
|
|
`ein:$notebook-worksheets' : list of `ein:worksheet'
|
|
|
|
|
List of worksheets.
|
2012-08-26 22:56:19 +02:00
|
|
|
|
|
|
|
|
|
`ein:$notebook-scratchsheets' : list of `ein:worksheet'
|
|
|
|
|
List of scratch worksheets.
|
2014-10-17 16:44:04 -05:00
|
|
|
|
|
|
|
|
|
`ein:$notebook-api-version' : integer
|
|
|
|
|
Major version of the IPython notebook server we are talking to.
|
2012-08-13 18:47:21 +02:00
|
|
|
|
"
|
2012-05-13 02:51:47 +02:00
|
|
|
|
url-or-port
|
2014-04-14 12:48:55 -05:00
|
|
|
|
notebook-id ;; In IPython-2.0 this is "[:path]/[:name].ipynb"
|
|
|
|
|
notebook-path
|
2012-05-13 05:46:24 +02:00
|
|
|
|
kernel
|
2012-08-26 15:14:59 +02:00
|
|
|
|
kernelinfo
|
2012-05-13 05:46:24 +02:00
|
|
|
|
pager
|
|
|
|
|
dirty
|
|
|
|
|
metadata
|
|
|
|
|
notebook-name
|
|
|
|
|
nbformat
|
2012-08-12 19:43:39 +02:00
|
|
|
|
nbformat-minor
|
2012-05-22 13:56:24 +02:00
|
|
|
|
events
|
2012-08-19 11:58:04 +02:00
|
|
|
|
worksheets
|
2012-08-26 22:56:19 +02:00
|
|
|
|
scratchsheets
|
2014-10-17 16:44:04 -05:00
|
|
|
|
api-version
|
2012-05-07 14:41:15 +02:00
|
|
|
|
)
|
|
|
|
|
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(ein:deflocal ein:%notebook% nil
|
2012-05-12 22:55:06 +02:00
|
|
|
|
"Buffer local variable to store an instance of `ein:$notebook'.")
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(define-obsolete-variable-alias 'ein:notebook 'ein:%notebook% "0.1.2")
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2014-04-14 12:48:55 -05:00
|
|
|
|
|
2012-08-27 18:34:25 +02:00
|
|
|
|
|
|
|
|
|
;;; Constructor
|
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-new (url-or-port notebook-path &rest args)
|
2012-05-11 05:24:34 +02:00
|
|
|
|
(let ((notebook (apply #'make-ein:$notebook
|
2012-05-13 02:51:47 +02:00
|
|
|
|
:url-or-port url-or-port
|
2014-04-14 12:48:55 -05:00
|
|
|
|
:notebook-path notebook-path
|
2012-05-11 05:24:34 +02:00
|
|
|
|
args)))
|
|
|
|
|
notebook))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-08-27 18:34:25 +02:00
|
|
|
|
|
|
|
|
|
;;; Destructor
|
|
|
|
|
|
2012-05-19 17:58:02 +02:00
|
|
|
|
(defun ein:notebook-del (notebook)
|
|
|
|
|
"Destructor for `ein:$notebook'."
|
2012-05-25 16:11:26 +02:00
|
|
|
|
(ein:log-ignore-errors
|
|
|
|
|
(ein:kernel-del (ein:$notebook-kernel notebook))))
|
2012-05-19 17:58:02 +02:00
|
|
|
|
|
2012-08-26 23:33:51 +02:00
|
|
|
|
(defun ein:notebook-close-worksheet (notebook ws)
|
|
|
|
|
"Close worksheet WS in NOTEBOOK. If WS is the last worksheet,
|
|
|
|
|
call notebook destructor `ein:notebook-del'."
|
2012-08-28 00:52:39 +02:00
|
|
|
|
(symbol-macrolet ((worksheets (ein:$notebook-worksheets notebook))
|
|
|
|
|
(scratchsheets (ein:$notebook-scratchsheets notebook)))
|
2012-08-29 19:07:53 +02:00
|
|
|
|
(cond
|
2012-08-30 02:42:49 +02:00
|
|
|
|
((ein:worksheet-p ws) (ein:worksheet-save-cells ws t))
|
2012-08-29 19:07:53 +02:00
|
|
|
|
(t (setq scratchsheets (delq ws scratchsheets))))
|
|
|
|
|
(unless (or (ein:filter (lambda (x)
|
|
|
|
|
(and (not (eq x ws))
|
|
|
|
|
(ein:worksheet-has-buffer-p x)))
|
|
|
|
|
worksheets)
|
|
|
|
|
scratchsheets)
|
2012-08-26 23:33:51 +02:00
|
|
|
|
(ein:notebook-del notebook))))
|
|
|
|
|
|
2012-08-27 18:34:25 +02:00
|
|
|
|
|
|
|
|
|
;;; Notebook utility functions
|
|
|
|
|
|
2012-05-17 20:12:40 +02:00
|
|
|
|
(defun ein:notebook-buffer (notebook)
|
|
|
|
|
"Return the buffer that is associated with NOTEBOOK."
|
2012-09-11 01:47:50 +02:00
|
|
|
|
;; FIXME: Find a better way to define notebook buffer!
|
|
|
|
|
;; For example, the last accessed buffer.
|
2012-08-29 20:14:55 +02:00
|
|
|
|
(let ((first-buffer
|
|
|
|
|
(lambda (ws-list)
|
|
|
|
|
(loop for ws in ws-list if (ein:worksheet-buffer ws) return it))))
|
|
|
|
|
(or (funcall first-buffer (ein:$notebook-worksheets notebook))
|
|
|
|
|
(funcall first-buffer (ein:$notebook-scratchsheets notebook)))))
|
2012-05-17 20:12:40 +02:00
|
|
|
|
|
2012-08-26 16:11:56 +02:00
|
|
|
|
(defun ein:notebook-buffer-list (notebook)
|
|
|
|
|
"Return the buffers associated with NOTEBOOK's kernel.
|
|
|
|
|
The buffer local variable `default-directory' of these buffers
|
|
|
|
|
will be updated with kernel's cwd."
|
2012-08-26 22:56:37 +02:00
|
|
|
|
(ein:filter #'identity
|
|
|
|
|
(mapcar #'ein:worksheet-buffer
|
|
|
|
|
(append (ein:$notebook-worksheets notebook)
|
|
|
|
|
(ein:$notebook-scratchsheets notebook)))))
|
2012-08-26 16:11:56 +02:00
|
|
|
|
|
2012-08-27 00:32:40 +02:00
|
|
|
|
(defun ein:notebook--get-nb-or-error ()
|
|
|
|
|
(or ein:%notebook% (error "Not in notebook buffer.")))
|
|
|
|
|
|
2012-09-01 20:51:55 +02:00
|
|
|
|
;;;###autoload
|
2012-08-14 20:39:05 +02:00
|
|
|
|
(defalias 'ein:notebook-name 'ein:$notebook-notebook-name)
|
|
|
|
|
|
2012-08-28 18:00:07 +02:00
|
|
|
|
(defun ein:notebook-name-getter (notebook)
|
|
|
|
|
(cons #'ein:notebook-name notebook))
|
|
|
|
|
|
2012-08-27 18:34:25 +02:00
|
|
|
|
|
|
|
|
|
;;; Open notebook
|
|
|
|
|
|
2012-05-12 23:13:28 +02:00
|
|
|
|
(defun ein:notebook-url (notebook)
|
2012-05-13 02:51:47 +02:00
|
|
|
|
(ein:notebook-url-from-url-and-id (ein:$notebook-url-or-port notebook)
|
2014-10-17 16:44:04 -05:00
|
|
|
|
(ein:$notebook-api-version notebook)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:$notebook-notebook-path notebook)))
|
2012-05-12 23:13:28 +02:00
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-url-from-url-and-id (url-or-port api-version path)
|
2014-10-17 16:44:04 -05:00
|
|
|
|
(cond ((= 2 api-version)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:url url-or-port "api/notebooks" path))
|
2014-10-17 16:44:04 -05:00
|
|
|
|
((= 3 api-version)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:url url-or-port "api/contents" path))))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-07-12 02:44:34 +02:00
|
|
|
|
(defun ein:notebook-pop-to-current-buffer (&rest -ignore-)
|
|
|
|
|
"Default callback for `ein:notebook-open'."
|
|
|
|
|
(pop-to-buffer (current-buffer)))
|
|
|
|
|
|
2014-09-11 20:04:00 -05:00
|
|
|
|
;;; TODO - I think notebook-path is unnecessary (JMM).
|
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-open (url-or-port path &optional callback cbargs)
|
|
|
|
|
"Open notebook at PATH in the server URL-OR-PORT.
|
2012-06-08 11:42:42 +02:00
|
|
|
|
Opened notebook instance is returned. Note that notebook might not be
|
|
|
|
|
ready at the time when this function is executed.
|
|
|
|
|
|
2012-07-12 02:44:34 +02:00
|
|
|
|
After the notebook is opened, CALLBACK is called as::
|
|
|
|
|
|
2012-06-08 11:42:42 +02:00
|
|
|
|
\(apply CALLBACK notebook CREATED CBARGS)
|
2012-07-12 02:44:34 +02:00
|
|
|
|
|
2012-06-08 11:42:42 +02:00
|
|
|
|
where the second argument CREATED indicates whether the notebook
|
2012-07-12 02:44:34 +02:00
|
|
|
|
is newly created or not. When CALLBACK is specified, buffer is
|
|
|
|
|
**not** brought up by `pop-to-buffer'. It is caller's
|
|
|
|
|
responsibility to do so. The current buffer is set to the
|
|
|
|
|
notebook buffer when CALLBACK is called."
|
2015-12-04 14:15:41 -06:00
|
|
|
|
;(interactive)
|
2012-07-12 02:44:34 +02:00
|
|
|
|
(unless callback (setq callback #'ein:notebook-pop-to-current-buffer))
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(let ((buffer (ein:notebook-get-opened-buffer url-or-port path)))
|
2012-05-18 03:48:36 +02:00
|
|
|
|
(if (buffer-live-p buffer)
|
|
|
|
|
(with-current-buffer buffer
|
2012-09-07 00:01:27 +02:00
|
|
|
|
(ein:log 'info "Notebook %s is already opened."
|
|
|
|
|
(ein:$notebook-notebook-name ein:%notebook%))
|
2012-06-08 11:42:42 +02:00
|
|
|
|
(when callback
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(apply callback ein:%notebook% nil cbargs))
|
|
|
|
|
ein:%notebook%)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:log 'info "Opening notebook %s..." path)
|
|
|
|
|
(ein:notebook-request-open url-or-port path callback cbargs))))
|
2012-05-18 03:39:39 +02:00
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-request-open (url-or-port path &optional callback cbargs)
|
|
|
|
|
"Request notebook at PATH from the server at URL-OR-PORT.
|
|
|
|
|
Return an `ein:$notebook' instance. Notebook kernel may not be ready to
|
|
|
|
|
receive messages after this call is executed.
|
2012-06-08 11:42:42 +02:00
|
|
|
|
|
|
|
|
|
CALLBACK is called as \(apply CALLBACK notebook t CBARGS). The second
|
|
|
|
|
argument `t' indicates that the notebook is newly opened.
|
|
|
|
|
See `ein:notebook-open' for more information."
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(let ((notebook (ein:notebook-new url-or-port path)))
|
|
|
|
|
(ein:log 'debug "Opening notebook at %s" path)
|
|
|
|
|
(ein:content-query-contents path url-or-port nil
|
|
|
|
|
(apply-partially #'ein:notebook-request-open-callback-with-callback
|
|
|
|
|
notebook callback cbargs))
|
|
|
|
|
;; (ein:query-singleton-ajax
|
|
|
|
|
;; (list 'notebook-open url-or-port api-version path)
|
|
|
|
|
;; url
|
|
|
|
|
;; :timeout ein:notebook-querty-timeout-open
|
|
|
|
|
;; :parser #'ein:json-read
|
|
|
|
|
;; :success (apply-partially
|
|
|
|
|
;; #'ein:notebook-request-open-callback-with-callback
|
|
|
|
|
;; notebook callback cbargs))
|
2012-05-17 20:12:40 +02:00
|
|
|
|
notebook))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2014-04-14 12:48:55 -05:00
|
|
|
|
|
2012-12-29 17:17:39 +01:00
|
|
|
|
(defun ein:notebook-request-open-callback-with-callback (notebook
|
|
|
|
|
callback
|
|
|
|
|
cbargs
|
2015-02-10 14:53:08 -06:00
|
|
|
|
content)
|
|
|
|
|
(funcall #'ein:notebook-request-open-callback notebook content)
|
2012-12-29 17:52:05 +01:00
|
|
|
|
(when callback
|
|
|
|
|
(with-current-buffer (ein:notebook-buffer notebook)
|
|
|
|
|
(apply callback notebook t cbargs))))
|
2012-06-08 11:42:42 +02:00
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-request-open-callback (notebook content)
|
|
|
|
|
(let ((notebook-path (ein:$notebook-notebook-path notebook)))
|
|
|
|
|
(setf (ein:$notebook-api-version notebook) (ein:$content-ipython-version content)
|
|
|
|
|
(ein:$notebook-notebook-name notebook) (ein:$content-name content))
|
2012-08-19 17:13:09 +02:00
|
|
|
|
(ein:notebook-bind-events notebook (ein:events-new))
|
|
|
|
|
(ein:notebook-start-kernel notebook)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:notebook-from-json notebook (ein:$content-raw-content content)) ; notebook buffer is created here
|
2012-08-26 15:14:59 +02:00
|
|
|
|
(setf (ein:$notebook-kernelinfo notebook)
|
2012-08-26 16:53:22 +02:00
|
|
|
|
(ein:kernelinfo-new (ein:$notebook-kernel notebook)
|
|
|
|
|
(cons #'ein:notebook-buffer-list notebook)))
|
2012-08-19 11:58:04 +02:00
|
|
|
|
(ein:notebook-put-opened-notebook notebook)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:notebook--check-nbformat (ein:$content-raw-content content))
|
2012-08-19 11:58:04 +02:00
|
|
|
|
(ein:log 'info "Notebook %s is ready"
|
|
|
|
|
(ein:$notebook-notebook-name notebook))))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-08-12 19:33:39 +02:00
|
|
|
|
(defun ein:notebook--different-number (n1 n2)
|
|
|
|
|
(and (numberp n1) (numberp n2) (not (= n1 n2))))
|
|
|
|
|
|
|
|
|
|
(defun ein:notebook--check-nbformat (data)
|
|
|
|
|
"Warn user when nbformat is changed on server side.
|
|
|
|
|
See https://github.com/ipython/ipython/pull/1934 for the purpose
|
|
|
|
|
of minor mode."
|
|
|
|
|
;; See `Notebook.prototype.load_notebook_success'
|
|
|
|
|
;; at IPython/frontend/html/notebook/static/js/notebook.js
|
|
|
|
|
(destructuring-bind (&key nbformat orig_nbformat
|
|
|
|
|
nbformat_minor orig_nbformat_minor
|
|
|
|
|
&allow-other-keys)
|
|
|
|
|
data
|
|
|
|
|
(cond
|
|
|
|
|
((ein:notebook--different-number nbformat orig_nbformat)
|
|
|
|
|
(ein:display-warning
|
|
|
|
|
(format "Notebook major version updated (v%d -> v%d).
|
|
|
|
|
To not update version, do not save this notebook."
|
|
|
|
|
orig_nbformat nbformat)))
|
|
|
|
|
((ein:notebook--different-number nbformat_minor orig_nbformat_minor)
|
|
|
|
|
(ein:display-warning
|
|
|
|
|
(format "This notebook is version v%s.%s, but IPython
|
|
|
|
|
server you are using only fully support up to v%s.%s.
|
|
|
|
|
Some features may not be available."
|
|
|
|
|
orig_nbformat orig_nbformat_minor
|
|
|
|
|
nbformat nbformat_minor))))))
|
|
|
|
|
|
2012-05-22 20:50:47 +02:00
|
|
|
|
|
|
|
|
|
;;; Initialization.
|
|
|
|
|
|
|
|
|
|
(defun ein:notebook-bind-events (notebook events)
|
|
|
|
|
"Bind events related to PAGER to the event handler EVENTS."
|
2012-08-19 17:13:09 +02:00
|
|
|
|
(setf (ein:$notebook-events notebook) events)
|
2012-08-27 23:21:47 +02:00
|
|
|
|
(ein:worksheet-class-bind-events events)
|
2012-05-22 20:50:47 +02:00
|
|
|
|
;; Bind events for sub components:
|
|
|
|
|
(setf (ein:$notebook-pager notebook)
|
|
|
|
|
(ein:pager-new
|
|
|
|
|
(format ein:notebook-pager-buffer-name-template
|
|
|
|
|
(ein:$notebook-url-or-port notebook)
|
|
|
|
|
(ein:$notebook-notebook-name notebook))
|
|
|
|
|
(ein:$notebook-events notebook))))
|
|
|
|
|
|
2012-08-15 21:41:05 +02:00
|
|
|
|
(define-obsolete-function-alias
|
|
|
|
|
'ein:notebook-show-in-shared-output
|
|
|
|
|
'ein:shared-output-show-code-cell-at-point "0.1.2")
|
2012-06-07 16:08:00 +02:00
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
|
|
|
|
;;; Kernel related things
|
|
|
|
|
|
2014-04-14 12:48:55 -05:00
|
|
|
|
;;; This no longer works in iPython-2.0. Protocol is to create a session for a
|
2014-09-11 20:04:00 -05:00
|
|
|
|
;;; notebook, which will automatically create and associate a kernel with the notebook.
|
2012-08-19 17:13:09 +02:00
|
|
|
|
(defun ein:notebook-start-kernel (notebook)
|
2012-05-22 20:50:47 +02:00
|
|
|
|
(let* ((base-url (concat ein:base-kernel-url "kernels"))
|
2012-08-19 17:13:09 +02:00
|
|
|
|
(kernel (ein:kernel-new (ein:$notebook-url-or-port notebook)
|
2012-05-22 22:34:00 +02:00
|
|
|
|
base-url
|
2014-10-17 16:44:04 -05:00
|
|
|
|
(ein:$notebook-events notebook)
|
|
|
|
|
(ein:$notebook-api-version notebook))))
|
2012-08-19 17:13:09 +02:00
|
|
|
|
(setf (ein:$notebook-kernel notebook) kernel)
|
2015-05-15 23:23:56 -05:00
|
|
|
|
(ein:pytools-setup-hooks kernel notebook)
|
2015-05-04 22:59:18 -05:00
|
|
|
|
(ein:kernel-start kernel notebook)))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-05-17 05:35:38 +02:00
|
|
|
|
(defun ein:notebook-restart-kernel (notebook)
|
2012-05-22 20:50:47 +02:00
|
|
|
|
(ein:kernel-restart (ein:$notebook-kernel notebook)))
|
2012-05-17 05:35:38 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:notebook-restart-kernel-command ()
|
2012-06-11 06:15:34 +02:00
|
|
|
|
"Send request to the server to restart kernel."
|
2012-05-17 05:35:38 +02:00
|
|
|
|
(interactive)
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(if ein:%notebook%
|
2012-05-17 05:35:38 +02:00
|
|
|
|
(when (y-or-n-p "Really restart kernel? ")
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(ein:notebook-restart-kernel ein:%notebook%))
|
2012-05-17 05:35:38 +02:00
|
|
|
|
(ein:log 'error "Not in notebook buffer!")))
|
|
|
|
|
|
2015-07-05 22:27:52 -05:00
|
|
|
|
(defun ein:notebook-reconnect-kernel ()
|
|
|
|
|
"Reconnect to the websocket connection for the running kernel."
|
|
|
|
|
(interactive)
|
|
|
|
|
(if ein:%notebook%
|
|
|
|
|
(ein:kernel-reconnect (ein:$notebook-kernel ein:%notebook%) ein:%notebook%)))
|
|
|
|
|
|
2012-08-19 21:36:35 +02:00
|
|
|
|
(define-obsolete-function-alias
|
|
|
|
|
'ein:notebook-request-tool-tip-or-help-command
|
|
|
|
|
'ein:pytools-request-tooltip-or-help "0.1.2")
|
2012-05-18 04:31:57 +02:00
|
|
|
|
|
2012-07-29 18:08:30 +02:00
|
|
|
|
(defun ein:notebook-complete-dot ()
|
|
|
|
|
"Insert dot and request completion."
|
|
|
|
|
(interactive)
|
2012-08-20 02:58:08 +02:00
|
|
|
|
(if (and ein:%notebook% (ein:codecell-p (ein:get-cell-at-point)))
|
|
|
|
|
(ein:completer-dot-complete)
|
|
|
|
|
(insert ".")))
|
2012-07-29 18:08:30 +02:00
|
|
|
|
|
2012-05-13 07:32:43 +02:00
|
|
|
|
(defun ein:notebook-kernel-interrupt-command ()
|
2012-06-11 06:15:34 +02:00
|
|
|
|
"Interrupt the kernel.
|
|
|
|
|
This is equivalent to do ``C-c`` in the console program."
|
2012-05-13 07:32:43 +02:00
|
|
|
|
(interactive)
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(ein:kernel-interrupt (ein:$notebook-kernel ein:%notebook%)))
|
2012-05-13 07:32:43 +02:00
|
|
|
|
|
2012-05-13 07:37:19 +02:00
|
|
|
|
(defun ein:notebook-kernel-kill-command ()
|
|
|
|
|
(interactive)
|
|
|
|
|
(when (y-or-n-p "Really kill kernel?")
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(ein:kernel-kill (ein:$notebook-kernel ein:%notebook%))))
|
2012-05-13 07:37:19 +02:00
|
|
|
|
|
2012-07-29 14:43:10 +02:00
|
|
|
|
;; autoexec
|
|
|
|
|
|
2012-07-29 14:58:56 +02:00
|
|
|
|
(defun ein:notebook-execute-autoexec-cells (notebook)
|
2012-07-29 16:52:54 +02:00
|
|
|
|
"Execute cells of which auto-execution flag is on."
|
2012-08-20 04:23:53 +02:00
|
|
|
|
(interactive (list (or ein:%notebook% (error "Not in notebook buffer!"))))
|
2012-08-20 02:44:46 +02:00
|
|
|
|
(mapc #'ein:worksheet-execute-autoexec-cells
|
|
|
|
|
(ein:$notebook-worksheets notebook)))
|
2012-07-29 14:58:56 +02:00
|
|
|
|
|
2012-08-15 23:08:35 +02:00
|
|
|
|
(define-obsolete-function-alias
|
|
|
|
|
'ein:notebook-eval-string
|
|
|
|
|
'ein:shared-output-eval-string "0.1.2")
|
2012-06-02 20:40:22 +02:00
|
|
|
|
|
2012-05-08 06:15:23 +02:00
|
|
|
|
|
2012-08-27 18:34:25 +02:00
|
|
|
|
;;; Persistence and loading
|
2012-05-08 06:15:23 +02:00
|
|
|
|
|
2012-05-13 05:06:49 +02:00
|
|
|
|
(defun ein:notebook-set-notebook-name (notebook name)
|
|
|
|
|
"Check NAME and change the name of NOTEBOOK to it."
|
|
|
|
|
(if (ein:notebook-test-notebook-name name)
|
2014-11-11 11:33:14 -06:00
|
|
|
|
(setf (ein:$notebook-notebook-name notebook) name
|
|
|
|
|
(ein:$notebook-notebook-id notebook) name)
|
2012-05-13 05:06:49 +02:00
|
|
|
|
(ein:log 'error "%S is not a good notebook name." name)
|
|
|
|
|
(error "%S is not a good notebook name." name)))
|
|
|
|
|
|
2012-05-13 04:47:41 +02:00
|
|
|
|
(defun ein:notebook-test-notebook-name (name)
|
|
|
|
|
(and (stringp name)
|
|
|
|
|
(> (length name) 0)
|
2012-10-15 18:39:50 +02:00
|
|
|
|
(not (string-match "[\\/\\\\:]" name))))
|
2012-05-13 04:47:41 +02:00
|
|
|
|
|
2012-08-28 17:55:45 +02:00
|
|
|
|
(defun* ein:notebook--worksheet-new (notebook
|
|
|
|
|
&optional (func #'ein:worksheet-new))
|
2012-08-28 20:51:18 +02:00
|
|
|
|
(funcall func
|
2012-08-28 17:55:45 +02:00
|
|
|
|
(ein:$notebook-nbformat notebook)
|
2012-08-28 18:00:07 +02:00
|
|
|
|
(ein:notebook-name-getter notebook)
|
2012-08-28 20:51:18 +02:00
|
|
|
|
(cons (lambda (notebook cell)
|
|
|
|
|
(ein:notebook-discard-output-p notebook cell))
|
|
|
|
|
notebook)
|
2012-08-28 17:55:45 +02:00
|
|
|
|
(ein:$notebook-kernel notebook)
|
|
|
|
|
(ein:$notebook-events notebook)))
|
|
|
|
|
|
2012-08-28 18:12:51 +02:00
|
|
|
|
(defun ein:notebook--worksheet-render (notebook ws)
|
|
|
|
|
(ein:worksheet-render ws)
|
|
|
|
|
(with-current-buffer (ein:worksheet-buffer ws)
|
|
|
|
|
(ein:notebook-mode)
|
2012-08-28 22:42:14 +02:00
|
|
|
|
;; Now that major-mode is set, set buffer local variables:
|
2012-10-09 23:35:36 +02:00
|
|
|
|
(ein:notebook--notification-setup notebook)
|
2012-08-28 18:12:51 +02:00
|
|
|
|
(ein:notebook-setup-kill-buffer-hook)
|
2015-05-16 07:46:47 -05:00
|
|
|
|
;(ein:notebook-set-buffer-file-name-maybe notebook)
|
2012-08-28 18:12:51 +02:00
|
|
|
|
(setq ein:%notebook% notebook)))
|
|
|
|
|
|
2012-10-09 23:35:36 +02:00
|
|
|
|
(defun ein:notebook--notification-setup (notebook)
|
|
|
|
|
(ein:notification-setup
|
|
|
|
|
(current-buffer)
|
|
|
|
|
(ein:$notebook-events notebook)
|
|
|
|
|
:get-list
|
|
|
|
|
(lambda () (ein:$notebook-worksheets ein:%notebook%))
|
|
|
|
|
:get-current
|
|
|
|
|
(lambda () ein:%worksheet%)
|
|
|
|
|
:get-name
|
|
|
|
|
#'ein:worksheet-name
|
|
|
|
|
:get-buffer
|
|
|
|
|
(lambda (ws)
|
|
|
|
|
(ein:notebook-worksheet--render-maybe ein:%notebook% ws "clicked")
|
|
|
|
|
(ein:worksheet-buffer ws))
|
|
|
|
|
:delete
|
|
|
|
|
(lambda (ws)
|
|
|
|
|
(ein:notebook-worksheet-delete ein:%notebook% ws t))
|
2012-10-09 23:47:11 +02:00
|
|
|
|
:insert-prev
|
|
|
|
|
(lambda (ws) (ein:notebook-worksheet-insert-prev ein:%notebook% ws))
|
|
|
|
|
:insert-next
|
|
|
|
|
(lambda (ws) (ein:notebook-worksheet-insert-next ein:%notebook% ws))
|
2012-10-10 00:06:54 +02:00
|
|
|
|
:move-prev
|
|
|
|
|
(lambda (ws) (ein:notebook-worksheet-move-prev ein:%notebook% ws))
|
|
|
|
|
:move-next
|
|
|
|
|
(lambda (ws) (ein:notebook-worksheet-move-next ein:%notebook% ws))
|
2012-10-09 23:35:36 +02:00
|
|
|
|
))
|
|
|
|
|
|
2012-10-09 15:43:15 +02:00
|
|
|
|
(defun ein:notebook-set-buffer-file-name-maybe (notebook)
|
|
|
|
|
"Set `buffer-file-name' of the current buffer to ipynb file
|
|
|
|
|
of NOTEBOOK."
|
|
|
|
|
(when ein:notebook-set-buffer-file-name
|
|
|
|
|
(ein:notebook-fetch-data
|
|
|
|
|
notebook
|
|
|
|
|
(lambda (data notebook buffer)
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(destructuring-bind (&key project &allow-other-keys)
|
|
|
|
|
data
|
|
|
|
|
(setq buffer-file-name
|
|
|
|
|
(expand-file-name
|
|
|
|
|
(format "%s.ipynb"
|
|
|
|
|
(ein:$notebook-notebook-name notebook))
|
|
|
|
|
project)))))
|
|
|
|
|
(list notebook (current-buffer)))))
|
|
|
|
|
|
2012-05-08 06:41:17 +02:00
|
|
|
|
(defun ein:notebook-from-json (notebook data)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(destructuring-bind (&key metadata nbformat nbformat_minor
|
|
|
|
|
&allow-other-keys)
|
|
|
|
|
data
|
|
|
|
|
(setf (ein:$notebook-metadata notebook) metadata)
|
|
|
|
|
(setf (ein:$notebook-nbformat notebook) nbformat)
|
|
|
|
|
(setf (ein:$notebook-nbformat-minor notebook) nbformat_minor)
|
|
|
|
|
;;(setf (ein:$notebook-notebook-name notebook) (plist-get metadata :name))
|
|
|
|
|
)
|
|
|
|
|
(setf (ein:$notebook-worksheets notebook)
|
|
|
|
|
(cl-case (ein:$notebook-nbformat notebook)
|
|
|
|
|
(3 (ein:read-nbformat3-worksheets notebook data))
|
|
|
|
|
(4 (ein:read-nbformat4-worksheets notebook data))
|
|
|
|
|
(t (ein:log 'error "Do not currently support nbformat version %s" (ein:$notebook-nbformat notebook)))))
|
|
|
|
|
(ein:notebook--worksheet-render notebook
|
|
|
|
|
(nth 0 (ein:$notebook-worksheets notebook)))
|
|
|
|
|
notebook)
|
2012-05-08 06:41:17 +02:00
|
|
|
|
|
2014-11-07 19:28:09 -06:00
|
|
|
|
(defun ein:read-nbformat3-worksheets (notebook data)
|
|
|
|
|
(mapcar (lambda (ws-data)
|
|
|
|
|
(ein:worksheet-from-json
|
|
|
|
|
(ein:notebook--worksheet-new notebook)
|
|
|
|
|
ws-data))
|
|
|
|
|
(or (plist-get data :worksheets)
|
|
|
|
|
(list nil))))
|
|
|
|
|
|
|
|
|
|
;; nbformat4 gets rid of the concenpt of worksheets. That means, for the moment,
|
|
|
|
|
;; ein will no longer support worksheets. There may be a path forward for
|
|
|
|
|
;; reimplementing this feature, however. The nbformat 4 json definition says
|
|
|
|
|
;; that cells are allowed to have tags. Clever use of this feature may lead to
|
|
|
|
|
;; good things.
|
|
|
|
|
|
|
|
|
|
(defun ein:read-nbformat4-worksheets (notebook data)
|
|
|
|
|
"Convert a notebook in nbformat4 to a list of worksheet-like
|
|
|
|
|
objects suitable for processing in ein:notebook-from-json."
|
|
|
|
|
(ein:log 'info "Reading nbformat4 notebook.")
|
|
|
|
|
(let* ((cells (plist-get data :cells))
|
|
|
|
|
(ws-cells (mapcar (lambda (data) (ein:cell-from-json data)) cells))
|
|
|
|
|
(worksheet (ein:notebook--worksheet-new notebook)))
|
|
|
|
|
(oset worksheet :saved-cells ws-cells)
|
|
|
|
|
(list worksheet)))
|
|
|
|
|
|
2012-05-08 06:15:23 +02:00
|
|
|
|
(defun ein:notebook-to-json (notebook)
|
2012-05-08 08:26:56 +02:00
|
|
|
|
"Return json-ready alist."
|
2015-02-12 08:45:29 -06:00
|
|
|
|
(let ((data
|
|
|
|
|
(case (ein:$notebook-nbformat notebook)
|
|
|
|
|
(3 (ein:write-nbformat3-worksheets notebook))
|
|
|
|
|
(4 (ein:write-nbformat4-worksheets notebook))
|
|
|
|
|
(t (ein:log 'error "EIN does not support saving notebook format %s" (ein:$notebook-nbformat notebook))))))
|
|
|
|
|
(plist-put (cdr (assq 'metadata data))
|
|
|
|
|
:name (ein:$notebook-notebook-name notebook))
|
|
|
|
|
(ein:aif (ein:$notebook-nbformat-minor notebook)
|
|
|
|
|
;; Do not set nbformat when it is not given from server.
|
|
|
|
|
(push `(nbformat_minor . ,it) data))
|
2015-03-25 09:52:16 -05:00
|
|
|
|
(push `(nbformat . ,(ein:$notebook-nbformat notebook)) data)
|
2015-02-12 08:45:29 -06:00
|
|
|
|
data))
|
2014-11-07 19:28:09 -06:00
|
|
|
|
|
2015-12-22 12:32:21 -06:00
|
|
|
|
|
2014-11-07 19:28:09 -06:00
|
|
|
|
(defun ein:write-nbformat3-worksheets (notebook)
|
2012-08-19 17:40:41 +02:00
|
|
|
|
(let ((worksheets (mapcar #'ein:worksheet-to-json
|
|
|
|
|
(ein:$notebook-worksheets notebook))))
|
|
|
|
|
`((worksheets . ,(apply #'vector worksheets))
|
2014-04-14 12:48:55 -05:00
|
|
|
|
(metadata . ,(ein:$notebook-metadata notebook))
|
|
|
|
|
)))
|
2012-05-08 06:15:23 +02:00
|
|
|
|
|
2014-11-07 19:28:09 -06:00
|
|
|
|
(defun ein:write-nbformat4-worksheets (notebook)
|
|
|
|
|
(ein:log 'info "Writing notebook %s as nbformat 4." (ein:$notebook-notebook-name notebook))
|
2015-05-15 18:28:13 -05:00
|
|
|
|
(let ((all-cells (loop for ws in (ein:$notebook-worksheets notebook)
|
2015-05-14 09:39:47 -05:00
|
|
|
|
for i from 0
|
2015-05-15 18:28:13 -05:00
|
|
|
|
append (ein:worksheet-to-nb4-json ws i))))
|
2015-01-09 10:00:22 -06:00
|
|
|
|
`((metadata . ,(ein:aif (ein:$notebook-metadata notebook)
|
|
|
|
|
it
|
|
|
|
|
(make-hash-table)))
|
2014-11-07 19:28:09 -06:00
|
|
|
|
(cells . ,(apply #'vector all-cells)))))
|
|
|
|
|
|
2015-02-16 21:14:47 -06:00
|
|
|
|
(defun ein:notebook-save-notebook (notebook retry &optional callback cbargs)
|
2015-02-12 08:45:29 -06:00
|
|
|
|
(let ((content (ein:content-from-notebook notebook)))
|
2012-05-22 13:56:24 +02:00
|
|
|
|
(ein:events-trigger (ein:$notebook-events notebook)
|
2012-06-06 21:03:54 +02:00
|
|
|
|
'notebook_saving.Notebook)
|
2015-02-16 21:14:47 -06:00
|
|
|
|
(ein:content-save content
|
|
|
|
|
#'ein:notebook-save-notebook-success
|
2015-05-14 09:39:47 -05:00
|
|
|
|
(list notebook callback cbargs))))
|
2012-05-08 08:24:20 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:notebook-save-notebook-command ()
|
2012-06-11 06:15:34 +02:00
|
|
|
|
"Save the notebook."
|
2012-05-08 08:24:20 +02:00
|
|
|
|
(interactive)
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(ein:notebook-save-notebook ein:%notebook% 0))
|
2012-05-08 08:24:20 +02:00
|
|
|
|
|
2012-12-29 17:52:05 +01:00
|
|
|
|
(defun* ein:notebook-save-notebook-workaround
|
|
|
|
|
(notebook retry callback cbarg
|
|
|
|
|
&key
|
|
|
|
|
status
|
|
|
|
|
response
|
|
|
|
|
&allow-other-keys
|
|
|
|
|
&aux
|
|
|
|
|
(response-status (request-response-status-code response)))
|
2012-05-25 22:12:34 +02:00
|
|
|
|
;; IPython server returns 204 only when the notebook URL is
|
|
|
|
|
;; accessed via PUT or DELETE. As it seems Emacs failed to
|
|
|
|
|
;; choose PUT method every two times, let's check the response
|
|
|
|
|
;; here and fail when 204 is not returned.
|
2014-09-12 12:37:24 -05:00
|
|
|
|
;; UPDATE 12Sep2014 (JMM) - IPython server now returns 200 on successful save.
|
|
|
|
|
(unless (eq response-status 200)
|
2012-12-29 17:52:05 +01:00
|
|
|
|
(with-current-buffer (ein:notebook-buffer notebook)
|
|
|
|
|
(if (< retry ein:notebook-save-retry-max)
|
|
|
|
|
(progn
|
|
|
|
|
(ein:log 'info "Retry saving... Next count: %s" (1+ retry))
|
|
|
|
|
(ein:notebook-save-notebook notebook (1+ retry)
|
|
|
|
|
callback cbarg))
|
|
|
|
|
(ein:notebook-save-notebook-error notebook :status status)
|
|
|
|
|
(ein:log 'info
|
2014-09-12 12:37:24 -05:00
|
|
|
|
"Status code (=%s) is not 200 and retry exceeds limit (=%s)."
|
2012-12-29 17:52:05 +01:00
|
|
|
|
response-status ein:notebook-save-retry-max)))))
|
2012-05-25 22:12:34 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:notebook-save-notebook-success (notebook &rest ignore)
|
2012-05-23 19:08:07 +02:00
|
|
|
|
(ein:log 'info "Notebook is saved.")
|
|
|
|
|
(setf (ein:$notebook-dirty notebook) nil)
|
2012-08-30 02:42:49 +02:00
|
|
|
|
(mapc (lambda (ws)
|
2012-08-30 03:07:16 +02:00
|
|
|
|
(ein:worksheet-save-cells ws) ; [#]_
|
2012-08-30 02:42:49 +02:00
|
|
|
|
(ein:worksheet-set-modified-p ws nil))
|
2012-08-20 11:39:07 +02:00
|
|
|
|
(ein:$notebook-worksheets notebook))
|
2012-05-22 13:56:24 +02:00
|
|
|
|
(ein:events-trigger (ein:$notebook-events notebook)
|
2012-06-06 21:03:54 +02:00
|
|
|
|
'notebook_saved.Notebook))
|
2012-08-30 03:07:16 +02:00
|
|
|
|
;; .. [#] Consider the following case.
|
|
|
|
|
;; (1) Open worksheet WS0 and other worksheets.
|
|
|
|
|
;; (2) Edit worksheet WS0 then save the notebook.
|
|
|
|
|
;; (3) Edit worksheet WS0.
|
|
|
|
|
;; (4) Kill WS0 buffer by discarding the edit.
|
|
|
|
|
;; (5) Save the notebook.
|
|
|
|
|
;; This should save the latest WS0. To do so, WS0 at the point (2)
|
|
|
|
|
;; must be cached in the worksheet slot `:saved-cells'.
|
2012-05-08 08:24:20 +02:00
|
|
|
|
|
2012-06-20 21:13:28 +02:00
|
|
|
|
(defun* ein:notebook-save-notebook-error (notebook &key symbol-status
|
|
|
|
|
&allow-other-keys)
|
|
|
|
|
(if (eq symbol-status 'user-cancel)
|
|
|
|
|
(ein:log 'info "Cancel saving notebook.")
|
|
|
|
|
(ein:log 'info "Failed to save notebook!")
|
|
|
|
|
(ein:events-trigger (ein:$notebook-events notebook)
|
|
|
|
|
'notebook_save_failed.Notebook)))
|
2012-05-08 08:24:20 +02:00
|
|
|
|
|
2015-02-16 21:14:47 -06:00
|
|
|
|
(defun ein:notebook-rename-command (path)
|
2012-05-13 05:06:49 +02:00
|
|
|
|
"Rename current notebook and save it immediately.
|
|
|
|
|
|
|
|
|
|
NAME is any non-empty string that does not contain '/' or '\\'."
|
|
|
|
|
(interactive
|
2015-02-16 21:14:47 -06:00
|
|
|
|
(list (read-string "Rename notebook: " (ein:$notebook-notebook-path ein:%notebook%))))
|
|
|
|
|
(unless (and (string-match ".ipynb" path) (= (match-end 0) (length path)))
|
2015-02-16 21:54:21 -06:00
|
|
|
|
(setq path (format "%s.ipynb" path)))
|
2015-02-16 13:06:35 -06:00
|
|
|
|
(let ((content (ein:content-from-notebook ein:%notebook%))
|
|
|
|
|
(old-name (ein:$notebook-notebook-name ein:%notebook%)))
|
2014-09-28 13:52:30 -05:00
|
|
|
|
(ein:log 'info "Renaming notebook at URL %s" (ein:notebook-url ein:%notebook%))
|
2015-02-16 21:14:47 -06:00
|
|
|
|
(ein:content-rename content path #'ein:notebook-rename-success (list ein:%notebook% content))))
|
2015-02-16 13:06:35 -06:00
|
|
|
|
|
|
|
|
|
;; (defun* ein:notebook-rename-error (old new notebook &key symbol-status response
|
|
|
|
|
;; error-thrown
|
|
|
|
|
;; &allow-other-keys)
|
|
|
|
|
;; (if (= (request-response-status-code response) 409)
|
|
|
|
|
;; (progn
|
|
|
|
|
;; (ein:log 'warn "IPython returned a 409 status code, but has still renamed the notebook. This may be an IPython bug.")
|
|
|
|
|
;; (ein:notebook-rename-success notebook new response))
|
|
|
|
|
;; (ein:log 'error
|
|
|
|
|
;; "Error (%s :: %s) while renaming notebook %s to %s."
|
|
|
|
|
;; symbol-status error-thrown old new)))
|
|
|
|
|
|
|
|
|
|
(defun* ein:notebook-rename-success (notebook content)
|
|
|
|
|
(ein:notebook-set-notebook-name notebook (ein:$content-name content))
|
2015-02-16 21:14:47 -06:00
|
|
|
|
(setf (ein:$notebook-notebook-path notebook) (ein:$content-path content))
|
2014-11-11 11:33:14 -06:00
|
|
|
|
(mapc #'ein:worksheet-set-buffer-name
|
|
|
|
|
(ein:$notebook-worksheets notebook))
|
2015-02-16 13:06:35 -06:00
|
|
|
|
(ein:log 'info "Notebook renamed to %s." (ein:$content-name content)))
|
2012-05-13 05:06:49 +02:00
|
|
|
|
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(defun ein:notebook-close (notebook)
|
|
|
|
|
"Close NOTEBOOK and kill its buffer."
|
2012-09-02 06:59:36 +02:00
|
|
|
|
(interactive (prog1 (list (ein:notebook--get-nb-or-error))
|
|
|
|
|
(or (ein:notebook-ask-before-kill-buffer)
|
|
|
|
|
(error "Quit"))))
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(let ((ein:notebook-kill-buffer-ask nil))
|
|
|
|
|
;; Let `ein:notebook-kill-buffer-callback' do its job.
|
2012-08-26 23:07:45 +02:00
|
|
|
|
(mapc #'kill-buffer (ein:notebook-buffer-list notebook))))
|
2012-08-19 04:17:34 +02:00
|
|
|
|
|
2012-06-14 12:24:40 +02:00
|
|
|
|
(defun ein:notebook-kill-kernel-then-close-command ()
|
|
|
|
|
"Kill kernel and then kill notebook buffer.
|
2012-07-19 00:35:21 +02:00
|
|
|
|
To close notebook without killing kernel, just close the buffer
|
|
|
|
|
as usual."
|
2012-06-14 12:24:40 +02:00
|
|
|
|
(interactive)
|
|
|
|
|
(when (ein:notebook-ask-before-kill-buffer)
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(let ((kernel (ein:$notebook-kernel ein:%notebook%)))
|
2012-07-19 00:35:21 +02:00
|
|
|
|
;; If kernel is live, kill it before closing.
|
|
|
|
|
(if (ein:kernel-live-p kernel)
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(ein:kernel-kill kernel #'ein:notebook-close (list ein:%notebook%))
|
|
|
|
|
(ein:notebook-close ein:%notebook%)))))
|
2012-06-14 12:24:40 +02:00
|
|
|
|
|
2012-08-29 23:50:24 +02:00
|
|
|
|
|
|
|
|
|
;;; Worksheet
|
|
|
|
|
|
|
|
|
|
(defmacro ein:notebook--worksheet-render-new (notebook type)
|
|
|
|
|
"Create new worksheet of TYPE in NOTEBOOK."
|
|
|
|
|
(let ((func (intern (format "ein:%s-new" type)))
|
|
|
|
|
(slot (list (intern (format "ein:$notebook-%ss" type)) notebook)))
|
|
|
|
|
`(let ((ws (ein:notebook--worksheet-new ,notebook #',func)))
|
|
|
|
|
(setf ,slot (append ,slot (list ws)))
|
|
|
|
|
(ein:notebook--worksheet-render ,notebook ws)
|
|
|
|
|
ws)))
|
|
|
|
|
|
|
|
|
|
(defun ein:notebook-worksheet-render-new (notebook)
|
|
|
|
|
"Create new worksheet in NOTEBOOK."
|
|
|
|
|
(ein:notebook--worksheet-render-new notebook worksheet))
|
|
|
|
|
|
2012-08-30 03:57:18 +02:00
|
|
|
|
(defun ein:notebook-worksheet-open-next-or-new (notebook ws &optional show)
|
2012-08-30 03:41:56 +02:00
|
|
|
|
"Open next worksheet. Create new if none.
|
|
|
|
|
|
|
|
|
|
Try to open the worksheet to the worksheet WS using the function
|
|
|
|
|
`ein:notebook-worksheet-open-next', open a new worksheet if not
|
|
|
|
|
found.
|
|
|
|
|
|
2012-08-30 03:57:18 +02:00
|
|
|
|
SHOW is a function to be called with the worksheet buffer if
|
|
|
|
|
given."
|
2012-08-30 00:51:58 +02:00
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)
|
2012-08-30 03:57:18 +02:00
|
|
|
|
#'switch-to-buffer))
|
2012-08-30 00:51:58 +02:00
|
|
|
|
(let ((next (ein:notebook-worksheet-open-next notebook ws)))
|
|
|
|
|
(unless next
|
|
|
|
|
(ein:log 'info "Creating new worksheet...")
|
|
|
|
|
(setq next (ein:notebook-worksheet-render-new notebook))
|
|
|
|
|
(ein:log 'info "Creating new worksheet... Done."))
|
2012-08-30 03:57:18 +02:00
|
|
|
|
(when show
|
|
|
|
|
(funcall show (ein:worksheet-buffer next)))))
|
2012-08-30 00:51:58 +02:00
|
|
|
|
|
2012-08-30 03:57:18 +02:00
|
|
|
|
(defun ein:notebook-worksheet-open-next-or-first (notebook ws &optional show)
|
2012-08-30 03:41:56 +02:00
|
|
|
|
"Open next or first worksheet.
|
|
|
|
|
|
|
|
|
|
Try to open the worksheet to the worksheet WS using the function
|
|
|
|
|
`ein:notebook-worksheet-open-next', open the first worksheet if
|
|
|
|
|
not found.
|
|
|
|
|
|
2012-08-30 03:57:18 +02:00
|
|
|
|
SHOW is a function to be called with the worksheet buffer if
|
|
|
|
|
given."
|
2012-08-30 00:51:58 +02:00
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)
|
2012-08-30 03:57:18 +02:00
|
|
|
|
#'switch-to-buffer))
|
2012-08-30 00:51:58 +02:00
|
|
|
|
(let ((next (ein:notebook-worksheet-open-next notebook ws)))
|
|
|
|
|
(unless next
|
|
|
|
|
(setq next (car (ein:$notebook-worksheets notebook))))
|
2012-08-30 03:57:18 +02:00
|
|
|
|
(when show
|
|
|
|
|
(funcall show (ein:worksheet-buffer next)))))
|
2012-08-30 00:51:58 +02:00
|
|
|
|
|
2012-09-02 00:14:34 +02:00
|
|
|
|
(defun ein:notebook-worksheet-open-prev-or-last (notebook ws &optional show)
|
|
|
|
|
"Open previous or last worksheet.
|
|
|
|
|
See also `ein:notebook-worksheet-open-next-or-first' and
|
|
|
|
|
`ein:notebook-worksheet-open-prev'."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)
|
|
|
|
|
#'switch-to-buffer))
|
|
|
|
|
(let ((prev (ein:notebook-worksheet-open-prev notebook ws)))
|
|
|
|
|
(unless prev
|
|
|
|
|
(setq prev (car (last (ein:$notebook-worksheets notebook)))))
|
|
|
|
|
(when show
|
|
|
|
|
(funcall show (ein:worksheet-buffer prev)))))
|
|
|
|
|
|
2012-10-09 22:52:40 +02:00
|
|
|
|
(defun* ein:notebook-worksheet--render-maybe
|
|
|
|
|
(notebook ws &optional (adj "next"))
|
|
|
|
|
"Render worksheet WS of NOTEBOOK if it does not have buffer.
|
|
|
|
|
ADJ is a adjective to describe worksheet to be rendered."
|
|
|
|
|
(if (ein:worksheet-has-buffer-p ws)
|
|
|
|
|
(ein:log 'verbose "The worksheet already has a buffer.")
|
|
|
|
|
(ein:log 'info "Rendering %s worksheet..." adj)
|
|
|
|
|
(ein:notebook--worksheet-render notebook ws)
|
|
|
|
|
(ein:log 'info "Rendering %s worksheet... Done." adj)))
|
|
|
|
|
|
2012-09-02 00:14:21 +02:00
|
|
|
|
(defun* ein:notebook-worksheet--open-new
|
|
|
|
|
(notebook new &optional (adj "next") show)
|
2012-10-09 22:52:40 +02:00
|
|
|
|
"Open (possibly new) worksheet NEW of NOTEBOOK with SHOW function.
|
|
|
|
|
ADJ is a adjective to describe worksheet to be opened.
|
|
|
|
|
SHOW is a function to be called with worksheet buffer if given."
|
2012-09-02 00:14:21 +02:00
|
|
|
|
(when new
|
2012-10-09 22:52:40 +02:00
|
|
|
|
(ein:notebook-worksheet--render-maybe notebook new adj))
|
2012-09-02 00:14:21 +02:00
|
|
|
|
(when show
|
|
|
|
|
(assert (ein:worksheet-p new) nil "No %s worksheet." adj)
|
|
|
|
|
(funcall show (ein:worksheet-buffer new))))
|
|
|
|
|
|
2012-08-30 03:57:18 +02:00
|
|
|
|
(defun ein:notebook-worksheet-open-next (notebook ws &optional show)
|
2012-08-30 03:41:56 +02:00
|
|
|
|
"Open next worksheet.
|
|
|
|
|
|
|
|
|
|
Search the worksheet after the worksheet WS, render it if it is
|
|
|
|
|
not yet, then return the worksheet. If there is no such
|
|
|
|
|
worksheet, return nil. Open the first worksheet if the worksheet
|
|
|
|
|
WS is an instance of `ein:scratchsheet'.
|
|
|
|
|
|
2012-08-30 03:57:18 +02:00
|
|
|
|
SHOW is a function to be called with the worksheet buffer if
|
|
|
|
|
given."
|
2012-08-30 00:17:19 +02:00
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)
|
2012-08-30 03:57:18 +02:00
|
|
|
|
#'switch-to-buffer))
|
2012-08-30 00:17:19 +02:00
|
|
|
|
(let ((next (if (ein:scratchsheet-p ws)
|
|
|
|
|
(car (ein:$notebook-worksheets notebook))
|
|
|
|
|
(loop with worksheets = (ein:$notebook-worksheets notebook)
|
|
|
|
|
for current in worksheets
|
|
|
|
|
for next in (cdr worksheets)
|
|
|
|
|
when (eq current ws) return next))))
|
2012-09-02 00:14:21 +02:00
|
|
|
|
(ein:notebook-worksheet--open-new notebook next "next" show)
|
2012-08-30 00:17:19 +02:00
|
|
|
|
next))
|
|
|
|
|
|
2012-09-02 00:14:21 +02:00
|
|
|
|
(defun ein:notebook-worksheet-open-prev (notebook ws &optional show)
|
|
|
|
|
"Open previous worksheet.
|
|
|
|
|
See also `ein:notebook-worksheet-open-next'."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)
|
|
|
|
|
#'switch-to-buffer))
|
|
|
|
|
(let ((prev (if (ein:scratchsheet-p ws)
|
|
|
|
|
(car (last (ein:$notebook-worksheets notebook)))
|
|
|
|
|
(loop for (prev current) on (ein:$notebook-worksheets notebook)
|
|
|
|
|
when (eq current ws) return prev))))
|
|
|
|
|
(ein:notebook-worksheet--open-new notebook prev "previous" show)
|
|
|
|
|
prev))
|
|
|
|
|
|
2012-09-02 00:56:02 +02:00
|
|
|
|
(defun ein:notebook-worksheet-open-ith (notebook i &optional show)
|
|
|
|
|
"Open I-th (zero-origin) worksheet."
|
|
|
|
|
(let ((ws (nth i (ein:$notebook-worksheets notebook))))
|
|
|
|
|
(unless ws (error "No %s-th worksheet" (1+ i)))
|
2012-10-09 22:48:14 +02:00
|
|
|
|
(ein:notebook-worksheet--open-new notebook ws (format "%s-th" i) show)))
|
2012-09-02 00:56:02 +02:00
|
|
|
|
|
|
|
|
|
(defmacro ein:notebook-worksheet--defun-open-nth (n)
|
|
|
|
|
"Define a command to open N-th (one-origin) worksheet."
|
|
|
|
|
(assert (and (integerp n) (> n 0)) t)
|
|
|
|
|
(let ((func (intern (format "ein:notebook-worksheet-open-%sth" n))))
|
|
|
|
|
`(defun ,func (notebook &optional show)
|
|
|
|
|
,(format "Open %d-th worksheet." n)
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
#'switch-to-buffer))
|
|
|
|
|
(ein:notebook-worksheet-open-ith notebook ,(1- n) show))))
|
|
|
|
|
|
|
|
|
|
(defmacro ein:notebook-worksheet--defun-all-open-nth (min max)
|
|
|
|
|
`(progn
|
|
|
|
|
,@(loop for n from min to max
|
|
|
|
|
collect `(ein:notebook-worksheet--defun-open-nth ,n))))
|
|
|
|
|
|
|
|
|
|
(ein:notebook-worksheet--defun-all-open-nth 1 8)
|
|
|
|
|
|
|
|
|
|
(defun ein:notebook-worksheet-open-last (notebook &optional show)
|
|
|
|
|
"Open the last worksheet."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
#'switch-to-buffer))
|
|
|
|
|
(let ((last (car (last (ein:$notebook-worksheets notebook)))))
|
|
|
|
|
(ein:notebook-worksheet--open-new notebook last "last" show)
|
|
|
|
|
last))
|
|
|
|
|
|
2012-09-01 23:39:21 +02:00
|
|
|
|
(defun ein:notebook-worksheet-insert-new (notebook ws &optional render show
|
|
|
|
|
inserter)
|
|
|
|
|
(let ((new (ein:notebook--worksheet-new notebook)))
|
|
|
|
|
(setf (ein:$notebook-worksheets notebook)
|
|
|
|
|
(funcall inserter (ein:$notebook-worksheets notebook) ws new))
|
|
|
|
|
(when (or render show)
|
|
|
|
|
(ein:notebook--worksheet-render notebook new))
|
|
|
|
|
(when show
|
|
|
|
|
(funcall show (ein:worksheet-buffer new)))
|
|
|
|
|
new))
|
|
|
|
|
|
2012-10-09 23:45:27 +02:00
|
|
|
|
(defun* ein:notebook-worksheet-insert-next
|
|
|
|
|
(notebook ws &optional (render t) (show #'switch-to-buffer))
|
2012-09-01 23:39:21 +02:00
|
|
|
|
"Insert a new worksheet after this worksheet and open it.
|
|
|
|
|
See also `ein:notebook-worksheet-insert-prev'.
|
|
|
|
|
|
|
|
|
|
.. The worksheet WS is searched in the worksheets slot of
|
|
|
|
|
NOTEBOOK and a newly created worksheet is inserted after WS.
|
|
|
|
|
Worksheet buffer is created when RENDER or SHOW is non-`nil'.
|
|
|
|
|
SHOW is a function which take a buffer."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
2012-10-09 23:45:27 +02:00
|
|
|
|
(ein:worksheet--get-ws-or-error)))
|
2012-09-01 23:39:21 +02:00
|
|
|
|
(ein:notebook-worksheet-insert-new notebook ws render show
|
|
|
|
|
#'ein:list-insert-after))
|
|
|
|
|
|
2012-10-09 23:45:27 +02:00
|
|
|
|
(defun* ein:notebook-worksheet-insert-prev
|
|
|
|
|
(notebook ws &optional (render t) (show #'switch-to-buffer))
|
2012-09-01 23:39:21 +02:00
|
|
|
|
"Insert a new worksheet before this worksheet and open it.
|
|
|
|
|
See also `ein:notebook-worksheet-insert-next'."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
2012-10-09 23:45:27 +02:00
|
|
|
|
(ein:worksheet--get-ws-or-error)))
|
2012-09-01 23:39:21 +02:00
|
|
|
|
(ein:notebook-worksheet-insert-new notebook ws render show
|
|
|
|
|
#'ein:list-insert-before))
|
|
|
|
|
|
2012-10-09 23:23:03 +02:00
|
|
|
|
(defun ein:notebook-worksheet-delete (notebook ws &optional confirm)
|
2012-08-30 00:17:19 +02:00
|
|
|
|
"Delete the current worksheet.
|
|
|
|
|
When used as a lisp function, delete worksheet WS from NOTEBOOk."
|
2012-10-09 23:23:03 +02:00
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)
|
|
|
|
|
t))
|
|
|
|
|
(when confirm
|
|
|
|
|
(unless (y-or-n-p
|
|
|
|
|
"Really remove this worksheet? There is no undo.")
|
|
|
|
|
(error "Quit deleting the current worksheet.")))
|
2012-08-30 00:17:19 +02:00
|
|
|
|
(setf (ein:$notebook-worksheets notebook)
|
|
|
|
|
(delq ws (ein:$notebook-worksheets notebook)))
|
|
|
|
|
(setf (ein:$notebook-dirty notebook) t)
|
|
|
|
|
(let ((ein:notebook-kill-buffer-ask nil))
|
|
|
|
|
(kill-buffer (ein:worksheet-buffer ws))))
|
|
|
|
|
|
2012-09-02 04:40:20 +02:00
|
|
|
|
(defun ein:notebook-worksheet-move-prev (notebook ws)
|
|
|
|
|
"Switch the current worksheet with the previous one."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)))
|
|
|
|
|
(assert (ein:worksheet-p ws) nil "Not worksheet.")
|
|
|
|
|
(setf (ein:$notebook-worksheets notebook)
|
|
|
|
|
(ein:list-move-left (ein:$notebook-worksheets notebook) ws)))
|
|
|
|
|
|
|
|
|
|
(defun ein:notebook-worksheet-move-next (notebook ws)
|
|
|
|
|
"Switch the current worksheet with the previous one."
|
|
|
|
|
(interactive (list (ein:notebook--get-nb-or-error)
|
|
|
|
|
(ein:worksheet--get-ws-or-error)))
|
|
|
|
|
(assert (ein:worksheet-p ws) nil "Not worksheet.")
|
|
|
|
|
(setf (ein:$notebook-worksheets notebook)
|
|
|
|
|
(ein:list-move-right (ein:$notebook-worksheets notebook) ws)))
|
|
|
|
|
|
2012-10-15 21:05:59 +02:00
|
|
|
|
(defun* ein:notebook-worksheet-index
|
|
|
|
|
(&optional (notebook ein:%notebook%)
|
|
|
|
|
(ws ein:%worksheet%))
|
|
|
|
|
"Return an index of the worksheet WS in NOTEBOOK."
|
|
|
|
|
(loop for i from 0
|
|
|
|
|
for ith-ws in (ein:$notebook-worksheets notebook)
|
|
|
|
|
when (eq ith-ws ws)
|
|
|
|
|
return i))
|
|
|
|
|
|
2012-08-27 00:32:40 +02:00
|
|
|
|
|
|
|
|
|
;;; Scratch sheet
|
|
|
|
|
|
2012-08-29 23:51:22 +02:00
|
|
|
|
(defun ein:notebook-scratchsheet-render-new (notebook)
|
2012-08-27 00:32:40 +02:00
|
|
|
|
"Create new scratchsheet in NOTEBOOK."
|
2012-08-29 23:50:24 +02:00
|
|
|
|
(ein:notebook--worksheet-render-new notebook scratchsheet))
|
2012-08-27 00:32:40 +02:00
|
|
|
|
|
2012-08-27 00:42:27 +02:00
|
|
|
|
(defun ein:notebook-scratchsheet-open (notebook &optional new popup)
|
|
|
|
|
"Open \"scratch sheet\".
|
|
|
|
|
Open a new one when prefix argument is given.
|
2012-08-27 00:32:40 +02:00
|
|
|
|
Scratch sheet is almost identical to worksheet. However, EIN
|
|
|
|
|
will not save the buffer. Use this buffer like of normal IPython
|
|
|
|
|
console. Note that you can always copy cells into the normal
|
|
|
|
|
worksheet to save result."
|
2012-08-31 17:21:19 +02:00
|
|
|
|
(interactive (list (ein:get-notebook-or-error)
|
2012-08-27 00:42:27 +02:00
|
|
|
|
current-prefix-arg
|
2012-08-27 00:32:40 +02:00
|
|
|
|
t))
|
2012-08-27 00:42:27 +02:00
|
|
|
|
(let ((ss (or (unless new
|
2012-08-27 00:51:33 +02:00
|
|
|
|
(car (ein:$notebook-scratchsheets notebook)))
|
2012-08-29 23:51:22 +02:00
|
|
|
|
(ein:notebook-scratchsheet-render-new notebook))))
|
2012-08-27 00:32:40 +02:00
|
|
|
|
(when popup
|
|
|
|
|
(pop-to-buffer (ein:worksheet-buffer ss)))
|
|
|
|
|
ss))
|
|
|
|
|
|
2012-08-19 03:19:46 +02:00
|
|
|
|
|
|
|
|
|
;;; Opened notebooks
|
|
|
|
|
|
|
|
|
|
(defvar ein:notebook--opened-map (make-hash-table :test 'equal)
|
|
|
|
|
"A map: (URL-OR-PORT NOTEBOOK-ID) => notebook instance.")
|
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-get-opened-notebook (url-or-port path)
|
|
|
|
|
(gethash (list url-or-port path) ein:notebook--opened-map))
|
2012-08-19 03:19:46 +02:00
|
|
|
|
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(defun ein:notebook-get-opened-buffer (url-or-port path)
|
|
|
|
|
(ein:aand (ein:notebook-get-opened-notebook url-or-port path)
|
2012-08-19 03:43:54 +02:00
|
|
|
|
(ein:notebook-buffer it)))
|
2012-08-19 03:19:46 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:notebook-put-opened-notebook (notebook)
|
|
|
|
|
(puthash (list (ein:$notebook-url-or-port notebook)
|
2015-02-10 14:53:08 -06:00
|
|
|
|
(ein:$notebook-notebook-path notebook))
|
2012-08-19 03:19:46 +02:00
|
|
|
|
notebook
|
|
|
|
|
ein:notebook--opened-map))
|
|
|
|
|
|
2012-09-23 15:26:57 +02:00
|
|
|
|
(defun ein:notebook-opened-notebooks (&optional predicate)
|
|
|
|
|
"Return list of opened notebook instances.
|
|
|
|
|
If PREDICATE is given, notebooks are filtered by PREDICATE.
|
|
|
|
|
PREDICATE is called with each notebook and notebook is included
|
|
|
|
|
in the returned list only when PREDICATE returns non-nil value."
|
2012-08-19 03:19:46 +02:00
|
|
|
|
(let (notebooks)
|
|
|
|
|
(maphash (lambda (k n) (if (ein:notebook-live-p n)
|
2015-02-12 08:45:29 -06:00
|
|
|
|
(push n notebooks)
|
2012-08-19 03:19:46 +02:00
|
|
|
|
(remhash k ein:notebook--opened-map)))
|
|
|
|
|
ein:notebook--opened-map)
|
2012-09-23 15:26:57 +02:00
|
|
|
|
(if predicate
|
|
|
|
|
(ein:filter predicate notebooks)
|
|
|
|
|
notebooks)))
|
2012-08-19 03:19:46 +02:00
|
|
|
|
|
2012-09-23 15:26:57 +02:00
|
|
|
|
(defun ein:notebook-opened-buffers (&optional predicate)
|
2012-08-19 03:19:46 +02:00
|
|
|
|
"Return list of opened notebook buffers."
|
2012-09-23 15:26:57 +02:00
|
|
|
|
(mapcar #'ein:notebook-buffer (ein:notebook-opened-notebooks predicate)))
|
2012-08-19 03:19:46 +02:00
|
|
|
|
|
2012-09-23 15:26:57 +02:00
|
|
|
|
(defun ein:notebook-opened-buffer-names (&optional predicate)
|
2012-08-19 04:18:02 +02:00
|
|
|
|
"Return list of opened notebook buffer names."
|
2012-09-23 15:26:57 +02:00
|
|
|
|
(mapcar #'buffer-name (ein:notebook-opened-buffers predicate)))
|
2012-08-19 04:18:02 +02:00
|
|
|
|
|
2012-08-13 18:55:32 +02:00
|
|
|
|
|
|
|
|
|
;;; Generic getter
|
|
|
|
|
|
|
|
|
|
(defun ein:get-url-or-port--notebook ()
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(when ein:%notebook% (ein:$notebook-url-or-port ein:%notebook%)))
|
2012-08-13 18:55:32 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:get-notebook--notebook ()
|
2012-08-18 22:33:42 +02:00
|
|
|
|
ein:%notebook%)
|
2012-08-13 18:55:32 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:get-kernel--notebook ()
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(when (ein:$notebook-p ein:%notebook%)
|
|
|
|
|
(ein:$notebook-kernel ein:%notebook%)))
|
2012-08-13 18:55:32 +02:00
|
|
|
|
|
2012-08-19 02:32:11 +02:00
|
|
|
|
|
2012-08-20 02:05:56 +02:00
|
|
|
|
;;; Predicate
|
2012-08-19 02:32:11 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:notebook-buffer-p ()
|
|
|
|
|
"Return non-`nil' if current buffer is notebook buffer."
|
|
|
|
|
ein:%notebook%)
|
|
|
|
|
|
2012-08-19 03:19:46 +02:00
|
|
|
|
(defun ein:notebook-live-p (notebook)
|
|
|
|
|
"Return non-`nil' if NOTEBOOK has live buffer."
|
|
|
|
|
(buffer-live-p (ein:notebook-buffer notebook)))
|
|
|
|
|
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(defun ein:notebook-modified-p (&optional notebook)
|
2012-08-27 00:08:19 +02:00
|
|
|
|
"Return non-nil if NOTEBOOK is modified.
|
|
|
|
|
If NOTEBOOK is not given or nil then consider the notebook
|
|
|
|
|
associated with current buffer (if any)."
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(unless notebook (setq notebook ein:%notebook%))
|
|
|
|
|
(and (ein:$notebook-p notebook)
|
|
|
|
|
(ein:notebook-live-p notebook)
|
|
|
|
|
(or (ein:$notebook-dirty notebook)
|
2012-08-20 02:05:56 +02:00
|
|
|
|
(loop for ws in (ein:$notebook-worksheets notebook)
|
|
|
|
|
when (ein:worksheet-modified-p ws)
|
|
|
|
|
return t))))
|
2012-08-19 04:17:34 +02:00
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
|
|
|
|
;;; Notebook mode
|
|
|
|
|
|
2012-05-21 17:55:23 +02:00
|
|
|
|
(defcustom ein:notebook-modes
|
2012-09-30 20:40:22 +02:00
|
|
|
|
'(ein:notebook-multilang-mode)
|
2012-05-21 18:05:57 +02:00
|
|
|
|
"Notebook modes to use \(in order of preference).
|
|
|
|
|
|
2012-05-21 19:47:38 +02:00
|
|
|
|
When the notebook is opened, mode in this value is checked one by one
|
2012-09-30 20:40:22 +02:00
|
|
|
|
and the first usable mode is used.
|
|
|
|
|
|
|
|
|
|
Available modes:
|
|
|
|
|
|
|
|
|
|
* `ein:notebook-multilang-mode'
|
|
|
|
|
* `ein:notebook-mumamo-mode'
|
|
|
|
|
* `ein:notebook-python-mode'
|
|
|
|
|
* `ein:notebook-plain-mode'
|
2012-05-21 19:47:38 +02:00
|
|
|
|
|
|
|
|
|
Examples:
|
2012-06-11 04:21:30 +02:00
|
|
|
|
|
2012-09-04 22:12:13 +02:00
|
|
|
|
Use MuMaMo if it is installed. Otherwise, use plain mode.
|
2012-09-30 20:40:22 +02:00
|
|
|
|
This is the old default setting::
|
2012-09-04 22:12:13 +02:00
|
|
|
|
|
|
|
|
|
(setq ein:notebook-modes '(ein:notebook-mumamo-mode ein:notebook-plain-mode))
|
|
|
|
|
|
2012-06-11 04:46:11 +02:00
|
|
|
|
Avoid using MuMaMo even when it is installed::
|
|
|
|
|
|
2012-09-04 22:09:20 +02:00
|
|
|
|
(setq ein:notebook-modes '(ein:notebook-plain-mode))
|
2012-06-11 04:46:11 +02:00
|
|
|
|
|
2012-09-04 22:09:20 +02:00
|
|
|
|
Use simple `python-mode' based notebook mode when MuMaMo is not installed::
|
2012-06-11 04:46:11 +02:00
|
|
|
|
|
2012-09-04 22:09:20 +02:00
|
|
|
|
(setq ein:notebook-modes '(ein:notebook-mumamo-mode ein:notebook-python-mode))
|
2012-05-21 18:05:57 +02:00
|
|
|
|
"
|
2012-09-30 20:40:22 +02:00
|
|
|
|
:type '(repeat (choice (const :tag "Multi-lang" ein:notebook-multilang-mode)
|
|
|
|
|
(const :tag "MuMaMo" ein:notebook-mumamo-mode)
|
2012-05-21 18:05:57 +02:00
|
|
|
|
(const :tag "Only Python" ein:notebook-python-mode)
|
2012-05-21 17:55:23 +02:00
|
|
|
|
(const :tag "Plain" ein:notebook-plain-mode)))
|
|
|
|
|
:group 'ein)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-09-04 16:51:37 +02:00
|
|
|
|
(defcustom ein:notebook-mode-hook nil
|
|
|
|
|
"Hook for `ein:notebook-mode'.
|
|
|
|
|
This hook is run regardless the actual major mode used."
|
|
|
|
|
:type 'hook
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(defun ein:notebook-choose-mode ()
|
2012-05-14 18:47:08 +02:00
|
|
|
|
"Return usable (defined) notebook mode."
|
|
|
|
|
;; So try to load extra modules here.
|
|
|
|
|
(when (require 'mumamo nil t)
|
|
|
|
|
(require 'ein-mumamo))
|
|
|
|
|
;; Return first matched mode
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(loop for mode in ein:notebook-modes
|
|
|
|
|
if (functionp mode)
|
|
|
|
|
return mode))
|
|
|
|
|
|
2012-06-14 12:42:57 +02:00
|
|
|
|
(defvar ein:notebook-mode-map (make-sparse-keymap))
|
|
|
|
|
|
|
|
|
|
(let ((map ein:notebook-mode-map))
|
2012-08-20 03:42:39 +02:00
|
|
|
|
(define-key map "\C-c\C-c" 'ein:worksheet-execute-cell)
|
|
|
|
|
(define-key map (kbd "M-RET") 'ein:worksheet-execute-cell-and-goto-next)
|
2012-08-21 11:52:43 +02:00
|
|
|
|
(define-key map (kbd "<M-S-return>")
|
|
|
|
|
'ein:worksheet-execute-cell-and-insert-below)
|
2012-08-20 03:42:39 +02:00
|
|
|
|
(define-key map (kbd "C-c C-'") 'ein:worksheet-turn-on-autoexec)
|
|
|
|
|
(define-key map "\C-c\C-e" 'ein:worksheet-toggle-output)
|
2012-08-26 18:16:53 +02:00
|
|
|
|
(define-key map "\C-c\C-v" 'ein:worksheet-set-output-visibility-all)
|
2012-08-20 03:42:39 +02:00
|
|
|
|
(define-key map "\C-c\C-l" 'ein:worksheet-clear-output)
|
|
|
|
|
(define-key map (kbd "C-c C-S-l") 'ein:worksheet-clear-all-output)
|
2012-08-15 21:41:05 +02:00
|
|
|
|
(define-key map (kbd "C-c C-;") 'ein:shared-output-show-code-cell-at-point)
|
2012-08-20 03:42:39 +02:00
|
|
|
|
(define-key map "\C-c\C-k" 'ein:worksheet-kill-cell)
|
|
|
|
|
(define-key map "\C-c\M-w" 'ein:worksheet-copy-cell)
|
|
|
|
|
(define-key map "\C-c\C-w" 'ein:worksheet-copy-cell)
|
|
|
|
|
(define-key map "\C-c\C-y" 'ein:worksheet-yank-cell)
|
|
|
|
|
(define-key map "\C-c\C-a" 'ein:worksheet-insert-cell-above)
|
|
|
|
|
(define-key map "\C-c\C-b" 'ein:worksheet-insert-cell-below)
|
|
|
|
|
(define-key map "\C-c\C-t" 'ein:worksheet-toggle-cell-type)
|
|
|
|
|
(define-key map "\C-c\C-u" 'ein:worksheet-change-cell-type)
|
|
|
|
|
(define-key map "\C-c\C-s" 'ein:worksheet-split-cell-at-point)
|
|
|
|
|
(define-key map "\C-c\C-m" 'ein:worksheet-merge-cell)
|
|
|
|
|
(define-key map "\C-c\C-n" 'ein:worksheet-goto-next-input)
|
|
|
|
|
(define-key map "\C-c\C-p" 'ein:worksheet-goto-prev-input)
|
|
|
|
|
(define-key map (kbd "C-<up>") 'ein:worksheet-goto-prev-input)
|
|
|
|
|
(define-key map (kbd "C-<down>") 'ein:worksheet-goto-next-input)
|
|
|
|
|
(define-key map (kbd "C-c <up>") 'ein:worksheet-move-cell-up)
|
|
|
|
|
(define-key map (kbd "C-c <down>") 'ein:worksheet-move-cell-down)
|
|
|
|
|
(define-key map (kbd "M-<up>") 'ein:worksheet-move-cell-up)
|
|
|
|
|
(define-key map (kbd "M-<down>") 'ein:worksheet-move-cell-down)
|
2012-08-19 21:36:35 +02:00
|
|
|
|
(define-key map "\C-c\C-f" 'ein:pytools-request-tooltip-or-help)
|
2012-08-19 22:23:51 +02:00
|
|
|
|
(define-key map "\C-c\C-i" 'ein:completer-complete)
|
2012-08-14 20:46:29 +02:00
|
|
|
|
(define-key map "\C-c\C-x" 'ein:tb-show)
|
2012-08-20 13:53:14 +02:00
|
|
|
|
(define-key map "\C-c\C-r" 'ein:notebook-restart-kernel-command)
|
2012-06-14 12:42:57 +02:00
|
|
|
|
(define-key map "\C-c\C-z" 'ein:notebook-kernel-interrupt-command)
|
|
|
|
|
(define-key map "\C-c\C-q" 'ein:notebook-kill-kernel-then-close-command)
|
2012-09-02 06:59:36 +02:00
|
|
|
|
(define-key map (kbd "C-c C-#") 'ein:notebook-close)
|
2012-08-15 23:08:35 +02:00
|
|
|
|
(define-key map (kbd "C-:") 'ein:shared-output-eval-string)
|
2012-08-16 15:48:11 +02:00
|
|
|
|
(define-key map "\C-c\C-o" 'ein:console-open)
|
2012-06-14 12:42:57 +02:00
|
|
|
|
(define-key map "\C-x\C-s" 'ein:notebook-save-notebook-command)
|
|
|
|
|
(define-key map "\C-x\C-w" 'ein:notebook-rename-command)
|
2012-06-17 02:36:00 +02:00
|
|
|
|
(define-key map "\M-." 'ein:pytools-jump-to-source-command)
|
|
|
|
|
(define-key map (kbd "C-c C-.") 'ein:pytools-jump-to-source-command)
|
|
|
|
|
(define-key map "\M-," 'ein:pytools-jump-back-command)
|
|
|
|
|
(define-key map (kbd "C-c C-,") 'ein:pytools-jump-back-command)
|
2012-08-28 12:23:47 +02:00
|
|
|
|
(define-key map "\M-p" 'ein:worksheet-previous-input-history)
|
|
|
|
|
(define-key map "\M-n" 'ein:worksheet-next-input-history)
|
2012-08-27 00:44:50 +02:00
|
|
|
|
(define-key map (kbd "C-c C-/") 'ein:notebook-scratchsheet-open)
|
2012-09-02 00:19:47 +02:00
|
|
|
|
;; Worksheets
|
2012-09-02 01:27:28 +02:00
|
|
|
|
(define-key map (kbd "C-c !") 'ein:worksheet-rename-sheet)
|
2012-09-02 00:19:47 +02:00
|
|
|
|
(define-key map (kbd "C-c {") 'ein:notebook-worksheet-open-prev-or-last)
|
|
|
|
|
(define-key map (kbd "C-c }") 'ein:notebook-worksheet-open-next-or-first)
|
2012-09-02 04:40:20 +02:00
|
|
|
|
(define-key map (kbd "C-c M-{") 'ein:notebook-worksheet-move-prev)
|
|
|
|
|
(define-key map (kbd "C-c M-}") 'ein:notebook-worksheet-move-next)
|
2012-09-02 00:19:47 +02:00
|
|
|
|
(define-key map (kbd "C-c +") 'ein:notebook-worksheet-insert-next)
|
|
|
|
|
(define-key map (kbd "C-c M-+") 'ein:notebook-worksheet-insert-prev)
|
|
|
|
|
(define-key map (kbd "C-c -") 'ein:notebook-worksheet-delete)
|
2012-09-02 00:56:02 +02:00
|
|
|
|
(loop for n from 1 to 8
|
|
|
|
|
do (define-key map (format "\C-c%d" n)
|
|
|
|
|
(intern (format "ein:notebook-worksheet-open-%sth" n))))
|
|
|
|
|
(define-key map "\C-c9" 'ein:notebook-worksheet-open-last)
|
2012-09-02 00:19:47 +02:00
|
|
|
|
;; Menu
|
2012-08-27 14:11:41 +02:00
|
|
|
|
(easy-menu-define ein:notebook-menu map "EIN Notebook Mode Menu"
|
|
|
|
|
`("EIN Notebook"
|
2012-08-28 09:02:07 +02:00
|
|
|
|
("File"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Save notebook" ein:notebook-save-notebook-command)
|
|
|
|
|
("Rename notebook" ein:notebook-rename-command)
|
2012-09-02 06:59:36 +02:00
|
|
|
|
("Close notebook without saving"
|
|
|
|
|
ein:notebook-close)
|
2012-08-28 09:02:07 +02:00
|
|
|
|
("Kill kernel then close notebook"
|
|
|
|
|
ein:notebook-kill-kernel-then-close-command))))
|
|
|
|
|
("Edit"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Kill cell" ein:worksheet-kill-cell)
|
|
|
|
|
("Copy cell" ein:worksheet-copy-cell)
|
|
|
|
|
("Yank cell" ein:worksheet-yank-cell)
|
|
|
|
|
("Insert cell above" ein:worksheet-insert-cell-above)
|
|
|
|
|
("Insert cell below" ein:worksheet-insert-cell-below)
|
|
|
|
|
("Toggle cell type" ein:worksheet-toggle-cell-type)
|
|
|
|
|
("Change cell type" ein:worksheet-change-cell-type)
|
|
|
|
|
("Split cell at point" ein:worksheet-split-cell-at-point)
|
|
|
|
|
("Merge cell" ein:worksheet-merge-cell)
|
|
|
|
|
("Go to next cell" ein:worksheet-goto-next-input)
|
|
|
|
|
("Go to previous cell" ein:worksheet-goto-prev-input)
|
|
|
|
|
("Move cell up" ein:worksheet-move-cell-up)
|
2012-10-09 14:04:37 +02:00
|
|
|
|
("Move cell down" ein:worksheet-move-cell-down)
|
|
|
|
|
("Dedent text in CELL" ein:worksheet-dedent-cell-text)
|
|
|
|
|
)))
|
2012-08-28 09:02:07 +02:00
|
|
|
|
("Cell/Code"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Execute cell" ein:worksheet-execute-cell
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
|
|
|
|
("Execute cell and go to next"
|
|
|
|
|
ein:worksheet-execute-cell-and-goto-next
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
|
|
|
|
("Execute cell and insert below"
|
|
|
|
|
ein:worksheet-execute-cell-and-insert-below
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
2013-04-12 18:20:35 +02:00
|
|
|
|
("Execute all"
|
|
|
|
|
ein:worksheet-execute-all-cell)
|
2012-08-28 09:02:07 +02:00
|
|
|
|
("Turn on auto execution flag" ein:worksheet-turn-on-autoexec
|
2012-09-01 21:32:20 +02:00
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
|
|
|
|
("Evaluate code in minibuffer" ein:shared-output-eval-string)
|
|
|
|
|
("Toggle instant cell execution mode" ein:iexec-mode)
|
|
|
|
|
))
|
2012-08-28 09:02:07 +02:00
|
|
|
|
"---"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Toggle output visibility" ein:worksheet-toggle-output
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
2012-08-28 09:12:31 +02:00
|
|
|
|
("Show all output"
|
2012-08-28 09:02:07 +02:00
|
|
|
|
ein:worksheet-set-output-visibility-all)
|
|
|
|
|
("Discard output" ein:worksheet-clear-output
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
2012-09-01 21:32:20 +02:00
|
|
|
|
("Discard all output" ein:worksheet-clear-all-output)
|
|
|
|
|
("Show full output" ein:shared-output-show-code-cell-at-point
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
|
|
|
|
("Traceback viewer" ein:tb-show)
|
|
|
|
|
))
|
2012-08-28 09:02:07 +02:00
|
|
|
|
"---"
|
|
|
|
|
,@(ein:generate-menu
|
2012-08-28 09:12:31 +02:00
|
|
|
|
'(("Show object help"
|
2012-08-28 09:02:07 +02:00
|
|
|
|
ein:pytools-request-tooltip-or-help)
|
|
|
|
|
("Complete code" ein:completer-complete
|
|
|
|
|
:active (ein:worksheet-at-codecell-p))
|
|
|
|
|
("Jump to definition" ein:pytools-jump-to-source-command)
|
|
|
|
|
("Go back to the previous jump point"
|
2012-08-28 12:23:47 +02:00
|
|
|
|
ein:pytools-jump-back-command)
|
|
|
|
|
("Previous input history"
|
|
|
|
|
ein:worksheet-previous-input-history)
|
|
|
|
|
("Next input history"
|
|
|
|
|
ein:worksheet-next-input-history))))
|
2012-08-28 09:02:07 +02:00
|
|
|
|
("Kernel"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Restart kernel" ein:notebook-restart-kernel-command)
|
|
|
|
|
("Interrupt kernel" ein:notebook-kernel-interrupt-command))))
|
2012-09-02 00:19:47 +02:00
|
|
|
|
("Worksheets [Experimental]"
|
|
|
|
|
,@(ein:generate-menu
|
2012-09-02 01:27:28 +02:00
|
|
|
|
'(("Rename worksheet" ein:worksheet-rename-sheet)
|
2012-09-02 01:32:44 +02:00
|
|
|
|
("Insert next worksheet"
|
|
|
|
|
ein:notebook-worksheet-insert-next)
|
|
|
|
|
("Insert previous worksheet"
|
|
|
|
|
ein:notebook-worksheet-insert-prev)
|
|
|
|
|
("Delete worksheet" ein:notebook-worksheet-delete)
|
2012-09-02 04:40:20 +02:00
|
|
|
|
("Move worksheet left" ein:notebook-worksheet-move-prev)
|
|
|
|
|
("Move worksheet right" ein:notebook-worksheet-move-next)
|
2012-09-02 01:32:44 +02:00
|
|
|
|
))
|
|
|
|
|
"---"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Open previous worksheet"
|
2012-09-02 00:19:47 +02:00
|
|
|
|
ein:notebook-worksheet-open-prev)
|
|
|
|
|
("Open previous or last worksheet"
|
|
|
|
|
ein:notebook-worksheet-open-prev-or-last)
|
|
|
|
|
("Open next worksheet"
|
|
|
|
|
ein:notebook-worksheet-open-next)
|
|
|
|
|
("Open next or first worksheet"
|
|
|
|
|
ein:notebook-worksheet-open-next-or-first)
|
|
|
|
|
("Open next or new worksheet"
|
|
|
|
|
ein:notebook-worksheet-open-next-or-new)
|
2012-09-02 00:56:02 +02:00
|
|
|
|
))
|
|
|
|
|
"---"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
(append
|
|
|
|
|
(loop for n from 1 to 8
|
|
|
|
|
collect
|
|
|
|
|
(list
|
|
|
|
|
(format "Open %d-th worksheet" n)
|
|
|
|
|
(intern (format "ein:notebook-worksheet-open-%sth" n))))
|
|
|
|
|
'(("Open last worksheet" ein:notebook-worksheet-open-last)))))
|
2012-09-01 18:53:18 +02:00
|
|
|
|
("Junk notebook"
|
|
|
|
|
,@(ein:generate-menu
|
|
|
|
|
'(("Junk this notebook" ein:junk-rename)
|
|
|
|
|
("Open new junk" ein:junk-new))))
|
2012-08-28 09:02:07 +02:00
|
|
|
|
;; Misc:
|
2012-08-27 14:11:41 +02:00
|
|
|
|
,@(ein:generate-menu
|
2012-08-28 09:02:07 +02:00
|
|
|
|
'(("Open regular IPython console" ein:console-open)
|
2012-09-01 21:32:20 +02:00
|
|
|
|
("Open scratch sheet" ein:notebook-scratchsheet-open)
|
|
|
|
|
("Toggle pseudo console mode" ein:pseudo-console-mode)
|
|
|
|
|
))
|
|
|
|
|
))
|
2012-06-14 12:42:57 +02:00
|
|
|
|
map)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-07-29 18:08:30 +02:00
|
|
|
|
(defun ein:notebook-mode ()
|
|
|
|
|
(funcall (ein:notebook-choose-mode))
|
|
|
|
|
(ein:complete-on-dot-install
|
2012-09-04 16:51:37 +02:00
|
|
|
|
ein:notebook-mode-map 'ein:notebook-complete-dot)
|
2012-09-05 23:27:17 +02:00
|
|
|
|
(ein:aif ein:helm-kernel-history-search-key
|
|
|
|
|
(define-key ein:notebook-mode-map it 'helm-ein-kernel-history))
|
|
|
|
|
(ein:aif ein:anything-kernel-history-search-key
|
|
|
|
|
(define-key ein:notebook-mode-map it 'anything-ein-kernel-history))
|
2012-09-04 17:01:54 +02:00
|
|
|
|
(ein:notebook-minor-mode +1)
|
2012-09-04 16:51:37 +02:00
|
|
|
|
(run-hooks 'ein:notebook-mode-hook))
|
2012-07-29 18:08:30 +02:00
|
|
|
|
|
2012-09-04 16:54:56 +02:00
|
|
|
|
(add-hook 'ein:notebook-mode-hook 'ein:worksheet-imenu-setup)
|
|
|
|
|
|
2012-09-04 17:01:54 +02:00
|
|
|
|
(define-minor-mode ein:notebook-minor-mode
|
|
|
|
|
"Minor mode to install `ein:notebook-mode-map' for `ein:notebook-mode'."
|
|
|
|
|
:keymap ein:notebook-mode-map
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
;; To avoid MuMaMo to discard `ein:notebook-minor-mode', make it
|
|
|
|
|
;; permanent local.
|
|
|
|
|
(put 'ein:notebook-minor-mode 'permanent-local t)
|
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(define-derived-mode ein:notebook-plain-mode fundamental-mode "ein:notebook"
|
2012-05-21 18:01:03 +02:00
|
|
|
|
"IPython notebook mode without fancy coloring."
|
2012-05-13 08:36:21 +02:00
|
|
|
|
(font-lock-mode))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-05-21 18:05:57 +02:00
|
|
|
|
(define-derived-mode ein:notebook-python-mode python-mode "ein:python"
|
|
|
|
|
"Use `python-mode' for whole notebook buffer.")
|
|
|
|
|
|
2012-06-17 14:49:54 +02:00
|
|
|
|
(defun ein:notebook-open-in-browser (&optional print)
|
|
|
|
|
"Open current notebook in web browser.
|
|
|
|
|
When the prefix argument (``C-u``) is given, print page is opened.
|
|
|
|
|
Note that print page is not supported in IPython 0.12.1."
|
|
|
|
|
(interactive "P")
|
|
|
|
|
(let ((url (apply #'ein:url
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(ein:$notebook-url-or-port ein:%notebook%)
|
|
|
|
|
(ein:$notebook-notebook-id ein:%notebook%)
|
2012-06-17 14:49:54 +02:00
|
|
|
|
(if print (list "print")))))
|
2012-05-19 17:16:30 +02:00
|
|
|
|
(message "Opening %s in browser" url)
|
|
|
|
|
(browse-url url)))
|
|
|
|
|
|
2012-10-09 15:30:44 +02:00
|
|
|
|
(defun ein:notebook-fetch-data (notebook callback &optional cbargs)
|
|
|
|
|
"Fetch data in body tag of NOTEBOOK html page.
|
|
|
|
|
CALLBACK is called with a plist with data in the body tag as
|
|
|
|
|
the first argument and CBARGS as the rest of arguments."
|
|
|
|
|
(let ((url-or-port (ein:$notebook-url-or-port notebook))
|
|
|
|
|
(notebook-id (ein:$notebook-notebook-id notebook)))
|
|
|
|
|
(ein:query-singleton-ajax
|
|
|
|
|
(list 'notebook-fetch-data url-or-port notebook-id)
|
|
|
|
|
(ein:url url-or-port notebook-id)
|
|
|
|
|
:parser
|
|
|
|
|
(lambda ()
|
|
|
|
|
(list
|
|
|
|
|
:project
|
|
|
|
|
(ein:html-get-data-in-body-tag "data-project")
|
|
|
|
|
:base-project-url
|
|
|
|
|
(ein:html-get-data-in-body-tag "data-base-project-url")
|
|
|
|
|
:base-kernel-url
|
|
|
|
|
(ein:html-get-data-in-body-tag "data-base-kernel-url")
|
|
|
|
|
:read-only
|
|
|
|
|
(ein:html-get-data-in-body-tag "data-read-only")
|
|
|
|
|
:notebook-id
|
|
|
|
|
(ein:html-get-data-in-body-tag "data-notebook-id")))
|
|
|
|
|
:success
|
2012-12-29 17:17:39 +01:00
|
|
|
|
(apply-partially (function*
|
|
|
|
|
(lambda (callback cbargs &key data &allow-other-keys)
|
|
|
|
|
(apply callback data cbargs)))
|
|
|
|
|
callback cbargs))))
|
2012-10-09 15:30:44 +02:00
|
|
|
|
|
2012-08-19 04:41:26 +02:00
|
|
|
|
|
|
|
|
|
;;; Buffer and kill hooks
|
|
|
|
|
|
2012-06-06 22:36:47 +02:00
|
|
|
|
(defcustom ein:notebook-kill-buffer-ask t
|
|
|
|
|
"Whether EIN should ask before killing unsaved notebook buffer."
|
|
|
|
|
:type '(choice (const :tag "Yes" t)
|
|
|
|
|
(const :tag "No" nil))
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-08-19 04:41:26 +02:00
|
|
|
|
;; -- `kill-buffer-query-functions'
|
2012-05-19 18:16:35 +02:00
|
|
|
|
(defun ein:notebook-ask-before-kill-buffer ()
|
2012-05-13 18:29:50 +02:00
|
|
|
|
"Return `nil' to prevent killing the notebook buffer.
|
|
|
|
|
Called via `kill-buffer-query-functions'."
|
2012-08-30 02:32:53 +02:00
|
|
|
|
(not (or (and ein:notebook-kill-buffer-ask
|
|
|
|
|
(ein:worksheet-p ein:%worksheet%) ; it's not `ein:scratchsheet'
|
|
|
|
|
(ein:notebook-modified-p)
|
|
|
|
|
(not (y-or-n-p
|
|
|
|
|
"You have unsaved changes. Discard changes?")))
|
|
|
|
|
(when (ein:worksheet-p ein:%worksheet%)
|
|
|
|
|
;; To make `ein:worksheet-save-cells' no-op.
|
2012-08-30 16:21:53 +02:00
|
|
|
|
(ein:worksheet-dont-save-cells ein:%worksheet%)
|
2012-08-30 02:32:53 +02:00
|
|
|
|
nil))))
|
2012-05-13 18:29:50 +02:00
|
|
|
|
|
2012-05-19 18:16:35 +02:00
|
|
|
|
(add-hook 'kill-buffer-query-functions 'ein:notebook-ask-before-kill-buffer)
|
|
|
|
|
|
2012-08-19 04:41:26 +02:00
|
|
|
|
;; -- `kill-emacs-query-functions'
|
2012-05-19 18:16:35 +02:00
|
|
|
|
(defun ein:notebook-ask-before-kill-emacs ()
|
|
|
|
|
"Return `nil' to prevent killing Emacs when unsaved notebook exists.
|
|
|
|
|
Called via `kill-emacs-query-functions'."
|
2012-08-26 23:56:43 +02:00
|
|
|
|
(condition-case err
|
|
|
|
|
(let ((unsaved (ein:filter #'ein:notebook-modified-p
|
|
|
|
|
(ein:notebook-opened-notebooks))))
|
|
|
|
|
(if (null unsaved)
|
|
|
|
|
t
|
|
|
|
|
(let ((answer
|
|
|
|
|
(y-or-n-p
|
|
|
|
|
(format "You have %s unsaved notebook(s). Discard changes?"
|
|
|
|
|
(length unsaved)))))
|
|
|
|
|
;; kill all unsaved buffers forcefully
|
|
|
|
|
(when answer
|
|
|
|
|
(mapc #'ein:notebook-close unsaved))
|
|
|
|
|
answer)))
|
|
|
|
|
((debug error)
|
|
|
|
|
(ein:log 'error "Got error: %S" err)
|
|
|
|
|
(y-or-n-p "Error while examine notebooks. Kill Emacs anyway? "))))
|
2012-05-19 18:16:35 +02:00
|
|
|
|
|
|
|
|
|
(add-hook 'kill-emacs-query-functions 'ein:notebook-ask-before-kill-emacs)
|
2012-05-13 18:29:50 +02:00
|
|
|
|
|
2012-08-19 04:41:26 +02:00
|
|
|
|
;; -- `kill-buffer-hook'
|
2012-05-19 17:58:02 +02:00
|
|
|
|
(defun ein:notebook-kill-buffer-callback ()
|
|
|
|
|
"Call notebook destructor. This function is called via `kill-buffer-hook'."
|
2012-08-18 22:33:42 +02:00
|
|
|
|
(when (ein:$notebook-p ein:%notebook%)
|
2012-08-26 23:33:51 +02:00
|
|
|
|
(ein:notebook-close-worksheet ein:%notebook% ein:%worksheet%)))
|
2012-05-19 17:58:02 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:notebook-setup-kill-buffer-hook ()
|
|
|
|
|
"Add \"notebook destructor\" to `kill-buffer-hook'."
|
|
|
|
|
(add-hook 'kill-buffer-hook 'ein:notebook-kill-buffer-callback))
|
|
|
|
|
|
2012-08-19 04:41:26 +02:00
|
|
|
|
;; Useful command to close notebooks.
|
2012-05-25 15:44:00 +02:00
|
|
|
|
(defun ein:notebook-kill-all-buffers ()
|
2012-07-19 14:21:15 +02:00
|
|
|
|
"Close all opened notebooks."
|
2012-05-25 15:44:00 +02:00
|
|
|
|
(interactive)
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(let* ((notebooks (ein:notebook-opened-notebooks))
|
|
|
|
|
(unsaved (ein:filter #'ein:notebook-modified-p notebooks)))
|
|
|
|
|
(if notebooks
|
2012-05-25 15:44:00 +02:00
|
|
|
|
(if (y-or-n-p
|
2012-07-19 14:21:15 +02:00
|
|
|
|
(format (concat "You have %s opened notebook(s). "
|
|
|
|
|
(when unsaved
|
|
|
|
|
(format "%s are UNSAVED. " (length unsaved)))
|
2012-05-25 15:44:00 +02:00
|
|
|
|
"Really kill all of them?")
|
2012-08-19 04:17:34 +02:00
|
|
|
|
(length notebooks)))
|
2012-05-25 15:44:00 +02:00
|
|
|
|
(progn (ein:log 'info "Killing all notebook buffers...")
|
2012-08-19 05:02:18 +02:00
|
|
|
|
(mapc #'ein:notebook-close notebooks)
|
2012-05-25 15:44:00 +02:00
|
|
|
|
(ein:log 'info "Killing all notebook buffers... Done!"))
|
|
|
|
|
(ein:log 'info "Canceled to kill all notebooks."))
|
|
|
|
|
(ein:log 'info "No opened notebooks."))))
|
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(provide 'ein-notebook)
|
|
|
|
|
|
|
|
|
|
;;; ein-notebook.el ends here
|