├── 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 | 37 | 38 | ") 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 | --------------------------------------------------------------------------------