├── tests
├── notebook
│ └── .gitignore
├── test-ein-smartrep.el
├── test-load.el
├── test-ein-ac.el
├── test-ein-completer.el
├── test-ein-notebooklist.el
├── test-ein-pytools.el
├── test-ein-shared-output.el
├── test-ein-console.el
├── test-ein-modes.el
├── test-ein-kill-ring.el
├── test-ein-iexec.el
├── test-ein-worksheet.el
├── test-ein-connect.el
├── test-ein-output-area.el
├── test-ein-worksheet-notebook.el
├── ein-testing.el
├── ein-testing-cell.el
├── ein-testing-kernel.el
├── test-ein-kernel.el
├── test-ein-core.el
├── test-ein-notification.el
├── test-ein-node.el
├── ein-testing-notebook.el
├── test-ein-utils.el
└── test-ein-cell-notebook.el
├── .gitignore
├── tools
├── requirement-ipy.0.13.0.txt
├── requirement-ipy.0.12.0.txt
├── requirement-ipy.0.12.1.txt
├── requirement-ipy.dev.txt
├── makeenv.sh
├── update-autoloads.sh
├── emacslisp.py
└── test_testein.py
├── doc
├── update-gh-pages.sh
├── source
│ ├── conf.el
│ └── conf.py
├── make.bat
└── Makefile
├── lisp
├── ein-pkg.el
├── ein-pseudo-console.el
├── ein-ipynb-mode.el
├── ein-scratchsheet.el
├── ein-smartrep.el
├── ein-kill-ring.el
├── ein.py
├── ein.el
├── ein-events.el
├── debug-ein.el
├── ein-node.el
├── ein-python.el
├── ein-iexec.el
├── ein-pager.el
├── ein-junk.el
├── ein-subpackages.el
├── ein-multilang-fontify.el
├── ein-jedi.el
├── ein-query.el
├── ein-log.el
├── zeroein.el
├── ein-websocket.el
├── ein-kernelinfo.el
├── ein-output-area.el
├── ein-org.el
├── ein-completer.el
├── ein-multilang.el
├── ein-traceback.el
├── ein-helm.el
├── ein-mumamo.el
├── ein-ac.el
└── ein-console.el
├── .gitmodules
├── Makefile
├── CONTRIBUTING.md
└── .travis.yml
/tests/notebook/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | doc/build/
2 | env
3 | log
4 |
--------------------------------------------------------------------------------
/tools/requirement-ipy.0.13.0.txt:
--------------------------------------------------------------------------------
1 | ipython==0.13
2 | pyzmq
3 | tornado
4 |
--------------------------------------------------------------------------------
/tools/requirement-ipy.0.12.0.txt:
--------------------------------------------------------------------------------
1 | ipython==0.12
2 | pyzmq==2.2.0.1
3 | tornado
4 |
--------------------------------------------------------------------------------
/tools/requirement-ipy.0.12.1.txt:
--------------------------------------------------------------------------------
1 | ipython==0.12.1
2 | pyzmq==2.2.0.1
3 | tornado
4 |
--------------------------------------------------------------------------------
/tools/requirement-ipy.dev.txt:
--------------------------------------------------------------------------------
1 | -e git://github.com/ipython/ipython.git#egg=ipython
2 | pyzmq
3 | tornado
4 | jinja2
5 |
--------------------------------------------------------------------------------
/doc/update-gh-pages.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | cd build/html/
3 | git add .
4 | if [ -n "$(git ls-files --deleted)" ]
5 | then
6 | git ls-files --deleted | xargs git rm
7 | fi
8 | git commit -m "Update"
9 |
--------------------------------------------------------------------------------
/lisp/ein-pkg.el:
--------------------------------------------------------------------------------
1 | (define-package "ein"
2 | "0.2.0alpha0"
3 | "Emacs IPython Notebook"
4 | '((websocket "0.9")
5 | (request "0.2")
6 | ;; `auto-complete' is not really a dependency, but who use EIN w/o AC?
7 | (auto-complete "1.4")))
8 |
--------------------------------------------------------------------------------
/tests/test-ein-smartrep.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-smartrep)
5 |
6 | (ert-deftest ein:smartrep-notebook-mode-alist-fboundp ()
7 | (loop for (k . f) in ein:smartrep-notebook-mode-alist
8 | do (should (fboundp f))))
9 |
--------------------------------------------------------------------------------
/tools/makeenv.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | env="$1"
4 | req="$2"
5 | activate=$env/bin/activate
6 |
7 | if [ -z "$env" -o -z "$req" ]; then
8 | echo "Usage:"
9 | echo " $0 ENVIRONMENT REQUIREMENT"
10 | exit 1
11 | fi
12 |
13 | if [ -e $activate ]; then
14 | echo "virtualenv $env exists."
15 | else
16 | echo "Creating virtualenv $env."
17 | virtualenv $env
18 | fi
19 |
20 | . $activate
21 | pip install --quiet --requirement $req
22 |
--------------------------------------------------------------------------------
/tools/update-autoloads.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Update ein-loaddefs.el
4 | #
5 | # --commit Automatically commit updated changes in ein-loaddefs.el
6 |
7 | if [ -z "$EMACS" ]; then
8 | EMACS="$(which emacs)"
9 | fi
10 |
11 | # To omit slashes in the second FILE argument, need to go to the
12 | # directory.
13 | cd lisp || exit $?
14 |
15 | $EMACS -Q -batch --eval \
16 | "(setq generated-autoload-file \"$(pwd)/ein-loaddefs.el\")" \
17 | -f batch-update-autoloads .
18 |
19 | if [ "$1" = "--commit" ]; then
20 | git commit --message "Update ein-loaddefs.el" ein-loaddefs.el
21 | fi
22 |
--------------------------------------------------------------------------------
/tests/test-load.el:
--------------------------------------------------------------------------------
1 | ;; Load all test-ein-*.el files for interactive/batch use.
2 |
3 | ;; Usage:
4 | ;; emacs -Q -batch -L ... -l tests/test-load.el -f ert-run-tests-batch
5 | ;; You will need to set load paths using `-L' switch.
6 |
7 | (require 'ein-dev)
8 | (require 'ein-testing)
9 |
10 | (ein:setq-if-not ein:testing-dump-file-log "test-batch-log.log")
11 | (ein:setq-if-not ein:testing-dump-file-messages "test-batch-messages.log")
12 | (setq message-log-max t)
13 |
14 |
15 | (ein:load-files "^test-ein-.*\\.el$"
16 | (file-name-directory load-file-name)
17 | t) ; ignore-compiled
18 |
--------------------------------------------------------------------------------
/tests/test-ein-ac.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-ac)
5 | (require 'ein-testing-kernel)
6 |
7 |
8 | (ert-deftest ein:ac-set-document ()
9 | (let ((string "candidate string"))
10 | (should-not (get-text-property 0 'document string))
11 | (ein:testing-kernel-construct-help-string-loop
12 | (lambda (content result)
13 | (ein:ac-set-document string content '-not-used-)
14 | (let ((props (text-properties-at 0 string)))
15 | ;; document property may be nil, but must be set.
16 | (should (member 'document props))
17 | (should (equal (plist-get props 'document) result)))))))
18 |
--------------------------------------------------------------------------------
/tests/test-ein-completer.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (when load-file-name
5 | (add-to-list 'load-path
6 | (concat (file-name-directory load-file-name) "mocker")))
7 | (require 'mocker)
8 |
9 | (require 'ein-completer)
10 |
11 |
12 | (ert-deftest ein:completer-finish-completing ()
13 | (let* ((matched-text 'dummy-matched-text-value) ; value can be anything
14 | (matches 'dummy-matches-value)
15 | (content (list :matched_text matched-text
16 | :matches matches))
17 | (args '(:extend t)))
18 | (mocker-let
19 | ((ein:completer-choose () ((:output 'completer)))
20 | (completer
21 | (matched-text matches &rest args)
22 | ((:input (list matched-text matches args)))))
23 | (ein:completer-finish-completing args content '-not-used-))))
24 |
--------------------------------------------------------------------------------
/tests/test-ein-notebooklist.el:
--------------------------------------------------------------------------------
1 | (require 'ein-notebooklist)
2 |
3 | (defun eintest:notebooklist-make-empty (&optional url-or-port)
4 | "Make empty notebook list buffer."
5 | (ein:notebooklist-url-retrieve-callback (or url-or-port "DUMMY-URL")))
6 |
7 | (defmacro eintest:notebooklist-is-empty-context-of (func)
8 | `(ert-deftest ,(intern (format "%s--notebooklist" func)) ()
9 | (with-current-buffer (eintest:notebooklist-make-empty)
10 | (should-not (,func)))))
11 |
12 |
13 | ;; Generic getter
14 |
15 | (ert-deftest ein:get-url-or-port--notebooklist ()
16 | (with-current-buffer (eintest:notebooklist-make-empty "DUMMY-URL")
17 | (should (equal (ein:get-url-or-port) "DUMMY-URL"))))
18 |
19 | (eintest:notebooklist-is-empty-context-of ein:get-notebook)
20 | (eintest:notebooklist-is-empty-context-of ein:get-kernel)
21 | (eintest:notebooklist-is-empty-context-of ein:get-cell-at-point)
22 | (eintest:notebooklist-is-empty-context-of ein:get-traceback-data)
23 |
--------------------------------------------------------------------------------
/tests/test-ein-pytools.el:
--------------------------------------------------------------------------------
1 | (require 'ert)
2 |
3 | (when load-file-name
4 | (add-to-list 'load-path
5 | (concat (file-name-directory load-file-name) "mocker")))
6 | (require 'mocker)
7 |
8 | (require 'ein-pytools)
9 | (require 'ein-testing-kernel)
10 |
11 |
12 | (ert-deftest ein:pytools-finish-tooltip ()
13 | (ein:testing-kernel-construct-help-string-loop
14 | (lambda (content result)
15 | (if result
16 | (mocker-let
17 | ((featurep
18 | (feature)
19 | ((:input '(pos-tip) :output t)))
20 | (pos-tip-show
21 | (string &optional tip-color pos window timeout)
22 | ((:input (list result 'ein:pos-tip-face nil nil 0)))))
23 | (let ((window-system t))
24 | (ein:pytools-finish-tooltip '-not-used- content '-not-used-)))
25 | (mocker-let
26 | ((featurep (feature) ()))
27 | (ein:pytools-finish-tooltip '-not-used- content '-not-used-))))))
28 |
--------------------------------------------------------------------------------
/doc/source/conf.el:
--------------------------------------------------------------------------------
1 | (let* (join ; to suppress compiler warning...
2 | (join (lambda (p &rest ps)
3 | (if ps (apply join (expand-file-name (car ps) p) (cdr ps)) p)))
4 | (current-directory (file-name-directory load-file-name))
5 | (project-directory (funcall join current-directory ".." ".."))
6 | (path (lambda (&rest ps) (apply join project-directory ps))))
7 | (add-to-list 'load-path (funcall path "lisp"))
8 | (add-to-list 'load-path (funcall path "lib" "websocket"))
9 | (add-to-list 'load-path (funcall path "lib" "request"))
10 | (add-to-list 'load-path (funcall path "lib" "nxhtml" "util")) ; mumamo
11 | (add-to-list 'load-path (funcall path "lib" "auto-complete"))
12 | (add-to-list 'load-path (funcall path "lib" "popup"))) ; for auto-complete
13 |
14 | (require 'ein-dev)
15 | (ein:dev-require-all)
16 |
17 | ;; Load `wid-edit'. Otherwise the following error will be raised:
18 | ;; Symbol's function definition is void: widget-button-press
19 | (require 'wid-edit)
20 |
--------------------------------------------------------------------------------
/tools/emacslisp.py:
--------------------------------------------------------------------------------
1 | """
2 | Emacs Lisp Display object/Formatter for IPython.
3 |
4 | Usage::
5 |
6 | In [1]:
7 | %run path/to/emacslisp.py
8 |
9 | In [2]:
10 | EmacsLisp('(+ 1 2 3)')
11 | Out [2]:
12 | 6
13 |
14 | """
15 |
16 | from IPython.core.formatters import BaseFormatter, Unicode, ObjectName
17 | from IPython.core.display import DisplayObject
18 |
19 |
20 | def add_display_formatter(new_formatter):
21 | from IPython.core.formatters import FormatterABC
22 | FormatterABC.register(new_formatter)
23 | from IPython.core.interactiveshell import InteractiveShell
24 | inst = InteractiveShell.instance()
25 | f = new_formatter(config=inst.display_formatter.config)
26 | inst.display_formatter.formatters[f.format_type] = f
27 |
28 |
29 | class EmacsLispFormatter(BaseFormatter):
30 | format_type = Unicode('application/emacs-lisp')
31 | print_method = ObjectName('_repr_emacs_lisp_')
32 |
33 |
34 | class EmacsLisp(DisplayObject):
35 |
36 | def _repr_emacs_lisp_(self):
37 | return self.data
38 |
39 | if __name__ == '__main__':
40 | add_display_formatter(EmacsLispFormatter)
41 |
--------------------------------------------------------------------------------
/tests/test-ein-shared-output.el:
--------------------------------------------------------------------------------
1 | (require 'ein-shared-output)
2 |
3 | (defmacro eintest:shared-output-with-buffer (&rest body)
4 | (declare (indent 0))
5 | `(with-current-buffer (ein:shared-output-create-buffer)
6 | (ein:shared-output-get-or-create)
7 | ,@body))
8 |
9 | (defmacro eintest:shared-output-is-empty-context-of (func)
10 | `(ert-deftest ,(intern (format "%s--shared-output" func)) ()
11 | (eintest:shared-output-with-buffer
12 | (should-not (,func)))))
13 |
14 |
15 | ;; Generic getter
16 |
17 | (ert-deftest ein:get-cell-at-point--shared-output ()
18 | (eintest:shared-output-with-buffer
19 | (should (eq (ein:get-cell-at-point)
20 | (ein:shared-output-get-cell))))
21 | (with-temp-buffer
22 | (should-not (ein:get-cell-at-point--shared-output))))
23 |
24 | ;; FIXME: Add tests with non-empty shared output buffer.
25 | (eintest:shared-output-is-empty-context-of ein:get-url-or-port)
26 | (eintest:shared-output-is-empty-context-of ein:get-notebook)
27 | (eintest:shared-output-is-empty-context-of ein:get-kernel)
28 | (eintest:shared-output-is-empty-context-of ein:get-traceback-data)
29 |
--------------------------------------------------------------------------------
/tests/test-ein-console.el:
--------------------------------------------------------------------------------
1 | (require 'ein-console)
2 |
3 | (ert-deftest ein:console-security-dir-string ()
4 | (let ((ein:console-security-dir "/some/dir/"))
5 | (should (equal (ein:console-security-dir-get "DUMMY-URL-OR-PORT")
6 | ein:console-security-dir))))
7 |
8 | (ert-deftest ein:console-security-dir-list ()
9 | (let ((ein:console-security-dir
10 | '((8888 . "/dir/8888/")
11 | ("htttp://dummy.org" . "/dir/http/")
12 | (7777 . my-secret-directory)
13 | (default . "/dir/default/")))
14 | (my-secret-directory "/dir/secret/"))
15 | (should (equal (ein:console-security-dir-get 8888) "/dir/8888/"))
16 | (should (equal (ein:console-security-dir-get "htttp://dummy.org")
17 | "/dir/http/"))
18 | (should (equal (ein:console-security-dir-get 7777) "/dir/secret/"))
19 | (should (equal (ein:console-security-dir-get 9999) "/dir/default/"))))
20 |
21 | (ert-deftest ein:console-security-dir-func ()
22 | (let ((ein:console-security-dir
23 | '(lambda (x) (should (equal x "DUMMY-URL-OR-PORT")) "/dir/")))
24 | (should (equal (ein:console-security-dir-get "DUMMY-URL-OR-PORT")
25 | "/dir/"))))
26 |
--------------------------------------------------------------------------------
/tests/test-ein-modes.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-dev)
5 | (ein:dev-require-all :ignore-p (lambda (f) (equal f "ein-mumamo.el")))
6 | (eval-when-compile
7 | ;; do it also at compile time.
8 | (ein:dev-require-all :ignore-p (lambda (f) (equal f "ein-mumamo.el"))))
9 |
10 |
11 | (defun eintest:assert-keymap-fboundp (keymap)
12 | (let (assert-fboundp)
13 | (setq assert-fboundp
14 | (lambda (event value)
15 | (cond
16 | ((keymapp value)
17 | (map-keymap assert-fboundp value))
18 | ((and (listp value) (eq (car value) 'menu-item))
19 | (funcall assert-fboundp (cadr value) (caddr value)))
20 | (value ; nil is also valid in keymap
21 | (should (commandp value))))))
22 | (map-keymap assert-fboundp keymap)))
23 |
24 | (defmacro eintest:test-keymap (keymap)
25 | `(ert-deftest ,(intern (format "%s--assert-fboundp" keymap)) ()
26 | (eintest:assert-keymap-fboundp ,keymap)))
27 |
28 | (eintest:test-keymap ein:notebooklist-mode-map)
29 | (eintest:test-keymap ein:notebook-mode-map)
30 | (eintest:test-keymap ein:connect-mode-map)
31 | (eintest:test-keymap ein:traceback-mode-map)
32 | (eintest:test-keymap ein:shared-output-mode-map)
33 | (eintest:test-keymap ein:pager-mode-map)
34 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "tests/mocker"]
2 | path = tests/mocker
3 | url = https://github.com/sigma/mocker.el.git
4 | [submodule "doc/eldomain"]
5 | path = doc/eldomain
6 | url = git://github.com/tkf/sphinx-eldomain.git
7 | [submodule "lib/websocket"]
8 | path = lib/websocket
9 | url = git://github.com/ahyatt/emacs-websocket.git
10 | [submodule "lib/auto-complete"]
11 | path = lib/auto-complete
12 | url = git://github.com/auto-complete/auto-complete.git
13 | [submodule "lib/fuzzy"]
14 | path = lib/fuzzy
15 | url = git://github.com/auto-complete/fuzzy-el.git
16 | [submodule "lib/popup"]
17 | path = lib/popup
18 | url = git://github.com/auto-complete/popup-el.git
19 | [submodule "lib/pos-tip"]
20 | path = lib/pos-tip
21 | url = git://github.com/emacsmirror/pos-tip.git
22 | [submodule "lib/smartrep"]
23 | path = lib/smartrep
24 | url = git://github.com/myuhe/smartrep.el.git
25 | [submodule "lib/python"]
26 | path = lib/python
27 | url = git://github.com/fgallina/python.el.git
28 | [submodule "lib/markdown-mode"]
29 | path = lib/markdown-mode
30 | url = git://jblevins.org/git/markdown-mode.git
31 | [submodule "lib/nxhtml"]
32 | path = lib/nxhtml
33 | url = git://github.com/emacsmirror/nxhtml.git
34 | [submodule "lib/ert"]
35 | path = lib/ert
36 | url = git://github.com/ohler/ert.git
37 | [submodule "lib/request"]
38 | path = lib/request
39 | url = git://github.com/tkf/emacs-request
40 |
--------------------------------------------------------------------------------
/tests/test-ein-kill-ring.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-kill-ring)
5 |
6 | (ert-deftest ein:kill-ring-simple ()
7 | (let (ein:kill-ring
8 | ein:kill-ring-yank-pointer)
9 | (ein:kill-new 1)
10 | (should (equal (ein:current-kill 0) 1))))
11 |
12 | (defun eintest:kill-ring-simple-repeat-setup ()
13 | (loop for i from 0 below 5
14 | do (ein:kill-new i)
15 | do (should (equal (ein:current-kill 0) i))))
16 |
17 | (ert-deftest ein:kill-ring-simple-repeat ()
18 | (let (ein:kill-ring
19 | ein:kill-ring-yank-pointer)
20 | (eintest:kill-ring-simple-repeat-setup)
21 | (should (equal ein:kill-ring ein:kill-ring-yank-pointer))
22 | (should (equal ein:kill-ring '(4 3 2 1 0)))))
23 |
24 | (ert-deftest ein:kill-ring-repeat-n-1 ()
25 | (let (ein:kill-ring
26 | ein:kill-ring-yank-pointer)
27 | (eintest:kill-ring-simple-repeat-setup)
28 | (loop for i in '(3 2 1 0 4 3 2)
29 | do (should (equal (ein:current-kill 1) i)))
30 | (should-not (equal ein:kill-ring ein:kill-ring-yank-pointer))
31 | (should (equal ein:kill-ring '(4 3 2 1 0)))
32 | (should (equal ein:kill-ring-yank-pointer '(2 1 0)))))
33 |
34 | (ert-deftest ein:kill-ring-exceeds-max ()
35 | (let (ein:kill-ring
36 | ein:kill-ring-yank-pointer
37 | (ein:kill-ring-max 3))
38 | (eintest:kill-ring-simple-repeat-setup)
39 | (should (equal ein:kill-ring ein:kill-ring-yank-pointer))
40 | (should (equal (length ein:kill-ring) ein:kill-ring-max))
41 | (should (equal ein:kill-ring '(4 3 2)))))
42 |
--------------------------------------------------------------------------------
/tests/test-ein-iexec.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-iexec)
5 | (require 'ein-testing-notebook)
6 |
7 |
8 | ;;; `ein:iexec-should-execute-p'
9 |
10 | (defun* eintest:iexec-should-execute-p (cell &key (this-command t) beg end)
11 | "Simple wrapper for `ein:iexec-should-execute-p' which
12 | returns `t' by default, if the CELL is code cell."
13 | (unless beg (setq beg (ein:cell-input-pos-min cell)))
14 | (unless end (setq end (ein:cell-input-pos-max cell)))
15 | (ein:iexec-should-execute-p cell beg end))
16 |
17 | ;; cell types
18 |
19 | (ert-deftest ein:iexec-should-execute-p-codecell ()
20 | (ein:testing-with-one-cell 'code
21 | (should (eintest:iexec-should-execute-p cell))))
22 |
23 | (ert-deftest ein:iexec-should-execute-p-markdowncell ()
24 | (ein:testing-with-one-cell 'markdown
25 | (should-not (eintest:iexec-should-execute-p cell))))
26 |
27 | (ert-deftest ein:iexec-should-execute-p-dead-cell ()
28 | (ein:testing-with-one-cell 'code
29 | (should-not (eintest:iexec-should-execute-p (ein:cell-copy cell)))))
30 |
31 | ;; other
32 |
33 | (ert-deftest ein:iexec-should-execute-p-non-interactive ()
34 | (ein:testing-with-one-cell 'code
35 | (should-not (eintest:iexec-should-execute-p cell :this-command nil))))
36 |
37 | (ert-deftest ein:iexec-should-execute-p-beg-too-small ()
38 | (ein:testing-with-one-cell 'code
39 | (should-not (eintest:iexec-should-execute-p cell :beg (point-min)))))
40 |
41 | (ert-deftest ein:iexec-should-execute-p-end-too-big ()
42 | (ein:testing-with-one-cell 'code
43 | (should-not (eintest:iexec-should-execute-p cell :end (point-max)))))
44 |
--------------------------------------------------------------------------------
/lisp/ein-pseudo-console.el:
--------------------------------------------------------------------------------
1 | ;;; ein-pseudo-console.el --- Pseudo console mode
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-pseudo-console.el is free software: you can redistribute it
10 | ;; and/or modify it under the terms of the GNU General Public License
11 | ;; as published by the Free Software Foundation, either version 3 of
12 | ;; the License, or (at your option) any later version.
13 |
14 | ;; ein-pseudo-console.el is distributed in the hope that it will be
15 | ;; useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 | ;; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-pseudo-console.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (defvar ein:pseudo-console-mode-map (make-sparse-keymap))
30 |
31 | (let ((map ein:pseudo-console-mode-map))
32 | (define-key map "\C-m" 'ein:worksheet-execute-cell-and-insert-below))
33 |
34 | ;;;###autoload
35 | (define-minor-mode ein:pseudo-console-mode
36 | "Pseudo console mode. Hit RET to execute code."
37 | :lighter " ein:pseudo"
38 | :keymap ein:pseudo-console-mode-map
39 | :group 'ein)
40 |
41 | ;; To avoid MuMaMo to discard `ein:pseudo-console-mode', make it
42 | ;; permanent local.
43 | (put 'ein:pseudo-console-mode 'permanent-local t)
44 |
45 | (provide 'ein-pseudo-console)
46 |
47 | ;;; ein-pseudo-console.el ends here
48 |
--------------------------------------------------------------------------------
/tests/test-ein-worksheet.el:
--------------------------------------------------------------------------------
1 | (require 'ert)
2 |
3 | (require 'ein-worksheet)
4 | (require 'ein-testing-cell)
5 |
6 | (defvar ein:testing-worksheet-example-data
7 | (list (ein:testing-codecell-data "code example input")
8 | (ein:testing-markdowncell-data "markdown example input")
9 | (ein:testing-rawcell-data "raw example input")
10 | (ein:testing-htmlcell-data "html example input")
11 | (ein:testing-headingcell-data "heading example input")))
12 |
13 | (defun ein:testing-worksheet-new ()
14 | (make-instance 'ein:worksheet
15 | :discard-output-p (cons #'ignore nil)))
16 |
17 | (defun ein:testing-worksheet-to-json (cells &optional metadata)
18 | (let* ((ws-0 (ein:worksheet-from-json (ein:testing-worksheet-new)
19 | (list :cells cells
20 | :metadata metadata)))
21 | (ws-1 (ein:testing-worksheet-new))
22 | (json-0 (ein:worksheet-to-json ws-0))
23 | (json-1 (ein:worksheet-to-json
24 | (ein:worksheet-from-json ws-1
25 | (ein:json-read-from-string
26 | (json-encode json-0))))))
27 | (let* ((found (assoc 'metadata json-0)))
28 | (when found
29 | (should (cdr found))))
30 | (should (equal json-0 json-1))))
31 |
32 | (ert-deftest ein:worksheet-to-json/empty ()
33 | (ein:testing-worksheet-to-json nil))
34 |
35 | (ert-deftest ein:worksheet-to-json/example-data ()
36 | (ein:testing-worksheet-to-json ein:testing-worksheet-example-data))
37 |
38 | (ert-deftest ein:worksheet-to-json/example-data-with-metadata ()
39 | (ein:testing-worksheet-to-json ein:testing-worksheet-example-data
40 | '(:name "Worksheet name")))
41 |
--------------------------------------------------------------------------------
/tests/test-ein-connect.el:
--------------------------------------------------------------------------------
1 | (require 'ein-connect)
2 | (require 'ein-testing-notebook)
3 |
4 | (defmacro eintest:with-connected-buffer (&rest body)
5 | (declare (indent 0))
6 | `(let* ((notebook-buffer (ein:testing-notebook-make-empty))
7 | (notebook (buffer-local-value 'ein:notebook notebook-buffer)))
8 | (with-temp-buffer
9 | (erase-buffer)
10 | (ein:connect-buffer-to-notebook notebook)
11 | ,@body)))
12 |
13 | (ert-deftest ein:get-url-or-port--connect ()
14 | (eintest:with-connected-buffer
15 | (should (equal (ein:get-url-or-port)
16 | (ein:$notebook-url-or-port notebook)))))
17 |
18 | (ert-deftest ein:get-notebook--connect ()
19 | (eintest:with-connected-buffer
20 | (should (eq (ein:get-notebook) notebook))))
21 |
22 | (ert-deftest ein:get-kernel--connect ()
23 | (eintest:with-connected-buffer
24 | (should (eq (ein:get-kernel)
25 | (ein:$notebook-kernel notebook)))))
26 |
27 | (ert-deftest ein:get-cell-at-point--connect ()
28 | "`ein:get-cell-at-point' is in empty context in connected buffer."
29 | (eintest:with-connected-buffer
30 | (should-not (ein:get-cell-at-point))))
31 |
32 | (ert-deftest ein:get-traceback-data--connect ()
33 | (eintest:with-connected-buffer
34 | ;; FIXME: write test with non-empty TB
35 | (should-not (ein:get-traceback-data))))
36 |
37 | (ert-deftest ein:connect-mode-revert-buffer-resistance ()
38 | (let ((temp-file (make-temp-file "ein")))
39 | (unwind-protect
40 | (with-temp-buffer
41 | (setq buffer-file-name temp-file)
42 | (ein:connect-mode 1)
43 | (setq ein:%connect% 'very-important-value)
44 | (revert-buffer t t nil)
45 | (should ein:connect-mode)
46 | (should (eq ein:%connect% 'very-important-value)))
47 | (delete-file temp-file))))
48 |
--------------------------------------------------------------------------------
/tests/test-ein-output-area.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-output-area)
5 |
6 | (defun ein:testing-insert-html--fix-urls-do-test (source desired)
7 | (setq source (ein:xml-parse-html-string source))
8 | (setq desired (ein:xml-parse-html-string desired))
9 | (ein:insert-html--fix-urls source 8888)
10 | (should (equal source desired)))
11 |
12 | (defmacro ein:testing-insert-html--fix-urls-deftests (args-list)
13 | `(progn
14 | ,@(loop for i from 0
15 | for args in args-list
16 | for test = (intern (format "ein:insert-html--fix-urls/%s" i))
17 | collect
18 | `(ert-deftest ,test ()
19 | (ein:testing-insert-html--fix-urls-do-test ,@args)))))
20 |
21 | (when (require 'shr nil t)
22 | (ein:testing-insert-html--fix-urls-deftests
23 | (;; Simple replaces
24 | ("text"
25 | "text")
26 | ("text"
27 | "text")
28 | ("
"
29 | "
")
30 | ("
"
31 | "
")
32 | ;; Do not modify dom in these cases:
33 | ("text"
34 | "text")
35 | ("text"
36 | "text")
37 | ("
"
38 | "
")
39 | ;; Bit more complicated cases:
40 | ("link normal
"
41 | "link normal
")
42 | ("![]()
normal
"
43 | "![]()
normal")
44 | )))
45 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | EMACS ?= emacs
2 | IPYTHON = env/ipy.$(IPY_VERSION)/bin/ipython
3 | IPY_VERSION = 0.13.0
4 | TESTEIN = tools/testein.py
5 | TESTEIN_OPTS =
6 | PKG_INFO = \
7 | grep '^Version' \
8 | env/ipy.$(IPY_VERSION)/lib/python*/site-packages/*.egg-info/PKG-INFO \
9 | | sed -r 's%.*/site-packages/(.*)-py.*\.egg-info/.*:Version: (.*)$$%\1\t\2%'
10 |
11 | testein: test-requirements
12 | ${MAKE} testein-1
13 |
14 | interactive-testein: test-requirements
15 | ${MAKE} TESTEIN_OPTS="--no-batch" testein-1
16 |
17 | clean: ert-clean
18 | rm -f lisp/*.elc
19 |
20 | purge: clean
21 | rm -rf env log
22 |
23 | pkg-info:
24 | @echo "**************************************************"
25 | @echo "Installed Python Packages"
26 | $(PKG_INFO)
27 |
28 | submodule:
29 | git submodule update --init
30 |
31 | ERT_DIR = lib/ert/lisp/emacs-lisp
32 | ert-compile: submodule ert-clean log
33 | $(EMACS) -Q -batch -L $(ERT_DIR) \
34 | -f batch-byte-compile $(ERT_DIR)/*.el 2> log/ert-compile.log
35 |
36 | ert-clean:
37 | rm -f lib/ert/lisp/emacs-lisp/*.elc
38 |
39 | env-ipy.%:
40 | tools/makeenv.sh env/ipy.$* tools/requirement-ipy.$*.txt
41 |
42 | log:
43 | mkdir log
44 |
45 | test-requirements: ert-compile env-ipy.$(IPY_VERSION)
46 | ${MAKE} pkg-info
47 |
48 | travis-ci-testein: test-requirements
49 | ${MAKE} testein-2
50 |
51 | testein-2: testein-2-url-retrieve testein-2-curl
52 |
53 | testein-2-curl:
54 | EL_REQUEST_BACKEND=curl ${MAKE} testein-1
55 |
56 | testein-2-url-retrieve:
57 | EL_REQUEST_BACKEND=url-retrieve ${MAKE} testein-1
58 |
59 | testein-1:
60 | $(EMACS) --version
61 | python --version
62 | env/ipy.$(IPY_VERSION)/bin/ipython --version
63 | $(TESTEIN) --clean-elc -e $(EMACS) \
64 | --ipython $(IPYTHON) ${TESTEIN_OPTS}
65 |
66 | travis-ci-zeroein:
67 | $(EMACS) --version
68 | EMACS=$(EMACS) lisp/zeroein.el -batch
69 | rm -rf lib/*
70 | EMACS=$(EMACS) lisp/zeroein.el -batch
71 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution guide line
2 |
3 | Please use `M-x ein:dev-bug-report-template` to write a bug report.
4 | It pops up a buffer containing some system information and instruction
5 | for bug report.
6 |
7 |
8 | ## Avoid standard Emacs traps
9 |
10 | ### It is Emacs not all
11 |
12 | Do you try the same thing in normal IPython notebook (i.e., browser)?
13 | If not, please try. There can be problem in your IPython installation.
14 |
15 |
16 | ### Your Emacs configuration
17 |
18 | There can be some configuration EIN does not work well with. To check
19 | if the problem is in the configuration or not, the best way is to start
20 | EIN in a clean Emacs (i.e., without your configuration).
21 |
22 | You can use zeroein.el to start EIN in a clean Emacs.
23 | See the Quick try section in the manual:
24 | http://tkf.github.com/emacs-ipython-notebook/#quick-try
25 |
26 |
27 | ### Badly compiled file
28 |
29 | Remove all `*.elc` files from EIN source directory and its
30 | dependencies. Then restart Emacs and try the procedure to reproduce
31 | the problem again.
32 |
33 | You will have problem with compiled files if they are older than the
34 | source files and/or the files are compiled with different Emacs
35 | versions.
36 |
37 |
38 | ### Make sure that the right library is loaded.
39 |
40 | Sometimes you accidentally load libraries from unexpected location,
41 | if you installed it in different places in the past or another
42 | Emacs lisp libraries you are using bundles the old version of the
43 | libraries.
44 |
45 | To make sure that all EIN dependencies are loaded from the intended
46 | place, use `M-x locate-library`. Also, `M-x ein:dev-bug-report-template`
47 | does it for you for all EIN dependencies.
48 |
49 |
50 | ## Log and backtrace
51 |
52 | Please consider putting log and backtrace in your bug report.
53 | Follow the instruction in the manual:
54 | http://tkf.github.com/emacs-ipython-notebook/#reporting-issue
55 |
--------------------------------------------------------------------------------
/tools/test_testein.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | import testein
4 |
5 |
6 | class TestSequenceFunctions(unittest.TestCase):
7 |
8 | def setUp(self):
9 | self.runner = testein.TestRunner(
10 | batch=True, debug_on_error=False, emacs='emacs',
11 | testfile='func-test.el', log_dir='log',
12 | ein_log_level=40, ein_message_level=30, ein_debug=False)
13 |
14 | def test_is_known_failure__yes(self):
15 | self.runner.stdout = """
16 | ein: [info] Notebook Untitled0 is already opened.
17 | ein: [verbose] ERT TESTING-GET-UNTITLED0-OR-CREATE end
18 | passed 7/7 ein:testing-get-untitled0-or-create
19 |
20 | Ran 7 tests, 6 results as expected, 1 unexpected (2012-12-17 22:27:38+0000)
21 |
22 | 1 unexpected results:
23 | FAILED ein:notebook-execute-current-cell-pyout-image
24 |
25 | Wrote /home/travis/builds/....
26 | """
27 | assert self.runner.is_known_failure()
28 |
29 | def test_is_known_failure__no_failures(self):
30 | self.runner.stdout = """
31 | ein: [info] Notebook Untitled0 is already opened.
32 | ein: [verbose] ERT TESTING-GET-UNTITLED0-OR-CREATE end
33 | passed 7/7 ein:testing-get-untitled0-or-create
34 |
35 | Ran 7 tests, 7 results as expected (2012-12-17 22:27:38+0000)
36 |
37 | Wrote /home/travis/builds/....
38 | """
39 | assert self.runner.is_known_failure()
40 |
41 | def test_is_known_failure__no(self):
42 | self.runner.stdout = """
43 | ein: [info] Notebook Untitled0 is already opened.
44 | ein: [verbose] ERT TESTING-GET-UNTITLED0-OR-CREATE end
45 | passed 7/7 ein:testing-get-untitled0-or-create
46 |
47 | Ran 7 tests, 4 results as expected, 2 unexpected (2012-12-17 22:27:38+0000)
48 |
49 | 2 unexpected results:
50 | FAILED ein:notebook-execute-current-cell-pyout-image
51 | FAILED some-unknown-failure
52 |
53 | Wrote /home/travis/builds/....
54 | """
55 | assert not self.runner.is_known_failure()
56 |
--------------------------------------------------------------------------------
/lisp/ein-ipynb-mode.el:
--------------------------------------------------------------------------------
1 | ;;; ein-ipynb-mode.el --- A simple mode for ipynb file
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-ipynb-mode.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-ipynb-mode.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-ipynb-mode.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'ein-notebooklist)
30 |
31 |
32 | (defvar ein:ipynb-parent-mode 'js-mode
33 | "A mode (a symbol) to use for parent mode for `ein:ipynb-mode'.
34 | Note that this variable must be set *before* compiling EIN.")
35 |
36 | (defalias 'ein:ipynb-parent-mode ein:ipynb-parent-mode)
37 |
38 | ;;;###autoload
39 | (define-derived-mode ein:ipynb-mode ein:ipynb-parent-mode "ein:ipynb"
40 | "A simple mode for ipynb file.")
41 |
42 | (let ((map ein:ipynb-mode-map))
43 | (define-key map "\C-c\C-z" 'ein:notebooklist-open-notebook-by-file-name)
44 | (define-key map "\C-c\C-o" 'ein:notebooklist-open-notebook-by-file-name)
45 | (easy-menu-define ein:ipynb-menu map "EIN IPyNB Mode Menu"
46 | `("EIN IPyNB File"
47 | ,@(ein:generate-menu
48 | '(("Open notebook" ein:notebooklist-open-notebook-by-file-name))))))
49 |
50 | ;;;###autoload
51 | (add-to-list 'auto-mode-alist '(".*\\.ipynb\\'" . ein:ipynb-mode))
52 |
53 |
54 | (provide 'ein-ipynb-mode)
55 |
56 | ;;; ein-ipynb-mode.el ends here
57 |
--------------------------------------------------------------------------------
/lisp/ein-scratchsheet.el:
--------------------------------------------------------------------------------
1 | ;;; ein-scratchsheet.el --- Worksheet without needs for saving
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-scratchsheet.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-scratchsheet.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-scratchsheet.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'ein-worksheet)
30 |
31 | (defvar ein:scratchsheet-buffer-name-template "*ein:scratch %s/%s*")
32 |
33 | (defclass ein:scratchsheet (ein:worksheet)
34 | ;; Note that `data' slot is accessed when rendering worksheet.
35 | ;; So, set valid empty data (`nil') here.
36 | ((data :initarg :data :initform nil))
37 | :documentation
38 | "Worksheet without needs for saving.")
39 |
40 | (defun ein:scratchsheet-new (nbformat get-notebook-name discard-output-p
41 | kernel events &rest args)
42 | (apply #'make-instance 'ein:scratchsheet
43 | :nbformat nbformat :get-notebook-name get-notebook-name
44 | :discard-output-p discard-output-p :kernel kernel :events events
45 | args))
46 |
47 | (defmethod ein:worksheet--buffer-name ((ws ein:scratchsheet))
48 | (format ein:scratchsheet-buffer-name-template
49 | (ein:worksheet-url-or-port ws)
50 | (ein:worksheet-full-name ws)))
51 |
52 | (provide 'ein-scratchsheet)
53 |
54 | ;;; ein-scratchsheet.el ends here
55 |
--------------------------------------------------------------------------------
/lisp/ein-smartrep.el:
--------------------------------------------------------------------------------
1 | ;;; ein-smartrep.el --- smartrep integration
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-smartrep.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-smartrep.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-smartrep.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (require 'smartrep nil t)
29 | (require 'ein-notebook)
30 |
31 | (defcustom ein:smartrep-notebook-mode-alist
32 | '(("C-t" . ein:worksheet-toggle-cell-type)
33 | ("C-l" . ein:worksheet-clear-output)
34 | ("C-k" . ein:worksheet-kill-cell)
35 | ("C-y" . ein:worksheet-yank-cell)
36 | ("C-a" . ein:worksheet-insert-cell-above)
37 | ("C-b" . ein:worksheet-insert-cell-below)
38 | ("C-n" . ein:worksheet-goto-next-input)
39 | ("C-p" . ein:worksheet-goto-prev-input)
40 | ("C-m" . ein:worksheet-merge-cell)
41 | ("" . ein:worksheet-move-cell-up)
42 | ("" . ein:worksheet-move-cell-down)
43 | )
44 | "alist passed to `smartrep-define-key'."
45 | :group 'ein)
46 |
47 | (defun ein:smartrep-config ()
48 | (interactive)
49 | (smartrep-define-key
50 | ein:notebook-mode-map
51 | "C-c"
52 | ein:smartrep-notebook-mode-alist))
53 |
54 |
55 | (defvar ein:smartrep-config-once-called nil)
56 |
57 | (defun ein:smartrep-config-once ()
58 | (unless ein:smartrep-config-once-called
59 | (setq ein:smartrep-config-once-called t)
60 | (ein:smartrep-config)))
61 |
62 | (provide 'ein-smartrep)
63 |
64 | ;;; ein-smartrep.el ends here
65 |
--------------------------------------------------------------------------------
/tests/test-ein-worksheet-notebook.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-notebook)
5 | (require 'ein-testing-notebook)
6 |
7 |
8 | ;;; Event handler
9 |
10 | (defun ein:testing-worksheet-set-dirty
11 | (pre-dirty value post-dirty fired-in)
12 | (with-current-buffer (ein:testing-make-notebook-with-outputs '(nil))
13 | (when pre-dirty
14 | (ein:cell-goto (ein:worksheet-get-current-cell))
15 | (insert "something"))
16 | (should (equal (ein:worksheet-modified-p ein:%worksheet%) pre-dirty))
17 | (with-current-buffer (funcall fired-in)
18 | (let ((events (oref ein:%worksheet% :events))
19 | (cell (ein:worksheet-get-current-cell)))
20 | (ein:events-trigger events 'set_dirty.Worksheet
21 | (list :cell cell :value value))))
22 | (should (equal (ein:worksheet-modified-p ein:%worksheet%) post-dirty))))
23 |
24 | (defun ein:testing-scratchsheet-buffer ()
25 | (ein:worksheet-buffer (ein:notebook-scratchsheet-open ein:%notebook%)))
26 |
27 | (defmacro ein:testing-worksheet-set-dirty-deftest
28 | (pre-dirty value post-dirty &optional fired-in)
29 | (let ((name (intern (format "ein:worksheet-set-dirty/%s-to-%s-fired-in-%s"
30 | pre-dirty value
31 | (or fired-in "current-buffer"))))
32 | (fired-in-defun
33 | (case fired-in
34 | (scratchsheet 'ein:testing-scratchsheet-buffer)
35 | (t 'current-buffer))))
36 | `(ert-deftest ,name ()
37 | (ein:testing-worksheet-set-dirty ,pre-dirty ,value ,post-dirty
38 | #',fired-in-defun))))
39 |
40 | (ein:testing-worksheet-set-dirty-deftest t nil nil)
41 | (ein:testing-worksheet-set-dirty-deftest t t t )
42 | (ein:testing-worksheet-set-dirty-deftest nil nil nil)
43 | (ein:testing-worksheet-set-dirty-deftest nil t t )
44 | (ein:testing-worksheet-set-dirty-deftest t nil t scratchsheet)
45 | (ein:testing-worksheet-set-dirty-deftest t t t scratchsheet)
46 | (ein:testing-worksheet-set-dirty-deftest nil nil nil scratchsheet)
47 | (ein:testing-worksheet-set-dirty-deftest nil t nil scratchsheet)
48 |
--------------------------------------------------------------------------------
/lisp/ein-kill-ring.el:
--------------------------------------------------------------------------------
1 | ;;; ein-kill-ring.el --- Kill-ring for cells
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-kill-ring.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-kill-ring.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-kill-ring.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;; Stolen from simple.el.
25 |
26 | ;;; Code:
27 |
28 | (defvar ein:kill-ring nil)
29 | (defvar ein:kill-ring-yank-pointer nil)
30 | (defvar ein:kill-ring-max kill-ring-max)
31 |
32 | (defun ein:kill-new (obj)
33 | "Make OBJ the latest kill in the kill ring `ein:kill-ring'.
34 | Set `ein:kill-ring-yank-pointer' to point to it."
35 | (push obj ein:kill-ring)
36 | (if (> (length ein:kill-ring) ein:kill-ring-max)
37 | (setcdr (nthcdr (1- ein:kill-ring-max) ein:kill-ring) nil))
38 | (setq ein:kill-ring-yank-pointer ein:kill-ring))
39 |
40 | (defun ein:current-kill (n &optional do-not-move)
41 | "Rotate the yanking point by N places, and then return that kill.
42 | If optional arg DO-NOT-MOVE is non-nil, then don't actually
43 | move the yanking point; just return the Nth kill forward."
44 | (unless ein:kill-ring (error "Kill ring is empty"))
45 | (let ((ARGth-kill-element
46 | (nthcdr (mod (- n (length ein:kill-ring-yank-pointer))
47 | (length ein:kill-ring))
48 | ein:kill-ring)))
49 | (unless do-not-move
50 | (setq ein:kill-ring-yank-pointer ARGth-kill-element))
51 | (car ARGth-kill-element)))
52 |
53 | (provide 'ein-kill-ring)
54 |
55 | ;;; ein-kill-ring.el ends here
56 |
--------------------------------------------------------------------------------
/lisp/ein.py:
--------------------------------------------------------------------------------
1 | """
2 | Python utilities to use it from ein.el
3 |
4 | Copyright (C) 2012- Takafumi Arakaki
5 |
6 | Author: Takafumi Arakaki
7 |
8 | ein.py is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | ein.py is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with ein.py. If not, see .
20 |
21 | """
22 |
23 |
24 | def _find_edit_target_012(*args, **kwds):
25 | from IPython.core.interactiveshell import InteractiveShell
26 | inst = InteractiveShell.instance()
27 | return inst._find_edit_target(*args, **kwds)
28 |
29 |
30 | def _find_edit_target_013(*args, **kwds):
31 | from IPython.core.interactiveshell import InteractiveShell
32 | inst = InteractiveShell.instance()
33 | return CodeMagics._find_edit_target(inst, *args, **kwds)
34 |
35 | try:
36 | from IPython.core.magics import CodeMagics
37 | _find_edit_target = _find_edit_target_013
38 | except ImportError:
39 | _find_edit_target = _find_edit_target_012
40 |
41 |
42 | def find_source(name):
43 | """Given an object as string, `name`, print its place in source code."""
44 | # FIXME: use JSON display object instead of stdout
45 | ret = _find_edit_target(name, {}, [])
46 | if ret:
47 | (filename, lineno, use_temp) = ret
48 | if not use_temp:
49 | print filename
50 | print lineno
51 | return
52 | raise RuntimeError("Source code for {0} cannot be found".format(name))
53 |
54 |
55 | def run_docstring_examples(obj, verbose=True):
56 | from IPython.core.interactiveshell import InteractiveShell
57 | import doctest
58 | inst = InteractiveShell.instance()
59 | globs = inst.user_ns
60 | return doctest.run_docstring_examples(obj, globs, verbose=verbose)
61 |
--------------------------------------------------------------------------------
/lisp/ein.el:
--------------------------------------------------------------------------------
1 | ;;; ein.el --- IPython notebook client in Emacs
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 | ;; URL: http://tkf.github.com/emacs-ipython-notebook/
7 | ;; Keywords: applications, tools
8 | ;; Version: 0.2.1alpha2
9 |
10 | ;; This file is NOT part of GNU Emacs.
11 |
12 | ;; ein.el is free software: you can redistribute it and/or modify
13 | ;; it under the terms of the GNU General Public License as published by
14 | ;; the Free Software Foundation, either version 3 of the License, or
15 | ;; (at your option) any later version.
16 |
17 | ;; ein.el is distributed in the hope that it will be useful,
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | ;; GNU General Public License for more details.
21 |
22 | ;; You should have received a copy of the GNU General Public License
23 | ;; along with ein.el. If not, see .
24 |
25 | ;;; Commentary:
26 |
27 | ;; Development
28 | ;; ===========
29 |
30 | ;; Event vs hook vs callback
31 | ;; -------------------------
32 | ;;
33 | ;; * Use events (`ein:events') for calling (possibly multiple) functions
34 | ;; for its side effect.
35 | ;; * Use hooks for global/configurable setting.
36 | ;; * Use callback when caller needs returned value.
37 | ;; (e.g., `:get-buffers' slot in `ein:kernelinfo')
38 |
39 | ;; Naming
40 | ;; ------
41 | ;;
42 | ;; Variable named `ein:%VAR-NAME%' is a permanent buffer local
43 | ;; variable defined by `ein:deflocal'. It is often an instance of a
44 | ;; class/struct named `ein:VAR-NAME'.
45 | ;;
46 | ;; Old naming rule:
47 | ;; * `ein:@VAR-NAME'/`ein:VAR-NAME' is a permanent buffer local
48 | ;; variable. These variables are obsolete now.
49 | ;; * `ein:$STRUCT-NAME' is a name of struct.
50 | ;; These strcuts will be renamed to `ein:CLASS-NAME' when
51 | ;; reimplementing them using EIEIO class instead of CL struct.
52 | ;;
53 | ;; See also:
54 | ;; `CLiki : naming conventions `_
55 |
56 | ;;; Code:
57 |
58 | ;; For backward compatibility + providing easy way to load EIN for
59 | ;; users who prefer manual installation.
60 | (require 'ein-loaddefs)
61 |
62 | (provide 'ein)
63 |
64 | ;;; ein.el ends here
65 |
--------------------------------------------------------------------------------
/lisp/ein-events.el:
--------------------------------------------------------------------------------
1 | ;;; ein-events.el --- Event module
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-events.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-events.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-events.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'eieio)
30 |
31 | (require 'ein-core)
32 | (require 'ein-log)
33 |
34 |
35 | ;;; Events handling class
36 |
37 | (defclass ein:events ()
38 | ((callbacks :initarg :callbacks :type hash-table
39 | :initform (make-hash-table :test 'eq)))
40 | "Event handler class.")
41 |
42 | (defun ein:events-new ()
43 | "Return a new event handler instance."
44 | (make-instance 'ein:events))
45 |
46 | (defun ein:events-trigger (events event-type &optional data)
47 | "Trigger EVENT-TYPE and let event handler EVENTS handle that event."
48 | (ein:log 'debug "Event: %S" event-type)
49 | (ein:aif (gethash event-type (oref events :callbacks))
50 | (mapc (lambda (cb-arg) (ein:funcall-packed cb-arg data)) it)
51 | (ein:log 'info "Unknown event: %S" event-type)))
52 |
53 |
54 | (defmethod ein:events-on ((events ein:events) event-type
55 | callback &optional arg)
56 | "Set event trigger hook.
57 |
58 | When EVENT-TYPE is triggered on the event handler EVENTS,
59 | CALLBACK is called. CALLBACK must take two arguments:
60 | ARG as the first argument and DATA, which is passed via
61 | `ein:events-trigger', as the second."
62 | (assert (symbolp event-type))
63 | (let* ((table (oref events :callbacks))
64 | (cbs (gethash event-type table)))
65 | (push (cons callback arg) cbs)
66 | (puthash event-type cbs table)))
67 |
68 |
69 | (provide 'ein-events)
70 |
71 | ;;; ein-events.el ends here
72 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: emacs-lisp
2 | before_install:
3 | - git submodule --quiet update --init
4 | - sudo apt-get install -qq python-virtualenv
5 | - if [ "$EMACS" = "emacs24" ]; then
6 | sudo add-apt-repository -y ppa:cassou/emacs &&
7 | sudo apt-get update -qq &&
8 | sudo apt-get install -qq emacs24 emacs24-el;
9 | fi
10 | - if [ "$EMACS" = 'emacs-snapshot' ]; then
11 | sudo add-apt-repository -y ppa:cassou/emacs &&
12 | sudo apt-get update -qq &&
13 | sudo apt-get install -qq
14 | emacs-snapshot-el emacs-snapshot-gtk emacs-snapshot;
15 | fi
16 | env:
17 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=dev EMACS=emacs
18 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.13.0 EMACS=emacs
19 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.1 EMACS=emacs
20 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.0 EMACS=emacs
21 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=dev EMACS=emacs24
22 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.13.0 EMACS=emacs24
23 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.1 EMACS=emacs24
24 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.0 EMACS=emacs24
25 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=dev EMACS=emacs-snapshot
26 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.13.0 EMACS=emacs-snapshot
27 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.1 EMACS=emacs-snapshot
28 | - EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.0 EMACS=emacs-snapshot
29 | - EIN_TEST_TARGET=travis-ci-zeroein EMACS=emacs
30 | - EIN_TEST_TARGET=travis-ci-zeroein EMACS=emacs24
31 | - EIN_TEST_TARGET=travis-ci-zeroein EMACS=emacs-snapshot
32 | matrix:
33 | allow_failures:
34 | # IPY_VERSION=0.12.*
35 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.1 EMACS=emacs
36 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.0 EMACS=emacs
37 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.1 EMACS=emacs24
38 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.0 EMACS=emacs24
39 | # EMACS=emacs-snapshot
40 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=dev EMACS=emacs-snapshot
41 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.13.0 EMACS=emacs-snapshot
42 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.1 EMACS=emacs-snapshot
43 | - env: EIN_TEST_TARGET=travis-ci-testein IPY_VERSION=0.12.0 EMACS=emacs-snapshot
44 | script:
45 | make $EIN_TEST_TARGET IPY_VERSION=$IPY_VERSION
46 |
--------------------------------------------------------------------------------
/lisp/debug-ein.el:
--------------------------------------------------------------------------------
1 | ;;; debug-ein.el --- Debug ein.el
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; debug-ein.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; debug-ein.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with debug-ein.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;; emacs -Q -L path/to/nxhtml/util/ -l debug-ein.el
25 |
26 | ;;; Code:
27 |
28 | (add-to-list 'load-path (file-name-directory load-file-name))
29 | (require 'ein)
30 | (require 'ein-dev)
31 |
32 | (ein:dev-start-debug)
33 | (ein:notebooklist-open)
34 |
35 |
36 | ;;; Extra stuff
37 |
38 | (require 'markdown-mode nil t)
39 | (require 'rst nil t)
40 |
41 | (declare-function ein:ac-config "ein-ac")
42 | (declare-function global-auto-complete-mode "auto-complete")
43 | (when (featurep 'auto-complete)
44 | (global-auto-complete-mode t)
45 | (setq ein:use-auto-complete-superpack t))
46 |
47 | (declare-function ein:smartrep-config "ein-smartrep")
48 | (when (featurep 'smartrep)
49 | (setq ein:use-smartrep t))
50 |
51 | (custom-set-faces
52 | ;; Turn off background color for mumamo major chunk, to see
53 | ;; highlighting of prompt and stderr.
54 | '(mumamo-background-chunk-major
55 | ((((class color) (min-colors 88) (background dark)) nil)))
56 | ;; '(mumamo-background-chunk-submode1
57 | ;; ((((class color) (min-colors 88) (background dark)) nil)))
58 | )
59 |
60 |
61 | ;; Suppress this warning when using mumamo:
62 | ;; Warning: `font-lock-syntactic-keywords' is an obsolete variable (as of 24.1);
63 | ;; use `syntax-propertize-function' instead.
64 | ;; See: http://stackoverflow.com/a/5470584/727827
65 | (when (and (equal emacs-major-version 24)
66 | (equal emacs-minor-version 1))
67 | (eval-after-load "bytecomp"
68 | '(add-to-list 'byte-compile-not-obsolete-vars
69 | 'font-lock-syntactic-keywords)))
70 |
71 | ;;; debug-ein.el ends here
72 |
--------------------------------------------------------------------------------
/lisp/ein-node.el:
--------------------------------------------------------------------------------
1 | ;;; ein-node.el --- Structure to hold data in ewoc node
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-node.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-node.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-node.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'ewoc)
30 |
31 | (require 'ein-core)
32 |
33 |
34 | (defstruct ein:$node
35 | path ; list of path
36 | data ; actual data
37 | class ; list
38 | )
39 |
40 | (defun ein:node-new (path data &optional class &rest args)
41 | (apply #'make-ein:$node :path path :data data :class class args))
42 |
43 | (defun ein:node-add-class (node &rest classes)
44 | (mapc (lambda (c) (add-to-list (ein:$node-class node) c)) classes))
45 |
46 | (defun ein:node-remove-class (node &rest classes)
47 | (let ((node-class (ein:$node-class node)))
48 | (mapc (lambda (c) (setq node-class (delq c node-class))) classes)
49 | (setf (ein:$node-class node) node-class)))
50 |
51 | (defun ein:node-has-class (node class)
52 | (memq class (ein:$node-class node)))
53 |
54 | (defun ein:node-filter (ewoc-node-list &rest args)
55 | (loop for (key . class) in (ein:plist-iter args)
56 | do (setq ewoc-node-list
57 | (loop for ewoc-node in ewoc-node-list
58 | for node = (ewoc-data ewoc-node)
59 | when (case key
60 | (:is (ein:node-has-class node class))
61 | (:not (not (ein:node-has-class node class)))
62 | (t (error "%s is not supported" key)))
63 | collect ewoc-node)))
64 | ewoc-node-list)
65 |
66 | (provide 'ein-node)
67 |
68 | ;;; ein-node.el ends here
69 |
--------------------------------------------------------------------------------
/lisp/ein-python.el:
--------------------------------------------------------------------------------
1 | ;;; ein-python.el --- Workarounds for python.el
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-python.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-python.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-python.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'python)
30 |
31 | (require 'ein-worksheet)
32 |
33 | (defvar ein:python-block-start
34 | (rx line-start
35 | symbol-start
36 | (or "def" "class" "if" "elif" "else" "try"
37 | "except" "finally" "for" "while" "with")
38 | symbol-end))
39 |
40 | (defun ein:python-indent-calculate-levels ()
41 | "Forcefully set indent level to 0 when there is no python block
42 | yet in this cell."
43 | (ein:and-let* ((cell (ein:worksheet-get-current-cell :noerror t))
44 | (beg (ein:cell-input-pos-min cell))
45 | ((< beg (point))))
46 | (save-excursion
47 | (unless (search-backward-regexp ein:python-block-start beg t)
48 | (setq python-indent-levels (list 0))
49 | (setq python-indent-current-level 0)
50 | t))))
51 |
52 | (defadvice python-indent-calculate-levels
53 | (around ein:python-indent-calculate-levels activate)
54 | "Hack `python-indent-calculate-levels' to reset indent per cell.
55 |
56 | Let's say you have a notebook something like this::
57 |
58 | In [1]:
59 | def func():
60 | pass
61 |
62 | In [2]:
63 | something[]
64 |
65 | Here, ``[]`` is the cursor position. When you hit the tab here,
66 | you don't expect it to indent. However, python.el tries to follow
67 | the indent of ``func()`` then you get indentation. This advice
68 | workaround this problem.
69 |
70 | Note that this workaround does not work with the MuMaMo based
71 | notebook mode."
72 | (unless (ein:python-indent-calculate-levels)
73 | ad-do-it))
74 |
75 | (provide 'ein-python)
76 |
77 | ;;; ein-python.el ends here
78 |
--------------------------------------------------------------------------------
/tests/ein-testing.el:
--------------------------------------------------------------------------------
1 | ;;; ein-testing.el --- Tools for testing
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-testing.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-testing.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-testing.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (require 'ein-log)
29 |
30 | (defmacro ein:setq-if-not (sym val)
31 | `(unless ,sym (setq ,sym ,val)))
32 |
33 | (defvar ein:testing-dump-file-log nil
34 | "File to save buffer specified by `ein:log-all-buffer-name'.")
35 |
36 | (defvar ein:testing-dump-file-messages nil
37 | "File to save the ``*Messages*`` buffer.")
38 |
39 | (defvar ein:testing-dump-file-debug nil)
40 |
41 | (defun ein:testing-save-buffer (buffer-or-name file-name)
42 | (when (and buffer-or-name file-name)
43 | (with-current-buffer (get-buffer buffer-or-name)
44 | (write-region (point-min) (point-max) file-name))))
45 |
46 | (defun ein:testing-dump-logs ()
47 | (ein:testing-save-buffer "*Messages*" ein:testing-dump-file-messages)
48 | (ein:testing-save-buffer ein:log-all-buffer-name ein:testing-dump-file-log))
49 |
50 | (defvar ein:testing-dump-logs--saved nil)
51 |
52 | (defun ein:testing-dump-logs-noerror ()
53 | (if ein:testing-dump-logs--saved
54 | (message "EIN:TESTING-DUMP-LOGS-NOERROR called but already saved.")
55 | (condition-case err
56 | (progn (ein:testing-dump-logs)
57 | (setq ein:testing-dump-logs--saved t))
58 | (error
59 | (message "Error while executing EIN:TESTING-DUMP-LOGS. err = %S"
60 | err)
61 | (when ein:testing-dump-file-debug
62 | (signal (car err) (cdr err)))))))
63 |
64 | (defadvice ert-run-tests-batch (after ein:testing-dump-logs-hook activate)
65 | "Hook `ein:testing-dump-logs-noerror' because `kill-emacs-hook'
66 | is not run in batch mode before Emacs 24.1."
67 | (ein:testing-dump-logs-noerror))
68 |
69 | (add-hook 'kill-emacs-hook #'ein:testing-dump-logs-noerror)
70 |
71 | (provide 'ein-testing)
72 |
73 | ;;; ein-testing.el ends here
74 |
--------------------------------------------------------------------------------
/tests/ein-testing-cell.el:
--------------------------------------------------------------------------------
1 | ;;; ein-testing-cell.el --- Testing utilities for cell module
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-testing-cell.el is free software: you can redistribute it
10 | ;; and/or modify it under the terms of the GNU General Public License
11 | ;; as published by the Free Software Foundation, either version 3 of
12 | ;; the License, or (at your option) any later version.
13 |
14 | ;; ein-testing-cell.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-testing-cell.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'json)
30 |
31 | (defvar ein:testing-example-svg "\
32 |
33 |
35 |
36 | ")
39 |
40 | (defun ein:testing-codecell-pyout-data (text &optional prompt-number)
41 | "Create a plist representing JSON data for code-cell output.
42 | TEXT is a string and PROMPT-NUMBER is an integer."
43 | (list :output_type "pyout"
44 | :prompt_number (or prompt-number 0)
45 | :text text))
46 |
47 | (defun ein:testing-codecell-data (&optional input prompt-number outputs)
48 | "Create a plist representing JSON data for code-type cell.
49 | To make OUTPUTS data, use `ein:testing-codecell-pyout-data'."
50 | (list :cell_type "code"
51 | :input (or input "")
52 | :language "python"
53 | :outputs outputs
54 | :collapsed json-false
55 | :prompt_number prompt-number))
56 |
57 | (defun ein:testing-textcell-data (&optional source cell-type)
58 | (list :cell_type cell-type
59 | :source (or source "")))
60 |
61 | (defun ein:testing-markdowncell-data (&optional source)
62 | (ein:testing-textcell-data source "markdown"))
63 |
64 | (defun ein:testing-rawcell-data (&optional source)
65 | (ein:testing-textcell-data source "raw"))
66 |
67 | (defun ein:testing-htmlcell-data (&optional source)
68 | (ein:testing-textcell-data source "html"))
69 |
70 | (defun ein:testing-headingcell-data (&optional source level)
71 | (append (ein:testing-textcell-data source "heading")
72 | (list :level (or level 1))))
73 |
74 | (provide 'ein-testing-cell)
75 |
76 | ;;; ein-testing-cell.el ends here
77 |
--------------------------------------------------------------------------------
/lisp/ein-iexec.el:
--------------------------------------------------------------------------------
1 | ;;; ein-iexec.el --- Instant execution mode for notebook
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-iexec.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-iexec.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-iexec.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (require 'ein-worksheet)
29 |
30 | (defcustom ein:iexec-delay 0.3
31 | "Delay before executing cell after change in second."
32 | :type 'number
33 | :group 'ein)
34 |
35 | (defvar ein:iexec-timer nil)
36 |
37 | (defun ein:iexec-execute-cell (cell)
38 | "Call `ein:notebook-execute-cell' after `ein:iexec-delay' second.
39 | If the previous execution timer is not fired yet, cancel the timer."
40 | (when ein:iexec-timer
41 | (cancel-timer ein:iexec-timer))
42 | (setq ein:iexec-timer
43 | (run-with-idle-timer ein:iexec-delay nil
44 | #'ein:worksheet-execute-cell
45 | ein:%worksheet% cell)))
46 |
47 | (defun ein:iexec-should-execute-p (cell beg end)
48 | "Return non-`nil' if CELL should be executed by the change within
49 | BEG and END."
50 | (and (ein:codecell-p cell)
51 | this-command
52 | (ein:aif (ein:cell-input-pos-min cell) (<= it beg))
53 | (ein:aif (ein:cell-input-pos-max cell) (>= it end))))
54 |
55 | (defun ein:iexec-after-change (beg end -ignore-len-)
56 | "Called via `after-change-functions' hook."
57 | (let ((cell (ein:worksheet-get-current-cell :pos beg)))
58 | (when (ein:iexec-should-execute-p cell beg end)
59 | (ein:iexec-execute-cell cell))))
60 |
61 | ;;;###autoload
62 | (define-minor-mode ein:iexec-mode
63 | "Instant cell execution minor mode.
64 | Code cell at point will be automatically executed after any
65 | change in its input area."
66 | :lighter " ein:i"
67 | :group 'ein
68 | (if ein:iexec-mode
69 | (add-hook 'after-change-functions 'ein:iexec-after-change nil t)
70 | (remove-hook 'after-change-functions 'ein:iexec-after-change t)))
71 |
72 | ;; To avoid MuMaMo to discard `ein:iexec-after-change', make it
73 | ;; permanent local.
74 | (put 'ein:iexec-after-change 'permanent-local-hook t)
75 | (put 'ein:iexec-mode 'permanent-local t)
76 |
77 | (provide 'ein-iexec)
78 |
79 | ;;; ein-iexec.el ends here
80 |
--------------------------------------------------------------------------------
/lisp/ein-pager.el:
--------------------------------------------------------------------------------
1 | ;;; ein-pager.el --- Pager module
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-pager.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-pager.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-pager.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (require 'ansi-color)
29 |
30 | (require 'ein-core)
31 | (require 'ein-events)
32 |
33 | ;; FIXME: Make a class with `:get-notebook-name' slot like `ein:worksheet'
34 |
35 | (defun ein:pager-new (name events)
36 | ;; currently pager = name.
37 | (ein:pager-bind-events name events)
38 | name)
39 |
40 | (defun ein:pager-bind-events (pager events)
41 | "Bind events related to PAGER to the event handler EVENTS."
42 | (ein:events-on events
43 | 'open_with_text.Pager
44 | #'ein:pager--open-with-text
45 | pager))
46 |
47 | (defun ein:pager--open-with-text (pager data)
48 | (let ((text (plist-get data :text)))
49 | (unless (equal (ein:trim text) "")
50 | (ein:pager-clear pager)
51 | (ein:pager-expand pager)
52 | (ein:pager-append-text pager text))))
53 |
54 | (defun ein:pager-clear (pager)
55 | (ein:with-read-only-buffer (get-buffer-create pager)
56 | (erase-buffer)))
57 |
58 | (defun ein:pager-expand (pager)
59 | (pop-to-buffer (get-buffer-create pager))
60 | (goto-char (point-min)))
61 |
62 | (defun ein:pager-append-text (pager text)
63 | (ein:with-read-only-buffer (get-buffer-create pager)
64 | (insert (ansi-color-apply text))
65 | (ein:pager-mode)))
66 |
67 | ;; FIXME: this should be automatically called when opening pager.
68 | (defun ein:pager-goto-docstring-bset-loc ()
69 | "Goto the best location of the documentation."
70 | (interactive)
71 | (goto-char (point-min))
72 | (search-forward-regexp "^Docstring:")
73 | (beginning-of-line 0)
74 | (recenter 0))
75 |
76 | (define-derived-mode ein:pager-mode fundamental-mode "ein:pager"
77 | "IPython notebook pager mode."
78 | (view-mode)
79 | (font-lock-mode))
80 |
81 | (setq ein:pager-mode-map (make-sparse-keymap))
82 |
83 | (let ((map ein:pager-mode-map))
84 | (define-key map "\C-c\C-b" 'ein:pager-goto-docstring-bset-loc)
85 | (define-key map "q" 'bury-buffer)
86 | map)
87 |
88 | (provide 'ein-pager)
89 |
90 | ;;; ein-pager.el ends here
91 |
--------------------------------------------------------------------------------
/lisp/ein-junk.el:
--------------------------------------------------------------------------------
1 | ;;; ein-junk.el --- Open a notebook to do random things
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-junk.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-junk.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-junk.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'ein-notebooklist)
30 |
31 |
32 | (define-obsolete-variable-alias 'ein:scratch-notebook-name-template
33 | 'ein:junk-notebook-name-template "0.2.0")
34 |
35 | (defcustom ein:junk-notebook-name-template "junk-%Y-%m-%d-%H%M%S"
36 | "Junk notebook name template.
37 | This value is used from `ein:notebooklist-new-scratch-notebook'
38 | and `ein:notebook-rename-to-scratch-command'. This must be a
39 | format string which can be passed to `format-time-string'."
40 | :type '(string :tag "Format string")
41 | :group 'ein)
42 |
43 | (defun ein:junk-notebook-name ()
44 | "Generate new scratch notebook name based on `current-time' and
45 | `ein:junk-notebook-name-template'."
46 | (format-time-string ein:junk-notebook-name-template (current-time)))
47 |
48 |
49 | (define-obsolete-function-alias 'ein:notebooklist-new-scratch-notebook
50 | 'ein:junk-new)
51 |
52 | ;;;###autoload
53 | (defun ein:junk-new (name url-or-port)
54 | "Open a notebook to try random thing.
55 | Notebook name is determined based on
56 | `ein:junk-notebook-name-template'.
57 |
58 | When prefix argument is given, it asks URL or port to use."
59 | (interactive (let ((name (ein:junk-notebook-name))
60 | (url-or-port (or (ein:get-url-or-port)
61 | (ein:default-url-or-port))))
62 | (setq name (read-string "Open notebook as: " name))
63 | (when current-prefix-arg
64 | (setq url-or-port (ein:notebooklist-ask-url-or-port)))
65 | (list name url-or-port)))
66 | (ein:notebooklist-new-notebook-with-name name url-or-port))
67 |
68 |
69 | (define-obsolete-function-alias ' ein:notebook-rename-to-scratch-command
70 | 'ein:junk-rename)
71 |
72 | ;;;###autoload
73 | (defun ein:junk-rename (name)
74 | "Rename the current notebook based on `ein:junk-notebook-name-template'
75 | and save it immediately."
76 | (interactive
77 | (list (read-string "Rename notebook: "
78 | (ein:junk-notebook-name))))
79 | (ein:notebook-rename-command name))
80 |
81 | (provide 'ein-junk)
82 |
83 | ;;; ein-junk.el ends here
84 |
--------------------------------------------------------------------------------
/lisp/ein-subpackages.el:
--------------------------------------------------------------------------------
1 | ;;; ein-subpackages.el --- Subpacakge management
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-subpackages.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-subpackages.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-subpackages.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (defvar ein:ac-config-once-called)
29 | (defvar ein:smartrep-config-once-called))
30 |
31 | (declare-function ein:ac-config-once "ein-ac")
32 | (declare-function ein:smartrep-config-once "ein-smartrep")
33 |
34 |
35 | (defcustom ein:use-auto-complete nil
36 | "Set to `t' to use preset auto-complete configuration.
37 | Use `ein:use-auto-complete-superpack' when you need more powerful
38 | auto completion."
39 | :type 'boolean
40 | :group 'ein)
41 |
42 | (defcustom ein:use-auto-complete-superpack nil
43 | "Set to `t' to use preset a little bit hacky auto-complete configuration.
44 | When this option is enabled, cached omni completion is available."
45 | :type 'boolean
46 | :group 'ein)
47 |
48 | (defcustom ein:use-smartrep nil
49 | "Set to `t' to use preset smartrep configuration.
50 |
51 | .. warning:: When used with MuMaMo (see `ein:notebook-modes'),
52 | keyboard macro which manipulates cell (add, remove, move,
53 | etc.) may start infinite loop (you need to stop it with
54 | ``C-g``). Please be careful using this option if you are a
55 | heavy keyboard macro user. Using keyboard macro for other
56 | commands is fine.
57 |
58 | .. (Comment) I guess this infinite loop happens because the three
59 | modules (kmacro.el, mumamo.el and smartrep.el) touches to
60 | `unread-command-events' in somehow inconsistent ways."
61 | :type 'boolean
62 | :group 'ein)
63 |
64 | (defcustom ein:load-dev nil
65 | "Load development helper."
66 | :type 'boolean
67 | :group 'ein)
68 |
69 | (defun ein:subpackages-load ()
70 | "Load sub-packages depending on configurations."
71 | (when (or ein:use-auto-complete
72 | ein:use-auto-complete-superpack)
73 | (require 'ein-ac)
74 | (ein:ac-config-once ein:use-auto-complete-superpack))
75 | (when ein:use-smartrep
76 | (require 'ein-smartrep)
77 | (ein:smartrep-config-once))
78 | (when ein:load-dev
79 | (require 'ein-dev)))
80 |
81 | (defun ein:subpackages-reload ()
82 | "Reload sub-packages."
83 | (interactive)
84 | (setq ein:ac-config-once-called nil)
85 | (setq ein:smartrep-config-once-called nil)
86 | (ein:subpackages-load))
87 |
88 | (provide 'ein-subpackages)
89 |
90 | ;;; ein-subpackages.el ends here
91 |
--------------------------------------------------------------------------------
/lisp/ein-multilang-fontify.el:
--------------------------------------------------------------------------------
1 | ;;; ein-multilang-fontify.el --- Syntax highlighting for multiple-languages
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-multilang-fontify.el is free software: you can redistribute it
10 | ;; and/or modify it under the terms of the GNU General Public License
11 | ;; as published by the Free Software Foundation, either version 3 of
12 | ;; the License, or (at your option) any later version.
13 |
14 | ;; ein-multilang-fontify.el is distributed in the hope that it will be
15 | ;; useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 | ;; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-multilang-fontify.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | ;; It would be nice if org-src is available, but this module should
30 | ;; work without org-src. Data on `org-src-lang-modes' is used
31 | ;; if this variable is bound.
32 | (require 'org-src nil t)
33 |
34 | (defun ein:mlf-get-lang-mode (lang)
35 | "Return major mode for LANG.
36 | Modified version of `org-src-get-lang-mode'."
37 | (when (symbolp lang)
38 | (setq lang (symbol-name lang)))
39 | (intern
40 | (format "%s-mode"
41 | (or (and (bound-and-true-p org-src-lang-modes)
42 | (cdr (assoc lang org-src-lang-modes)))
43 | lang))))
44 |
45 | (defun ein:mlf-font-lock-fontify-block (lang start end)
46 | "Patched version of `org-src-font-lock-fontify-block'."
47 | (let ((lang-mode (ein:mlf-get-lang-mode lang)))
48 | (if (fboundp lang-mode)
49 | (let ((string (buffer-substring-no-properties start end))
50 | (modified (buffer-modified-p))
51 | (orig-buffer (current-buffer))
52 | pos
53 | next)
54 | (remove-text-properties start end '(face nil))
55 | (with-current-buffer
56 | (get-buffer-create
57 | (concat " ein:mlf-fontification:" (symbol-name lang-mode)))
58 | (delete-region (point-min) (point-max))
59 | (insert (concat string " ")) ;; so there's a final property change
60 | (unless (eq major-mode lang-mode) (funcall lang-mode))
61 | (font-lock-fontify-buffer)
62 | (setq pos (point-min))
63 | (while (setq next (next-single-property-change pos 'face))
64 | (put-text-property
65 | ;; `font-lock-face' property is used instead of `font'.
66 | ;; This is the only difference from org-src.
67 | (+ start (1- pos)) (+ start next) 'font-lock-face
68 | (get-text-property pos 'face) orig-buffer)
69 | (setq pos next)))
70 | (add-text-properties
71 | start end
72 | '(font-lock-fontified t fontified t font-lock-multiline t))
73 | (set-buffer-modified-p modified)))))
74 |
75 | (provide 'ein-multilang-fontify)
76 |
77 | ;;; ein-multilang-fontify.el ends here
78 |
--------------------------------------------------------------------------------
/tests/ein-testing-kernel.el:
--------------------------------------------------------------------------------
1 | ;;; ein-testing-kernel.el --- Testing utilities for kernel module
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-testing-kernel.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-testing-kernel.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-testing-kernel.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'ert)
30 |
31 | (require 'ein-kernel)
32 |
33 |
34 |
35 | ;;; Test `ein:kernel-construct-help-string'
36 |
37 | (defvar ein:testing-kernel-construct-help-string-pcallsig-list
38 | '(nil :call_def :init_definition :definition))
39 |
40 | (defvar ein:testing-kernel-construct-help-string-pdocstring-list
41 | '(nil :call_docstring :init_docstring :docstring))
42 |
43 | (defun ein:testing-kernel-construct-help-string-test-func (content result)
44 | (should (equal (ein:kernel-construct-help-string content) result)))
45 |
46 | (defun ein:testing-kernel-construct-help-string-loop
47 | (&optional test pcallsig-list pdocstring-list)
48 | "Run tests for `ein:kernel-construct-help-string-loop'.
49 |
50 | TEST
51 | A function takes two arguments, namely CONTENT and RESULT.
52 | CONTENT is the argument to `ein:kernel-construct-help-string' and
53 | RESULT must match to its returned value. Use `should' to test
54 | equality.
55 | PCALLSIG-LIST
56 | `nil' or (subset of) `ein:testing-kernel-construct-help-string-pcallsig-list'.
57 | PDOCSTRING-LIST
58 | `nil' or (subset of) `ein:testing-kernel-construct-help-string-pdocstring-list'.
59 |
60 | All combinations of PCALLSIG-LIST and PDOCSTRING-LIST are used to
61 | construct CONTENT and RESULT."
62 | (unless test
63 | (setq test #'ein:testing-kernel-construct-help-string-test-func))
64 | (unless pcallsig-list
65 | (setq pcallsig-list
66 | ein:testing-kernel-construct-help-string-pcallsig-list))
67 | (unless pdocstring-list
68 | (setq pdocstring-list
69 | ein:testing-kernel-construct-help-string-pdocstring-list))
70 | (loop with callsig = "function(a=1, b=2, c=d)"
71 | with docstring = "This function does what."
72 | for pcallsig in pcallsig-list
73 | do (loop for pdoc in pdocstring-list
74 | for content = (append
75 | (when pcallsig (list pcallsig callsig))
76 | (when pdoc (list pdoc docstring)))
77 | for result = (ein:aif (append
78 | (when pcallsig (list callsig))
79 | (when pdoc (list docstring)))
80 | (ein:join-str "\n" it))
81 | do (funcall test content result))))
82 |
83 | (provide 'ein-testing-kernel)
84 |
85 | ;;; ein-testing-kernel.el ends here
86 |
--------------------------------------------------------------------------------
/tests/test-ein-kernel.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-kernel)
5 | (require 'ein-testing-kernel)
6 |
7 |
8 | (defun eintest:kernel-new (port)
9 | (ein:kernel-new port "/kernels"
10 | (get-buffer-create "*eintest: dummy for kernel test*")))
11 |
12 | (ert-deftest ein:kernel-start-check-url ()
13 | (let* ((kernel (eintest:kernel-new 8888))
14 | (notebook-id "NOTEBOOK-ID")
15 | (desired-url "http://127.0.0.1:8888/kernels?notebook=NOTEBOOK-ID")
16 | (dummy-response (make-request-response))
17 | got-url)
18 | (flet ((request (url &rest ignore) (setq got-url url) dummy-response)
19 | (set-process-query-on-exit-flag (process flag)))
20 | (ein:kernel-start kernel notebook-id)
21 | (should (equal got-url desired-url)))))
22 |
23 | (ert-deftest ein:kernel-restart-check-url ()
24 | (let* ((kernel (eintest:kernel-new 8888))
25 | (kernel-id "KERNEL-ID")
26 | (desired-url "http://127.0.0.1:8888/kernels/KERNEL-ID/restart")
27 | (dummy-response (make-request-response))
28 | got-url)
29 | (flet ((request (url &rest ignore) (setq got-url url) dummy-response)
30 | (set-process-query-on-exit-flag (process flag))
31 | (ein:kernel-stop-channels (&rest ignore))
32 | (ein:websocket (&rest ignore) (make-ein:$websocket))
33 | (ein:events-trigger (&rest ignore)))
34 | (ein:kernel--kernel-started
35 | kernel :data (list :ws_url "ws://127.0.0.1:8888" :kernel_id kernel-id))
36 | (ein:kernel-restart kernel)
37 | (should (equal got-url desired-url)))))
38 |
39 |
40 | (ert-deftest ein:kernel-interrupt-check-url ()
41 | (let* ((kernel (eintest:kernel-new 8888))
42 | (kernel-id "KERNEL-ID")
43 | (desired-url "http://127.0.0.1:8888/kernels/KERNEL-ID/interrupt")
44 | (dummy-response (make-request-response))
45 | got-url)
46 | (flet ((request (url &rest ignore) (setq got-url url) dummy-response)
47 | (set-process-query-on-exit-flag (process flag))
48 | (ein:kernel-stop-channels (&rest ignore))
49 | (ein:websocket (&rest ignore) (make-ein:$websocket)))
50 | (ein:kernel--kernel-started
51 | kernel :data (list :ws_url "ws://127.0.0.1:8888" :kernel_id kernel-id))
52 | (ein:kernel-interrupt kernel)
53 | (should (equal got-url desired-url)))))
54 |
55 | (ert-deftest ein:kernel-kill-check-url ()
56 | (let* ((kernel (eintest:kernel-new 8888))
57 | (kernel-id "KERNEL-ID")
58 | (desired-url "http://127.0.0.1:8888/kernels/KERNEL-ID")
59 | (dummy-response (make-request-response))
60 | got-url)
61 | (flet ((request (url &rest ignore) (setq got-url url) dummy-response)
62 | (set-process-query-on-exit-flag (process flag))
63 | (ein:kernel-stop-channels (&rest ignore))
64 | (ein:websocket (&rest ignore) (make-ein:$websocket)))
65 | (ein:kernel--kernel-started
66 | kernel :data (list :ws_url "ws://127.0.0.1:8888" :kernel_id kernel-id))
67 | (ein:kernel-kill kernel)
68 | (should (equal got-url desired-url)))))
69 |
70 |
71 | ;;; Test `ein:kernel-construct-help-string'
72 |
73 | (ert-deftest ein:kernel-construct-help-string-when-found ()
74 | (ein:testing-kernel-construct-help-string-loop))
75 |
76 | (ert-deftest ein:kernel-construct-help-string-when-not-found ()
77 | (should (equal (ein:kernel-construct-help-string nil) nil)))
78 | ;; Included in `ein:kernel-construct-help-string-when-found', but test
79 | ;; it explicitly to be sure.
80 |
--------------------------------------------------------------------------------
/lisp/ein-jedi.el:
--------------------------------------------------------------------------------
1 | ;;; ein-jedi.el --- ein Jedi
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-jedi.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-jedi.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-jedi.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'jedi nil t)
30 |
31 | (require 'ein-ac)
32 | (require 'ein-completer)
33 | (eval-when-compile (require 'ein-connect))
34 |
35 | (defvar ein:jedi-dot-complete-sources
36 | '(ac-source-jedi-direct ac-source-ein-direct))
37 |
38 | (defun ein:jedi--completer-complete ()
39 | (let ((d (deferred:new #'identity))
40 | (kernel (ein:get-kernel)))
41 | (if (ein:kernel-live-p kernel)
42 | (ein:completer-complete
43 | kernel
44 | :callbacks
45 | (list :complete_reply
46 | (cons (lambda (d &rest args) (deferred:callback-post d args))
47 | d)))
48 | ;; Pass "no match" result when kernel the request was not sent:
49 | (deferred:callback-post d (list nil nil)))
50 | d))
51 |
52 | ;;;###autoload
53 | (defun* ein:jedi-complete (&key (expand ac-expand-on-auto-complete))
54 | "Run completion using candidates calculated by EIN and Jedi."
55 | (interactive)
56 | (lexical-let ((expand expand))
57 | (deferred:$
58 | (deferred:parallel ; or `deferred:earlier' is better?
59 | (jedi:complete-request)
60 | (ein:jedi--completer-complete))
61 | (deferred:nextc it
62 | (lambda (replies)
63 | (destructuring-bind
64 | (_ ; ignore `jedi:complete-request' what returns.
65 | ((&key matched_text matches &allow-other-keys) ; :complete_reply
66 | _)) ; ignore metadata
67 | replies
68 | (ein:ac-prepare-completion matches)
69 | (let ((ac-expand-on-auto-complete expand))
70 | (ac-start))))))))
71 | ;; Why `ac-start'? See: `jedi:complete'.
72 |
73 | ;;;###autoload
74 | (defun ein:jedi-dot-complete ()
75 | "Insert \".\" and run `ein:jedi-complete'."
76 | (interactive)
77 | (insert ".")
78 | (unless (ac-cursor-on-diable-face-p)
79 | (ein:jedi-complete :expand nil)))
80 |
81 | (defun ein:jedi-complete-on-dot-install (map)
82 | (ein:complete-on-dot-install map #'ein:jedi-dot-complete))
83 |
84 | ;;;###autoload
85 | (defun ein:jedi-setup ()
86 | "Setup auto-completion using EIN and Jedi.el_ together.
87 |
88 | Jedi.el_ is a Python auto-completion library for Emacs.
89 | To use EIN and Jedi together, add the following in your Emacs setup.::
90 |
91 | (add-hook 'ein:connect-mode-hook 'ein:jedi-setup)
92 |
93 | .. _Jedi.el: https://github.com/tkf/emacs-jedi"
94 | (let ((map ein:connect-mode-map))
95 | (define-key map "\C-c\C-i" 'ein:jedi-complete)
96 | (ein:jedi-complete-on-dot-install map)))
97 |
98 | (provide 'ein-jedi)
99 |
100 | ;;; ein-jedi.el ends here
101 |
--------------------------------------------------------------------------------
/tests/test-ein-core.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-core)
5 |
6 |
7 |
8 | ;;; `ein:version'
9 |
10 | (ert-deftest ein:version ()
11 | "Check if `ein:version' can be parsed by `version-to-list'."
12 | (version-to-list ein:version))
13 |
14 | (ert-deftest ein:version-func-prefix-is-the-variable ()
15 | (should (string-prefix-p ein:version (ein:version)))
16 | (let ((default-directory "/tmp/"))
17 | (should (string-prefix-p ein:version (ein:version)))))
18 |
19 | (ert-deftest ein:version-func-outside-of-git-repo ()
20 | (flet ((ein:git-root-p (dir) nil))
21 | (should (equal (ein:version) ein:version)))
22 | (flet ((ein:git-revision-dirty () nil))
23 | (should (equal (ein:version) ein:version))))
24 |
25 |
26 |
27 | ;; Generic getter
28 |
29 | (defmacro eintest:generic-getter-should-return-nil (func)
30 | "In an \"empty\" context, generic getter should return nil."
31 | `(ert-deftest ,(intern (format "%s--nil name" func)) ()
32 | (with-temp-buffer
33 | (should (not (,func))))))
34 |
35 | (eintest:generic-getter-should-return-nil ein:get-url-or-port)
36 | (eintest:generic-getter-should-return-nil ein:get-notebook)
37 | (eintest:generic-getter-should-return-nil ein:get-kernel)
38 | (eintest:generic-getter-should-return-nil ein:get-cell-at-point)
39 | (eintest:generic-getter-should-return-nil ein:get-traceback-data)
40 |
41 |
42 |
43 | ;;; File name translation
44 |
45 | ;; Requiring `tramp' during (inside of) tests yields error from
46 | ;; MuMaMo. Although I don't understand the reason, requiring it
47 | ;; before running tests workarounds this problem.
48 | (require 'tramp)
49 |
50 | (ert-deftest ein:filename-translations-from-to-tramp ()
51 | (loop with ein:filename-translations =
52 | `((8888 . ,(ein:tramp-create-filename-translator "HOST" "USER")))
53 | with filename = "/file/name"
54 | for port in '(7777 8888) ; check for the one w/o translation
55 | for emacs-filename = (ein:filename-from-python port filename)
56 | do (message "emacs-filename = %s" emacs-filename)
57 | do (should
58 | (equal (ein:filename-to-python port emacs-filename)
59 | filename))))
60 |
61 | (ert-deftest ein:filename-translations-to-from-tramp ()
62 | (loop with ein:filename-translations =
63 | `((8888 . ,(ein:tramp-create-filename-translator "HOST" "USER")))
64 | with filename = "/USER@HOST:/filename"
65 | for port in '(8888)
66 | do (should
67 | (equal (ein:filename-from-python
68 | port (ein:filename-to-python port filename))
69 | filename))))
70 |
71 | (ert-deftest ein:filename-to-python-tramp ()
72 | (let* ((port 8888)
73 | (ein:filename-translations
74 | `((,port . ,(ein:tramp-create-filename-translator "DUMMY")))))
75 | (loop with python-filename = "/file/name"
76 | for emacs-filename in '("/scpc:HOST:/file/name"
77 | "/USER@HOST:/file/name")
78 | do (should
79 | (equal (ein:filename-to-python port emacs-filename)
80 | python-filename)))
81 | ;; Error: Not a Tramp file name: /file/name
82 | (should-error (ein:filename-to-python port "/file/name"))))
83 |
84 | (ert-deftest ein:filename-from-python-tramp ()
85 | (loop with ein:filename-translations =
86 | `((8888 . ,(ein:tramp-create-filename-translator "HOST" "USER")))
87 | with python-filename = "/file/name"
88 | for emacs-filename in '("/USER@HOST:/file/name" "/file/name")
89 | for port in '(8888 7777)
90 | do (should
91 | (equal (ein:filename-from-python port python-filename)
92 | emacs-filename))))
93 |
--------------------------------------------------------------------------------
/tests/test-ein-notification.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-notification)
5 |
6 | (defun ein:testing-notification-tab-mock ()
7 | (make-instance 'ein:notification-tab
8 | :get-list (lambda () '(a b c))
9 | :get-current (lambda () 'a)
10 | :get-name #'ignore))
11 |
12 | (ert-deftest ein:header-line-normal ()
13 | (let* ((ein:%notification% (ein:notification "NotificationTest"))
14 | (kernel (oref ein:%notification% :kernel)))
15 | (oset ein:%notification% :tab (ein:testing-notification-tab-mock))
16 | (should (equal (ein:header-line)
17 | "IP[y]: /1\\ /2\\ /3\\ [+]"))))
18 |
19 | (ert-deftest ein:header-line-kernel-status-busy ()
20 | (let* ((ein:%notification% (ein:notification "NotificationTest"))
21 | (kernel (oref ein:%notification% :kernel)))
22 | (oset ein:%notification% :tab (ein:testing-notification-tab-mock))
23 | (ein:notification-status-set kernel
24 | 'status_busy.Kernel)
25 | (should (equal (ein:header-line)
26 | "IP[y]: Kernel is busy... | /1\\ /2\\ /3\\ [+]"))))
27 |
28 | (ert-deftest ein:header-line-notebook-status-busy ()
29 | (let* ((ein:%notification% (ein:notification "NotificationTest"))
30 | (notebook (oref ein:%notification% :notebook)))
31 | (oset ein:%notification% :tab (ein:testing-notification-tab-mock))
32 | (ein:notification-status-set notebook
33 | 'notebook_saved.Notebook)
34 | (should (equal (ein:header-line)
35 | "IP[y]: Notebook is saved | /1\\ /2\\ /3\\ [+]"))))
36 |
37 | (ert-deftest ein:header-line-notebook-complex ()
38 | (let* ((ein:%notification% (ein:notification "NotificationTest"))
39 | (kernel (oref ein:%notification% :kernel))
40 | (notebook (oref ein:%notification% :notebook)))
41 | (oset ein:%notification% :tab (ein:testing-notification-tab-mock))
42 | (ein:notification-status-set kernel
43 | 'status_dead.Kernel)
44 | (ein:notification-status-set notebook
45 | 'notebook_saving.Notebook)
46 | (should (equal
47 | (ein:header-line)
48 | (concat "IP[y]: Saving Notebook... | "
49 | "Kernel is dead. Need restart. | "
50 | "/1\\ /2\\ /3\\ [+]")))))
51 |
52 | (ert-deftest ein:notification-and-events ()
53 | (let* ((notification (ein:notification "NotificationTest"))
54 | (kernel (oref notification :kernel))
55 | (notebook (oref notification :notebook))
56 | (events (ein:events-new))
57 | (event-symbols
58 | '(notebook_saved.Notebook
59 | notebook_saving.Notebook
60 | notebook_save_failed.Notebook
61 | execution_count.Kernel
62 | status_restarting.Kernel
63 | status_idle.Kernel
64 | status_busy.Kernel
65 | status_dead.Kernel
66 | ))
67 | (callbacks (oref events :callbacks)))
68 | (ein:notification-bind-events notification events)
69 | (mapc (lambda (s) (should (gethash s callbacks))) event-symbols)
70 | (should (= (hash-table-count callbacks) (length event-symbols)))
71 | (should (equal (oref kernel :status) nil))
72 | (loop for et in (mapcar #'car (oref kernel :s2m))
73 | do (ein:events-trigger events et)
74 | do (should (equal (oref kernel :status) et))
75 | do (should (equal (oref notebook :status) nil)))
76 | (loop for et in (mapcar #'car (oref notebook :s2m))
77 | do (ein:events-trigger events et)
78 | do (should (equal (oref kernel :status) 'status_dead.Kernel))
79 | do (should (equal (oref notebook :status) et)))))
80 |
--------------------------------------------------------------------------------
/lisp/ein-query.el:
--------------------------------------------------------------------------------
1 | ;;; ein-query.el --- jQuery like interface on to of url-retrieve
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-query.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-query.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-query.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'request)
30 |
31 | (require 'ein-core)
32 | (require 'ein-log)
33 |
34 |
35 | ;;; Utils
36 |
37 | (defun ein:safe-funcall-packed (packed &rest args)
38 | (when packed
39 | (ein:log-ignore-errors (apply #'ein:funcall-packed packed args))))
40 |
41 |
42 | ;;; Variables
43 |
44 | (defcustom ein:query-timeout
45 | (if (eq request-backend 'url-retrieve) 1000 nil)
46 | "Default query timeout for HTTP access in millisecond.
47 |
48 | Setting this to `nil' means no timeout.
49 | If you have ``curl`` command line program, it is automatically set to
50 | `nil' as ``curl`` is reliable than `url-retrieve' therefore no need for
51 | a workaround (see below).
52 |
53 | If you do the same operation before the timeout, old operation
54 | will be canceled \(see also `ein:query-singleton-ajax').
55 |
56 | .. note:: This value exists because it looks like `url-retrieve'
57 | occasionally fails to finish \(start?) querying. Timeout is
58 | used to let user notice that their operation is not finished.
59 | It also prevent opening a lot of useless process buffers.
60 | You will see them when closing Emacs if there is no timeout.
61 |
62 | If you know how to fix the problem with `url-retrieve', please
63 | let me know or send pull request at github!
64 | \(Related bug report in Emacs bug tracker:
65 | http://debbugs.gnu.org/cgi/bugreport.cgi?bug=11469)"
66 | :type '(choice (integer :tag "Timeout [ms]" 5000)
67 | (const :tag "No timeout" nil))
68 | :group 'ein)
69 |
70 |
71 | ;;; Functions
72 |
73 | (defvar ein:query-running-process-table (make-hash-table :test 'equal))
74 |
75 | (defun* ein:query-singleton-ajax (key url &rest settings
76 | &key
77 | (timeout ein:query-timeout)
78 | &allow-other-keys)
79 | "Cancel the old process if there is a process associated with
80 | KEY, then call `request' with URL and SETTINGS. KEY is compared by
81 | `equal'."
82 | (ein:query-gc-running-process-table)
83 | (when timeout
84 | (setq settings (plist-put settings :timeout (/ timeout 1000.0))))
85 | (ein:aif (gethash key ein:query-running-process-table)
86 | (unless (request-response-done-p it)
87 | (request-abort it))) ; This will run callbacks
88 | (let ((response (apply #'request url settings)))
89 | (puthash key response ein:query-running-process-table)
90 | response))
91 |
92 | (defun ein:query-gc-running-process-table ()
93 | "Garbage collect dead processes in `ein:query-running-process-table'."
94 | (maphash
95 | (lambda (key buffer)
96 | (when (request-response-done-p buffer)
97 | (remhash key ein:query-running-process-table)))
98 | ein:query-running-process-table))
99 |
100 |
101 | ;;; Cookie
102 |
103 | (defalias 'ein:query-get-cookie 'request-cookie-string)
104 |
105 | (provide 'ein-query)
106 |
107 | ;;; ein-query.el ends here
108 |
--------------------------------------------------------------------------------
/tests/test-ein-node.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein-node)
5 |
6 | (defun ein:testing-node-dummy-ewco-node (data)
7 | `[nil nil ,data])
8 |
9 | (defun ein:testing-node-ewoc-data (ewoc-node)
10 | (ein:$node-data (ewoc-data ewoc-node)))
11 |
12 | (ert-deftest ein:testing-node-dummy-ewco-node ()
13 | (let* ((obj "some-object")
14 | (ewoc-node (ein:testing-node-dummy-ewco-node obj)))
15 | (should (eq (ewoc-data ewoc-node) obj))))
16 |
17 | (ert-deftest ein:node-filter-is ()
18 | (let ((en-list (mapcar
19 | #'ein:testing-node-dummy-ewco-node
20 | (list (ein:node-new nil "s" '(spam sag))
21 | (ein:node-new nil "p" '(spam))
22 | (ein:node-new nil "e" '(egg))
23 | (ein:node-new nil "a" '(spam sag))
24 | (ein:node-new nil "g" '(egg sag))
25 | (ein:node-new nil "m" '(spam))
26 | (ein:node-new nil "g" '(egg))))))
27 | (should (equal (mapcar #'ein:testing-node-ewoc-data
28 | (ein:node-filter en-list :is 'spam))
29 | '("s" "p" "a" "m")))
30 | (should (equal (mapcar #'ein:testing-node-ewoc-data
31 | (ein:node-filter en-list :is 'egg))
32 | '("e" "g" "g")))
33 | (should (equal (mapcar #'ein:testing-node-ewoc-data
34 | (ein:node-filter en-list :is 'sag))
35 | '("s" "a" "g")))))
36 |
37 | (ert-deftest ein:node-filter-not ()
38 | (let ((en-list (mapcar
39 | #'ein:testing-node-dummy-ewco-node
40 | (list (ein:node-new nil "s" '(spam sag))
41 | (ein:node-new nil "p" '(spam))
42 | (ein:node-new nil "e" '(egg))
43 | (ein:node-new nil "a" '(spam sag))
44 | (ein:node-new nil "g" '(egg sag))
45 | (ein:node-new nil "m" '(spam))
46 | (ein:node-new nil "g" '(egg))))))
47 | (should (equal (mapcar #'ein:testing-node-ewoc-data
48 | (ein:node-filter en-list :not 'spam))
49 | '("e" "g" "g")))
50 | (should (equal (mapcar #'ein:testing-node-ewoc-data
51 | (ein:node-filter en-list :not 'egg))
52 | '("s" "p" "a" "m")))
53 | (should (equal (mapcar #'ein:testing-node-ewoc-data
54 | (ein:node-filter en-list :not 'sag))
55 | '("p" "e" "m" "g")))))
56 |
57 | (ert-deftest ein:node-filter-is-and-not ()
58 | (let ((en-list (mapcar
59 | #'ein:testing-node-dummy-ewco-node
60 | (list (ein:node-new nil "s" '(spam sag))
61 | (ein:node-new nil "p" '(spam))
62 | (ein:node-new nil "e" '(egg))
63 | (ein:node-new nil "a" '(spam sag))
64 | (ein:node-new nil "g" '(egg sag))
65 | (ein:node-new nil "m" '(spam))
66 | (ein:node-new nil "g" '(egg))))))
67 | (should (equal (mapcar #'ein:testing-node-ewoc-data
68 | (ein:node-filter en-list :not 'spam :is 'sag))
69 | '("g")))
70 | (should (equal (mapcar #'ein:testing-node-ewoc-data
71 | (ein:node-filter en-list :is 'sag :not 'spam))
72 | '("g")))
73 | (should (equal (mapcar #'ein:testing-node-ewoc-data
74 | (ein:node-filter en-list :is 'spam :is 'sag))
75 | '("s" "a")))
76 | (should (equal (mapcar #'ein:testing-node-ewoc-data
77 | (ein:node-filter en-list :is 'sag :not 'spam
78 | :not 'not-existing))
79 | '("g")))
80 | (should (equal (mapcar #'ein:testing-node-ewoc-data
81 | (ein:node-filter en-list :is 'sag :is 'spam))
82 | '("s" "a")))))
83 |
--------------------------------------------------------------------------------
/lisp/ein-log.el:
--------------------------------------------------------------------------------
1 | ;;; ein-log.el --- Logging module for ein.el
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-log.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-log.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-log.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'ein-core)
30 |
31 |
32 | (defvar ein:log-all-buffer-name " *ein:log-all*")
33 |
34 | (defvar ein:log-level-def
35 | '(;; debugging
36 | (blather . 60) (trace . 50) (debug . 40)
37 | ;; information
38 | (verbose . 30) (info . 20)
39 | ;; errors
40 | (warn . 10) (error . 0))
41 | "Named logging levels.")
42 | ;; Some names are stolen from supervisord (http://supervisord.org/logging.html)
43 |
44 | (defvar ein:log-level 30)
45 | (defvar ein:log-message-level 20)
46 |
47 | (defvar ein:log-print-level 1 "`print-level' for `ein:log'")
48 | (defvar ein:log-print-length 10 "`print-length' for `ein:log'")
49 | (defvar ein:log-max-string 1000)
50 |
51 |
52 | (defun ein:log-set-level (level)
53 | (setq ein:log-level (ein:log-level-name-to-int level)))
54 |
55 | (defun ein:log-set-message-level (level)
56 | (setq ein:log-message-level (ein:log-level-name-to-int level)))
57 |
58 | (defun ein:log-level-int-to-name (int)
59 | (loop for (n . i) in ein:log-level-def
60 | when (>= int i)
61 | return n
62 | finally 'error))
63 |
64 | (defun ein:log-level-name-to-int (name)
65 | (cdr (assq name ein:log-level-def)))
66 |
67 | (defun ein:log-wrapper (level func)
68 | (setq level (ein:log-level-name-to-int level))
69 | (when (<= level ein:log-level)
70 | (let* ((levname (ein:log-level-int-to-name level))
71 | (print-level ein:log-print-level)
72 | (print-length ein:log-print-length)
73 | (msg (format "[%s] %s" levname (funcall func)))
74 | (orig-buffer (current-buffer)))
75 | (if (and ein:log-max-string
76 | (> (length msg) ein:log-max-string))
77 | (setq msg (substring msg 0 ein:log-max-string)))
78 | (ein:with-read-only-buffer (get-buffer-create ein:log-all-buffer-name)
79 | (goto-char (point-max))
80 | (insert msg (format " @%S" orig-buffer) "\n"))
81 | (when (<= level ein:log-message-level)
82 | (message "ein: %s" msg)))))
83 |
84 | (defmacro ein:log (level string &rest args)
85 | (declare (indent 1))
86 | `(ein:log-wrapper ,level (lambda () (format ,string ,@args))))
87 |
88 | ;; FIXME: this variable must go to somewhere more central
89 | (defvar ein:debug nil
90 | "Set to non-`nil' to raise errors instead of suppressing it.
91 | Change the behavior of `ein:log-ignore-errors'.")
92 |
93 | (defmacro ein:log-ignore-errors (&rest body)
94 | "Execute BODY; if an error occurs, log the error and return nil.
95 | Otherwise, return result of last form in BODY."
96 | (declare (debug t) (indent 0))
97 | `(if ein:debug
98 | (progn ,@body)
99 | (condition-case err
100 | (progn ,@body)
101 | (error
102 | (ein:log 'debug "Error: %S" err)
103 | (ein:log 'error (error-message-string err))
104 | nil))))
105 |
106 | (defun ein:log-pop-to-all-buffer ()
107 | (interactive)
108 | (pop-to-buffer (get-buffer-create ein:log-all-buffer-name)))
109 |
110 | (provide 'ein-log)
111 |
112 | ;;; ein-log.el ends here
113 |
--------------------------------------------------------------------------------
/lisp/zeroein.el:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | ":"; exec ${EMACS:-emacs} -Q -l "$0" "$@" # -*-emacs-lisp-*-
3 | ;;; zeroein.el --- Zero setup Emacs IPython Notebook client
4 |
5 | ;; Copyright (C) 2012- Takafumi Arakaki
6 |
7 | ;; Author: Takafumi Arakaki
8 |
9 | ;; This file is NOT part of GNU Emacs.
10 |
11 | ;; zeroein.el is free software: you can redistribute it and/or modify
12 | ;; it under the terms of the GNU General Public License as published by
13 | ;; the Free Software Foundation, either version 3 of the License, or
14 | ;; (at your option) any later version.
15 |
16 | ;; zeroein.el is distributed in the hope that it will be useful,
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | ;; GNU General Public License for more details.
20 |
21 | ;; You should have received a copy of the GNU General Public License
22 | ;; along with zeroein.el. If not, see .
23 |
24 | ;;; Commentary:
25 |
26 | ;;
27 |
28 | ;;; Code:
29 |
30 | (eval-when-compile (require 'cl))
31 |
32 |
33 | ;;; Utilities
34 |
35 | (defvar zeroein:lisp-dir
36 | (or (if load-file-name (file-name-directory load-file-name))
37 | default-directory))
38 |
39 | (defvar zeroein:root-dir
40 | (file-name-as-directory
41 | (expand-file-name ".." (file-name-as-directory zeroein:lisp-dir))))
42 |
43 | (defun zeroein:path (p &rest ps)
44 | (if ps
45 | (apply #'zeroein:path
46 | (concat (file-name-as-directory p) (car ps)) (cdr ps))
47 | (concat zeroein:root-dir p)))
48 |
49 | (defvar zeroein:dependencies
50 | '("nxhtml" "markdown-mode" "websocket" "request"
51 | "auto-complete" "popup" "fuzzy" "pos-tip" "smartrep"))
52 |
53 | ;; Loading the new python.el fails in Emacs 23.
54 | (when (>= emacs-major-version 24)
55 | (add-to-list 'zeroein:dependencies "python"))
56 |
57 |
58 | ;;; Install dependencies
59 |
60 | (call-process "git" nil (get-buffer "*Messages*") nil
61 | "submodule" "update" "--init")
62 |
63 |
64 |
65 | ;;; `load-path' configurations
66 |
67 | (add-to-list 'load-path (zeroein:path "lisp"))
68 | (add-to-list 'load-path (zeroein:path "lib" "nxhtml" "util"))
69 | (mapc (lambda (path) (add-to-list 'load-path (zeroein:path "lib" path)))
70 | zeroein:dependencies)
71 |
72 |
73 | ;;; Configurations
74 | (eval-when-compile (require 'ein-notebooklist))
75 | (require 'ein)
76 |
77 | ;; auto-complete
78 | (setq ein:use-auto-complete-superpack t)
79 | ;; (setq ein:use-smartrep t)
80 |
81 | (require 'auto-complete-config nil t)
82 | (declare-function global-auto-complete-mode "auto-complete.el")
83 | (when (featurep 'auto-complete-config)
84 | (ac-config-default)
85 | (add-to-list 'ac-dictionary-directories
86 | (zeroein:path "lib" "auto-complete" "dict"))
87 | (global-auto-complete-mode t))
88 |
89 | ;; MuMaMo
90 | (custom-set-faces
91 | '(mumamo-background-chunk-major
92 | ((((class color) (min-colors 88) (background dark)) nil)))
93 | ;; '(mumamo-background-chunk-submode1
94 | ;; ((((class color) (min-colors 88) (background dark)) nil)))
95 | )
96 |
97 |
98 | ;;; Workaround
99 |
100 | ;; Suppress this warning when using mumamo:
101 | ;; Warning: `font-lock-syntactic-keywords' is an obsolete variable (as of 24.1);
102 | ;; use `syntax-propertize-function' instead.
103 | (when (and (equal emacs-major-version 24)
104 | (equal emacs-minor-version 1))
105 | (eval-after-load "bytecomp"
106 | '(add-to-list 'byte-compile-not-obsolete-vars
107 | 'font-lock-syntactic-keywords)))
108 | ;; See: http://stackoverflow.com/a/5470584/727827
109 |
110 |
111 | ;;; Finally, open notebook list
112 | (if noninteractive
113 | (progn
114 | ;; When called in batch mode, print system info.
115 | (require 'ein-dev)
116 | (ein:dev-print-sys-info))
117 | ;; To make EIN configurable by --eval, use idle timer:
118 | (run-with-idle-timer 0 nil 'call-interactively 'ein:notebooklist-open))
119 |
120 | ;;; zeroein.el ends here
121 |
--------------------------------------------------------------------------------
/lisp/ein-websocket.el:
--------------------------------------------------------------------------------
1 | ;;; ein-websocket.el --- Wrapper of websocket.el
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-websocket.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-websocket.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-websocket.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'websocket)
30 |
31 | (require 'ein-core)
32 |
33 |
34 | (defstruct ein:$websocket
35 | "A wrapper object of `websocket'.
36 |
37 | `ein:$websocket-ws' : an instance returned by `websocket-open'
38 |
39 | `ein:$websocket-onmessage' : function called with (PACKET &rest ARGS)'
40 | `ein:$websocket-onclose' : function called with (WEBSOCKET &rest ARGS)'
41 | `ein:$websocket-onopen' : function called with (&rest ARGS)'
42 |
43 | `ein:$websocket-onmessage-args' : optional arguments for onmessage callback'
44 | `ein:$websocket-onclose-args' : optional arguments for onclose callback'
45 | `ein:$websocket-onopen-args' : optional arguments for onopen callback'
46 |
47 | `ein:$websocket-closed-by-client' : t/nil'
48 | "
49 | ws
50 | onmessage
51 | onmessage-args
52 | onclose
53 | onclose-args
54 | onopen
55 | onopen-args
56 | closed-by-client)
57 |
58 |
59 | (defun ein:websocket (url &optional onmessage onclose onopen
60 | onmessage-args onclose-args onopen-args)
61 | (let ((websocket (make-ein:$websocket
62 | :onmessage onmessage
63 | :onclose onclose
64 | :onopen onopen
65 | :onmessage-args onmessage-args
66 | :onclose-args onclose-args
67 | :onopen-args onopen-args))
68 | (ws (websocket-open
69 | url
70 | :on-open
71 | (lambda (ws)
72 | (let ((websocket (websocket-client-data ws)))
73 | (ein:aif (ein:$websocket-onopen websocket)
74 | (apply it (ein:$websocket-onopen-args websocket)))))
75 | :on-message
76 | (lambda (ws frame)
77 | (let ((websocket (websocket-client-data ws))
78 | (packet (websocket-frame-payload frame)))
79 | (ein:aif (ein:$websocket-onmessage websocket)
80 | (when packet
81 | (apply it packet
82 | (ein:$websocket-onmessage-args websocket))))))
83 | :on-close
84 | (lambda (ws)
85 | (let ((websocket (websocket-client-data ws)))
86 | (ein:aif (ein:$websocket-onclose websocket)
87 | (apply it websocket
88 | (ein:$websocket-onclose-args websocket))))))))
89 | (setf (websocket-client-data ws) websocket)
90 | (setf (ein:$websocket-ws websocket) ws)
91 | websocket))
92 |
93 |
94 | (defun ein:websocket-open-p (websocket)
95 | (eql (websocket-ready-state (ein:$websocket-ws websocket)) 'open))
96 |
97 |
98 | (defun ein:websocket-send (websocket text)
99 | (websocket-send-text (ein:$websocket-ws websocket) text))
100 |
101 |
102 | (defun ein:websocket-close (websocket)
103 | (setf (ein:$websocket-closed-by-client websocket) t)
104 | (websocket-close (ein:$websocket-ws websocket)))
105 |
106 |
107 | (provide 'ein-websocket)
108 |
109 | ;;; ein-websocket.el ends here
110 |
--------------------------------------------------------------------------------
/lisp/ein-kernelinfo.el:
--------------------------------------------------------------------------------
1 | ;;; ein-kernelinfo.el --- Kernel info module
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-kernelinfo.el is free software: you can redistribute it and/or
10 | ;; modify it under the terms of the GNU General Public License as
11 | ;; published by the Free Software Foundation, either version 3 of the
12 | ;; License, or (at your option) any later version.
13 |
14 | ;; ein-kernelinfo.el is distributed in the hope that it will be
15 | ;; useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 | ;; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-kernelinfo.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'ein-kernel)
30 | (require 'eieio)
31 |
32 | (defclass ein:kernelinfo ()
33 | ((kernel
34 | :initarg :kernel :type ein:$kernel
35 | :documentation "Kernel instance.")
36 | (get-buffers
37 | :initarg :get-buffers
38 | :documentation "A packed function to get buffers associated
39 | with the kernel. The buffer local `default-directory' variable
40 | in these buffer will be synced with the kernel's cwd.")
41 | (hostname
42 | :initarg :hostname :type string
43 | :documentation "Host name of the machine where the kernel is running on.")
44 | (ccwd
45 | :initarg :ccwd :type string
46 | :documentation "cached CWD (last time checked CWD)."))
47 | :documentation "Info related (but unimportant) to kernel")
48 |
49 | (defun ein:kernelinfo-new (kernel get-buffers)
50 | "Make a new `ein:kernelinfo' instance based on KERNEL and GET-BUFFERS."
51 | (let ((kerinfo (make-instance 'ein:kernelinfo)))
52 | (oset kerinfo :kernel kernel)
53 | (oset kerinfo :get-buffers get-buffers)
54 | (ein:kernelinfo-setup-hooks kerinfo)
55 | kerinfo))
56 |
57 | (defun ein:kernelinfo-setup-hooks (kerinfo)
58 | "Add `ein:kernelinfo-update-*' to `ein:$kernel-after-*-hook'."
59 | (with-slots (kernel) kerinfo
60 | (push (cons #'ein:kernelinfo-update-all kerinfo)
61 | (ein:$kernel-after-start-hook kernel))
62 | (push (cons #'ein:kernelinfo-update-ccwd kerinfo)
63 | (ein:$kernel-after-execute-hook kernel))))
64 |
65 | (defun ein:kernelinfo-update-all (kerinfo)
66 | "Update KERINFO slots by triggering all update functions."
67 | (ein:log 'debug "EIN:KERNELINFO-UPDATE-ALL")
68 | (ein:log 'debug "(ein:kernel-live-p kernel) = %S"
69 | (ein:kernel-live-p (oref kerinfo :kernel)))
70 | (ein:kernelinfo-update-ccwd kerinfo)
71 | (ein:kernelinfo-update-hostname kerinfo))
72 |
73 | (defun ein:kernelinfo-update-ccwd (kerinfo)
74 | "Update cached current working directory (CCWD) and change
75 | `default-directory' of kernel related buffers."
76 | (ein:kernel-request-stream
77 | (oref kerinfo :kernel)
78 | "__import__('sys').stdout.write(__import__('os').getcwd())"
79 | (lambda (cwd kerinfo)
80 | (with-slots (kernel get-buffers) kerinfo
81 | (setq cwd (ein:kernel-filename-from-python kernel cwd))
82 | (oset kerinfo :ccwd cwd)
83 | ;; sync buffer's `default-directory' with CWD
84 | (when (file-accessible-directory-p cwd)
85 | (mapc (lambda (buffer)
86 | (with-current-buffer buffer
87 | (setq default-directory (file-name-as-directory cwd))))
88 | (ein:filter #'buffer-live-p
89 | (ein:funcall-packed get-buffers))))))
90 | (list kerinfo)))
91 |
92 | (defun ein:kernelinfo-update-hostname (kerinfo)
93 | "Get hostname in which kernel is running and store it in KERINFO."
94 | (ein:kernel-request-stream
95 | (oref kerinfo :kernel)
96 | "__import__('sys').stdout.write(__import__('os').uname()[1])"
97 | (lambda (hostname kerinfo)
98 | (oset kerinfo :hostname hostname))
99 | (list kerinfo)))
100 |
101 |
102 | (provide 'ein-kernelinfo)
103 |
104 | ;;; ein-kernelinfo.el ends here
105 |
--------------------------------------------------------------------------------
/tests/ein-testing-notebook.el:
--------------------------------------------------------------------------------
1 | ;;; ein-testing-notebook.el --- Testing utilities for notebook module
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-testing-notebook.el is free software: you can redistribute it
10 | ;; and/or modify it under the terms of the GNU General Public License
11 | ;; as published by the Free Software Foundation, either version 3 of
12 | ;; the License, or (at your option) any later version.
13 |
14 | ;; ein-testing-notebook.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-testing-notebook.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (eval-when-compile (require 'cl))
30 |
31 | (require 'ein-notebook)
32 | (require 'ein-testing-cell)
33 |
34 | (defun ein:testing-notebook-from-json (json-string &optional notebook-id)
35 | (unless notebook-id (setq notebook-id "NOTEBOOK-ID"))
36 | (flet ((pop-to-buffer (buf) buf)
37 | (ein:notebook-start-kernel (notebook)))
38 | (let ((notebook (ein:notebook-new "DUMMY-URL" notebook-id)))
39 | (setf (ein:$notebook-kernel notebook)
40 | (ein:kernel-new 8888 "/kernels" (ein:$notebook-events notebook)))
41 | (setf (ein:$kernel-events (ein:$notebook-kernel notebook))
42 | (ein:events-new))
43 | (ein:notebook-request-open-callback
44 | notebook :data (ein:json-read-from-string json-string))
45 | (ein:notebook-buffer notebook))))
46 |
47 | (defun ein:testing-notebook-make-data (cells &optional name)
48 | (setq cells
49 | (ein:testing-notebook--preprocess-cells-data-for-json-encode cells))
50 | (unless name (setq name "Dummy Name"))
51 | `((metadata . ((name . ,name)))
52 | (nbformat . 2)
53 | (name . ,name)
54 | (worksheets . [((cells . ,(apply #'vector cells)))])))
55 |
56 | (defun ein:testing-notebook--preprocess-cells-data-for-json-encode (cells)
57 | "Preprocess CELLS data to make it work nice with `json-encode'."
58 | (mapcar (lambda (c)
59 | (cond
60 | ((equal (plist-get c :cell_type) "code")
61 | ;; turn `:outputs' into an array.
62 | (plist-put c :outputs (apply #'vector (plist-get c :outputs))))
63 | (t c)))
64 | cells))
65 |
66 | (defun ein:testing-notebook-make-new (&optional name notebook-id cells-data)
67 | "Make new notebook. One empty cell will be inserted
68 | automatically if CELLS-DATA is nil."
69 | (ein:testing-notebook-from-json
70 | (json-encode (ein:testing-notebook-make-data cells-data name)) notebook-id))
71 |
72 | (defun ein:testing-notebook-make-empty (&optional name notebook-id)
73 | "Make empty notebook and return its buffer.
74 | Automatically inserted cell for new notebook is deleted."
75 | (let ((buffer (ein:testing-notebook-make-new name notebook-id)))
76 | (with-current-buffer buffer
77 | (call-interactively #'ein:worksheet-delete-cell))
78 | buffer))
79 |
80 | (defmacro ein:testing-with-one-cell (cell-type &rest body)
81 | "Insert new cell of CELL-TYPE in a clean notebook and execute BODY.
82 | The new cell is bound to a variable `cell'."
83 | (declare (indent 1))
84 | `(with-current-buffer (ein:testing-notebook-make-empty)
85 | (let ((cell (ein:worksheet-insert-cell-below ein:%worksheet%
86 | ,cell-type nil t)))
87 | ,@body)))
88 |
89 | (defun ein:testing-make-notebook-with-outputs (list-outputs)
90 | "Make a new notebook with cells with output.
91 | LIST-OUTPUTS is a list of list of strings (pyout text). Number
92 | of LIST-OUTPUTS equals to the number cells to be contained in the
93 | notebook."
94 | (ein:testing-notebook-make-new
95 | nil nil
96 | (mapcar (lambda (outputs)
97 | (ein:testing-codecell-data
98 | nil nil (mapcar #'ein:testing-codecell-pyout-data outputs)))
99 | list-outputs)))
100 |
101 | (provide 'ein-testing-notebook)
102 |
103 | ;;; ein-testing-notebook.el ends here
104 |
--------------------------------------------------------------------------------
/lisp/ein-output-area.el:
--------------------------------------------------------------------------------
1 | ;;; ein-output-area.el --- Output area module
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-output-area.el is free software: you can redistribute it and/or
10 | ;; modify it under the terms of the GNU General Public License as
11 | ;; published by the Free Software Foundation, either version 3 of the
12 | ;; License, or (at your option) any later version.
13 |
14 | ;; ein-output-area.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-output-area.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (eval-when-compile (require 'cl))
30 | (require 'xml)
31 |
32 | (require 'ein-core)
33 |
34 |
35 |
36 | ;;; XML/HTML utils
37 |
38 | (defun ein:xml-parse-html-string (html-string)
39 | "Parse HTML-STRING and return a dom object which
40 | can be handled by the xml module."
41 | (with-temp-buffer
42 | (erase-buffer)
43 | (insert html-string)
44 | (libxml-parse-html-region (point-min) (point-max))))
45 |
46 | (defalias 'ein:xml-node-p 'listp)
47 |
48 | (defun ein:xml-tree-apply (dom operation)
49 | "Apply OPERATION on nodes in DOM. Apply the same OPERATION on
50 | the next level children when it returns `nil'."
51 | (loop for child in (xml-node-children dom)
52 | if (and (not (funcall operation child))
53 | (ein:xml-node-p child))
54 | do (ein:xml-tree-apply child operation)))
55 |
56 | (defun ein:xml-replace-attributes (dom tag attr replace-p replacer)
57 | "Replace value of ATTR of TAG in DOM using REPLACER
58 | when REPLACE-P returns non-`nil'."
59 | (ein:xml-tree-apply
60 | dom
61 | (lambda (node)
62 | (ein:and-let* (((ein:xml-node-p node))
63 | ((eq (xml-node-name node) tag))
64 | (attr-cell (assoc attr (xml-node-attributes node)))
65 | (val (cdr attr-cell))
66 | ((funcall replace-p val)))
67 | (setcdr attr-cell (funcall replacer val))
68 | t))))
69 |
70 |
71 | ;;; HTML renderer
72 |
73 | (defun ein:output-area-get-html-renderer ()
74 | ;; FIXME: make this configurable
75 | (cond
76 | ((and (fboundp 'shr-insert-document)
77 | (fboundp 'libxml-parse-xml-region))
78 | #'ein:insert-html-shr)
79 | (t #'ein:insert-read-only)))
80 |
81 | (defcustom ein:shr-env
82 | '((shr-table-horizontal-line ?-)
83 | (shr-table-vertical-line ?|)
84 | (shr-table-corner ?+))
85 | "Variables let-bound while calling `shr-insert-document'.
86 |
87 | To use default shr setting::
88 |
89 | (setq ein:shr-env nil)
90 |
91 | Draw boundaries for table (default)::
92 |
93 | (setq ein:shr-env
94 | '((shr-table-horizontal-line ?-)
95 | (shr-table-vertical-line ?|)
96 | (shr-table-corner ?+)))
97 | "
98 | :group 'ein)
99 |
100 | (defun ein:shr-insert-document (dom)
101 | "`shr-insert-document' with EIN setting."
102 | (eval `(let ,ein:shr-env (shr-insert-document dom))))
103 |
104 | (defun ein:insert-html-shr (html-string)
105 | "Render HTML-STRING using `shr-insert-document'.
106 |
107 | Usage::
108 |
109 | (ein:insert-html-shr \"HTML string\")
110 |
111 | "
112 | (let ((dom (ein:xml-parse-html-string html-string))
113 | (start (point))
114 | end)
115 | (ein:insert-html--fix-urls dom)
116 | (ein:shr-insert-document dom)
117 | (setq end (point))
118 | (put-text-property start end 'read-only t)
119 | (put-text-property start end 'front-sticky t)))
120 |
121 | (defun ein:insert-html--fix-urls (dom &optional url-or-port)
122 | "Destructively prepend notebook server URL to local URLs in DOM."
123 | (ein:and-let* ((url-or-port (or url-or-port (ein:get-url-or-port)))
124 | (replace-p (lambda (val) (string-match-p "^/?files/" val)))
125 | (replacer (lambda (val) (ein:url url-or-port val))))
126 | (ein:xml-replace-attributes dom 'a 'href replace-p replacer)
127 | (ein:xml-replace-attributes dom 'img 'src replace-p replacer)))
128 |
129 |
130 | (provide 'ein-output-area)
131 |
132 | ;;; ein-output-area.el ends here
133 |
--------------------------------------------------------------------------------
/lisp/ein-org.el:
--------------------------------------------------------------------------------
1 | ;;; ein-org.el --- Org-mode link support for EIN
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-org.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-org.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-org.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (require 'org)
30 | (require 'ein-notebooklist)
31 |
32 | ;; FIXME: Separate org-unrelated cores from the following code and
33 | ;; expose them as API in ein-link.el.
34 |
35 | (defun* ein:org-goto-link (notebook created
36 | &key
37 | worksheet-index
38 | search
39 | &allow-other-keys)
40 | (if created
41 | (ein:log 'info "Linked notebook did not exist. Created a new one.")
42 | (if worksheet-index
43 | (ein:notebook-worksheet-open-ith notebook worksheet-index
44 | #'pop-to-buffer)
45 | (pop-to-buffer (ein:notebook-buffer notebook)))
46 | (when search
47 | (goto-char (point-min))
48 | (search-forward search nil t))
49 | ;; More to come here:
50 | ))
51 |
52 | ;;;###autoload
53 | (defun ein:org-open (link-path)
54 | "Open IPython notebook specified by LINK-PATH.
55 | This function is to be used for FOLLOW function of
56 | `org-add-link-type'."
57 | (let ((link (read link-path)))
58 | (destructuring-bind (&key url-or-port name &allow-other-keys)
59 | link
60 | (ein:notebooklist-open-notebook-by-name name url-or-port
61 | #'ein:org-goto-link link))))
62 |
63 | ;;;###autoload
64 | (defun ein:org-store-link ()
65 | "Call `org-store-link-props' when in notebook buffer.
66 | This function is to be used for `org-store-link-functions'.
67 |
68 | Examples::
69 |
70 | ipynb:(:url-or-port 8888 :name \"My_Notebook\")
71 | ipynb:(:url-or-port \"http://notebook-server\" :name \"My_Notebook\")
72 |
73 | Note that spaces will be escaped in org files.
74 |
75 | As how IPython development team supports multiple directory in
76 | IPython notebook server is unclear, it is not easy to decide the
77 | format for notebook links. Current approach is to use
78 | S-expression based (rather verbose) serialization, so that
79 | extending link spec without loosing backward compatibility is
80 | easier. For the examples of link format in general, see Info
81 | node `(org) External links' and Info node `(org) Search options'"
82 | (ein:and-let* (((ein:worksheet-buffer-p))
83 | (notebook (ein:get-notebook))
84 | (name (ein:notebook-name notebook))
85 | (link (list :url-or-port (ein:get-url-or-port)
86 | :name name))
87 | (description name))
88 | (ein:aif (ein:notebook-worksheet-index notebook)
89 | (unless (= it 0)
90 | (plist-put link :worksheet-index it))
91 | (error "[ein] Cannot link to scratch sheet!"))
92 | (when (region-active-p)
93 | ;; FIXME: It does not work when selecting muli-line.
94 | (plist-put link :search (buffer-substring-no-properties
95 | (region-beginning) (region-end))))
96 | (org-store-link-props
97 | :type "ipynb"
98 | :link (let ((print-length nil)
99 | (print-level nil))
100 | (format "ipynb:%S" link))
101 | :description description)))
102 |
103 | ;;;###autoload
104 | (eval-after-load "org"
105 | '(progn
106 | (org-add-link-type "ipynb" 'ein:org-open)
107 | (add-hook 'org-store-link-functions 'ein:org-store-link)))
108 | ;; The above expression is evaluated via loaddef file. At the moment,
109 | ;; org.el nor ein-org.el need not be loaded. When org-mode is used,
110 | ;; the above `progn' is executed but still ein-org.el is not loaded.
111 | ;; When `ein:org-open' or `ein:org-store-link' is called for opening
112 | ;; or storing ipynb link, ein-org.el is loaded finally. (When
113 | ;; ein-org.el is loaded the above expression is evaluated again, but
114 | ;; that's OK as the expression is idempotent.)
115 |
116 |
117 | (provide 'ein-org)
118 |
119 | ;;; ein-org.el ends here
120 |
--------------------------------------------------------------------------------
/lisp/ein-completer.el:
--------------------------------------------------------------------------------
1 | ;;; ein-completer.el --- Completion module
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-completer.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-completer.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-completer.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (declare-function ac-cursor-on-diable-face-p "auto-complete")
29 |
30 | (eval-when-compile (require 'cl))
31 |
32 | (require 'ein-core)
33 | (require 'ein-log)
34 | (require 'ein-subpackages)
35 | (require 'ein-kernel)
36 |
37 | (defun ein:completer-choose ()
38 | (when (require 'auto-complete nil t)
39 | (require 'ein-ac))
40 | (cond
41 | ((and (or ein:use-auto-complete
42 | ein:use-auto-complete-superpack)
43 | (ein:eval-if-bound 'auto-complete-mode)
44 | (fboundp 'ein:completer-finish-completing-ac))
45 | #'ein:completer-finish-completing-ac)
46 | (t
47 | #'ein:completer-finish-completing-default)))
48 |
49 | (defun ein:completer-beginning (matched-text)
50 | (save-excursion
51 | (re-search-backward (concat matched-text "\\="))))
52 |
53 | (defun ein:completer-finish-completing (args content -metadata-not-used-)
54 | (ein:log 'debug "COMPLETER-FINISH-COMPLETING: content=%S" content)
55 | (let ((matched-text (plist-get content :matched_text))
56 | (matches (plist-get content :matches))
57 | (completer (ein:completer-choose)))
58 | (ein:log 'debug "COMPLETER-FINISH-COMPLETING: completer=%s" completer)
59 | (apply completer matched-text matches args)))
60 |
61 | (defun ein:completer-finish-completing-default (matched-text matches
62 | &rest -ignore-)
63 | (let* ((end (point))
64 | (beg (ein:completer-beginning matched-text))
65 | (word (if (and beg matches)
66 | (completing-read "Complete: " matches
67 | nil nil matched-text))))
68 | (when word
69 | (delete-region beg end)
70 | (insert word))))
71 |
72 | (defun* ein:completer-complete
73 | (kernel &rest args &key callbacks &allow-other-keys)
74 | "Start completion for the code at point.
75 |
76 | .. It sends `:complete_request' to KERNEL.
77 | CALLBACKS is passed to `ein:kernel-complete'.
78 |
79 | If you specify CALLBACKS explicitly (i.e., you are not using
80 | `ein:completer-finish-completing'), keyword argument will be
81 | ignored. Otherwise, ARGS are passed as additional arguments
82 | to completer callback functions. ARGS **must** be keyword
83 | arguments.
84 |
85 | EXPAND keyword argument is supported by
86 | `ein:completer-finish-completing-ac'. When it is specified,
87 | it overrides `ac-expand-on-auto-complete' when calling
88 | `auto-complete'."
89 | (interactive (list (ein:get-kernel)))
90 | (unless callbacks
91 | (setq callbacks
92 | (list :complete_reply
93 | (cons #'ein:completer-finish-completing
94 | (ein:plist-exclude args '(:callbacks))))))
95 | (ein:kernel-complete kernel
96 | (thing-at-point 'line)
97 | (current-column)
98 | callbacks))
99 |
100 | (defun ein:completer-dot-complete ()
101 | "Insert dot and request completion."
102 | (interactive)
103 | (insert ".")
104 | (ein:and-let* ((kernel (ein:get-kernel))
105 | ((not (ac-cursor-on-diable-face-p)))
106 | ((ein:kernel-live-p kernel)))
107 | (ein:completer-complete kernel :expand nil)))
108 |
109 | (defcustom ein:complete-on-dot t
110 | "Start completion when inserting a dot. Note that
111 | `ein:use-auto-complete' (or `ein:use-auto-complete-superpack')
112 | must be `t' to enable this option. This variable has effect on
113 | notebook buffers and connected buffers."
114 | :type 'boolean
115 | :group 'ein)
116 |
117 | (defun ein:complete-on-dot-install (map &optional func)
118 | (if (and ein:complete-on-dot
119 | (featurep 'auto-complete)
120 | (or ein:use-auto-complete
121 | ein:use-auto-complete-superpack))
122 | (define-key map "." (or func #'ein:completer-dot-complete))
123 | (define-key map "." nil)))
124 |
125 | (provide 'ein-completer)
126 |
127 | ;;; ein-completer.el ends here
128 |
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Command file for Sphinx documentation
4 |
5 | if "%SPHINXBUILD%" == "" (
6 | set SPHINXBUILD=sphinx-build
7 | )
8 | set BUILDDIR=build
9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
10 | set I18NSPHINXOPTS=%SPHINXOPTS% source
11 | if NOT "%PAPER%" == "" (
12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
14 | )
15 |
16 | if "%1" == "" goto help
17 |
18 | if "%1" == "help" (
19 | :help
20 | echo.Please use `make ^` where ^ is one of
21 | echo. html to make standalone HTML files
22 | echo. dirhtml to make HTML files named index.html in directories
23 | echo. singlehtml to make a single large HTML file
24 | echo. pickle to make pickle files
25 | echo. json to make JSON files
26 | echo. htmlhelp to make HTML files and a HTML help project
27 | echo. qthelp to make HTML files and a qthelp project
28 | echo. devhelp to make HTML files and a Devhelp project
29 | echo. epub to make an epub
30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
31 | echo. text to make text files
32 | echo. man to make manual pages
33 | echo. texinfo to make Texinfo files
34 | echo. gettext to make PO message catalogs
35 | echo. changes to make an overview over all changed/added/deprecated items
36 | echo. linkcheck to check all external links for integrity
37 | echo. doctest to run all doctests embedded in the documentation if enabled
38 | goto end
39 | )
40 |
41 | if "%1" == "clean" (
42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
43 | del /q /s %BUILDDIR%\*
44 | goto end
45 | )
46 |
47 | if "%1" == "html" (
48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
49 | if errorlevel 1 exit /b 1
50 | echo.
51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html.
52 | goto end
53 | )
54 |
55 | if "%1" == "dirhtml" (
56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
57 | if errorlevel 1 exit /b 1
58 | echo.
59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
60 | goto end
61 | )
62 |
63 | if "%1" == "singlehtml" (
64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
65 | if errorlevel 1 exit /b 1
66 | echo.
67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
68 | goto end
69 | )
70 |
71 | if "%1" == "pickle" (
72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
73 | if errorlevel 1 exit /b 1
74 | echo.
75 | echo.Build finished; now you can process the pickle files.
76 | goto end
77 | )
78 |
79 | if "%1" == "json" (
80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
81 | if errorlevel 1 exit /b 1
82 | echo.
83 | echo.Build finished; now you can process the JSON files.
84 | goto end
85 | )
86 |
87 | if "%1" == "htmlhelp" (
88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
89 | if errorlevel 1 exit /b 1
90 | echo.
91 | echo.Build finished; now you can run HTML Help Workshop with the ^
92 | .hhp project file in %BUILDDIR%/htmlhelp.
93 | goto end
94 | )
95 |
96 | if "%1" == "qthelp" (
97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
98 | if errorlevel 1 exit /b 1
99 | echo.
100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^
101 | .qhcp project file in %BUILDDIR%/qthelp, like this:
102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\EmacsIPythonNotebook.qhcp
103 | echo.To view the help file:
104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\EmacsIPythonNotebook.ghc
105 | goto end
106 | )
107 |
108 | if "%1" == "devhelp" (
109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
110 | if errorlevel 1 exit /b 1
111 | echo.
112 | echo.Build finished.
113 | goto end
114 | )
115 |
116 | if "%1" == "epub" (
117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
118 | if errorlevel 1 exit /b 1
119 | echo.
120 | echo.Build finished. The epub file is in %BUILDDIR%/epub.
121 | goto end
122 | )
123 |
124 | if "%1" == "latex" (
125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
126 | if errorlevel 1 exit /b 1
127 | echo.
128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
129 | goto end
130 | )
131 |
132 | if "%1" == "text" (
133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
134 | if errorlevel 1 exit /b 1
135 | echo.
136 | echo.Build finished. The text files are in %BUILDDIR%/text.
137 | goto end
138 | )
139 |
140 | if "%1" == "man" (
141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
142 | if errorlevel 1 exit /b 1
143 | echo.
144 | echo.Build finished. The manual pages are in %BUILDDIR%/man.
145 | goto end
146 | )
147 |
148 | if "%1" == "texinfo" (
149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
150 | if errorlevel 1 exit /b 1
151 | echo.
152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
153 | goto end
154 | )
155 |
156 | if "%1" == "gettext" (
157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
158 | if errorlevel 1 exit /b 1
159 | echo.
160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
161 | goto end
162 | )
163 |
164 | if "%1" == "changes" (
165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
166 | if errorlevel 1 exit /b 1
167 | echo.
168 | echo.The overview file is in %BUILDDIR%/changes.
169 | goto end
170 | )
171 |
172 | if "%1" == "linkcheck" (
173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
174 | if errorlevel 1 exit /b 1
175 | echo.
176 | echo.Link check complete; look for any errors in the above output ^
177 | or in %BUILDDIR%/linkcheck/output.txt.
178 | goto end
179 | )
180 |
181 | if "%1" == "doctest" (
182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
183 | if errorlevel 1 exit /b 1
184 | echo.
185 | echo.Testing of doctests in the sources finished, look at the ^
186 | results in %BUILDDIR%/doctest/output.txt.
187 | goto end
188 | )
189 |
190 | :end
191 |
--------------------------------------------------------------------------------
/lisp/ein-multilang.el:
--------------------------------------------------------------------------------
1 | ;;; ein-multilang.el --- Notebook mode with multiple language fontification
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-multilang.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-multilang.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-multilang.el.
21 | ;; If not, see .
22 |
23 | ;;; Commentary:
24 |
25 | ;;
26 |
27 | ;;; Code:
28 |
29 | (eval-when-compile (require 'cl))
30 | (eval-when-compile (defvar markdown-mode-map))
31 |
32 | (require 'ein-worksheet)
33 | (require 'ein-multilang-fontify)
34 |
35 | (defun ein:ml-fontify (limit)
36 | "Fontify next input area comes after the current point then
37 | return `t' or `nil' if not found.
38 | See info node `(elisp) Search-based Fontification'."
39 | (ein:log-ignore-errors
40 | (ein:ml-fontify-1 limit)))
41 |
42 | (defun ein:ml-current-or-next-input-cell (ewoc-node)
43 | "Almost identical to `ein:worksheet-next-input-cell' but return
44 | the current cell if EWOC-NODE is the input area node."
45 | (let* ((ewoc-data (ewoc-data ewoc-node))
46 | (cell (ein:$node-data ewoc-data))
47 | (path (ein:$node-path ewoc-data))
48 | (element (nth 1 path)))
49 | (if (memql element '(prompt input))
50 | cell
51 | (ein:cell-next cell))))
52 |
53 | (defun ein:ml-fontify-1 (limit)
54 | "Actual implementation of `ein:ml-fontify'.
55 | This function may raise an error."
56 | (ein:and-let* ((pos (point))
57 | (node (ein:worksheet-get-nearest-cell-ewoc-node pos limit))
58 | (cell (ein:ml-current-or-next-input-cell node))
59 | (start (ein:cell-input-pos-min cell))
60 | (end (ein:cell-input-pos-max cell))
61 | ((<= end limit))
62 | ((< start end))
63 | (lang (ein:cell-language cell)))
64 | (let ((inhibit-read-only t))
65 | (ein:mlf-font-lock-fontify-block lang start end)
66 | ;; Emacs fontification mechanism requires the function to move
67 | ;; the point. Do *not* use `(goto-char end)'. As END is in the
68 | ;; input area, fontification falls into an infinite loop.
69 | (ewoc-goto-node (oref cell :ewoc) (ein:cell-element-get cell :footer)))
70 | t))
71 |
72 | (defun ein:ml-back-to-prev-node ()
73 | (ein:aand (ein:worksheet-get-ewoc) (ewoc-goto-prev it 1)))
74 |
75 | (defvar ein:ml-font-lock-keywords
76 | '((ein:ml-fontify))
77 | "Default `font-lock-keywords' for `ein:notebook-multilang-mode'.")
78 |
79 | (defun ein:ml-set-font-lock-defaults ()
80 | (set (make-local-variable 'font-lock-defaults)
81 | '(ein:ml-font-lock-keywords
82 | ;; The following are adapted from org-mode but I am not sure
83 | ;; if I need them:
84 | t nil nil
85 | ein:ml-back-to-prev-node)))
86 |
87 | ;;;###autoload
88 | (define-derived-mode ein:notebook-multilang-mode fundamental-mode "ein:ml"
89 | "Notebook mode with multiple language fontification."
90 | (make-local-variable 'comment-start)
91 | (make-local-variable 'comment-start-skip)
92 | (make-local-variable 'parse-sexp-lookup-properties)
93 | (make-local-variable 'parse-sexp-ignore-comments)
94 | (make-local-variable 'indent-line-function)
95 | (make-local-variable 'indent-region-function)
96 | (make-local-variable 'beginning-of-defun-function)
97 | (make-local-variable 'end-of-defun-function)
98 | (setq beginning-of-defun-function 'ein:worksheet-beginning-of-cell-input)
99 | (setq end-of-defun-function 'ein:worksheet-end-of-cell-input)
100 | (ein:ml-lang-setup-python)
101 | (ein:ml-set-font-lock-defaults))
102 |
103 | (eval-after-load "auto-complete"
104 | '(add-to-list 'ac-modes 'ein:notebook-multilang-mode))
105 |
106 |
107 | ;;; Language setup functions
108 |
109 | (defun ein:ml-lang-setup-python ()
110 | (setq comment-start "# ")
111 | (setq comment-start-skip "#+\\s-*")
112 | (setq parse-sexp-lookup-properties t)
113 | (setq parse-sexp-ignore-comments t)
114 |
115 | (when (boundp 'python-mode-map)
116 | (set-keymap-parent ein:notebook-multilang-mode-map python-mode-map))
117 | (cond
118 | ((featurep 'python)
119 | (setq indent-line-function #'python-indent-line-function)
120 | (setq indent-region-function #'python-indent-region))
121 | ((featurep 'python-mode)
122 | ;; FIXME: write keymap setup for python-mode.el
123 | )))
124 |
125 | (defun ein:ml-lang-setup-markdown ()
126 | "Use `markdown-mode-map'. NOTE: This function is not used now."
127 | (when (featurep 'markdown-mode)
128 | (set-keymap-parent ein:notebook-multilang-mode-map markdown-mode-map)))
129 |
130 | ;; FIXME: dynamically call ein:ml-lang-setup-LANG using
131 | ;; `post-command-hook'.
132 | ;; FIMXE: add more ein:ml-lang-setup-LANG to switch kaymap.
133 |
134 |
135 | ;;; yasnippet
136 |
137 | (defvar ein:ml-yasnippet-parents '(python-mode markdown-mode)
138 | "Parent modes for `ein:notebook-multilang-mode' to register in yasnippet.")
139 |
140 | (defun ein:ml-setup-yasnippet ()
141 | (loop for define-parents in '(yas/define-parents
142 | yas--define-parents)
143 | when (fboundp define-parents)
144 | do (ignore-errors
145 | ;; `let' is for workaround the bug in yasnippet
146 | (let ((mode-sym 'ein:notebook-multilang-mode))
147 | (funcall define-parents
148 | mode-sym
149 | ein:ml-yasnippet-parents)))))
150 |
151 | (eval-after-load "yasnippet" '(ein:ml-setup-yasnippet))
152 |
153 | (provide 'ein-multilang)
154 |
155 | ;;; ein-multilang.el ends here
156 |
--------------------------------------------------------------------------------
/lisp/ein-traceback.el:
--------------------------------------------------------------------------------
1 | ;;; ein-traceback.el --- Traceback module
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-traceback.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-traceback.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-traceback.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'eieio)
30 | (require 'ewoc)
31 | (require 'ansi-color)
32 |
33 | (require 'ein-core)
34 |
35 | (defclass ein:traceback ()
36 | ((tb-data :initarg :tb-data :type list)
37 | (buffer-name :initarg :buffer-name :type string)
38 | (buffer :initarg :buffer :type buffer)
39 | (ewoc :initarg :ewoc :type ewoc)))
40 |
41 | (ein:deflocal ein:%traceback% nil
42 | "Buffer local variable to store an instance of `ein:traceback'.")
43 |
44 | (defvar ein:tb-buffer-name-template "*ein:tb %s/%s*")
45 |
46 | (defun ein:tb-new (buffer-name)
47 | (ein:traceback "Traceback" :buffer-name buffer-name))
48 |
49 | (defmethod ein:tb-get-buffer ((traceback ein:traceback))
50 | (unless (and (slot-boundp traceback :buffer)
51 | (buffer-live-p (oref traceback :buffer)))
52 | (let ((buf (get-buffer-create (oref traceback :buffer-name))))
53 | (oset traceback :buffer buf)))
54 | (oref traceback :buffer))
55 |
56 | (defun ein:tb-pp (ewoc-data)
57 | (insert (ansi-color-apply ewoc-data)))
58 |
59 | (defmethod ein:tb-render ((traceback ein:traceback) tb-data)
60 | (with-current-buffer (ein:tb-get-buffer traceback)
61 | (setq ein:%traceback% traceback)
62 | (setq buffer-read-only t)
63 | (let ((inhibit-read-only t)
64 | (ewoc (ein:ewoc-create #'ein:tb-pp)))
65 | (erase-buffer)
66 | (oset traceback :ewoc ewoc)
67 | (oset traceback :tb-data tb-data)
68 | (mapc (lambda (data) (ewoc-enter-last ewoc data)) tb-data))
69 | (ein:traceback-mode)))
70 |
71 | (defmethod ein:tb-popup ((traceback ein:traceback) tb-data)
72 | (ein:tb-render traceback tb-data)
73 | (pop-to-buffer (ein:tb-get-buffer traceback)))
74 |
75 | ;;;###autoload
76 | (defun ein:tb-show ()
77 | "Show full traceback in traceback viewer."
78 | (interactive)
79 | (unless
80 | (ein:and-let* ((tb-data (ein:get-traceback-data))
81 | (url-or-port (ein:get-url-or-port))
82 | (kernel (ein:get-kernel))
83 | (kr-id (ein:kernel-id kernel))
84 | (tb-name (format ein:tb-buffer-name-template
85 | url-or-port kr-id)))
86 | (ein:tb-popup (ein:tb-new tb-name) tb-data)
87 | t)
88 | (error "No traceback is available.")))
89 |
90 | (defmethod ein:tb-range-of-node-at-point ((traceback ein:traceback))
91 | (let* ((ewoc (oref traceback :ewoc))
92 | (ewoc-node (ewoc-locate ewoc))
93 | (beg (ewoc-location ewoc-node))
94 | (end (ein:aand (ewoc-next ewoc ewoc-node) (ewoc-location it))))
95 | (list beg end)))
96 |
97 | (defmethod ein:tb-file-path-at-point ((traceback ein:traceback))
98 | (destructuring-bind (beg end)
99 | (ein:tb-range-of-node-at-point traceback)
100 | (let* ((file-tail
101 | (if (>= emacs-major-version 24)
102 | (next-single-property-change beg 'font-lock-face nil end)
103 | ;; For Emacs 23.x:
104 | (next-single-property-change beg 'face nil end)))
105 | (file (when file-tail
106 | (buffer-substring-no-properties beg file-tail))))
107 | (if (string-match "\\.pyc$" file)
108 | (concat (file-name-sans-extension file) ".py")
109 | file))))
110 |
111 | (defmethod ein:tb-file-lineno-at-point ((traceback ein:traceback))
112 | (destructuring-bind (beg end)
113 | (ein:tb-range-of-node-at-point traceback)
114 | (when (save-excursion
115 | (goto-char beg)
116 | (search-forward-regexp "^[-]+> \\([0-9]+\\)" end t))
117 | (string-to-number (match-string 1)))))
118 |
119 | (defmethod ein:tb-jump-to-source-at-point ((traceback ein:traceback)
120 | &optional select)
121 | (let ((file (ein:tb-file-path-at-point traceback))
122 | (lineno (ein:tb-file-lineno-at-point traceback)))
123 | (assert (file-exists-p file) nil "File %s does not exist." file)
124 | (let ((buf (find-file-noselect file))
125 | (scroll (lambda ()
126 | (goto-char (point-min))
127 | (forward-line (1- lineno)))))
128 | (if select
129 | (progn (pop-to-buffer buf)
130 | (funcall scroll))
131 | (with-selected-window (display-buffer buf)
132 | (funcall scroll))))))
133 |
134 | (defun ein:tb-jump-to-source-at-point-command (&optional select)
135 | (interactive "P")
136 | (ein:tb-jump-to-source-at-point ein:%traceback% select))
137 |
138 |
139 | ;;; ein:traceback-mode
140 |
141 | (defun ein:tb-prev-item ()
142 | (interactive)
143 | (ewoc-goto-prev (oref ein:%traceback% :ewoc) 1))
144 |
145 | (defun ein:tb-next-item ()
146 | (interactive)
147 | (ewoc-goto-next (oref ein:%traceback% :ewoc) 1))
148 |
149 | (define-derived-mode ein:traceback-mode fundamental-mode "ein:tb"
150 | (font-lock-mode))
151 |
152 | (add-hook 'ein:traceback-mode-hook 'ein:truncate-lines-on)
153 |
154 | (let ((map ein:traceback-mode-map))
155 | (define-key map (kbd "RET") 'ein:tb-jump-to-source-at-point-command)
156 | (define-key map "p" 'ein:tb-prev-item)
157 | (define-key map "n" 'ein:tb-next-item)
158 | (define-key map "q" 'bury-buffer))
159 |
160 | (provide 'ein-traceback)
161 |
162 | ;;; ein-traceback.el ends here
163 |
--------------------------------------------------------------------------------
/lisp/ein-helm.el:
--------------------------------------------------------------------------------
1 | ;;; ein-helm.el --- Helm/anything commands
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-helm.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-helm.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-helm.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 |
30 | (declare-function anything-other-buffer "anything")
31 | (declare-function helm-other-buffer "helm")
32 |
33 | (require 'ein-kernel)
34 |
35 |
36 | ;;; Macros
37 |
38 | (defmacro ein:helm-export-source (name)
39 | (let* ((orig-source (intern (format "ein:helm-source-%s" name)))
40 | (any-source (intern (format "anything-c-source-ein-%s" name)))
41 | (helm-source (intern (format "helm-c-source-ein-%s" name)))
42 | (docstring (format "Alias to `%s'" orig-source)))
43 | `(progn
44 | (defvaralias ',helm-source ',orig-source ,docstring)
45 | (defvaralias ',any-source ',orig-source ,docstring))))
46 |
47 |
48 | ;;; Dynamic Variables
49 |
50 | (defvar ein:helm-pattern 'helm-pattern
51 | "Dynamically bound to one of `helm-pattern' or `anything-pattern'.")
52 |
53 | (defvar ein:helm-kernel nil
54 | "Dynamically bound to a kernel object.")
55 |
56 |
57 |
58 | ;;; History search
59 |
60 | (defcustom ein:helm-kernel-history-search-auto-pattern t
61 | "Automatically construct search pattern when non-`nil'.
62 |
63 | 1. Single space is converted to \"*\".
64 | 2. A backslash followed by a space is converted to a single space.
65 | 3. A \"*\" is added at the beginning and end of the pattern.
66 |
67 | This variable applies to both `helm-ein-kernel-history' and
68 | `anything-ein-kernel-history'."
69 | :group 'ein)
70 |
71 | (defun ein:helm-kernel-history-search-construct-pattern (pattern)
72 | (when ein:helm-kernel-history-search-auto-pattern
73 | (setq pattern
74 | (replace-regexp-in-string "[^\\\\ ]\\( \\)[^\\\\ ]"
75 | "*" pattern nil nil 1))
76 | (setq pattern
77 | (replace-regexp-in-string "\\\\ " " " pattern))
78 | (setq pattern (concat "*" pattern "*")))
79 | pattern)
80 |
81 | (defun ein:helm-kernel-history-search-get-candidates ()
82 | "Retrieve search result from kernel.
83 | It requires the following dynamical variables:
84 | * `ein:helm-pattern'
85 | * `ein:helm-kernel'"
86 | (let* ((pattern (ein:helm-kernel-history-search-construct-pattern
87 | (eval ein:helm-pattern)))
88 | (candidates (ein:kernel-history-search-synchronously
89 | ein:helm-kernel pattern :unique t)))
90 | ;; Most recent history first:
91 | (nreverse candidates)))
92 |
93 | (defvar ein:helm-source-kernel-history
94 | '((name . "IPython history")
95 | (candidates . ein:helm-kernel-history-search-get-candidates)
96 | (requires-pattern . 3)
97 | ;; There is no need to filter out candidates:
98 | (match . (identity))
99 | (volatile)
100 | (action . insert)
101 | (delayed)
102 | (multiline))
103 | "Helm/anything source for searching kernel history.")
104 |
105 | ;;;###autoload
106 | (defun anything-ein-kernel-history ()
107 | "Search kernel execution history then insert the selected one."
108 | (interactive)
109 | (let ((ein:helm-pattern 'anything-pattern)
110 | (ein:helm-kernel (ein:get-kernel-or-error)))
111 | (anything-other-buffer ein:helm-source-kernel-history "*anything ein*")))
112 |
113 | ;;;###autoload
114 | (defun helm-ein-kernel-history ()
115 | "Search kernel execution history then insert the selected one."
116 | (interactive)
117 | (let ((ein:helm-pattern 'helm-pattern)
118 | (ein:helm-kernel (ein:get-kernel-or-error)))
119 | (helm-other-buffer ein:helm-source-kernel-history "*helm ein*")))
120 |
121 |
122 |
123 | ;;; Notebook buffers
124 |
125 | (defvar ein:helm-source-notebook-buffers
126 | '((name . "All IPython notebook buffers")
127 | (candidates . ein:notebook-opened-buffer-names)
128 | (type . buffer))
129 | "Helm/anything source for all opened notebook buffers.")
130 |
131 | (defvar ein:helm-source-modified-notebook-buffers
132 | '((name . "Modified IPython notebook buffers")
133 | (candidates
134 | . (lambda ()
135 | (ein:notebook-opened-buffer-names #'ein:notebook-modified-p)))
136 | (type . buffer))
137 | "Helm/anything source for modified notebook buffers.")
138 |
139 | (defvar ein:helm-source-saved-notebook-buffers
140 | '((name . "Saved IPython notebook buffers")
141 | (candidates
142 | . (lambda ()
143 | (ein:notebook-opened-buffer-names
144 | (lambda (nb) (not (ein:notebook-modified-p nb))))))
145 | (type . buffer))
146 | "Helm/anything source for saved notebook buffers.")
147 |
148 |
149 | ;;; "Export" sources to `helm/anything-c-source-*'
150 | (ein:helm-export-source notebook-buffers)
151 | (ein:helm-export-source modified-notebook-buffers)
152 | (ein:helm-export-source saved-notebook-buffers)
153 |
154 |
155 | ;;; Helm/anything commands
156 |
157 | (defvar ein:helm-notebook-buffer-sources
158 | '(ein:helm-source-modified-notebook-buffers
159 | ein:helm-source-saved-notebook-buffers))
160 |
161 | ;;;###autoload
162 | (defun anything-ein-notebook-buffers ()
163 | "Choose opened notebook using anything.el interface."
164 | (interactive)
165 | (anything-other-buffer ein:helm-notebook-buffer-sources "*anything ein*"))
166 |
167 | ;;;###autoload
168 | (defun helm-ein-notebook-buffers ()
169 | "Choose opened notebook using helm interface."
170 | (interactive)
171 | (helm-other-buffer ein:helm-notebook-buffer-sources "*helm ein*"))
172 |
173 | (provide 'ein-helm)
174 | ;;; ein-helm.el ends here
175 |
--------------------------------------------------------------------------------
/tests/test-ein-utils.el:
--------------------------------------------------------------------------------
1 | (eval-when-compile (require 'cl))
2 | (require 'ert)
3 |
4 | (require 'ein) ; for `ein:version'
5 | (require 'ein-utils)
6 |
7 | (ert-deftest ein-url-simple ()
8 | (should (equal (ein:url 8888) "http://127.0.0.1:8888"))
9 | (should (equal (ein:url "http://localhost") "http://localhost")))
10 |
11 | (ert-deftest ein-url-slashes ()
12 | (loop for a in '("a" "a/" "/a")
13 | do (loop for b in '("b" "/b")
14 | do (should (equal (ein:url 8888 a b)
15 | "http://127.0.0.1:8888/a/b")))
16 | do (should (equal (ein:url 8888 a "b/")
17 | "http://127.0.0.1:8888/a/b/"))))
18 |
19 | (ert-deftest ein-trim-simple ()
20 | (should (equal (ein:trim "a") "a"))
21 | (should (equal (ein:trim " a ") "a"))
22 | (should (equal (ein:trim "\na\n") "a")))
23 |
24 | (ert-deftest ein-trim-middle-spaces ()
25 | (should (equal (ein:trim "a b") "a b"))
26 | (should (equal (ein:trim " a b ") "a b"))
27 | (should (equal (ein:trim "\na b\n") "a b")))
28 |
29 | (ert-deftest ein-trim-left-simple ()
30 | (should (equal (ein:trim-left "a") "a"))
31 | (should (equal (ein:trim-left " a ") "a "))
32 | (should (equal (ein:trim-left "\na\n") "a\n")))
33 |
34 | (ert-deftest ein-trim-right-simple ()
35 | (should (equal (ein:trim-right "a") "a"))
36 | (should (equal (ein:trim-right " a ") " a"))
37 | (should (equal (ein:trim-right "\na\n") "\na")))
38 |
39 | (ert-deftest ein:trim-indent-empty ()
40 | (should (equal (ein:trim-indent "") "")))
41 |
42 | (ert-deftest ein:trim-indent-one-line ()
43 | (should (equal (ein:trim-indent "one line") "one line")))
44 |
45 | (ert-deftest ein:trim-indent-one-newline ()
46 | (should (equal (ein:trim-indent "one line\n") "one line\n")))
47 |
48 | (ert-deftest ein:trim-indent-multi-lines-no-trim ()
49 | (let ((original "\
50 | def func():
51 | pass
52 | ")
53 | (trimmed "\
54 | def func():
55 | pass
56 | "))
57 | (should (equal (ein:trim-indent original) trimmed))))
58 |
59 | (ert-deftest ein:trim-indent-multi-lines-one-trim ()
60 | (let ((original "\
61 | def func():
62 | pass
63 | ")
64 | (trimmed "\
65 | def func():
66 | pass
67 | "))
68 | (should (equal (ein:trim-indent original) trimmed))))
69 |
70 | (ert-deftest ein:trim-indent-multi-lines-with-empty-lines ()
71 | (let ((original "\
72 |
73 | def func():
74 | pass
75 |
76 | ")
77 | (trimmed "\
78 |
79 | def func():
80 | pass
81 |
82 | "))
83 | (should (equal (ein:trim-indent original) trimmed))))
84 |
85 |
86 | ;;; Text manipulation on buffer
87 |
88 | (ert-deftest ein:find-leftmot-column-simple-cases ()
89 | (loop for (indent text) in
90 | '(;; No indent
91 | (0 "\
92 | def f():
93 | pass")
94 | ;; Indented python code
95 | (4 "\
96 | def f():
97 | pass")
98 | ;; Deeper indent can come first
99 | (4 "\
100 | # indent = 8
101 | # indent 4")
102 | ;; With empty lines
103 | (4 "\
104 |
105 | # indent = 8
106 |
107 | # indent 4
108 |
109 | ")
110 | )
111 | do (with-temp-buffer
112 | (insert text)
113 | (should (= (ein:find-leftmot-column (point-min) (point-max))
114 | indent)))))
115 |
116 |
117 | ;;; Misc
118 |
119 | (ert-deftest ein:list-insert-after ()
120 | (should (equal (ein:list-insert-after '(a) 'a 'X) '(a X)))
121 | (should (equal (ein:list-insert-after '(a b c) 'a 'X) '(a X b c)))
122 | (should (equal (ein:list-insert-after '(a b c) 'b 'X) '(a b X c)))
123 | (should (equal (ein:list-insert-after '(a b c) 'c 'X) '(a b c X)))
124 | (should-error (ein:list-insert-after '(a b c) 'd 'X)))
125 |
126 | (ert-deftest ein:list-insert-before ()
127 | (should (equal (ein:list-insert-before '(a) 'a 'X) '(X a)))
128 | (should (equal (ein:list-insert-before '(a b c) 'a 'X) '(X a b c)))
129 | (should (equal (ein:list-insert-before '(a b c) 'b 'X) '(a X b c)))
130 | (should (equal (ein:list-insert-before '(a b c) 'c 'X) '(a b X c)))
131 | (should-error (ein:list-insert-before '(a b c) 'd 'X)))
132 |
133 | (ert-deftest ein:list-move-left ()
134 | (should (equal (ein:list-move-left '(a) 'a) '(a)))
135 | (should (equal (ein:list-move-left '(a b) 'a) '(b a)))
136 | (should (equal (ein:list-move-left '(a b) 'b) '(b a)))
137 | (should (equal (ein:list-move-left '(a b c d) 'a) '(b c d a)))
138 | (should (equal (ein:list-move-left '(a b c d) 'b) '(b a c d)))
139 | (should (equal (ein:list-move-left '(a b c d) 'c) '(a c b d)))
140 | (should (equal (ein:list-move-left '(a b c d) 'd) '(a b d c)))
141 | (should-error (ein:list-move-left '(a b c d) 'X)))
142 |
143 | (ert-deftest ein:list-move-right ()
144 | (should (equal (ein:list-move-right '(a) 'a) '(a)))
145 | (should (equal (ein:list-move-right '(a b) 'a) '(b a)))
146 | (should (equal (ein:list-move-right '(a b) 'b) '(b a)))
147 | (should (equal (ein:list-move-right '(a b c d) 'a) '(b a c d)))
148 | (should (equal (ein:list-move-right '(a b c d) 'b) '(a c b d)))
149 | (should (equal (ein:list-move-right '(a b c d) 'c) '(a b d c)))
150 | (should (equal (ein:list-move-right '(a b c d) 'd) '(d a b c)))
151 | (should-error (ein:list-move-right '(a b c d) 'X)))
152 |
153 | (defun ein:testing-choose-setting-should-equal
154 | (setting value desired &optional single-p)
155 | (let ((setting setting))
156 | (should (equal (ein:choose-setting 'setting value single-p) desired))))
157 |
158 | (ert-deftest ein:choose-setting-single-string ()
159 | (let ((test 'ein:testing-choose-setting-should-equal))
160 | (funcall test "a" nil "a")
161 | (funcall test "a" 'whatever "a")))
162 |
163 | (ert-deftest ein:choose-setting-single-int ()
164 | (let ((test #'ein:testing-choose-setting-should-equal))
165 | (funcall test 1 nil 1 #'integerp)
166 | (funcall test 1 'whatever 1 #'integerp)))
167 |
168 | (ert-deftest ein:choose-setting-alist ()
169 | (let* ((test (lambda (&rest args)
170 | (apply #'ein:testing-choose-setting-should-equal
171 | '(("a" . 1) ("b" . 2) ("c" . 3))
172 | args))))
173 | (funcall test "a" 1)
174 | (funcall test "b" 2)))
175 |
176 | (ert-deftest ein:choose-setting-func ()
177 | (let* ((test (lambda (&rest args)
178 | (apply #'ein:testing-choose-setting-should-equal
179 | (lambda (x) 1)
180 | args))))
181 | (funcall test nil 1)
182 | (funcall test 'whatever 1)))
183 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp \
18 | qthelp devhelp epub latex latexpdf text man changes linkcheck \
19 | doctest gettext gh-pages-update gh-pages-push gh-pages-clone \
20 | gh-pages-pull
21 |
22 | help:
23 | @echo "Please use \`make ' where is one of"
24 | @echo " html to make standalone HTML files"
25 | @echo " dirhtml to make HTML files named index.html in directories"
26 | @echo " singlehtml to make a single large HTML file"
27 | @echo " pickle to make pickle files"
28 | @echo " json to make JSON files"
29 | @echo " htmlhelp to make HTML files and a HTML help project"
30 | @echo " qthelp to make HTML files and a qthelp project"
31 | @echo " devhelp to make HTML files and a Devhelp project"
32 | @echo " epub to make an epub"
33 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
34 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
35 | @echo " text to make text files"
36 | @echo " man to make manual pages"
37 | @echo " texinfo to make Texinfo files"
38 | @echo " info to make Texinfo files and run them through makeinfo"
39 | @echo " gettext to make PO message catalogs"
40 | @echo " changes to make an overview of all changed/added/deprecated items"
41 | @echo " linkcheck to check all external links for integrity"
42 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
43 |
44 | clean:
45 | -rm -rf $(BUILDDIR)/*/*
46 |
47 | html:
48 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
49 | @echo
50 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
51 |
52 | dirhtml:
53 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
54 | @echo
55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
56 |
57 | singlehtml:
58 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
59 | @echo
60 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
61 |
62 | pickle:
63 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
64 | @echo
65 | @echo "Build finished; now you can process the pickle files."
66 |
67 | json:
68 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
69 | @echo
70 | @echo "Build finished; now you can process the JSON files."
71 |
72 | htmlhelp:
73 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
74 | @echo
75 | @echo "Build finished; now you can run HTML Help Workshop with the" \
76 | ".hhp project file in $(BUILDDIR)/htmlhelp."
77 |
78 | qthelp:
79 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
80 | @echo
81 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
82 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
83 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/EmacsIPythonNotebook.qhcp"
84 | @echo "To view the help file:"
85 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/EmacsIPythonNotebook.qhc"
86 |
87 | devhelp:
88 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
89 | @echo
90 | @echo "Build finished."
91 | @echo "To view the help file:"
92 | @echo "# mkdir -p $$HOME/.local/share/devhelp/EmacsIPythonNotebook"
93 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/EmacsIPythonNotebook"
94 | @echo "# devhelp"
95 |
96 | epub:
97 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
98 | @echo
99 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
100 |
101 | latex:
102 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
103 | @echo
104 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
105 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
106 | "(use \`make latexpdf' here to do that automatically)."
107 |
108 | latexpdf:
109 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
110 | @echo "Running LaTeX files through pdflatex..."
111 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
112 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
113 |
114 | text:
115 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
116 | @echo
117 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
118 |
119 | man:
120 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
121 | @echo
122 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
123 |
124 | texinfo:
125 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
126 | @echo
127 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
128 | @echo "Run \`make' in that directory to run these through makeinfo" \
129 | "(use \`make info' here to do that automatically)."
130 |
131 | info:
132 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
133 | @echo "Running Texinfo files through makeinfo..."
134 | make -C $(BUILDDIR)/texinfo info
135 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
136 |
137 | gettext:
138 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
139 | @echo
140 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
141 |
142 | changes:
143 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
144 | @echo
145 | @echo "The overview file is in $(BUILDDIR)/changes."
146 |
147 | linkcheck:
148 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
149 | @echo
150 | @echo "Link check complete; look for any errors in the above output " \
151 | "or in $(BUILDDIR)/linkcheck/output.txt."
152 |
153 | doctest:
154 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
155 | @echo "Testing of doctests in the sources finished, look at the " \
156 | "results in $(BUILDDIR)/doctest/output.txt."
157 |
158 | # Check if build/html is really a git repository. Otherwise,
159 | # committing files in there is pretty dangerous as it might goes into
160 | # EIN's master branch.
161 | _gh-pages-assert-repo:
162 | test -d build/html/.git
163 |
164 | gh-pages-clone:
165 | rm -rf build/html
166 | git clone --branch gh-pages \
167 | git@github.com:tkf/emacs-ipython-notebook.git \
168 | build/html
169 |
170 | gh-pages-pull: _gh-pages-assert-repo
171 | cd build/html && git pull
172 |
173 | gh-pages-update: _gh-pages-assert-repo clean html
174 | @echo "Update gh-pages"
175 | ./update-gh-pages.sh
176 |
177 | gh-pages-push: _gh-pages-assert-repo
178 | cd build/html && git push origin gh-pages
179 |
--------------------------------------------------------------------------------
/tests/test-ein-cell-notebook.el:
--------------------------------------------------------------------------------
1 | ;; Tests for cell function that requires notebook buffer
2 |
3 | (eval-when-compile (require 'cl))
4 | (require 'ert)
5 |
6 | (require 'ein-notebook)
7 | (require 'ein-testing-notebook)
8 |
9 |
10 | ;; ein:cell-location
11 |
12 | (ert-deftest ein:cell-location-codecell-prompt-beg ()
13 | (ein:testing-with-one-cell 'code
14 | (should (equal (marker-position (ein:cell-location cell :prompt))
15 | (save-excursion
16 | (goto-char (point-max))
17 | (search-backward "In [ ]:")
18 | (point))))))
19 |
20 | (ert-deftest ein:cell-location-codecell-prompt-end ()
21 | (ein:testing-with-one-cell 'code
22 | (should (equal (marker-position (ein:cell-location cell :prompt t))
23 | (1- (point))))))
24 |
25 | (ert-deftest ein:cell-location-codecell-input-beg ()
26 | (ein:testing-with-one-cell 'code
27 | (insert "some text")
28 | (should (equal (marker-position (ein:cell-location cell :input))
29 | (1- (point-at-bol))))))
30 |
31 | (ert-deftest ein:cell-location-codecell-input-end ()
32 | (ein:testing-with-one-cell 'code
33 | (insert "some text")
34 | (should (equal (marker-position (ein:cell-location cell :input t))
35 | (1+ (point))))))
36 |
37 |
38 | ;; from-json
39 |
40 | (ert-deftest eintest:cell-input-prompt-number ()
41 | (ein:testing-with-one-cell
42 | (ein:cell-from-json
43 | (list :cell_type "code"
44 | :input "some input"
45 | :prompt_number 111)
46 | :ewoc (oref ein:%worksheet% :ewoc))
47 | (goto-char (ein:cell-location cell))
48 | (should (looking-at "\
49 | In \\[111\\]:
50 | some input
51 | "))))
52 |
53 | (ert-deftest eintest:cell-input-prompt-star ()
54 | (ein:testing-with-one-cell
55 | (ein:cell-from-json
56 | (list :cell_type "code"
57 | :input "some input"
58 | :prompt_number "*")
59 | :ewoc (oref ein:%worksheet% :ewoc))
60 | (goto-char (ein:cell-location cell))
61 | (should (looking-at "\
62 | In \\[\\*\\]:
63 | some input
64 | "))))
65 |
66 | (ert-deftest eintest:cell-input-prompt-empty ()
67 | (ein:testing-with-one-cell
68 | (ein:cell-from-json
69 | (list :cell_type "code"
70 | :input "some input")
71 | :ewoc (oref ein:%worksheet% :ewoc))
72 | (goto-char (ein:cell-location cell))
73 | (should (looking-at "\
74 | In \\[ \\]:
75 | some input
76 | "))))
77 |
78 |
79 | ;; Insert pyout/display_data
80 |
81 | (defun eintest:cell-insert-output (outputs regexp)
82 | (let ((ein:output-type-preference
83 | '(emacs-lisp svg png jpeg text html latex javascript)))
84 | (ein:testing-with-one-cell
85 | (ein:cell-from-json
86 | (list :cell_type "code"
87 | :outputs outputs
88 | :input "some input"
89 | :prompt_number 111)
90 | :ewoc (oref ein:%worksheet% :ewoc))
91 | (goto-char (ein:cell-location cell))
92 | (should (looking-at (format "\
93 | In \\[111\\]:
94 | some input
95 | %s" regexp))))))
96 |
97 | (defmacro eintest:gene-test-cell-insert-output-pyout-and-display-data
98 | (name regexps outputs)
99 | (declare (indent defun))
100 | (let ((test-pyout
101 | (intern (format "ein:cell-insert-output-pyout-%s" name)))
102 | (test-display-data
103 | (intern (format "ein:cell-insert-output-display-data-%s" name)))
104 | (outputs-pyout
105 | (loop for i from 1
106 | for x in outputs
107 | collect
108 | (append x (list :output_type "pyout" :prompt_number i))))
109 | (outputs-display-data
110 | (mapcar (lambda (x) (append '(:output_type "display_data") x))
111 | outputs))
112 | (regexp-pyout
113 | (ein:join-str
114 | ""
115 | (loop for i from 1
116 | for x in regexps
117 | collect (format "Out \\[%s\\]:\n%s\n" i x))))
118 | (regexp-display-data
119 | (concat (ein:join-str "\n" regexps) "\n")))
120 | `(progn
121 | (ert-deftest ,test-pyout ()
122 | (eintest:cell-insert-output ',outputs-pyout
123 | ,regexp-pyout))
124 | (ert-deftest ,test-display-data ()
125 | (eintest:cell-insert-output ',outputs-display-data
126 | ,regexp-display-data)))))
127 |
128 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
129 | text ("some output") ((:text "some output")))
130 |
131 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
132 | latex
133 | ("some output \\\\LaTeX")
134 | ((:latex "some output \\LaTeX")))
135 |
136 | (when (image-type-available-p 'svg)
137 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
138 | svg
139 | (" ")
140 | ((:text "some output text" :svg ein:testing-example-svg))))
141 |
142 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
143 | html
144 | ("some output text")
145 | ((:text "some output text" :html "not shown")))
146 |
147 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
148 | javascript
149 | ("some output text")
150 | ((:text "some output text" :javascript "$.do.something()")))
151 |
152 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
153 | text-two
154 | ("first output text" "second output text")
155 | ((:text "first output text") (:text "second output text")))
156 |
157 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
158 | text-javascript
159 | ("first output text" "second output text")
160 | ((:text "first output text")
161 | (:text "second output text" :javascript "$.do.something()")))
162 |
163 | (when (image-type-available-p 'svg)
164 | (eintest:gene-test-cell-insert-output-pyout-and-display-data
165 | text-latex-svg
166 | ("first output text" "second output \\\\LaTeX" " ")
167 | ((:text "first output text")
168 | (:latex "second output \\LaTeX")
169 | (:text "some output text" :svg ein:testing-example-svg))))
170 |
171 |
172 | ;; Insert pyerr
173 |
174 | (ert-deftest ein:cell-insert-output-pyerr-simple ()
175 | (eintest:cell-insert-output
176 | (list (list :output_type "pyerr"
177 | :traceback '("some traceback 1"
178 | "some traceback 2")))
179 | "\
180 | some traceback 1
181 | some traceback 2
182 | "))
183 |
184 |
185 | ;; Insert stream
186 |
187 | (ert-deftest ein:cell-insert-output-stream-simple-stdout ()
188 | (eintest:cell-insert-output
189 | (list (list :output_type "stream"
190 | :stream "stdout"
191 | :text "some stdout 1"))
192 | "\
193 | some stdout 1
194 | "))
195 |
196 | (ert-deftest ein:cell-insert-output-stream-stdout-stderr ()
197 | (eintest:cell-insert-output
198 | (list (list :output_type "stream"
199 | :stream "stdout"
200 | :text "some stdout 1")
201 | (list :output_type "stream"
202 | :stream "stderr"
203 | :text "some stderr 1"))
204 | "\
205 | some stdout 1
206 | some stderr 1
207 | "))
208 |
209 | (ert-deftest ein:cell-insert-output-stream-flushed-stdout ()
210 | (eintest:cell-insert-output
211 | (list (list :output_type "stream"
212 | :stream "stdout"
213 | :text "some stdout 1")
214 | (list :output_type "stream"
215 | :stream "stdout"
216 | :text "some stdout 2"))
217 | "\
218 | some stdout 1some stdout 2
219 | "))
220 |
221 | (ert-deftest ein:cell-insert-output-stream-flushed-stdout-and-stderr ()
222 | (eintest:cell-insert-output
223 | (list (list :output_type "stream"
224 | :stream "stdout"
225 | :text "some stdout 1")
226 | (list :output_type "stream"
227 | :stream "stderr"
228 | :text "some stderr 1")
229 | (list :output_type "stream"
230 | :stream "stdout"
231 | :text "some stdout 2")
232 | (list :output_type "stream"
233 | :stream "stderr"
234 | :text "some stderr 2"))
235 | "\
236 | some stdout 1
237 | some stderr 1
238 | some stdout 2
239 | some stderr 2
240 | "))
241 |
--------------------------------------------------------------------------------
/doc/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Emacs IPython Notebook documentation build configuration file, created by
4 | # sphinx-quickstart on Sun Jun 10 13:37:13 2012.
5 | #
6 | # This file is execfile()d with the current directory set to its containing dir.
7 | #
8 | # Note that not all possible configuration values are present in this
9 | # autogenerated file.
10 | #
11 | # All configuration values have a default; values that are commented out
12 | # serve to show the default.
13 |
14 | import sys, os
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | sys.path.insert(0, os.path.join(os.path.abspath('..'), 'eldomain'))
20 |
21 | # -- General configuration -----------------------------------------------------
22 |
23 | # If your documentation needs a minimal Sphinx version, state it here.
24 | #needs_sphinx = '1.0'
25 |
26 | # Add any Sphinx extension module names here, as strings. They can be extensions
27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28 | extensions = [
29 | 'sphinx.ext.todo',
30 | 'eldomain',
31 | ]
32 |
33 | # Add any paths that contain templates here, relative to this directory.
34 | templates_path = ['_templates']
35 |
36 | # The suffix of source filenames.
37 | source_suffix = '.rst'
38 |
39 | # The encoding of source files.
40 | #source_encoding = 'utf-8-sig'
41 |
42 | # The master toctree document.
43 | master_doc = 'index'
44 |
45 | # General information about the project.
46 | project = u'Emacs IPython Notebook'
47 | copyright = u'2012, Takafumi Arakaki'
48 |
49 | # The version info for the project you're documenting, acts as replacement for
50 | # |version| and |release|, also used in various other places throughout the
51 | # built documents.
52 | #
53 | # The short X.Y version.
54 | version = '0.2.1'
55 | # The full version, including alpha/beta/rc tags.
56 | release = '0.2.1alpha2'
57 |
58 | # The language for content autogenerated by Sphinx. Refer to documentation
59 | # for a list of supported languages.
60 | #language = None
61 |
62 | # There are two options for replacing |today|: either, you set today to some
63 | # non-false value, then it is used:
64 | #today = ''
65 | # Else, today_fmt is used as the format for a strftime call.
66 | #today_fmt = '%B %d, %Y'
67 |
68 | # List of patterns, relative to source directory, that match files and
69 | # directories to ignore when looking for source files.
70 | exclude_patterns = []
71 |
72 | # The reST default role (used for this markup: `text`) to use for all documents.
73 | #default_role = None
74 |
75 | # If true, '()' will be appended to :func: etc. cross-reference text.
76 | #add_function_parentheses = True
77 |
78 | # If true, the current module name will be prepended to all description
79 | # unit titles (such as .. function::).
80 | #add_module_names = True
81 |
82 | # If true, sectionauthor and moduleauthor directives will be shown in the
83 | # output. They are ignored by default.
84 | #show_authors = False
85 |
86 | # The name of the Pygments (syntax highlighting) style to use.
87 | pygments_style = 'sphinx'
88 |
89 | # A list of ignored prefixes for module index sorting.
90 | #modindex_common_prefix = []
91 |
92 | highlight_language = 'cl'
93 |
94 | # -- Options for HTML output ---------------------------------------------------
95 |
96 | # The theme to use for HTML and HTML Help pages. See the documentation for
97 | # a list of builtin themes.
98 | html_theme = 'nature'
99 |
100 | # Theme options are theme-specific and customize the look and feel of a theme
101 | # further. For a list of options available for each theme, see the
102 | # documentation.
103 | html_theme_options = {
104 | 'nosidebar': True,
105 | }
106 |
107 | # Add any paths that contain custom themes here, relative to this directory.
108 | #html_theme_path = []
109 |
110 | # The name for this set of Sphinx documents. If None, it defaults to
111 | # " v documentation".
112 | #html_title = None
113 |
114 | # A shorter title for the navigation bar. Default is the same as html_title.
115 | #html_short_title = None
116 |
117 | # The name of an image file (relative to this directory) to place at the top
118 | # of the sidebar.
119 | #html_logo = None
120 |
121 | # The name of an image file (within the static path) to use as favicon of the
122 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
123 | # pixels large.
124 | #html_favicon = None
125 |
126 | # Add any paths that contain custom static files (such as style sheets) here,
127 | # relative to this directory. They are copied after the builtin static files,
128 | # so a file named "default.css" will overwrite the builtin "default.css".
129 | #html_static_path = ['_static']
130 |
131 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
132 | # using the given strftime format.
133 | #html_last_updated_fmt = '%b %d, %Y'
134 |
135 | # If true, SmartyPants will be used to convert quotes and dashes to
136 | # typographically correct entities.
137 | #html_use_smartypants = True
138 |
139 | # Custom sidebar templates, maps document names to template names.
140 | #html_sidebars = {}
141 |
142 | # Additional templates that should be rendered to pages, maps page names to
143 | # template names.
144 | #html_additional_pages = {}
145 |
146 | # If false, no module index is generated.
147 | #html_domain_indices = True
148 |
149 | # If false, no index is generated.
150 | #html_use_index = True
151 |
152 | # If true, the index is split into individual pages for each letter.
153 | #html_split_index = False
154 |
155 | # If true, links to the reST sources are added to the pages.
156 | #html_show_sourcelink = True
157 |
158 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
159 | #html_show_sphinx = True
160 |
161 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
162 | #html_show_copyright = True
163 |
164 | # If true, an OpenSearch description file will be output, and all pages will
165 | # contain a tag referring to it. The value of this option must be the
166 | # base URL from which the finished HTML is served.
167 | #html_use_opensearch = ''
168 |
169 | # This is the file name suffix for HTML files (e.g. ".xhtml").
170 | #html_file_suffix = None
171 |
172 | # Output file base name for HTML help builder.
173 | htmlhelp_basename = 'EmacsIPythonNotebookdoc'
174 |
175 |
176 | # -- Options for LaTeX output --------------------------------------------------
177 |
178 | latex_elements = {
179 | # The paper size ('letterpaper' or 'a4paper').
180 | #'papersize': 'letterpaper',
181 |
182 | # The font size ('10pt', '11pt' or '12pt').
183 | #'pointsize': '10pt',
184 |
185 | # Additional stuff for the LaTeX preamble.
186 | #'preamble': '',
187 | }
188 |
189 | # Grouping the document tree into LaTeX files. List of tuples
190 | # (source start file, target name, title, author, documentclass [howto/manual]).
191 | latex_documents = [
192 | ('index', 'EmacsIPythonNotebook.tex', u'Emacs IPython Notebook Documentation',
193 | u'Takafumi Arakaki', 'manual'),
194 | ]
195 |
196 | # The name of an image file (relative to this directory) to place at the top of
197 | # the title page.
198 | #latex_logo = None
199 |
200 | # For "manual" documents, if this is true, then toplevel headings are parts,
201 | # not chapters.
202 | #latex_use_parts = False
203 |
204 | # If true, show page references after internal links.
205 | #latex_show_pagerefs = False
206 |
207 | # If true, show URL addresses after external links.
208 | #latex_show_urls = False
209 |
210 | # Documents to append as an appendix to all manuals.
211 | #latex_appendices = []
212 |
213 | # If false, no module index is generated.
214 | #latex_domain_indices = True
215 |
216 |
217 | # -- Options for manual page output --------------------------------------------
218 |
219 | # One entry per manual page. List of tuples
220 | # (source start file, name, description, authors, manual section).
221 | man_pages = [
222 | ('index', 'emacsipythonnotebook', u'Emacs IPython Notebook Documentation',
223 | [u'Takafumi Arakaki'], 1)
224 | ]
225 |
226 | # If true, show URL addresses after external links.
227 | #man_show_urls = False
228 |
229 |
230 | # -- Options for Texinfo output ------------------------------------------------
231 |
232 | # Grouping the document tree into Texinfo files. List of tuples
233 | # (source start file, target name, title, author,
234 | # dir menu entry, description, category)
235 | texinfo_documents = [
236 | ('index', 'EmacsIPythonNotebook', u'Emacs IPython Notebook Documentation',
237 | u'Takafumi Arakaki', 'EmacsIPythonNotebook', 'One line description of project.',
238 | 'Miscellaneous'),
239 | ]
240 |
241 | # Documents to append as an appendix to all manuals.
242 | #texinfo_appendices = []
243 |
244 | # If false, no module index is generated.
245 | #texinfo_domain_indices = True
246 |
247 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
248 | #texinfo_show_urls = 'footnote'
249 |
250 |
251 | # -- Options for EL domain -----------------------------------------------------
252 |
253 | elisp_packages = {
254 | 'ein': 'ein:',
255 | 'helm': 'helm-',
256 | 'anything': 'anything-',
257 | }
258 |
--------------------------------------------------------------------------------
/lisp/ein-mumamo.el:
--------------------------------------------------------------------------------
1 | ;;; ein-mumamo.el --- MuMaMo for notebook
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-mumamo.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-mumamo.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-mumamo.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (require 'mumamo)
29 |
30 | (require 'ein-worksheet)
31 |
32 |
33 |
34 | ;;; Customization
35 |
36 | (defcustom ein:mumamo-codecell-mode 'python-mode
37 | "Major Mode for Code Cell."
38 | :type '(symbol :tag "Major Mode")
39 | :group 'ein)
40 |
41 | (defcustom ein:mumamo-textcell-mode 'text-mode
42 | "Major Mode for Text Cell."
43 | :type '(symbol :tag "Major Mode")
44 | :group 'ein)
45 |
46 | (defcustom ein:mumamo-htmlcell-mode 'html-mode
47 | "Major Mode for HTML Cell."
48 | :type '(symbol :tag "Major Mode")
49 | :group 'ein)
50 |
51 | (defcustom ein:mumamo-markdowncell-mode 'markdown-mode
52 | "Major Mode for Markdown Cell."
53 | :type '(symbol :tag "Major Mode")
54 | :group 'ein)
55 |
56 | (defcustom ein:mumamo-rawcell-mode 'rst-mode
57 | "Major Mode for Raw Cell."
58 | :type '(symbol :tag "Major Mode")
59 | :group 'ein)
60 |
61 | (defcustom ein:mumamo-headingcell-mode 'text-mode
62 | "Major Mode for Heading Cell."
63 | :type '(symbol :tag "Major Mode")
64 | :group 'ein)
65 |
66 | (defcustom ein:mumamo-fallback-mode 'text-mode
67 | "Fallback Major Mode."
68 | :type '(symbol :tag "Major Mode")
69 | :group 'ein)
70 |
71 | (defcustom ein:use-mumamo-indent-line-function-workaround t
72 | "Turn on workaround for `mumamo-indent-line-function'.
73 |
74 | In code cell, hitting TAB or C-j at the end of input area causes
75 | error from MuMaMo. When this variable is non-`nil', EIN patches
76 | `mumamo-indent-line-function' to workaround this problem. This
77 | workaround is on by default.
78 |
79 | Note that python-mode's indentation function has other problems
80 | with MuMaMo. For example, hitting TAB twice, which decreases the
81 | indentation level by one in normal Python buffer, causes similar
82 | error in code cell. The current workaround does not fix this
83 | problem."
84 | :type 'boolean
85 | :group 'ein)
86 |
87 | (defcustom ein:mumamo-indent-line-function-dummy-code "
88 | def ein_dummy():
89 | return"
90 | "Dummy code block for `mumamo-indent-line-function' workaround.
91 | This code block will be inserted at the end of cell input before
92 | indentation and then removed afterward (so user will not see this
93 | code).
94 |
95 | This is ugly but... \"practicality beats purity\"...
96 | I guess somebody should fix python.el and/or MuMaMo, in order to
97 | remove this ugliness.
98 |
99 | To make the workaround less aggressive, you can set a newline
100 | \"\\n\" for this variable. In that case, you will be affected by
101 | `issue 24`_.
102 |
103 | .. _issue 24: https://github.com/tkf/emacs-ipython-notebook/issues/24"
104 | :type 'boolean
105 | :group 'ein)
106 |
107 |
108 |
109 | ;;; Workaround
110 |
111 | (defadvice mumamo-indent-line-function
112 | (around ein:mumamo-indent-line-function-workaround)
113 | "Workaround the indentation problem when the cursor is in the
114 | code cell."
115 | (let ((cell (ein:worksheet-get-current-cell)))
116 | ;; Check if the current buffer is notebook AND the current cell is
117 | ;; code cell.
118 | (if (ein:codecell-p cell)
119 | (let ((cur (copy-marker (point)))
120 | (end (copy-marker (1+ (ein:cell-input-pos-max cell)))))
121 | ;; v-- execute `delete-char' here
122 | ;; ... [] ......DUMMY
123 | ;; ^- cur ^- end (non-inclusive end of cell)
124 | ;; ^- `ad-do-it' here
125 | (unwind-protect
126 | (progn
127 | (goto-char (1- end))
128 | (insert ein:mumamo-indent-line-function-dummy-code)
129 | (goto-char cur)
130 | ad-do-it)
131 | (save-excursion
132 | (let ((len (length ein:mumamo-indent-line-function-dummy-code)))
133 | (goto-char (- end 1 len))
134 | (delete-char len)))))
135 | ad-do-it)))
136 |
137 | (defun ein:mumamo-indent-line-function-workaround-turn-on ()
138 | "Activate advice for `mumamo-indent-line-function'.
139 | Called via `ein:notebook-mumamo-mode-hook'."
140 | (when ein:use-mumamo-indent-line-function-workaround
141 | (ad-enable-advice 'mumamo-indent-line-function 'around
142 | 'ein:mumamo-indent-line-function-workaround)
143 | (ad-activate 'mumamo-indent-line-function)))
144 |
145 | (defun ein:mumamo-imenu-setup-maybe ()
146 | "Set `imenu-create-index-function' if the current buffer is the
147 | notebook buffer.
148 | This function is called via `after-change-major-mode-hook', to set
149 | the variable every time visiting the different chunks.
150 |
151 | .. note:: Making `imenu-create-index-function' permanent-local
152 | also solves the problem. However, this will make the variable
153 | permanent-local in *any* buffer, including the buffers
154 | irrelevant to EIN. Therefore, the current approach is taken.
155 |
156 | This is the same workaround as `ein:ac-setup-maybe'."
157 | (when (ein:worksheet-buffer-p)
158 | (ein:worksheet-imenu-setup)))
159 |
160 | (add-hook 'after-change-major-mode-hook 'ein:mumamo-imenu-setup-maybe)
161 |
162 |
163 |
164 | ;;; `ein:notebook-mumamo-mode'
165 |
166 | (define-derived-mode ein:notebook-bg-mode fundamental-mode "ein:bg"
167 | "Background mode for `ein:notebook-mumamo-mode'."
168 | (setq font-lock-defaults '(nil t))
169 | (font-lock-mode))
170 |
171 | (define-mumamo-multi-major-mode ein:notebook-mumamo-mode
172 | "IPython notebook mode."
173 | ("IPython notebook familiy" ein:notebook-bg-mode
174 | (ein:mumamo-chunk-codecell
175 | ein:mumamo-chunk-textcell
176 | ein:mumamo-chunk-htmlcell
177 | ein:mumamo-chunk-markdowncell
178 | ein:mumamo-chunk-rawcell
179 | ein:mumamo-chunk-headingcell
180 | )))
181 |
182 | (add-hook 'ein:notebook-mumamo-mode-hook
183 | 'ein:mumamo-indent-line-function-workaround-turn-on)
184 |
185 |
186 |
187 | ;;; Chunk functions
188 |
189 | (defmacro ein:mumamo-define-chunk (name)
190 | (let ((funcname (intern (format "ein:mumamo-chunk-%s" name)))
191 | (mode (intern (format "ein:mumamo-%s-mode" name)))
192 | (cell-p (intern (format "ein:%s-p" name))))
193 | `(defun ,funcname (pos max)
194 | (mumamo-possible-chunk-forward
195 | pos max
196 | (lambda (pos max) "CHUNK-START-FUN"
197 | (ein:log 'blather "CHUNK-START-FUN(pos=%s max=%s)" pos max)
198 | (ein:aif (ein:mumamo-find-edge pos max nil #',cell-p)
199 | (list it (if (functionp ,mode)
200 | ,mode
201 | ein:mumamo-fallback-mode)
202 | nil)))
203 | (lambda (pos max) "CHUNK-END-FUN"
204 | (ein:log 'blather "CHUNK-END-FUN(pos=%s max=%s)" pos max)
205 | (ein:mumamo-find-edge pos max t #',cell-p))))))
206 |
207 | (ein:mumamo-define-chunk codecell)
208 | (ein:mumamo-define-chunk textcell)
209 | (ein:mumamo-define-chunk htmlcell)
210 | (ein:mumamo-define-chunk markdowncell)
211 | (ein:mumamo-define-chunk rawcell)
212 | (ein:mumamo-define-chunk headingcell)
213 |
214 | (defun ein:mumamo-find-edge (pos max end cell-p)
215 | "Helper function for `ein:mumamo-chunk-codecell'.
216 |
217 | Return the point of beginning of the input element of cell after
218 | the point POS. Return `nil' if it cannot be found before the point
219 | MAX. If END is non-`nil', end of the input element is returned."
220 | (ein:log 'blather "EIN:MUMAMO-FIND-EDGE(pos=%s max=%s end=%s cell-p=%s)"
221 | pos max end cell-p)
222 | (let* ((ewoc-node
223 | (ein:worksheet-get-nearest-cell-ewoc-node pos max cell-p))
224 | (_ (ein:log 'blather "(null ewoc-node) = %s" (null ewoc-node)))
225 | (cell (ein:aand ewoc-node
226 | (ein:$node-data (ewoc-data it))))
227 | (_ (ein:log 'blather "(null cell) = %s" (null cell)))
228 | (find
229 | (lambda (c)
230 | (ein:aand c
231 | (ein:cell-element-get it (if end :after-input :input))
232 | (progn
233 | (ein:log 'blather "(null it) = %s" (null it))
234 | (ewoc-location it))
235 | (if end it (1+ it)))))
236 | (input-pos (funcall find cell)))
237 | (ein:log 'blather "input-pos (1) = %s" input-pos)
238 | (when (and input-pos (< input-pos pos))
239 | (setq input-pos (ein:aand (ein:cell-next cell)
240 | (when (funcall cell-p it) (funcall find it)))))
241 | (ein:log 'blather "input-pos (2) = %s" input-pos)
242 | (when (and input-pos (> input-pos max))
243 | (setq input-pos nil))
244 | (ein:log 'blather "input-pos (3) = %s" input-pos)
245 | input-pos))
246 |
247 | (provide 'ein-mumamo)
248 |
249 | ;;; ein-mumamo.el ends here
250 |
--------------------------------------------------------------------------------
/lisp/ein-ac.el:
--------------------------------------------------------------------------------
1 | ;;; ein-ac.el --- Auto-complete extension
2 |
3 | ;; Copyright (C) 2012- Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-ac.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-ac.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-ac.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 | (eval-when-compile (require 'cl))
29 | (require 'auto-complete nil t)
30 |
31 | (require 'ein-core)
32 | (eval-when-compile (require 'ein-notebook)
33 | (defvar ein:mumamo-codecell-mode))
34 |
35 |
36 | ;;; Configuration
37 |
38 | (defvar ein:ac-sources (and (boundp 'ac-sources)
39 | (default-value 'ac-sources))
40 | "Extra `ac-sources' used in notebook.")
41 |
42 | (make-obsolete-variable 'ein:ac-max-cache nil "0.1.2")
43 | (defcustom ein:ac-max-cache 1000
44 | "[This value is not used anymore!]
45 | Maximum number of cache to store."
46 | :type 'integer
47 | :group 'ein)
48 |
49 |
50 | ;;; Chunk (adapted from auto-complete-chunk.el)
51 |
52 | (defvar ein:ac-chunk-regex
53 | (rx (group (| (syntax whitespace)
54 | (syntax open-parenthesis)
55 | (syntax close-parenthesis)
56 | (syntax string-quote) ; Complete files for `open("path/..`
57 | bol))
58 | (? (syntax punctuation)) ; to complete ``~/PATH/...``
59 | (* (+ (| (syntax word) (syntax symbol)))
60 | (syntax punctuation))
61 | (+ (| (syntax word) (syntax symbol)))
62 | (? (syntax punctuation))
63 | point)
64 | "A regexp that matches to a \"chunk\" containing words and dots.")
65 |
66 | (defun ein:ac-chunk-beginning ()
67 | "Return the position where the chunk begins."
68 | (ignore-errors
69 | (save-excursion
70 | (+ (re-search-backward ein:ac-chunk-regex) (length (match-string 1))))))
71 |
72 | (defun ein:ac-chunk-candidates-from-list (chunk-list)
73 | "Return matched candidates in CHUNK-LIST."
74 | (let* ((start (ein:ac-chunk-beginning)))
75 | (when start
76 | (loop with prefix = (buffer-substring start (point))
77 | for cc in chunk-list
78 | when (string-prefix-p prefix cc)
79 | collect cc))))
80 |
81 |
82 | ;;; AC Source
83 |
84 | (defvar ein:ac-direct-matches nil
85 | "Variable to store completion candidates for `auto-completion'.")
86 | ;; FIXME: Maybe this should be buffer-local?
87 |
88 | (defun ein:ac-direct-get-matches ()
89 | (ein:ac-chunk-candidates-from-list ein:ac-direct-matches))
90 |
91 | (ac-define-source ein-direct
92 | '((candidates . ein:ac-direct-get-matches)
93 | (requires . 0)
94 | (prefix . ein:ac-chunk-beginning)
95 | (symbol . "s")))
96 |
97 | (ac-define-source ein-async
98 | '((candidates . ein:ac-direct-get-matches)
99 | (requires . 0)
100 | (prefix . ein:ac-chunk-beginning)
101 | (init . ein:ac-request-in-background)
102 | (symbol . "c")))
103 |
104 | (define-obsolete-function-alias 'ac-complete-ein-cached 'ac-complete-ein-async
105 | "0.2.1")
106 | (define-obsolete-variable-alias 'ac-source-ein-cached 'ac-source-ein-async
107 | "0.2.1")
108 |
109 | (defun ein:ac-request-in-background ()
110 | (ein:and-let* ((kernel (ein:get-kernel))
111 | ((ein:kernel-live-p kernel)))
112 | (ein:completer-complete
113 | kernel
114 | :callbacks
115 | (list :complete_reply
116 | (cons (lambda (_ content __)
117 | (ein:ac-prepare-completion (plist-get content :matches)))
118 | nil)))))
119 |
120 |
121 | ;;; Completer interface
122 |
123 | (defun ein:ac-prepare-completion (matches)
124 | "Prepare `ac-source-ein-direct' using MATCHES from kernel.
125 | Call this function before calling `auto-complete'."
126 | (when matches
127 | (setq ein:ac-direct-matches matches))) ; let-binding won't work
128 |
129 | (defun* ein:completer-finish-completing-ac
130 | (matched-text
131 | matches
132 | &key (expand ac-expand-on-auto-complete)
133 | &allow-other-keys)
134 | "Invoke completion using `auto-complete'.
135 | Only the argument MATCHES is used. MATCHED-TEXT is for
136 | compatibility with `ein:completer-finish-completing-default'."
137 | ;; I don't need to check if the point is at right position, as in
138 | ;; `ein:completer-finish-completing-default' because `auto-complete'
139 | ;; checks it anyway.
140 | (ein:log 'debug "COMPLETER-FINISH-COMPLETING-AC: matched-text=%S matches=%S"
141 | matched-text matches)
142 | (ein:ac-prepare-completion matches)
143 | (when matches ; No auto-complete drop-down list when no matches
144 | (let ((ac-expand-on-auto-complete expand))
145 | (ac-start))))
146 | ;; Why `ac-start'? See: `jedi:complete'.
147 |
148 |
149 | ;;; Async document request hack
150 |
151 | (defun ein:ac-request-document-for-selected-candidate ()
152 | "Request object information for the candidate at point.
153 | This is called via `ac-next'/`ac-previous'/`ac-update' and set
154 | `document' property of the current candidate string. If server
155 | replied within `ac-quick-help-delay' seconds, auto-complete will
156 | popup help string."
157 | (let* ((candidate (ac-selected-candidate))
158 | (kernel (ein:get-kernel))
159 | (callbacks (list :object_info_reply
160 | (cons #'ein:ac-set-document candidate))))
161 | (when (and candidate
162 | (ein:kernel-live-p kernel)
163 | (not (get-text-property 0 'document candidate)))
164 | (ein:log 'debug "Requesting object info for AC candidate %S"
165 | candidate)
166 | (ein:kernel-object-info-request kernel candidate callbacks))))
167 |
168 | (defun ein:ac-set-document (candidate content -metadata-not-used-)
169 | (ein:log 'debug "EIN:AC-SET-DOCUMENT candidate=%S content=%S"
170 | candidate content)
171 | (put-text-property 0 (length candidate)
172 | 'document (ein:kernel-construct-help-string content)
173 | candidate))
174 |
175 | (defadvice ac-next (after ein:ac-next-request)
176 | "Monkey patch `auto-complete' internal function to request
177 | help documentation asynchronously."
178 | (ein:ac-request-document-for-selected-candidate))
179 |
180 | (defadvice ac-previous (after ein:ac-previous-request)
181 | "Monkey patch `auto-complete' internal function to request
182 | help documentation asynchronously."
183 | (ein:ac-request-document-for-selected-candidate))
184 |
185 | (defadvice ac-update (after ein:ac-update-request)
186 | "Monkey patch `auto-complete' internal function to request help
187 | documentation asynchronously. This will request info for the
188 | first candidate when the `ac-menu' pops up."
189 | (ein:ac-request-document-for-selected-candidate))
190 |
191 |
192 | ;;; Setup
193 |
194 | (defun ein:ac-superpack ()
195 | "Enable richer auto-completion.
196 |
197 | * Enable auto-completion help by monkey patching `ac-next'/`ac-previous'"
198 | (interactive)
199 | (ad-enable-advice 'ac-next 'after 'ein:ac-next-request)
200 | (ad-enable-advice 'ac-previous 'after 'ein:ac-previous-request)
201 | (ad-enable-advice 'ac-update 'after 'ein:ac-update-request)
202 | (ad-activate 'ac-next)
203 | (ad-activate 'ac-previous)
204 | (ad-activate 'ac-update))
205 |
206 | (defun ein:ac-setup ()
207 | "Call this function from mode hook (see `ein:ac-config')."
208 | (setq ac-sources (append '(ac-source-ein-async) ein:ac-sources)))
209 |
210 | (defun ein:ac-setup-maybe ()
211 | "Setup `ac-sources' for mumamo.
212 |
213 | .. note:: Setting `ein:notebook-mumamo-mode-hook' does not work
214 | because `ac-sources' in `ein:notebook-mumamo-mode'-enabled
215 | buffer is *chunk local*, rather than buffer local.
216 |
217 | Making `ac-sources' permanent-local also addresses issue of
218 | MuMaMo discarding `ac-sources'. However, it effects to entire
219 | Emacs setting. So this is not the right way to do it.
220 |
221 | Using `mumamo-make-variable-buffer-permanent' (i.e., adding
222 | `ac-sources' to `mumamo-per-buffer-local-vars' or
223 | `mumamo-per-main-major-local-vars') is also not appropriate.
224 | Adding `ac-sources' to them makes it impossible to different
225 | `ac-sources' between chunks, which is good for EIN but may not
226 | for other package."
227 | (and ein:%notebook%
228 | (ein:eval-if-bound 'ein:notebook-mumamo-mode)
229 | (eql major-mode ein:mumamo-codecell-mode)
230 | (ein:ac-setup)))
231 |
232 | (defun ein:ac-config (&optional superpack)
233 | "Install auto-complete-mode for notebook modes.
234 | Specifying non-`nil' to SUPERPACK enables richer auto-completion
235 | \(see `ein:ac-superpack')."
236 | (add-hook 'after-change-major-mode-hook 'ein:ac-setup-maybe)
237 | (add-hook 'ein:notebook-mode-hook 'ein:ac-setup)
238 | (when superpack
239 | (ein:ac-superpack)))
240 |
241 |
242 | (defvar ein:ac-config-once-called nil)
243 |
244 | (defun ein:ac-config-once (&optional superpack)
245 | (unless ein:ac-config-once-called
246 | (setq ein:ac-config-once-called t)
247 | (ein:ac-config superpack)))
248 |
249 | (provide 'ein-ac)
250 |
251 | ;;; ein-ac.el ends here
252 |
--------------------------------------------------------------------------------
/lisp/ein-console.el:
--------------------------------------------------------------------------------
1 | ;;; ein-console.el --- IPython console integration
2 |
3 | ;; Copyright (C) 2012 Takafumi Arakaki
4 |
5 | ;; Author: Takafumi Arakaki
6 |
7 | ;; This file is NOT part of GNU Emacs.
8 |
9 | ;; ein-console.el is free software: you can redistribute it and/or modify
10 | ;; it under the terms of the GNU General Public License as published by
11 | ;; the Free Software Foundation, either version 3 of the License, or
12 | ;; (at your option) any later version.
13 |
14 | ;; ein-console.el is distributed in the hope that it will be useful,
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | ;; GNU General Public License for more details.
18 |
19 | ;; You should have received a copy of the GNU General Public License
20 | ;; along with ein-console.el. If not, see .
21 |
22 | ;;; Commentary:
23 |
24 | ;;
25 |
26 | ;;; Code:
27 |
28 |
29 | (require 'ein-core)
30 |
31 | ;; Functions from `Fabian Gallina's python.el`_
32 | ;; NOTE: Do *not* load python.el here, since user may be using the other
33 | ;; version of python-mode.
34 | (declare-function python-shell-make-comint "python")
35 | (declare-function python-shell-get-process-name "python")
36 | (declare-function python-shell-switch-to-shell "python")
37 |
38 |
39 |
40 | ;;; Define aliases to old variables and functions.
41 |
42 | (define-obsolete-variable-alias
43 | 'ein:notebook-console-security-dir 'ein:console-security-dir "0.1.2")
44 | (define-obsolete-variable-alias
45 | 'ein:notebook-console-executable 'ein:console-executable "0.1.2")
46 | (define-obsolete-variable-alias
47 | 'ein:notebook-console-args 'ein:console-args "0.1.2")
48 | (define-obsolete-function-alias
49 | 'ein:notebook-console-open 'ein:console-open "0.1.2")
50 |
51 |
52 | ;;; Configuration
53 |
54 | (defcustom ein:console-security-dir ""
55 | "Security directory setting.
56 |
57 | Following types are valid:
58 |
59 | string
60 | Use this value as a path to security directory.
61 | Handy when you have only one IPython server.
62 | alist
63 | An alist whose element is \"(URL-OR-PORT . DIR)\".
64 | Key (URL-OR-PORT) can be string (URL), integer (port), or
65 | `default' (symbol). The value of `default' is used when
66 | other key does not much. Normally you should have this
67 | entry.
68 | function
69 | Called with an argument URL-OR-PORT (integer or string).
70 | You can have complex setting using this."
71 | :type '(choice
72 | (string :tag "Security directory"
73 | "~/.config/ipython/profile_nbserver/security/")
74 | (alist :tag "Security directory mapping"
75 | :key-type (choice :tag "URL or PORT"
76 | (string :tag "URL" "http://127.0.0.1:8888")
77 | (integer :tag "PORT" 8888)
78 | (const default))
79 | :value-type (string :tag "Security directory"))
80 | (function :tag "Security directory getter"
81 | (lambda (url-or-port)
82 | (format "~/.config/ipython/profile_%s/security/"
83 | url-or-port))))
84 | :group 'ein)
85 |
86 | (defcustom ein:console-executable (executable-find "ipython")
87 | "IPython executable used for console.
88 |
89 | Example: ``\"/user/bin/ipython\"``.
90 | Types same as `ein:console-security-dir' are valid."
91 | :type '(choice
92 | (string :tag "IPython executable" "/user/bin/ipython")
93 | (alist :tag "IPython executable mapping"
94 | :key-type (choice :tag "URL or PORT"
95 | (string :tag "URL" "http://127.0.0.1:8888")
96 | (integer :tag "PORT" 8888)
97 | (const default))
98 | :value-type (string :tag "IPython executable"
99 | "/user/bin/ipython"))
100 | (function :tag "IPython executable getter"
101 | (lambda (url-or-port) (executable-find "ipython"))))
102 | :group 'ein)
103 |
104 | (defcustom ein:console-args '("--profile" "nbserver")
105 | "Additional argument when using console.
106 |
107 | .. warning:: Space-separated string is obsolete now. Use a list
108 | of string as value now.
109 |
110 | Setting to use IPython profile named \"YOUR-IPYTHON-PROFILE\"::
111 |
112 | (setq ein:console-args '(\"--profile\" \"YOUR-IPYTHON-PROFILE\"))
113 |
114 | Together with `ein:console-security-dir', you can open IPython
115 | console connecting to a remote kernel.::
116 |
117 | (setq ein:console-args '(\"--ssh\" \"HOSTNAME\"))
118 | (setq ein:console-security-dir \"PATH/TO/SECURITY/DIR\")
119 |
120 | You can setup `ein:console-args' per server basis using alist form::
121 |
122 | (setq ein:console-args
123 | '((8888 . '(\"--profile\" \"PROFILE\"))
124 | (8889 . '(\"--ssh\" \"HOSTNAME\"))
125 | (default . '(\"--profile\" \"default\"))))
126 |
127 | If you want to use more complex setting, you can set a function to it::
128 |
129 | (setq ein:console-args
130 | (lambda (url-or-port) '(\"--ssh\" \"HOSTNAME\")))
131 |
132 | See also: `ein:console-security-dir'."
133 | :type '(choice
134 | (repeat (string :tag "Arguments to IPython" "--profile"))
135 | (alist :tag "Arguments mapping"
136 | :key-type (choice :tag "URL or PORT"
137 | (string :tag "URL" "http://127.0.0.1:8888")
138 | (integer :tag "PORT" 8888)
139 | (const default))
140 | :value-type
141 | (repeat (string :tag "Arguments to IPython" "--profile")))
142 | (function :tag "Additional arguments getter"
143 | (lambda (url-or-port)
144 | (list "--ssh" (format "%s" url-or-port)))))
145 | :group 'ein)
146 |
147 | (defun ein:console-security-dir-get (url-or-port)
148 | (let ((dir (ein:choose-setting 'ein:console-security-dir url-or-port)))
149 | (if (equal dir "")
150 | dir
151 | (file-name-as-directory (expand-file-name dir)))))
152 |
153 | (defun ein:console-executable-get (url-or-port)
154 | (ein:choose-setting 'ein:console-executable url-or-port))
155 |
156 | (defun ein:console-args-get (url-or-port)
157 | (ein:choose-setting 'ein:console-args url-or-port
158 | (lambda (x)
159 | (or (stringp x)
160 | (and (listp x)
161 | (stringp (car x)))))))
162 |
163 | (defun ein:console-make-command ()
164 | ;; FIXME: use %connect_info to get connection file, then I can get
165 | ;; rid of `ein:console-security-dir'.
166 | (let* ((url-or-port (or (ein:get-url-or-port)
167 | (error "Cannot find notebook to connect!")))
168 | (dir (ein:console-security-dir-get url-or-port))
169 | (kid (ein:kernel-id (ein:get-kernel)))
170 | (ipy (ein:console-executable-get url-or-port))
171 | (args (ein:console-args-get url-or-port)))
172 | ;; FIMXE: do I need "python" here?
173 | (append (list "python" ipy "console" "--existing"
174 | (format "%skernel-%s.json" dir kid))
175 | (if (listp args)
176 | args
177 | (ein:display-warning-once
178 | "String value for `ein:console-args' is obsolete.
179 | Use list of string instead of space separated string.")
180 | (split-string-and-unquote args)))))
181 |
182 | (defun ein:console-get-buffer ()
183 | (let ((url-or-port (ein:get-url-or-port))
184 | (notebook (ein:get-notebook)))
185 | (format "*ein:console %s/%s*" url-or-port (ein:notebook-name notebook))))
186 |
187 | ;;;###autoload
188 | (defun ein:console-open ()
189 | "Open IPython console.
190 | To use this function, `ein:console-security-dir' and
191 | `ein:console-args' must be set properly.
192 | This function works best with the new python.el_ which is shipped
193 | with Emacs 24.2 or later. If you don't have it, this function
194 | opens a \"plain\" command line interpreter (comint) buffer where
195 | you cannot use fancy stuff such as TAB completion.
196 | It should be possible to support python-mode.el. Patches are welcome!
197 |
198 | .. _python.el: https://github.com/fgallina/python.el"
199 | (interactive)
200 | (if (fboundp 'python-shell-switch-to-shell)
201 | (let ((cmd (mapconcat #'shell-quote-argument
202 | (ein:console-make-command) " "))
203 | ;; python.el settings:
204 | (python-shell-setup-codes nil)
205 | ;; python.el makes dedicated process when
206 | ;; `buffer-file-name' has some value.
207 | (buffer-file-name (buffer-name)))
208 | ;; The following line does what `run-python' does.
209 | ;; But as `run-python' changed the call signature in the new
210 | ;; version, let's do this manually.
211 | ;; See also: https://github.com/tkf/emacs-ipython-notebook/pull/50
212 | (python-shell-make-comint cmd (python-shell-get-process-name t))
213 | ;; Pop to inferior Python process buffer
214 | (python-shell-switch-to-shell))
215 | (let* ((command (ein:console-make-command))
216 | (program (car command))
217 | (args (cdr command))
218 | (buffer (ein:console-get-buffer)))
219 | (apply #'make-comint-in-buffer
220 | "ein:console" buffer program nil args)
221 | (pop-to-buffer buffer))))
222 |
223 | (provide 'ein-console)
224 |
225 | ;;; ein-console.el ends here
226 |
--------------------------------------------------------------------------------