2012-05-07 14:41:15 +02:00
|
|
|
|
;;; ein-mumamo.el --- MuMaMo for notebook
|
|
|
|
|
|
|
|
|
|
;; 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-mumamo.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-mumamo.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-mumamo.el. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
|
|
(require 'mumamo)
|
|
|
|
|
|
|
|
|
|
(require 'ein-notebook)
|
|
|
|
|
|
2012-07-17 07:25:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Customization
|
|
|
|
|
|
2012-05-22 00:10:48 +02:00
|
|
|
|
(defcustom ein:mumamo-codecell-mode 'python-mode
|
|
|
|
|
"Major Mode for Code Cell."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:mumamo-textcell-mode 'text-mode
|
|
|
|
|
"Major Mode for Text Cell."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:mumamo-htmlcell-mode 'html-mode
|
|
|
|
|
"Major Mode for HTML Cell."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:mumamo-markdowncell-mode 'markdown-mode
|
|
|
|
|
"Major Mode for Markdown Cell."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:mumamo-rawcell-mode 'rst-mode
|
|
|
|
|
"Major Mode for Raw Cell."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:mumamo-headingcell-mode 'text-mode
|
|
|
|
|
"Major Mode for Heading Cell."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
|
|
|
|
(defcustom ein:mumamo-fallback-mode 'text-mode
|
|
|
|
|
"Fallback Major Mode."
|
|
|
|
|
:type '(symbol :tag "Major Mode")
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-07-17 08:16:55 +02:00
|
|
|
|
(defcustom ein:use-mumamo-indent-line-function-workaround t
|
|
|
|
|
"Turn on workaround for `mumamo-indent-line-function'.
|
|
|
|
|
|
|
|
|
|
In code cell, hitting TAB or C-j at the end of input area causes
|
|
|
|
|
error from MuMaMo. When this variable is non-`nil', EIN patches
|
|
|
|
|
`mumamo-indent-line-function' to workaround this problem. This
|
|
|
|
|
workaround is on by default.
|
|
|
|
|
|
|
|
|
|
Note that python-mode's indentation function has other problems
|
|
|
|
|
with MuMaMo. For example, hitting TAB twice, which decreases the
|
|
|
|
|
indentation level by one in normal Python buffer, causes similar
|
|
|
|
|
error in code cell. The current workaround does not fix this
|
|
|
|
|
problem."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-07-22 00:34:15 +02:00
|
|
|
|
(defcustom ein:mumamo-indent-line-function-dummy-code "
|
|
|
|
|
def ein_dummy():
|
|
|
|
|
return"
|
|
|
|
|
"Dummy code block for `mumamo-indent-line-function' workaround.
|
|
|
|
|
This code block will be inserted at the end of cell input before
|
|
|
|
|
indentation and then removed afterward (so user will not see this
|
|
|
|
|
code).
|
|
|
|
|
|
|
|
|
|
This is ugly but... \"practicality beats purity\"...
|
|
|
|
|
I guess somebody should fix python.el and/or MuMaMo, in order to
|
|
|
|
|
remove this ugliness.
|
|
|
|
|
|
|
|
|
|
To make the workaround less aggressive, you can set a newline
|
|
|
|
|
\"\\n\" for this variable. In that case, you will be affected by
|
|
|
|
|
`issue 24`_.
|
|
|
|
|
|
|
|
|
|
.. _issue 24: https://github.com/tkf/emacs-ipython-notebook/issues/24"
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'ein)
|
|
|
|
|
|
2012-07-17 08:16:55 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Workaround
|
|
|
|
|
|
|
|
|
|
(defadvice mumamo-indent-line-function
|
|
|
|
|
(around ein:mumamo-indent-line-function-workaround)
|
2012-07-22 00:11:35 +02:00
|
|
|
|
"Workaround the indentation problem when the cursor is in the
|
|
|
|
|
code cell."
|
|
|
|
|
(let ((cell (ein:notebook-get-current-cell)))
|
2012-07-22 01:22:54 +02:00
|
|
|
|
;; Check if the current buffer is notebook AND the current cell is
|
|
|
|
|
;; code cell.
|
2012-07-22 00:11:35 +02:00
|
|
|
|
(if (ein:codecell-p cell)
|
|
|
|
|
(let ((cur (copy-marker (point)))
|
|
|
|
|
(end (copy-marker (1+ (ein:cell-input-pos-max cell)))))
|
|
|
|
|
;; v-- execute `delete-char' here
|
2012-07-22 00:34:15 +02:00
|
|
|
|
;; ... [] ......DUMMY
|
|
|
|
|
;; ^- cur ^- end (non-inclusive end of cell)
|
2012-07-22 00:11:35 +02:00
|
|
|
|
;; ^- `ad-do-it' here
|
|
|
|
|
(unwind-protect
|
|
|
|
|
(progn
|
|
|
|
|
(goto-char (1- end))
|
2012-07-22 00:34:15 +02:00
|
|
|
|
(insert ein:mumamo-indent-line-function-dummy-code)
|
2012-07-22 00:11:35 +02:00
|
|
|
|
(goto-char cur)
|
|
|
|
|
ad-do-it)
|
|
|
|
|
(save-excursion
|
2012-07-22 00:34:15 +02:00
|
|
|
|
(let ((len (length ein:mumamo-indent-line-function-dummy-code)))
|
|
|
|
|
(goto-char (- end 1 len))
|
|
|
|
|
(delete-char len)))))
|
2012-07-22 00:11:35 +02:00
|
|
|
|
ad-do-it)))
|
2012-07-17 08:16:55 +02:00
|
|
|
|
|
|
|
|
|
(defun ein:mumamo-indent-line-function-workaround-turn-on ()
|
|
|
|
|
"Activate advice for `mumamo-indent-line-function'.
|
|
|
|
|
Called via `ein:notebook-mumamo-mode-hook'."
|
|
|
|
|
(when ein:use-mumamo-indent-line-function-workaround
|
|
|
|
|
(ad-enable-advice 'mumamo-indent-line-function 'around
|
|
|
|
|
'ein:mumamo-indent-line-function-workaround)
|
|
|
|
|
(ad-activate 'mumamo-indent-line-function)))
|
|
|
|
|
|
2012-07-20 18:30:54 +02:00
|
|
|
|
(defun ein:mumamo-imenu-setup-maybe ()
|
|
|
|
|
"Set `imenu-create-index-function' if the current buffer is the
|
|
|
|
|
notebook buffer.
|
|
|
|
|
This function is called via `after-change-major-mode-hook', to set
|
|
|
|
|
the variable every time visiting the different chunks.
|
|
|
|
|
|
|
|
|
|
.. note:: Making `imenu-create-index-function' permanent-local
|
|
|
|
|
also solves the problem. However, this will make the variable
|
|
|
|
|
permanent-local in *any* buffer, including the buffers
|
|
|
|
|
irrelevant to EIN. Therefore, the current approach is taken.
|
|
|
|
|
|
|
|
|
|
This is the same workaround as `ein:ac-setup-maybe'."
|
|
|
|
|
(when ein:notebook
|
|
|
|
|
(ein:notebook-imenu-setup)))
|
|
|
|
|
|
|
|
|
|
(add-hook 'after-change-major-mode-hook 'ein:mumamo-imenu-setup-maybe)
|
|
|
|
|
|
2012-05-10 20:38:40 +02:00
|
|
|
|
|
2012-07-17 07:25:57 +02:00
|
|
|
|
|
|
|
|
|
;;; `ein:notebook-mumamo-mode'
|
|
|
|
|
|
2012-05-19 18:02:03 +02:00
|
|
|
|
(define-derived-mode ein:notebook-bg-mode fundamental-mode "ein:bg"
|
|
|
|
|
"Background mode for `ein:notebook-mumamo-mode'."
|
2012-06-16 15:28:02 +02:00
|
|
|
|
(setq font-lock-defaults '(nil t))
|
2012-05-19 18:02:03 +02:00
|
|
|
|
(font-lock-mode))
|
2012-05-10 20:22:58 +02:00
|
|
|
|
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(define-mumamo-multi-major-mode ein:notebook-mumamo-mode
|
|
|
|
|
"IPython notebook mode."
|
2012-05-19 18:02:03 +02:00
|
|
|
|
("IPython notebook familiy" ein:notebook-bg-mode
|
2012-05-10 20:21:16 +02:00
|
|
|
|
(ein:mumamo-chunk-codecell
|
2012-05-10 20:38:40 +02:00
|
|
|
|
ein:mumamo-chunk-textcell
|
|
|
|
|
ein:mumamo-chunk-htmlcell
|
|
|
|
|
ein:mumamo-chunk-markdowncell
|
2012-05-19 23:59:38 +02:00
|
|
|
|
ein:mumamo-chunk-rawcell
|
|
|
|
|
ein:mumamo-chunk-headingcell
|
2012-05-07 14:41:15 +02:00
|
|
|
|
)))
|
|
|
|
|
|
2012-07-29 18:09:16 +02:00
|
|
|
|
(set-keymap-parent ein:notebook-mumamo-mode-map ein:notebook-mode-map)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-05-19 17:58:02 +02:00
|
|
|
|
(add-hook 'ein:notebook-mumamo-mode-hook 'ein:notebook-setup-kill-buffer-hook)
|
2012-07-17 08:16:55 +02:00
|
|
|
|
(add-hook 'ein:notebook-mumamo-mode-hook
|
|
|
|
|
'ein:mumamo-indent-line-function-workaround-turn-on)
|
2012-05-19 17:58:02 +02:00
|
|
|
|
|
2012-07-17 07:25:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Chunk functions
|
|
|
|
|
|
2012-05-10 20:22:58 +02:00
|
|
|
|
(defmacro ein:mumamo-define-chunk (name)
|
|
|
|
|
(let ((funcname (intern (format "ein:mumamo-chunk-%s" name)))
|
|
|
|
|
(mode (intern (format "ein:mumamo-%s-mode" name)))
|
|
|
|
|
(cell-p (intern (format "ein:%s-p" name))))
|
|
|
|
|
`(defun ,funcname (pos max)
|
|
|
|
|
(mumamo-possible-chunk-forward
|
|
|
|
|
pos max
|
|
|
|
|
(lambda (pos max) "CHUNK-START-FUN"
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "CHUNK-START-FUN(pos=%s max=%s)" pos max)
|
2012-05-10 20:22:58 +02:00
|
|
|
|
(ein:aif (ein:mumamo-find-edge pos max nil #',cell-p)
|
2012-05-10 21:56:28 +02:00
|
|
|
|
(list it (if (functionp ,mode)
|
|
|
|
|
,mode
|
|
|
|
|
ein:mumamo-fallback-mode)
|
|
|
|
|
nil)))
|
2012-05-10 20:22:58 +02:00
|
|
|
|
(lambda (pos max) "CHUNK-END-FUN"
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "CHUNK-END-FUN(pos=%s max=%s)" pos max)
|
2012-05-10 20:22:58 +02:00
|
|
|
|
(ein:mumamo-find-edge pos max t #',cell-p))))))
|
|
|
|
|
|
|
|
|
|
(ein:mumamo-define-chunk codecell)
|
2012-05-10 20:38:40 +02:00
|
|
|
|
(ein:mumamo-define-chunk textcell)
|
|
|
|
|
(ein:mumamo-define-chunk htmlcell)
|
|
|
|
|
(ein:mumamo-define-chunk markdowncell)
|
2012-05-19 23:59:38 +02:00
|
|
|
|
(ein:mumamo-define-chunk rawcell)
|
|
|
|
|
(ein:mumamo-define-chunk headingcell)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
2012-05-10 20:08:55 +02:00
|
|
|
|
(defun ein:mumamo-find-edge (pos max end cell-p)
|
2012-05-10 20:21:16 +02:00
|
|
|
|
"Helper function for `ein:mumamo-chunk-codecell'.
|
2012-05-07 14:41:15 +02:00
|
|
|
|
|
|
|
|
|
Return the point of beginning of the input element of cell after
|
|
|
|
|
the point POS. Return `nil' if it cannot be found before the point
|
|
|
|
|
MAX. If END is non-`nil', end of the input element is returned."
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "EIN:MUMAMO-FIND-EDGE(pos=%s max=%s end=%s cell-p=%s)"
|
2012-05-10 20:48:32 +02:00
|
|
|
|
pos max end cell-p)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(let* ((ewoc-node
|
2012-05-10 21:52:40 +02:00
|
|
|
|
(ein:notebook-get-nearest-cell-ewoc-node pos max cell-p))
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(_ (ein:log 'blather "(null ewoc-node) = %s" (null ewoc-node)))
|
2012-05-10 20:08:55 +02:00
|
|
|
|
(cell (ein:aand ewoc-node
|
2012-05-10 21:52:40 +02:00
|
|
|
|
(ein:$node-data (ewoc-data it))))
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(_ (ein:log 'blather "(null cell) = %s" (null cell)))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(find
|
|
|
|
|
(lambda (c)
|
|
|
|
|
(ein:aand c
|
|
|
|
|
(ein:cell-element-get it (if end :after-input :input))
|
|
|
|
|
(progn
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "(null it) = %s" (null it))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(ewoc-location it))
|
|
|
|
|
(if end it (1+ it)))))
|
|
|
|
|
(input-pos (funcall find cell)))
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "input-pos (1) = %s" input-pos)
|
2012-05-10 20:38:40 +02:00
|
|
|
|
(when (and input-pos (< input-pos pos))
|
2012-05-10 23:07:28 +02:00
|
|
|
|
(setq input-pos (ein:aand (ein:cell-next cell)
|
|
|
|
|
(when (funcall cell-p it) (funcall find it)))))
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "input-pos (2) = %s" input-pos)
|
2012-05-10 23:14:00 +02:00
|
|
|
|
(when (and input-pos (> input-pos max))
|
2012-05-07 14:41:15 +02:00
|
|
|
|
(setq input-pos nil))
|
2012-07-22 13:16:29 +02:00
|
|
|
|
(ein:log 'blather "input-pos (3) = %s" input-pos)
|
2012-05-07 14:41:15 +02:00
|
|
|
|
input-pos))
|
|
|
|
|
|
|
|
|
|
(provide 'ein-mumamo)
|
|
|
|
|
|
|
|
|
|
;;; ein-mumamo.el ends here
|