Merge branch 'autoexec2'

This commit is contained in:
Takafumi Arakaki 2012-07-29 17:16:05 +02:00
commit 6b38440568
4 changed files with 147 additions and 7 deletions

View file

@ -304,6 +304,7 @@ Notebook
.. el:variable:: ein:notebook-console-args
.. el:variable:: ein:cell-traceback-level
.. el:variable:: ein:cell-max-num-outputs
.. el:variable:: ein:cell-autoexec-prompt
.. el:variable:: ein:scratch-notebook-name-template
.. el:variable:: ein:iexec-delay
@ -313,6 +314,7 @@ Connect
.. el:variable:: ein:connect-run-command
.. el:variable:: ein:connect-save-before-run
.. el:variable:: ein:propagate-connect
.. el:variable:: ein:connect-aotoexec-lighter
MuMaMo
^^^^^^
@ -477,6 +479,9 @@ v0.1.1
* Add Imenu support.
* Better heading cell faces.
* Add :el:symbol:`ein:iexec-mode`
* Add auto-execution mode
(see :el:symbol:`ein:connect-toggle-autoexec` and
:el:symbol:`ein:notebook-turn-on-autoexec`).
v0.1

View file

@ -123,6 +123,12 @@ To view full output, use `ein:notebook-show-in-shared-output'."
(const :tag "Show all traceback" nil))
:group 'ein)
(defcustom ein:cell-autoexec-prompt ""
"String shown in the cell prompt when the auto-execution flag
is on. See also `ein:connect-aotoexec-lighter'."
:type 'string
:group 'ein)
;;; EIEIO related utils
@ -174,7 +180,13 @@ to `t' when executing cell. See `ein:notebook-execute-cell'.
In the implantation of IPython web client it is passed around via
argument, but since it is difficult to pass argument to EWOC
pretty printer, `ein:codecell' instance holds this setting in a
slot.")))
slot.")
(autoexec :initarg :autoexec :initform nil :type boolean
:documentation "Auto-execution flag.
This cell is executed when the connected buffer is saved,
provided that (1) this flag is `t' and (2) corresponding
auto-execution mode flag in the connected buffer is `t'.")))
(defclass ein:textcell (ein:basecell)
((cell-type :initarg :cell-type :initform "text")
@ -416,7 +428,9 @@ A specific node can be specified using optional ARGS."
Called from ewoc pretty printer via `ein:cell-pp'."
;; Newline is inserted in `ein:cell-insert-input'.
(ein:insert-read-only
(format "In [%s]:" (or (ein:oref-safe cell :input-prompt-number) " "))
(concat
(format "In [%s]:" (or (ein:oref-safe cell :input-prompt-number) " "))
(when (oref cell :autoexec) " %s" ein:cell-autoexec-prompt))
'font-lock-face 'ein:cell-input-prompt))
(defmethod ein:cell-insert-prompt ((cell ein:textcell))
@ -575,13 +589,35 @@ If the input area of the CELL does not exist, return `nil'"
"Toggle `:collapsed' slot of CELL and invalidate output ewoc nodes."
(ein:cell-set-collapsed cell (not (oref cell :collapsed))))
(defmethod ein:cell-set-input-prompt ((cell ein:codecell) &optional number)
(oset cell :input-prompt-number number)
(defmethod ein:cell-invalidate-prompt ((cell ein:codecell))
(let ((inhibit-read-only t)
(buffer-undo-list t)) ; disable undo recording
(ewoc-invalidate (oref cell :ewoc)
(ein:cell-element-get cell :prompt))))
(defmethod ein:cell-set-input-prompt ((cell ein:codecell) &optional number)
(oset cell :input-prompt-number number)
(ein:cell-invalidate-prompt cell))
(defmethod ein:cell-set-autoexec ((cell ein:codecell) bool)
"Set auto-execution flag of CELL to BOOL and invalidate the
prompt EWOC node."
(oset cell :autoexec bool)
(ein:cell-invalidate-prompt cell))
(defmethod ein:cell-autoexec-p ((cell ein:basecell))
"Auto-execution flag set to CELL.
Return `nil' always for non-code cells."
nil)
(defmethod ein:cell-autoexec-p ((cell ein:codecell))
(oref cell :autoexec))
(defmethod ein:cell-toggle-autoexec ((cell ein:codecell))
"Toggle auto-execution flag of CELL to BOOL and invalidate the
prompt EWOC node."
(ein:cell-set-autoexec cell (not (ein:cell-autoexec-p cell))))
(declare-function pos-tip-show "pos-tip")
(declare-function popup-tip "popup")

View file

@ -78,6 +78,14 @@ Types same as `ein:notebook-console-security-dir' are valid."
(lambda (url-or-port) (format "%%run -n -i -t -d"))))
:group 'ein)
(defcustom ein:connect-aotoexec-lighter nil
"String appended to the lighter of `ein:connect-mode' (`ein:c')
when auto-execution mode is on. When `nil', use the same string
as `ein:cell-autoexec-prompt'."
:type '(choice (string :tag "String appended to ein:c" "@")
(const :tag "Use `ein:cell-autoexec-prompt'." nil))
:group 'ein)
(defun ein:connect-run-command-get ()
(ein:choose-setting 'ein:connect-run-command
(ein:$notebook-url-or-port (ein:connect-get-notebook))))
@ -94,7 +102,12 @@ Types same as `ein:notebook-console-security-dir' are valid."
(defclass ein:$connect ()
((notebook :initarg :notebook :type ein:$notebook)
(buffer :initarg :buffer :type buffer)))
(buffer :initarg :buffer :type buffer)
(autoexec :initarg :autoexec :initform nil :type boolean
:document "Auto-execution mode flag.
See also the document of the `autoexec' slot of `ein:codecell'
class.")))
(defun ein:connect-setup (notebook buffer)
(with-current-buffer buffer
@ -229,6 +242,38 @@ See also: `ein:connect-run-buffer', `ein:connect-eval-buffer'."
(interactive)
(pop-to-buffer (ein:notebook-buffer (ein:connect-get-notebook))))
;;; Auto-execution
(defun ein:connect-assert-connected ()
(assert (ein:$connect-p ein:@connect) nil
"Current buffer (%s) is not connected to IPython notebook."
(buffer-name)))
(defun ein:connect-execute-autoexec-cells ()
"Call `ein:notebook-execute-autoexec-cells' via `after-save-hook'."
(ein:connect-assert-connected)
(let ((notebook (ein:connect-get-notebook)))
(ein:notebook-with-buffer notebook
(ein:notebook-execute-autoexec-cells notebook))))
(defun ein:connect-toggle-autoexec ()
"Toggle auto-execution mode of the current connected buffer.
Note that you need to set cells to run in the connecting buffer
or no cell will be executed.
Use the `ein:notebook-turn-on-autoexec' command in notebook to
change the cells to run."
(interactive)
(ein:connect-assert-connected)
(oset ein:@connect :autoexec (not (oref ein:@connect :autoexec)))
(let ((autoexec-p (oref ein:@connect :autoexec)))
(if autoexec-p
(add-hook 'after-save-hook 'ein:connect-execute-autoexec-cells nil t)
(remove-hook 'after-save-hook 'ein:connect-execute-autoexec-cells t))
(ein:log 'info "Auto-execution mode is %s."
(if autoexec-p "enabled" "disabled"))))
;;; ein:connect-mode
@ -241,17 +286,24 @@ See also: `ein:connect-run-buffer', `ein:connect-eval-buffer'."
(define-key map "\C-c\C-f" 'ein:connect-request-tool-tip-or-help-command)
(define-key map "\C-c\C-i" 'ein:connect-complete-command)
(define-key map "\C-c\C-z" 'ein:connect-pop-to-notebook)
(define-key map "\C-c\C-a" 'ein:connect-toggle-autoexec)
(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)
map)
(defun ein:connect-mode-get-lighter ()
(if (oref ein:@connect :autoexec)
(format " ein:c%s" (or ein:connect-aotoexec-lighter
ein:cell-autoexec-prompt))
" ein:c"))
(define-minor-mode ein:connect-mode
"Minor mode for communicating with IPython notebook.
\\{ein:connect-mode-map}"
:lighter " ein:c"
:lighter (:eval (ein:connect-mode-get-lighter))
:keymap ein:connect-mode-map
:group 'ein)

View file

@ -231,13 +231,21 @@ is `nil', BODY is executed with any cell types."
(ein:log 'warn "Not in cell"))))
(defmacro ein:notebook-with-cells-in-region (&rest body)
"Similar to `ein:notebook-with-cell' but sets a list of cells to `cells'."
"Similar to `ein:notebook-with-cell' but sets a list of cells to `cells'.
Cells are fetched by `ein:notebook-get-cells-in-region-or-at-point'."
(declare (indent 0))
`(let* ((cells (ein:notebook-get-cells-in-region-or-at-point)))
(if cells
(progn ,@body)
(ein:log 'warn "Not in cell"))))
(defmacro ein:notebook-with-buffer (notebook &rest body)
"Execute BODY with current buffer setting at the one of NOTEBOOK."
;; FIXME: MANY functions can use this macro. Refactor them!
(declare (indent 1))
`(with-current-buffer (ein:notebook-buffer ,notebook)
,@body))
(defun ein:notebook-new (url-or-port notebook-id &rest args)
(let ((notebook (apply #'make-ein:$notebook
:url-or-port url-or-port
@ -980,6 +988,44 @@ This is equivalent to do ``C-c`` in the console program."
(when (y-or-n-p "Really kill kernel?")
(ein:kernel-kill (ein:$notebook-kernel ein:notebook))))
;; autoexec
(defun ein:notebook-toggle-autoexec ()
"Toggle auto-execution flag of the cell at point."
(interactive)
(ein:notebook-with-cell #'ein:codecell-p
(ein:cell-toggle-autoexec cell)))
(defun ein:notebook-turn-on-autoexec (cells &optional off)
"Turn on auto-execution flag of the cells in region or cell at point.
When the prefix argument is given, turn off the flag instead.
To use autoexec feature, you need to turn on auto-execution mode
in connected buffers, using the `ein:connect-toggle-autoexec'
command."
(interactive
(list (let ((cells
(ein:filter #'ein:codecell-p
(ein:notebook-get-cells-in-region-or-at-point))))
(if cells
cells
(error "Cell note found.")))
current-prefix-arg))
(mapc (lambda (c) (ein:cell-set-autoexec c (not off))) cells)
(ein:log 'info "Turn %s auto-execution flag of %s cells."
(if off "off" "on")
(length cells)))
(defun ein:notebook-execute-autoexec-cells (notebook)
"Execute cells of which auto-execution flag is on."
(interactive (if ein:notebook
(list ein:notebook)
(error "Not in notebook buffer!")))
(ein:kernel-if-ready (ein:$notebook-kernel notebook)
(mapc #'ein:cell-execute
(ein:filter #'ein:cell-autoexec-p
(ein:notebook-get-cells notebook)))))
;; misc kernel related
(defun ein:notebook-eval-string (code)
@ -1223,6 +1269,7 @@ Do not use `python-mode'. Use plain mode when MuMaMo is not installed::
(define-key map "\C-c\C-c" 'ein:notebook-execute-current-cell)
(define-key map (kbd "M-RET")
'ein:notebook-execute-current-cell-and-goto-next)
(define-key map (kbd "C-c C-'") 'ein:notebook-turn-on-autoexec)
(define-key map "\C-c\C-e" 'ein:notebook-toggle-output-command)
(define-key map "\C-c\C-v" 'ein:notebook-set-collapsed-all-command)
(define-key map "\C-c\C-l" 'ein:notebook-clear-output-command)