ein-traceback.el 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. ;;; ein-traceback.el --- Traceback module
  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-traceback.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-traceback.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-traceback.el. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;;
  17. ;;; Code:
  18. (eval-when-compile (require 'cl))
  19. (require 'eieio)
  20. (require 'ewoc)
  21. (require 'ansi-color)
  22. (require 'ein-core)
  23. (defclass ein:traceback ()
  24. ((tb-data :initarg :tb-data :type list)
  25. (buffer-name :initarg :buffer-name :type string)
  26. (buffer :initarg :buffer :type buffer)
  27. (ewoc :initarg :ewoc :type ewoc)))
  28. (ein:deflocal ein:%traceback% nil
  29. "Buffer local variable to store an instance of `ein:traceback'.")
  30. (defvar ein:tb-buffer-name-template "*ein:tb %s/%s*")
  31. (defun ein:tb-new (buffer-name)
  32. (ein:traceback "Traceback" :buffer-name buffer-name))
  33. (defmethod ein:tb-get-buffer ((traceback ein:traceback))
  34. (unless (and (slot-boundp traceback :buffer)
  35. (buffer-live-p (oref traceback :buffer)))
  36. (let ((buf (get-buffer-create (oref traceback :buffer-name))))
  37. (oset traceback :buffer buf)))
  38. (oref traceback :buffer))
  39. (defun ein:tb-pp (ewoc-data)
  40. (insert (ansi-color-apply ewoc-data)))
  41. (defmethod ein:tb-render ((traceback ein:traceback) tb-data)
  42. (with-current-buffer (ein:tb-get-buffer traceback)
  43. (setq ein:%traceback% traceback)
  44. (setq buffer-read-only t)
  45. (let ((inhibit-read-only t)
  46. (ewoc (ein:ewoc-create #'ein:tb-pp)))
  47. (erase-buffer)
  48. (oset traceback :ewoc ewoc)
  49. (oset traceback :tb-data tb-data)
  50. (mapc (lambda (data) (ewoc-enter-last ewoc data)) tb-data))
  51. (ein:traceback-mode)))
  52. (defmethod ein:tb-popup ((traceback ein:traceback) tb-data)
  53. (ein:tb-render traceback tb-data)
  54. (pop-to-buffer (ein:tb-get-buffer traceback)))
  55. ;;;###autoload
  56. (defun ein:tb-show ()
  57. "Show full traceback in traceback viewer."
  58. (interactive)
  59. (unless
  60. (ein:and-let* ((tb-data (ein:get-traceback-data))
  61. (url-or-port (ein:get-url-or-port))
  62. (kernel (ein:get-kernel))
  63. (kr-id (ein:kernel-id kernel))
  64. (tb-name (format ein:tb-buffer-name-template
  65. url-or-port kr-id)))
  66. (ein:tb-popup (ein:tb-new tb-name) tb-data)
  67. t)
  68. (error "No traceback is available.")))
  69. (defmethod ein:tb-range-of-node-at-point ((traceback ein:traceback))
  70. (let* ((ewoc (oref traceback :ewoc))
  71. (ewoc-node (ewoc-locate ewoc))
  72. (beg (ewoc-location ewoc-node))
  73. (end (ein:aand (ewoc-next ewoc ewoc-node) (ewoc-location it))))
  74. (list beg end)))
  75. (defmethod ein:tb-file-path-at-point ((traceback ein:traceback))
  76. (destructuring-bind (beg end)
  77. (ein:tb-range-of-node-at-point traceback)
  78. (let* ((file-tail
  79. (if (>= emacs-major-version 24)
  80. (next-single-property-change beg 'font-lock-face nil end)
  81. ;; For Emacs 23.x:
  82. (next-single-property-change beg 'face nil end)))
  83. (file (when file-tail
  84. (buffer-substring-no-properties beg file-tail))))
  85. (if (string-match "\\.pyc$" file)
  86. (concat (file-name-sans-extension file) ".py")
  87. file))))
  88. (defmethod ein:tb-file-lineno-at-point ((traceback ein:traceback))
  89. (destructuring-bind (beg end)
  90. (ein:tb-range-of-node-at-point traceback)
  91. (when (save-excursion
  92. (goto-char beg)
  93. (search-forward-regexp "^[-]+> \\([0-9]+\\)" end t))
  94. (string-to-number (match-string 1)))))
  95. (defmethod ein:tb-jump-to-source-at-point ((traceback ein:traceback)
  96. &optional select)
  97. (let ((file (ein:tb-file-path-at-point traceback))
  98. (lineno (ein:tb-file-lineno-at-point traceback)))
  99. (assert (file-exists-p file) nil "File %s does not exist." file)
  100. (let ((buf (find-file-noselect file))
  101. (scroll (lambda ()
  102. (goto-char (point-min))
  103. (forward-line (1- lineno)))))
  104. (if select
  105. (progn (pop-to-buffer buf)
  106. (funcall scroll))
  107. (with-selected-window (display-buffer buf)
  108. (funcall scroll))))))
  109. (defun ein:tb-jump-to-source-at-point-command (&optional select)
  110. (interactive "P")
  111. (ein:tb-jump-to-source-at-point ein:%traceback% select))
  112. ;;; ein:traceback-mode
  113. (defun ein:tb-prev-item ()
  114. (interactive)
  115. (ewoc-goto-prev (oref ein:%traceback% :ewoc) 1))
  116. (defun ein:tb-next-item ()
  117. (interactive)
  118. (ewoc-goto-next (oref ein:%traceback% :ewoc) 1))
  119. (define-derived-mode ein:traceback-mode fundamental-mode "ein:tb"
  120. (font-lock-mode))
  121. (add-hook 'ein:traceback-mode-hook 'ein:truncate-lines-on)
  122. (let ((map ein:traceback-mode-map))
  123. (define-key map (kbd "RET") 'ein:tb-jump-to-source-at-point-command)
  124. (define-key map "p" 'ein:tb-prev-item)
  125. (define-key map "n" 'ein:tb-next-item)
  126. (define-key map "q" 'bury-buffer))
  127. (provide 'ein-traceback)
  128. ;;; ein-traceback.el ends here