Klimi's new dotfiles with stow.
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.

184 lines
6.4 KiB

4 years ago
  1. (require 'slime)
  2. (require 'cl-lib)
  3. (define-slime-contrib slime-compiler-notes-tree
  4. "Display compiler messages in tree layout.
  5. M-x slime-list-compiler-notes display the compiler notes in a tree
  6. grouped by severity.
  7. `slime-maybe-list-compiler-notes' can be used as
  8. `slime-compilation-finished-hook'.
  9. "
  10. (:authors "Helmut Eller <heller@common-lisp.net>")
  11. (:license "GPL"))
  12. (defun slime-maybe-list-compiler-notes (notes)
  13. "Show the compiler notes if appropriate."
  14. ;; don't pop up a buffer if all notes are already annotated in the
  15. ;; buffer itself
  16. (unless (cl-every #'slime-note-has-location-p notes)
  17. (slime-list-compiler-notes notes)))
  18. (defun slime-list-compiler-notes (notes)
  19. "Show the compiler notes NOTES in tree view."
  20. (interactive (list (slime-compiler-notes)))
  21. (with-temp-message "Preparing compiler note tree..."
  22. (slime-with-popup-buffer ((slime-buffer-name :notes)
  23. :mode 'slime-compiler-notes-mode)
  24. (when (null notes)
  25. (insert "[no notes]"))
  26. (let ((collapsed-p))
  27. (dolist (tree (slime-compiler-notes-to-tree notes))
  28. (when (slime-tree.collapsed-p tree) (setf collapsed-p t))
  29. (slime-tree-insert tree "")
  30. (insert "\n"))
  31. (goto-char (point-min))))))
  32. (defvar slime-tree-printer 'slime-tree-default-printer)
  33. (defun slime-tree-for-note (note)
  34. (make-slime-tree :item (slime-note.message note)
  35. :plist (list 'note note)
  36. :print-fn slime-tree-printer))
  37. (defun slime-tree-for-severity (severity notes collapsed-p)
  38. (make-slime-tree :item (format "%s (%d)"
  39. (slime-severity-label severity)
  40. (length notes))
  41. :kids (mapcar #'slime-tree-for-note notes)
  42. :collapsed-p collapsed-p))
  43. (defun slime-compiler-notes-to-tree (notes)
  44. (let* ((alist (slime-alistify notes #'slime-note.severity #'eq))
  45. (collapsed-p (slime-length> alist 1)))
  46. (cl-loop for (severity . notes) in alist
  47. collect (slime-tree-for-severity severity notes
  48. collapsed-p))))
  49. (defvar slime-compiler-notes-mode-map)
  50. (define-derived-mode slime-compiler-notes-mode fundamental-mode
  51. "Compiler-Notes"
  52. "\\<slime-compiler-notes-mode-map>\
  53. \\{slime-compiler-notes-mode-map}
  54. \\{slime-popup-buffer-mode-map}
  55. "
  56. (slime-set-truncate-lines))
  57. (slime-define-keys slime-compiler-notes-mode-map
  58. ((kbd "RET") 'slime-compiler-notes-default-action-or-show-details)
  59. ([return] 'slime-compiler-notes-default-action-or-show-details)
  60. ([mouse-2] 'slime-compiler-notes-default-action-or-show-details/mouse))
  61. (defun slime-compiler-notes-default-action-or-show-details/mouse (event)
  62. "Invoke the action pointed at by the mouse, or show details."
  63. (interactive "e")
  64. (cl-destructuring-bind (mouse-2 (w pos &rest _) &rest __) event
  65. (save-excursion
  66. (goto-char pos)
  67. (let ((fn (get-text-property (point)
  68. 'slime-compiler-notes-default-action)))
  69. (if fn (funcall fn) (slime-compiler-notes-show-details))))))
  70. (defun slime-compiler-notes-default-action-or-show-details ()
  71. "Invoke the action at point, or show details."
  72. (interactive)
  73. (let ((fn (get-text-property (point) 'slime-compiler-notes-default-action)))
  74. (if fn (funcall fn) (slime-compiler-notes-show-details))))
  75. (defun slime-compiler-notes-show-details ()
  76. (interactive)
  77. (let* ((tree (slime-tree-at-point))
  78. (note (plist-get (slime-tree.plist tree) 'note))
  79. (inhibit-read-only t))
  80. (cond ((not (slime-tree-leaf-p tree))
  81. (slime-tree-toggle tree))
  82. (t
  83. (slime-show-source-location (slime-note.location note) t)))))
  84. ;;;;;; Tree Widget
  85. (cl-defstruct (slime-tree (:conc-name slime-tree.))
  86. item
  87. (print-fn #'slime-tree-default-printer :type function)
  88. (kids '() :type list)
  89. (collapsed-p t :type boolean)
  90. (prefix "" :type string)
  91. (start-mark nil)
  92. (end-mark nil)
  93. (plist '() :type list))
  94. (defun slime-tree-leaf-p (tree)
  95. (not (slime-tree.kids tree)))
  96. (defun slime-tree-default-printer (tree)
  97. (princ (slime-tree.item tree) (current-buffer)))
  98. (defun slime-tree-decoration (tree)
  99. (cond ((slime-tree-leaf-p tree) "-- ")
  100. ((slime-tree.collapsed-p tree) "[+] ")
  101. (t "-+ ")))
  102. (defun slime-tree-insert-list (list prefix)
  103. "Insert a list of trees."
  104. (cl-loop for (elt . rest) on list
  105. do (cond (rest
  106. (insert prefix " |")
  107. (slime-tree-insert elt (concat prefix " |"))
  108. (insert "\n"))
  109. (t
  110. (insert prefix " `")
  111. (slime-tree-insert elt (concat prefix " "))))))
  112. (defun slime-tree-insert-decoration (tree)
  113. (insert (slime-tree-decoration tree)))
  114. (defun slime-tree-indent-item (start end prefix)
  115. "Insert PREFIX at the beginning of each but the first line.
  116. This is used for labels spanning multiple lines."
  117. (save-excursion
  118. (goto-char end)
  119. (beginning-of-line)
  120. (while (< start (point))
  121. (insert-before-markers prefix)
  122. (forward-line -1))))
  123. (defun slime-tree-insert (tree prefix)
  124. "Insert TREE prefixed with PREFIX at point."
  125. (with-struct (slime-tree. print-fn kids collapsed-p start-mark end-mark) tree
  126. (let ((line-start (line-beginning-position)))
  127. (setf start-mark (point-marker))
  128. (slime-tree-insert-decoration tree)
  129. (funcall print-fn tree)
  130. (slime-tree-indent-item start-mark (point) (concat prefix " "))
  131. (add-text-properties line-start (point) (list 'slime-tree tree))
  132. (set-marker-insertion-type start-mark t)
  133. (when (and kids (not collapsed-p))
  134. (terpri (current-buffer))
  135. (slime-tree-insert-list kids prefix))
  136. (setf (slime-tree.prefix tree) prefix)
  137. (setf end-mark (point-marker)))))
  138. (defun slime-tree-at-point ()
  139. (cond ((get-text-property (point) 'slime-tree))
  140. (t (error "No tree at point"))))
  141. (defun slime-tree-delete (tree)
  142. "Delete the region for TREE."
  143. (delete-region (slime-tree.start-mark tree)
  144. (slime-tree.end-mark tree)))
  145. (defun slime-tree-toggle (tree)
  146. "Toggle the visibility of TREE's children."
  147. (with-struct (slime-tree. collapsed-p start-mark end-mark prefix) tree
  148. (setf collapsed-p (not collapsed-p))
  149. (slime-tree-delete tree)
  150. (insert-before-markers " ") ; move parent's end-mark
  151. (backward-char 1)
  152. (slime-tree-insert tree prefix)
  153. (delete-char 1)
  154. (goto-char start-mark)))
  155. (provide 'slime-compiler-notes-tree)