mirror of
https://github.com/vale981/emacs-ipython-notebook
synced 2025-03-06 09:31:39 -05:00
Merge branch 'worksheet-move'
* Add commands ein:notebook-worksheet-move-prev/next to reorder worksheet list. * Simple tab is added to header-line.
This commit is contained in:
commit
ad333957c9
5 changed files with 169 additions and 11 deletions
|
@ -474,7 +474,12 @@ This is equivalent to do ``C-c`` in the console program."
|
|||
(with-current-buffer (ein:worksheet-buffer ws)
|
||||
(ein:notebook-mode)
|
||||
;; Now that major-mode is set, set buffer local variables:
|
||||
(ein:notification-setup (current-buffer) (ein:$notebook-events notebook))
|
||||
(ein:notification-setup
|
||||
(current-buffer)
|
||||
(ein:$notebook-events notebook)
|
||||
(lambda () (ein:$notebook-worksheets ein:%notebook%))
|
||||
(lambda () ein:%worksheet%)
|
||||
#'ein:worksheet-name)
|
||||
(ein:notebook-setup-kill-buffer-hook)
|
||||
(setq ein:%notebook% notebook)))
|
||||
|
||||
|
@ -823,6 +828,22 @@ When used as a lisp function, delete worksheet WS from NOTEBOOk."
|
|||
(let ((ein:notebook-kill-buffer-ask nil))
|
||||
(kill-buffer (ein:worksheet-buffer ws))))
|
||||
|
||||
(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)))
|
||||
|
||||
|
||||
;;; Scratch sheet
|
||||
|
||||
|
@ -1008,6 +1029,8 @@ Do not use `python-mode'. Use plain mode when MuMaMo is not installed::
|
|||
(define-key map (kbd "C-c !") 'ein:worksheet-rename-sheet)
|
||||
(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)
|
||||
(define-key map (kbd "C-c M-{") 'ein:notebook-worksheet-move-prev)
|
||||
(define-key map (kbd "C-c M-}") 'ein:notebook-worksheet-move-next)
|
||||
(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)
|
||||
|
@ -1092,6 +1115,8 @@ Do not use `python-mode'. Use plain mode when MuMaMo is not installed::
|
|||
("Insert previous worksheet"
|
||||
ein:notebook-worksheet-insert-prev)
|
||||
("Delete worksheet" ein:notebook-worksheet-delete)
|
||||
("Move worksheet left" ein:notebook-worksheet-move-prev)
|
||||
("Move worksheet right" ein:notebook-worksheet-move-next)
|
||||
))
|
||||
"---"
|
||||
,@(ein:generate-menu
|
||||
|
|
|
@ -47,8 +47,14 @@
|
|||
(s2m :initarg :s2m))
|
||||
"Hold status and it's string representation (message).")
|
||||
|
||||
(defclass ein:notification-tab ()
|
||||
((get-list :initarg :get-list :type function)
|
||||
(get-current :initarg :get-current :type function)
|
||||
(get-name :initarg :get-name :type function)))
|
||||
|
||||
(defclass ein:notification ()
|
||||
((buffer :initarg :buffer :type buffer :document "Notebook buffer")
|
||||
(tab :initarg :tab :type ein:notification-tab)
|
||||
(notebook
|
||||
:initarg :notebook
|
||||
:initform
|
||||
|
@ -90,6 +96,13 @@ where NS is `:kernel' or `:notebook' slot of NOTIFICATION."
|
|||
st ; = event-type
|
||||
#'ein:notification--callback
|
||||
(cons ns st))))
|
||||
(ein:events-on events
|
||||
'notebook_saved.Notebook
|
||||
#'ein:notification--fadeout-callback
|
||||
(list (oref notification :notebook)
|
||||
"Notebook is saved"
|
||||
'notebook_saved.Notebook
|
||||
nil))
|
||||
(ein:events-on events
|
||||
'status_restarting.Kernel
|
||||
#'ein:notification--fadeout-callback
|
||||
|
@ -104,6 +117,8 @@ where NS is `:kernel' or `:notebook' slot of NOTIFICATION."
|
|||
(ein:notification-status-set ns status)))
|
||||
|
||||
(defun ein:notification--fadeout-callback (packed data)
|
||||
;; FIXME: I can simplify this.
|
||||
;; Do not pass around message, for exmaple.
|
||||
(let ((ns (nth 0 packed))
|
||||
(message (nth 1 packed))
|
||||
(status (nth 2 packed))
|
||||
|
@ -119,17 +134,60 @@ where NS is `:kernel' or `:notebook' slot of NOTIFICATION."
|
|||
(force-mode-line-update))))
|
||||
packed)))
|
||||
|
||||
(defun ein:notification-setup (buffer events)
|
||||
(defun ein:notification-setup (buffer events get-list get-current get-name)
|
||||
"Setup a new notification widget in the BUFFER.
|
||||
This function saves the new notification widget instance in the
|
||||
local variable of the BUFFER"
|
||||
local variable of the BUFFER.
|
||||
|
||||
Other arguments GET-LIST, GET-CURRENT and GET-NAME are used to
|
||||
draw tabs for worksheets. GET-LIST is a function returns a list
|
||||
of worksheets. GET-CURRENT is a function returns the current
|
||||
worksheet. GET-NAME is a function returns a name of the
|
||||
worksheet given as its argument."
|
||||
(with-current-buffer buffer
|
||||
(setq ein:%notification%
|
||||
(ein:notification "NotificationWidget" :buffer buffer))
|
||||
(setq header-line-format ein:header-line-format)
|
||||
(ein:notification-bind-events ein:%notification% events)
|
||||
(oset ein:%notification% :tab
|
||||
(make-instance 'ein:notification-tab
|
||||
:get-list get-list
|
||||
:get-current get-current
|
||||
:get-name get-name))
|
||||
ein:%notification%))
|
||||
|
||||
|
||||
;;; Tabs
|
||||
|
||||
(defface ein:notification-tab-selected
|
||||
'((t :inherit (header-line match)))
|
||||
"Face for headline selected tab."
|
||||
:group 'ein)
|
||||
|
||||
(defface ein:notification-tab-normal
|
||||
'((t :inherit (header-line)))
|
||||
"Face for headline selected tab."
|
||||
:group 'ein)
|
||||
|
||||
(defmethod ein:notification-tab-create-line ((tab ein:notification-tab))
|
||||
(let ((list (funcall (oref tab :get-list)))
|
||||
(current (funcall (oref tab :get-current)))
|
||||
(get-name (oref tab :get-name)))
|
||||
(ein:join-str
|
||||
" "
|
||||
(loop for i from 1
|
||||
for elem in list
|
||||
if (eq elem current)
|
||||
collect (propertize
|
||||
(or (ein:and-let* ((name (funcall get-name elem)))
|
||||
(format "[%d: %s]" i name))
|
||||
(format "[%d]" i))
|
||||
'face 'ein:notification-tab-selected)
|
||||
else
|
||||
collect (propertize
|
||||
(format " %d " i)
|
||||
'face 'ein:notification-tab-normal)))))
|
||||
|
||||
|
||||
;;; Header line
|
||||
|
||||
|
@ -141,7 +199,9 @@ local variable of the BUFFER"
|
|||
(ein:filter
|
||||
'identity
|
||||
(list (oref (oref ein:%notification% :notebook) :message)
|
||||
(oref (oref ein:%notification% :kernel) :message))))))
|
||||
(oref (oref ein:%notification% :kernel) :message)
|
||||
(ein:notification-tab-create-line
|
||||
(oref ein:%notification% :tab)))))))
|
||||
|
||||
(defun ein:header-line-setup-maybe ()
|
||||
"Setup `header-line-format' for mumamo.
|
||||
|
|
|
@ -341,6 +341,39 @@ Elements are compared using the function TEST (default: `eq')."
|
|||
return (progn (push new (cdr rest)) list)
|
||||
finally do (error "PIVOT %S is not in LIST %S" pivot list))))
|
||||
|
||||
(defun* ein:list-move-left (list elem &key (test #'eq))
|
||||
"Move ELEM in LIST left. TEST is used to compare elements"
|
||||
(macrolet ((== (a b) `(funcall test ,a ,b)))
|
||||
(cond
|
||||
((== (car list) elem)
|
||||
(append (cdr list) (list (car list))))
|
||||
(t
|
||||
(loop for rest on list
|
||||
when (== (cadr rest) elem)
|
||||
return (let ((prev (car rest)))
|
||||
(setf (car rest) elem)
|
||||
(setf (cadr rest) prev)
|
||||
list)
|
||||
finally do (error "ELEM %S is not in LIST %S" elem list))))))
|
||||
|
||||
(defun* ein:list-move-right (list elem &key (test #'eq))
|
||||
"Move ELEM in LIST right. TEST is used to compare elements"
|
||||
(loop with first = t
|
||||
for rest on list
|
||||
when (funcall test (car rest) elem)
|
||||
return (if (cdr rest)
|
||||
(let ((next (cadr rest)))
|
||||
(setf (car rest) next)
|
||||
(setf (cadr rest) elem)
|
||||
list)
|
||||
(if first
|
||||
list
|
||||
(setcdr rest-1 nil)
|
||||
(cons elem list)))
|
||||
finally do (error "ELEM %S is not in LIST %S" elem list)
|
||||
for rest-1 = rest
|
||||
do (setq first nil)))
|
||||
|
||||
(defun ein:get-value (obj)
|
||||
"Get value from obj if it is a variable or function."
|
||||
(cond
|
||||
|
|
|
@ -3,33 +3,53 @@
|
|||
|
||||
(require 'ein-notification)
|
||||
|
||||
(ert-deftest ein-header-line-kernel-status-busy ()
|
||||
(defun ein:testing-notification-tab-mock ()
|
||||
(make-instance 'ein:notification-tab
|
||||
:get-list (lambda () '(a b c))
|
||||
:get-current (lambda () 'a)
|
||||
:get-name #'ignore))
|
||||
|
||||
(ert-deftest ein:header-line-normal ()
|
||||
(let* ((ein:%notification% (ein:notification "NotificationTest"))
|
||||
(kernel (oref ein:%notification% :kernel)))
|
||||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||
(should (equal (ein:header-line)
|
||||
"IP[y]: [1] 2 3 "))))
|
||||
|
||||
(ert-deftest ein:header-line-kernel-status-busy ()
|
||||
(let* ((ein:%notification% (ein:notification "NotificationTest"))
|
||||
(kernel (oref ein:%notification% :kernel)))
|
||||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||
(ein:notification-status-set kernel
|
||||
'status_busy.Kernel)
|
||||
(should (equal (ein:header-line) "IP[y]: Kernel is busy..."))))
|
||||
(should (equal (ein:header-line)
|
||||
"IP[y]: Kernel is busy... | [1] 2 3 "))))
|
||||
|
||||
(ert-deftest ein-header-line-notebook-status-busy ()
|
||||
(ert-deftest ein:header-line-notebook-status-busy ()
|
||||
(let* ((ein:%notification% (ein:notification "NotificationTest"))
|
||||
(notebook (oref ein:%notification% :notebook)))
|
||||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||
(ein:notification-status-set notebook
|
||||
'notebook_saved.Notebook)
|
||||
(should (equal (ein:header-line) "IP[y]: Notebook is saved"))))
|
||||
(should (equal (ein:header-line)
|
||||
"IP[y]: Notebook is saved | [1] 2 3 "))))
|
||||
|
||||
(ert-deftest ein-header-line-notebook-complex ()
|
||||
(ert-deftest ein:header-line-notebook-complex ()
|
||||
(let* ((ein:%notification% (ein:notification "NotificationTest"))
|
||||
(kernel (oref ein:%notification% :kernel))
|
||||
(notebook (oref ein:%notification% :notebook)))
|
||||
(oset ein:%notification% :tab (ein:testing-notification-tab-mock))
|
||||
(ein:notification-status-set kernel
|
||||
'status_dead.Kernel)
|
||||
(ein:notification-status-set notebook
|
||||
'notebook_saving.Notebook)
|
||||
(should (equal
|
||||
(ein:header-line)
|
||||
"IP[y]: Saving Notebook... | Kernel is dead. Need restart."))))
|
||||
(concat "IP[y]: Saving Notebook... | "
|
||||
"Kernel is dead. Need restart. | "
|
||||
"[1] 2 3 ")))))
|
||||
|
||||
(ert-deftest ein-notification-and-events ()
|
||||
(ert-deftest ein:notification-and-events ()
|
||||
(let* ((notification (ein:notification "NotificationTest"))
|
||||
(kernel (oref notification :kernel))
|
||||
(notebook (oref notification :notebook))
|
||||
|
|
|
@ -95,3 +95,23 @@ def func():
|
|||
(should (equal (ein:list-insert-before '(a b c) 'b 'X) '(a X b c)))
|
||||
(should (equal (ein:list-insert-before '(a b c) 'c 'X) '(a b X c)))
|
||||
(should-error (ein:list-insert-before '(a b c) 'd 'X)))
|
||||
|
||||
(ert-deftest ein:list-move-left ()
|
||||
(should (equal (ein:list-move-left '(a) 'a) '(a)))
|
||||
(should (equal (ein:list-move-left '(a b) 'a) '(b a)))
|
||||
(should (equal (ein:list-move-left '(a b) 'b) '(b a)))
|
||||
(should (equal (ein:list-move-left '(a b c d) 'a) '(b c d a)))
|
||||
(should (equal (ein:list-move-left '(a b c d) 'b) '(b a c d)))
|
||||
(should (equal (ein:list-move-left '(a b c d) 'c) '(a c b d)))
|
||||
(should (equal (ein:list-move-left '(a b c d) 'd) '(a b d c)))
|
||||
(should-error (ein:list-move-left '(a b c d) 'X)))
|
||||
|
||||
(ert-deftest ein:list-move-right ()
|
||||
(should (equal (ein:list-move-right '(a) 'a) '(a)))
|
||||
(should (equal (ein:list-move-right '(a b) 'a) '(b a)))
|
||||
(should (equal (ein:list-move-right '(a b) 'b) '(b a)))
|
||||
(should (equal (ein:list-move-right '(a b c d) 'a) '(b a c d)))
|
||||
(should (equal (ein:list-move-right '(a b c d) 'b) '(a c b d)))
|
||||
(should (equal (ein:list-move-right '(a b c d) 'c) '(a b d c)))
|
||||
(should (equal (ein:list-move-right '(a b c d) 'd) '(d a b c)))
|
||||
(should-error (ein:list-move-right '(a b c d) 'X)))
|
||||
|
|
Loading…
Add table
Reference in a new issue