Move EIN specific stuff to ein-core from ein-utils

This commit is contained in:
Takafumi Arakaki 2012-08-28 15:33:35 +02:00
parent ca8c1678fe
commit bf9d4f7b5d
2 changed files with 227 additions and 216 deletions

View file

@ -26,9 +26,236 @@
;;; Code:
(eval-when-compile (require 'cl))
;; Optional dependency on tramp:
(declare-function tramp-make-tramp-file-name "tramp")
(declare-function tramp-file-name-localname "tramp")
(declare-function tramp-dissect-file-name "tramp")
(require 'ein) ; get autoloaded functions into namespace
(require 'ein-utils)
(defgroup ein nil
"IPython notebook client in Emacs"
:group 'applications
:prefix "ein:")
;;; Configuration
(defcustom ein:url-or-port '(8888)
"List of default url-or-port values.
This will be used for completion. So put your IPython servers.
You can connect to servers not in this list \(but you will need
to type every time)."
:type '(repeat (choice (integer :tag "Port number" 8888)
(string :tag "URL" "http://127.0.0.1:8888")))
:group 'ein)
(defcustom ein:default-url-or-port nil
"Default URL or port. This should be your main IPython
Notebook server."
:type '(choice (integer :tag "Port number" 8888)
(string :tag "URL" "http://127.0.0.1:8888")
(const :tag "First value of `ein:url-or-port'" nil))
:group 'ein)
(defcustom ein:scratch-notebook-name-template "_scratch_%Y-%m-%d-%H%M%S_"
"Template of scratch notebook name.
This value is used from `ein:notebooklist-new-scratch-notebook'
and `ein:notebook-rename-to-scratch-command'. This must be a
format string which can be passed to `format-time-string'."
:type '(string :tag "Format string")
:group 'ein)
(defcustom ein:filename-translations nil
"Convert file paths between Emacs and Python process.
This value can take these form:
alist
Its key specifies URL-OR-PORT and value must be a list of two
functions: (TO-PYTHON FROM-PYTHON). Key (URL-OR-PORT) can be
string (URL), integer (port), or `default' (symbol). The
value of `default' is used when other key does not much.
function
Called with an argument URL-OR-PORT (integer or string).
This function must return a list of two functions:
(TO-PYTHON FROM-PYTHON).
Here, the functions TO-PYTHON and FROM-PYTHON are defined as:
TO-PYTHON
A function which converts a file name (returned by
`buffer-file-name') to the one Python understands.
FROM-PYTHON
A function which converts a file path returned by
Python process to the one Emacs understands.
Use `ein:tramp-create-filename-translator' to easily generate the
pair of TO-PYTHON and FROM-PYTHON."
;; I've got the idea from `slime-filename-translations'.
:type '(choice
(alist :tag "Translations mapping"
:key-type (choice :tag "URL or PORT"
(string :tag "URL" "http://127.0.0.1:8888")
(integer :tag "PORT" 8888)
(const default))
:value-type (list (function :tag "TO-PYTHON")
(function :tag "FROM-PYTHON")))
(function :tag "Translations getter"))
:group 'ein)
(defvar ein:source-dir (file-name-directory load-file-name))
;;; Configuration getter
(defun ein:default-url-or-port ()
(or ein:default-url-or-port (car ein:url-or-port) 8888))
(defun ein:scratch-notebook-name ()
"Generate new scratch notebook name based on `current-time' and
`ein:scratch-notebook-name-template'."
(format-time-string ein:scratch-notebook-name-template (current-time)))
;;; File name translation (tramp support)
;; Probably it's better to define `ein:filename-translations-get' as
;; an EIEIO method so that I don't have to re-define functions such as
;; `ein:kernel-filename-to-python' and `ein:kernel-filename-from-python'.
(defun ein:filename-translations-get (url-or-port)
(ein:choose-setting 'ein:filename-translations url-or-port))
(defun ein:filename-to-python (url-or-port filename)
(ein:aif (car (ein:filename-translations-get url-or-port))
(funcall it filename)
filename))
(defun ein:filename-from-python (url-or-port filename)
(ein:aif (cadr (ein:filename-translations-get url-or-port))
(funcall it filename)
filename))
(defun ein:make-tramp-file-name (username remote-host python-filename)
"Old (with multi-hops) tramp compatability function.
Adapted from `slime-make-tramp-file-name'."
(if (boundp 'tramp-multi-methods)
(tramp-make-tramp-file-name nil nil
username
remote-host
python-filename)
(tramp-make-tramp-file-name nil
username
remote-host
python-filename)))
(defun ein:tramp-create-filename-translator (remote-host &optional username)
"Generate a pair of TO-PYTHON and FROM-PYTHON for
`ein:filename-translations'.
Usage::
(setq ein:filename-translations
`((8888
. ,(ein:tramp-create-filename-translator \"MY-HOSTNAME\"))))
;; Equivalently:
(setq ein:filename-translations
(lambda (url-or-port)
(when (equal url-or-port 8888)
(ein:tramp-create-filename-translator \"MY-HOSTNAME\"))))
This setting assumes that the IPython server which can be
connected using the port 8888 in localhost is actually running in
the host named MY-HOSTNAME.
Adapted from `slime-create-filename-translator'."
(require 'tramp)
(lexical-let ((remote-host remote-host)
(username (or username (user-login-name))))
(list (lambda (emacs-filename)
(tramp-file-name-localname
(tramp-dissect-file-name emacs-filename)))
(lambda (python-filename)
(ein:make-tramp-file-name username remote-host python-filename)))))
;;; Generic getter
(defun ein:generic-getter (func-list)
"Internal function for generic getter functions (`ein:get-*').
FUNC-LIST is a list of function which takes no argument and
return what is desired or nil. Each function in FUNC-LIST is
called one by one and the first non-nil result will be used. The
function is not called when it is not bound. So, it is safe to
give functions defined in lazy-loaded sub-modules.
This is something similar to dispatching in generic function such
as `defgeneric' in EIEIO, but it takes no argument. Actual
implementation is chosen based on context (buffer, point, etc.).
This helps writing generic commands which requires same object
but can operate in different contexts."
(loop for func in func-list
if (and (functionp func) (funcall func))
return it))
(defun ein:get-url-or-port ()
(ein:generic-getter '(ein:get-url-or-port--notebooklist
ein:get-url-or-port--notebook
ein:get-url-or-port--worksheet
ein:get-url-or-port--shared-output
ein:get-url-or-port--connect)))
(defun ein:get-notebook ()
(ein:generic-getter '(ein:get-notebook--notebook
ein:get-notebook--worksheet
;; ein:get-notebook--shared-output
ein:get-notebook--connect)))
(defun ein:get-kernel ()
(ein:generic-getter '(ein:get-kernel--notebook
ein:get-kernel--worksheet
ein:get-kernel--shared-output
ein:get-kernel--connect)))
(defun ein:get-kernel-or-error ()
(or (ein:get-kernel)
(error "No kernel related to the current buffer.")))
(defun ein:get-cell-at-point ()
(ein:generic-getter '(ein:get-cell-at-point--worksheet
ein:get-cell-at-point--shared-output)))
(defun ein:get-traceback-data ()
(ein:generic-getter '(ein:get-traceback-data--worksheet
ein:get-traceback-data--shared-output
ein:get-traceback-data--connect)))
;;; Emacs utilities
(defun ein:byte-compile-ein ()
"Byte compile EIN files."
(interactive)
(let* ((files (directory-files ein:source-dir 'full "^ein-.*\\.el$"))
(errors (ein:filter
'identity
(mapcar (lambda (f) (unless (byte-compile-file f) f))
files))))
(ein:aif errors
(error "Got %s errors while compiling these files: %s"
(length errors)
(ein:join-str " " (mapcar #'file-name-nondirectory it))))
(message "Compiled %s files" (length files))))
(provide 'ein-core)
;;; ein-core.el ends here

View file

@ -28,96 +28,9 @@
(eval-when-compile (require 'cl))
(require 'json)
;; Optional dependency on tramp:
(declare-function tramp-make-tramp-file-name "tramp")
(declare-function tramp-file-name-localname "tramp")
(declare-function tramp-dissect-file-name "tramp")
(defgroup ein nil
"IPython notebook client in Emacs"
:group 'applications
:prefix "ein:")
;;; Configuration
(defcustom ein:url-or-port '(8888)
"List of default url-or-port values.
This will be used for completion. So put your IPython servers.
You can connect to servers not in this list \(but you will need
to type every time)."
:type '(repeat (choice (integer :tag "Port number" 8888)
(string :tag "URL" "http://127.0.0.1:8888")))
:group 'ein)
(defcustom ein:default-url-or-port nil
"Default URL or port. This should be your main IPython
Notebook server."
:type '(choice (integer :tag "Port number" 8888)
(string :tag "URL" "http://127.0.0.1:8888")
(const :tag "First value of `ein:url-or-port'" nil))
:group 'ein)
(defcustom ein:scratch-notebook-name-template "_scratch_%Y-%m-%d-%H%M%S_"
"Template of scratch notebook name.
This value is used from `ein:notebooklist-new-scratch-notebook'
and `ein:notebook-rename-to-scratch-command'. This must be a
format string which can be passed to `format-time-string'."
:type '(string :tag "Format string")
:group 'ein)
(defcustom ein:filename-translations nil
"Convert file paths between Emacs and Python process.
This value can take these form:
alist
Its key specifies URL-OR-PORT and value must be a list of two
functions: (TO-PYTHON FROM-PYTHON). Key (URL-OR-PORT) can be
string (URL), integer (port), or `default' (symbol). The
value of `default' is used when other key does not much.
function
Called with an argument URL-OR-PORT (integer or string).
This function must return a list of two functions:
(TO-PYTHON FROM-PYTHON).
Here, the functions TO-PYTHON and FROM-PYTHON are defined as:
TO-PYTHON
A function which converts a file name (returned by
`buffer-file-name') to the one Python understands.
FROM-PYTHON
A function which converts a file path returned by
Python process to the one Emacs understands.
Use `ein:tramp-create-filename-translator' to easily generate the
pair of TO-PYTHON and FROM-PYTHON."
;; I've got the idea from `slime-filename-translations'.
:type '(choice
(alist :tag "Translations mapping"
:key-type (choice :tag "URL or PORT"
(string :tag "URL" "http://127.0.0.1:8888")
(integer :tag "PORT" 8888)
(const default))
:value-type (list (function :tag "TO-PYTHON")
(function :tag "FROM-PYTHON")))
(function :tag "Translations getter"))
:group 'ein)
;;; Macros and core functions/variables
(defun ein:default-url-or-port ()
(or ein:default-url-or-port (car ein:url-or-port) 8888))
(defun ein:scratch-notebook-name ()
"Generate new scratch notebook name based on `current-time' and
`ein:scratch-notebook-name-template'."
(format-time-string ein:scratch-notebook-name-template (current-time)))
(defvar ein:source-dir (file-name-directory load-file-name))
(defmacro ein:aif (test-form then-form &rest else-forms)
"Anaphoric IF. Adapted from `e2wm:aif'."
(declare (debug (form form &rest form)))
@ -479,20 +392,6 @@ NOTE: This function creates new list."
;;; Emacs utilities
(defun ein:byte-compile-ein ()
"Byte compile EIN files."
(interactive)
(let* ((files (directory-files ein:source-dir 'full "^ein-.*\\.el$"))
(errors (ein:filter
'identity
(mapcar (lambda (f) (unless (byte-compile-file f) f))
files))))
(ein:aif errors
(error "Got %s errors while compiling these files: %s"
(length errors)
(ein:join-str " " (mapcar #'file-name-nondirectory it))))
(message "Compiled %s files" (length files))))
(defun ein:display-warning (message &optional level)
"Simple wrapper around `display-warning'.
LEVEL must be one of :emergency, :error or :warning (default).
@ -521,121 +420,6 @@ Use `ein:log' for debugging and logging."
`[,name ,callback :help ,(ein:get-docstring callback) ,@args]))
list-name-callback))
;;; Generic getter
(defun ein:generic-getter (func-list)
"Internal function for generic getter functions (`ein:get-*').
FUNC-LIST is a list of function which takes no argument and
return what is desired or nil. Each function in FUNC-LIST is
called one by one and the first non-nil result will be used. The
function is not called when it is not bound. So, it is safe to
give functions defined in lazy-loaded sub-modules.
This is something similar to dispatching in generic function such
as `defgeneric' in EIEIO, but it takes no argument. Actual
implementation is chosen based on context (buffer, point, etc.).
This helps writing generic commands which requires same object
but can operate in different contexts."
(loop for func in func-list
if (and (functionp func) (funcall func))
return it))
(defun ein:get-url-or-port ()
(ein:generic-getter '(ein:get-url-or-port--notebooklist
ein:get-url-or-port--notebook
ein:get-url-or-port--worksheet
ein:get-url-or-port--shared-output
ein:get-url-or-port--connect)))
(defun ein:get-notebook ()
(ein:generic-getter '(ein:get-notebook--notebook
ein:get-notebook--worksheet
;; ein:get-notebook--shared-output
ein:get-notebook--connect)))
(defun ein:get-kernel ()
(ein:generic-getter '(ein:get-kernel--notebook
ein:get-kernel--worksheet
ein:get-kernel--shared-output
ein:get-kernel--connect)))
(defun ein:get-kernel-or-error ()
(or (ein:get-kernel)
(error "No kernel related to the current buffer.")))
(defun ein:get-cell-at-point ()
(ein:generic-getter '(ein:get-cell-at-point--worksheet
ein:get-cell-at-point--shared-output)))
(defun ein:get-traceback-data ()
(ein:generic-getter '(ein:get-traceback-data--worksheet
ein:get-traceback-data--shared-output
ein:get-traceback-data--connect)))
;;; File name translation (tramp support)
;; Probably it's better to define `ein:filename-translations-get' as
;; an EIEIO method so that I don't have to re-define functions such as
;; `ein:kernel-filename-to-python' and `ein:kernel-filename-from-python'.
(defun ein:filename-translations-get (url-or-port)
(ein:choose-setting 'ein:filename-translations url-or-port))
(defun ein:filename-to-python (url-or-port filename)
(ein:aif (car (ein:filename-translations-get url-or-port))
(funcall it filename)
filename))
(defun ein:filename-from-python (url-or-port filename)
(ein:aif (cadr (ein:filename-translations-get url-or-port))
(funcall it filename)
filename))
(defun ein:make-tramp-file-name (username remote-host python-filename)
"Old (with multi-hops) tramp compatability function.
Adapted from `slime-make-tramp-file-name'."
(if (boundp 'tramp-multi-methods)
(tramp-make-tramp-file-name nil nil
username
remote-host
python-filename)
(tramp-make-tramp-file-name nil
username
remote-host
python-filename)))
(defun ein:tramp-create-filename-translator (remote-host &optional username)
"Generate a pair of TO-PYTHON and FROM-PYTHON for
`ein:filename-translations'.
Usage::
(setq ein:filename-translations
`((8888
. ,(ein:tramp-create-filename-translator \"MY-HOSTNAME\"))))
;; Equivalently:
(setq ein:filename-translations
(lambda (url-or-port)
(when (equal url-or-port 8888)
(ein:tramp-create-filename-translator \"MY-HOSTNAME\"))))
This setting assumes that the IPython server which can be
connected using the port 8888 in localhost is actually running in
the host named MY-HOSTNAME.
Adapted from `slime-create-filename-translator'."
(require 'tramp)
(lexical-let ((remote-host remote-host)
(username (or username (user-login-name))))
(list (lambda (emacs-filename)
(tramp-file-name-localname
(tramp-dissect-file-name emacs-filename)))
(lambda (python-filename)
(ein:make-tramp-file-name username remote-host python-filename)))))
;;; utils.js compatible