Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.5 KiB

  1. ;;; -*- mode: emacs-lisp; lexical-binding: t; -*-
  2. ;;; ein-skewer.el --- Cell module
  3. ;; (C) 2016 - John M Miller
  4. ;; Author: John M Miller <millejoh at mac.com>
  5. ;; This file is NOT part of GNU Emacs.
  6. ;; ein-skewer.el is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; ein-skewre.el is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with ein-cell.el. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; This depends on the skewer package, so likely will get split into
  18. ;; its own package at some point.
  19. ;;; Code:
  20. (require 'skewer-mode)
  21. (require 'skewer-html)
  22. (require 'simple-httpd)
  23. (defvar *ein:skewer-running-p* nil "True if the emacs httpd server has been started.")
  24. (defun ein:js-prepare-result (result type)
  25. (list :output_type type :text result))
  26. (defun ein:update-javascript-output (cell json result)
  27. (let ((val (ein:js-prepare-result
  28. (or (cdr (assoc 'value result)) "See browser for result.")
  29. (plist-get json :output_type))))
  30. (setf (slot-value cell 'outputs) (list val))
  31. (ein:cell-append-output cell val (slot-value cell 'dynamic))))
  32. (defservlet current-jupyter-cell-output text/html (path)
  33. (let ((cell-id (file-name-nondirectory path)))
  34. (insert (gethash cell-id *ein:skewer-cell-output-cache*))))
  35. (defvar *ein:skewer-html-template*
  36. "<html>
  37. <head>
  38. <title>Emacs IPython Notebook</title>
  39. <script src=\"/skewer\"></script>
  40. </head>
  41. <body>
  42. %s
  43. </body>
  44. </html>")
  45. (defvar *ein:skewer-cell-output-cache* (make-hash-table :test #'equal))
  46. (defun ein:skewer--handle-html (cell string)
  47. (setf (gethash (slot-value cell 'cell-id) *ein:skewer-cell-output-cache*)
  48. (format *ein:skewer-html-template* string) ))
  49. ;; Format of result is ((id . STR) (type . STR) (status . STR) (value . STR) (time . FLOAT))
  50. (defun ein:execute-javascript (cell json)
  51. (unless (httpd-running-p) ;; *ein:skewer-running-p*
  52. (run-skewer))
  53. (deferred:$
  54. (deferred:next
  55. (lambda ()
  56. (let ((result nil))
  57. (ein:aif (plist-get json :html)
  58. (progn
  59. (let ((cell-id (slot-value cell 'cell-id)))
  60. (ein:skewer--handle-html cell it)
  61. (setq result (list '(id . nil)
  62. '(type . str)
  63. '(stats . nil)
  64. (cons 'value (format "Open http://localhost:8080/current-jupyter-cell-output/%s" cell-id))
  65. '(time . nil)))
  66. (browse-url (format "http://localhost:8080/current-jupyter-cell-output/%s" cell-id))))
  67. (skewer-eval (plist-get json :javascript)
  68. (lambda (v)
  69. (setq result v))
  70. :type (if (plist-get json :html)
  71. "html"
  72. "eval")))
  73. (cl-loop until result
  74. do (accept-process-output nil 0.01)
  75. finally (return result)))))
  76. (deferred:nextc it
  77. (lambda (result)
  78. (ein:update-javascript-output cell json result)))))
  79. (provide 'ein-skewer)