ein-dev.el 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. ;;; ein-dev.el --- Development tools
  2. ;; Copyright (C) 2012- Takafumi Arakaki
  3. ;; Author: Takafumi Arakaki <aka.tkf at gmail.com>
  4. ;; This file is NOT part of GNU Emacs.
  5. ;; ein-dev.el is free software: you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; ein-dev.el is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with ein-dev.el. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;
  17. ;;; Code:
  18. (eval-when-compile (require 'cl))
  19. (declare-function rst-shift-region "rst")
  20. (require 'ein-notebook)
  21. (require 'ein-subpackages)
  22. ;;;###autoload
  23. (defun ein:dev-insert-mode-map (map-string)
  24. "Insert mode-map into rst document. For README.rst."
  25. (save-excursion
  26. (insert "\n\n::\n\n")
  27. (let ((beg (point)))
  28. (search-forward ".. // KEYS END //")
  29. (move-beginning-of-line nil)
  30. (delete-region beg (point))
  31. (insert "\n")
  32. (goto-char beg)
  33. (insert (substitute-command-keys map-string))
  34. (rst-shift-region beg (point) 1))))
  35. (defun ein:load-files (&optional regex dir ignore-compiled)
  36. (let* ((dir (or dir ein:source-dir))
  37. (regex (or regex ".+"))
  38. (files (and
  39. (file-accessible-directory-p dir)
  40. (directory-files dir 'full regex))))
  41. (unless ignore-compiled
  42. (setq files (mapcar #'file-name-sans-extension files)))
  43. (mapc #'load files)))
  44. (defun ein:dev-reload ()
  45. "Reload ein-*.el modules."
  46. (interactive)
  47. (ein:notebook-kill-all-buffers)
  48. (makunbound 'ein:notebook-mode-map) ; so defvar works.
  49. (load "ein-notebook") ; ... but make sure it will be defined first.
  50. (ein:load-files "^ein-.*\\.el$")
  51. (ein:subpackages-reload))
  52. (defun* ein:dev-require-all (&key (ignore-p #'ignore))
  53. (loop for f in (directory-files ein:source-dir nil "^ein-.*\\.el$")
  54. unless (or (equal f "ein-pkg.el")
  55. (funcall ignore-p f))
  56. do (require (intern (file-name-sans-extension f)) nil t))
  57. ;; For `widget-button-press':
  58. (require 'wid-edit nil t))
  59. (defadvice backtrace (around ein:dev-short-backtrace)
  60. "A hack to shorten backtrace.
  61. As code cells hold base64-encoded image data, backtrace tends to
  62. be VERY long. So I am setting `print-level' to *1*. Note that
  63. setting it globally via `setq' does not work because the value
  64. for debugger is hard-coded. See `debugger-setup-buffer'."
  65. (let ((print-level 1))
  66. ad-do-it))
  67. (defun ein:dev-patch-backtrace ()
  68. "Monkey patch `backtrace' function to make it shorter."
  69. (interactive)
  70. (ad-enable-advice 'backtrace 'around 'ein:dev-short-backtrace)
  71. (ad-activate 'backtrace))
  72. (defun ein:dev-depatch-backtrace ()
  73. "Undo `ein:dev-patch-backtrace'."
  74. (interactive)
  75. (ad-deactivate 'backtrace)
  76. (ad-disable-advice 'backtrace 'around 'ein:dev-short-backtrace)
  77. ;; In case it has other advices.
  78. (ad-activate 'backtrace))
  79. (defun ein:dev-show-debug-setting ()
  80. "Show variables related to EIN debugging."
  81. (interactive)
  82. (message (concat "debug-on-error=%s websocket-debug=%s "
  83. "websocket-callback-debug-on-error=%s "
  84. "ein:debug=%s ein:log-level=%s ein:log-message-level=%s")
  85. debug-on-error websocket-debug websocket-callback-debug-on-error
  86. ein:debug
  87. (ein:log-level-int-to-name ein:log-level)
  88. (ein:log-level-int-to-name ein:log-message-level)))
  89. ;;;###autoload
  90. (defun ein:dev-start-debug (&optional ws-callback)
  91. "Enable EIN debugging support.
  92. When the prefix argument is given, debugging support for websocket
  93. callback (`websocket-callback-debug-on-error') is enabled."
  94. (interactive "P")
  95. (setq debug-on-error t)
  96. (setq websocket-debug t)
  97. (when ws-callback
  98. (setq websocket-callback-debug-on-error t))
  99. (setq ein:debug t)
  100. (ein:log-set-level 'debug)
  101. (ein:log-set-message-level 'verbose)
  102. (ein:dev-patch-backtrace)
  103. (ein:dev-show-debug-setting))
  104. ;;;###autoload
  105. (defun ein:dev-stop-debug ()
  106. "Disable debugging support enabled by `ein:dev-start-debug'."
  107. (interactive)
  108. (setq debug-on-error nil)
  109. (setq websocket-debug nil)
  110. (setq websocket-callback-debug-on-error nil)
  111. (setq ein:debug nil)
  112. (ein:log-set-level 'verbose)
  113. (ein:log-set-message-level 'info)
  114. (ein:dev-depatch-backtrace)
  115. (ein:dev-show-debug-setting))
  116. (defun ein:dev-pop-to-debug-shell ()
  117. "Open shell channel websocket log buffer."
  118. (interactive)
  119. (pop-to-buffer
  120. (websocket-get-debug-buffer-create
  121. (ein:$websocket-ws (ein:$kernel-shell-channel
  122. (ein:$notebook-kernel ein:%notebook%))))))
  123. (defun ein:dev-pop-to-debug-iopub ()
  124. "Open iopub channel websocket log buffer."
  125. (interactive)
  126. (pop-to-buffer
  127. (websocket-get-debug-buffer-create
  128. (ein:$websocket-ws (ein:$kernel-iopub-channel
  129. (ein:$notebook-kernel ein:%notebook%))))))
  130. (defun ein:dev-notebook-plain-mode ()
  131. "Use `ein:notebook-plain-mode'."
  132. (interactive)
  133. (setq ein:notebook-modes '(ein:notebook-plain-mode)))
  134. (defun ein:dev-notebook-python-mode ()
  135. "Use `ein:notebook-python-mode'."
  136. (interactive)
  137. (setq ein:notebook-modes '(ein:notebook-python-mode)))
  138. (defun ein:dev-notebook-mumamo-mode ()
  139. "Use `ein:notebook-mumamo-mode'."
  140. (interactive)
  141. (setq ein:notebook-modes '(ein:notebook-mumamo-mode)))
  142. (defun ein:dev-notebook-multilang-mode ()
  143. "Use `ein:notebook-multilang-mode'."
  144. (interactive)
  145. (setq ein:notebook-modes '(ein:notebook-multilang-mode)))
  146. (defun ein:dev-sys-info--lib (name)
  147. (let* ((libsym (intern-soft name))
  148. (version-var (loop for fmt in '("%s-version" "%s:version")
  149. if (intern-soft (format fmt name))
  150. return it))
  151. (version (symbol-value version-var)))
  152. (list :name name
  153. :path (ein:aand (locate-library name) (abbreviate-file-name it))
  154. :featurep (featurep libsym)
  155. :version-var version-var
  156. :version version)))
  157. (defun ein:dev-dump-vars (names)
  158. (loop for var in names
  159. collect (intern (format ":%s" var))
  160. collect (symbol-value (intern (format "ein:%s" var)))))
  161. (defun ein:dev-stdout-program (command args)
  162. "Safely call COMMAND with ARGS and return its stdout."
  163. (ein:aand (executable-find command)
  164. (with-temp-buffer
  165. (erase-buffer)
  166. (apply #'call-process it nil t nil args)
  167. (buffer-string))))
  168. (defun ein:dev-sys-info ()
  169. (list
  170. "EIN system info"
  171. :emacs-version (emacs-version)
  172. :emacs-bzr-version (ein:eval-if-bound 'emacs-bzr-version)
  173. :window-system window-system
  174. ;; Emacs variant detection
  175. ;; http://coderepos.org/share/browser/lang/elisp/init-loader/init-loader.el
  176. :emacs-variant
  177. (cond ((featurep 'meadow) 'meadow)
  178. ((featurep 'carbon-emacs-package) 'carbon))
  179. :os (list
  180. :uname (ein:dev-stdout-program "uname" '("-a"))
  181. :lsb-release (ein:dev-stdout-program "lsb_release" '("-a")))
  182. :image-types (ein:eval-if-bound 'image-types)
  183. :image-types-available (ein:filter #'image-type-available-p
  184. (ein:eval-if-bound 'image-types))
  185. :request (list :backend request-backend)
  186. :ein (append (list :version (ein:version))
  187. (ein:dev-dump-vars '("source-dir")))
  188. :lib (ein:filter (lambda (info) (plist-get info :path))
  189. (mapcar #'ein:dev-sys-info--lib
  190. '("websocket" "request" "auto-complete" "mumamo"
  191. "auto-complete" "popup" "fuzzy" "pos-tip"
  192. "python" "python-mode" "markdown-mode"
  193. "smartrep" "anything" "helm")))))
  194. (defun ein:dev-show-sys-info (&optional show-in-buffer)
  195. "Show Emacs and library information."
  196. (interactive (list t))
  197. (let ((info (ein:dev-sys-info)))
  198. (if show-in-buffer
  199. (let ((buffer (get-buffer-create "*ein:sys-info*")))
  200. (with-current-buffer buffer
  201. (erase-buffer)
  202. (pp info buffer)
  203. (pop-to-buffer buffer)))
  204. (message "EIN INFO:\n%s" (pp-to-string info)))))
  205. ;;;###autoload
  206. (defun ein:dev-bug-report-template ()
  207. "Open a buffer with bug report template."
  208. (interactive)
  209. (let ((buffer (generate-new-buffer "*ein:bug-report*")))
  210. (with-current-buffer buffer
  211. (erase-buffer)
  212. (insert "<!--
  213. This template is to help you write a good bug report.
  214. You may skip some sections, but please make sure to include
  215. the last section \"System info\", unless you find some
  216. personal information there.
  217. After finish writing it, please post it here:
  218. https://github.com/tkf/emacs-ipython-notebook/issues/new
  219. -->
  220. ## Check list
  221. - [ ] I read \"Avoid standard Emacs traps\" section in
  222. https://github.com/tkf/emacs-ipython-notebook/blob/master/CONTRIBUTING.md
  223. - [ ] I checked that IPython works with the browser interface.
  224. - [ ] I checked that the problem was not due to badly compiled
  225. files. Removing `*.elc` files from source directory of EIN and
  226. its dependencies did not solve the problem.
  227. - [ ] I checked that the libraries are loaded from intended place.
  228. (You can check the location in the \"System info\" section below)
  229. ## Description of the problem you have
  230. ## Steps to reproduce the problem
  231. 1.
  232. 2.
  233. 3.
  234. ## Expected output
  235. ## Your EIN configuration (in .emacs.d/init.el or somewhere else)
  236. ## Your IPython configuration
  237. 1. What is your IPython version? (run `ipython --version`):
  238. 2. How do you start IPython? (e.g., `ipython notebook --port 9999`):
  239. 3. What is your IPython notebook port number or URL?:
  240. ## Additional information (if any)
  241. ")
  242. (insert "## System info:\n\n```cl\n")
  243. (condition-case err
  244. (ein:dev-print-sys-info buffer)
  245. (error (insert (format "`ein:dev-sys-info' produce: %S" err))))
  246. (insert "```\n")
  247. (goto-char (point-min))
  248. (when (fboundp 'markdown-mode)
  249. (markdown-mode))
  250. (pop-to-buffer buffer))))
  251. (defun ein:dev-print-sys-info (&optional stream)
  252. (princ (ein:dev--pp-to-string (ein:dev-sys-info))
  253. (or stream standard-output)))
  254. (defun ein:dev--pp-to-string (object)
  255. "`pp-to-string' with additional prettifier."
  256. (with-temp-buffer
  257. (erase-buffer)
  258. (let ((pp-escape-newlines nil))
  259. (pp object (current-buffer)))
  260. (goto-char (point-min))
  261. (let ((emacs-lisp-mode-hook nil))
  262. (emacs-lisp-mode))
  263. (ein:dev--prettify-sexp)
  264. (buffer-string)))
  265. (defun ein:dev--prettify-sexp ()
  266. "Prettify s-exp at point recursively.
  267. Use this function in addition to `pp' (see `ein:dev--pp-to-string')."
  268. (down-list)
  269. (condition-case nil
  270. (while t
  271. (forward-sexp)
  272. ;; Prettify nested s-exp.
  273. (when (looking-back ")")
  274. (save-excursion
  275. (backward-sexp)
  276. (ein:dev--prettify-sexp)))
  277. ;; Add newline before keyword symbol.
  278. (when (looking-at-p " :")
  279. (newline-and-indent))
  280. ;; Add newline before long string literal.
  281. (when (and (looking-at-p " \"")
  282. (let ((end (save-excursion
  283. (forward-sexp)
  284. (point))))
  285. (> (- end (point)) 80)))
  286. (newline-and-indent)))
  287. (scan-error)))
  288. (provide 'ein-dev)
  289. ;;; ein-dev.el ends here