Path: blob/master/elisp/slime/contrib/slime-compiler-notes-tree.el
990 views
1(define-slime-contrib slime-compiler-notes-tree2"Display compiler messages in tree layout.34M-x slime-list-compiler-notes display the compiler notes in a tree5grouped by severity.67`slime-maybe-list-compiler-notes' can be used as8`slime-compilation-finished-hook'.9"10(:authors "Helmut Eller <[email protected]>")11(:license "GPL"))1213(defun slime-maybe-list-compiler-notes (notes)14"Show the compiler notes if appropriate."15;; don't pop up a buffer if all notes are already annotated in the16;; buffer itself17(unless (every #'slime-note-has-location-p notes)18(slime-list-compiler-notes notes)))1920(defun slime-list-compiler-notes (notes)21"Show the compiler notes NOTES in tree view."22(interactive (list (slime-compiler-notes)))23(with-temp-message "Preparing compiler note tree..."24(slime-with-popup-buffer ((slime-buffer-name :notes)25:mode 'slime-compiler-notes-mode)26(when (null notes)27(insert "[no notes]"))28(let ((collapsed-p))29(dolist (tree (slime-compiler-notes-to-tree notes))30(when (slime-tree.collapsed-p tree) (setf collapsed-p t))31(slime-tree-insert tree "")32(insert "\n"))33(goto-char (point-min))))))3435(defvar slime-tree-printer 'slime-tree-default-printer)3637(defun slime-tree-for-note (note)38(make-slime-tree :item (slime-note.message note)39:plist (list 'note note)40:print-fn slime-tree-printer))4142(defun slime-tree-for-severity (severity notes collapsed-p)43(make-slime-tree :item (format "%s (%d)"44(slime-severity-label severity)45(length notes))46:kids (mapcar #'slime-tree-for-note notes)47:collapsed-p collapsed-p))4849(defun slime-compiler-notes-to-tree (notes)50(let* ((alist (slime-alistify notes #'slime-note.severity #'eq))51(collapsed-p (slime-length> alist 1)))52(loop for (severity . notes) in alist53collect (slime-tree-for-severity severity notes54collapsed-p))))5556(defvar slime-compiler-notes-mode-map)5758(define-derived-mode slime-compiler-notes-mode fundamental-mode59"Compiler-Notes"60"\\<slime-compiler-notes-mode-map>\61\\{slime-compiler-notes-mode-map}62\\{slime-popup-buffer-mode-map}63"64(slime-set-truncate-lines))6566(slime-define-keys slime-compiler-notes-mode-map67((kbd "RET") 'slime-compiler-notes-default-action-or-show-details)68([return] 'slime-compiler-notes-default-action-or-show-details)69([mouse-2] 'slime-compiler-notes-default-action-or-show-details/mouse))7071(defun slime-compiler-notes-default-action-or-show-details/mouse (event)72"Invoke the action pointed at by the mouse, or show details."73(interactive "e")74(destructuring-bind (mouse-2 (w pos &rest _) &rest __) event75(save-excursion76(goto-char pos)77(let ((fn (get-text-property (point)78'slime-compiler-notes-default-action)))79(if fn (funcall fn) (slime-compiler-notes-show-details))))))8081(defun slime-compiler-notes-default-action-or-show-details ()82"Invoke the action at point, or show details."83(interactive)84(let ((fn (get-text-property (point) 'slime-compiler-notes-default-action)))85(if fn (funcall fn) (slime-compiler-notes-show-details))))8687(defun slime-compiler-notes-show-details ()88(interactive)89(let* ((tree (slime-tree-at-point))90(note (plist-get (slime-tree.plist tree) 'note))91(inhibit-read-only t))92(cond ((not (slime-tree-leaf-p tree))93(slime-tree-toggle tree))94(t95(slime-show-source-location (slime-note.location note) t)))))969798;;;;;; Tree Widget99100(defstruct (slime-tree (:conc-name slime-tree.))101item102(print-fn #'slime-tree-default-printer :type function)103(kids '() :type list)104(collapsed-p t :type boolean)105(prefix "" :type string)106(start-mark nil)107(end-mark nil)108(plist '() :type list))109110(defun slime-tree-leaf-p (tree)111(not (slime-tree.kids tree)))112113(defun slime-tree-default-printer (tree)114(princ (slime-tree.item tree) (current-buffer)))115116(defun slime-tree-decoration (tree)117(cond ((slime-tree-leaf-p tree) "-- ")118((slime-tree.collapsed-p tree) "[+] ")119(t "-+ ")))120121(defun slime-tree-insert-list (list prefix)122"Insert a list of trees."123(loop for (elt . rest) on list124do (cond (rest125(insert prefix " |")126(slime-tree-insert elt (concat prefix " |"))127(insert "\n"))128(t129(insert prefix " `")130(slime-tree-insert elt (concat prefix " "))))))131132(defun slime-tree-insert-decoration (tree)133(insert (slime-tree-decoration tree)))134135(defun slime-tree-indent-item (start end prefix)136"Insert PREFIX at the beginning of each but the first line.137This is used for labels spanning multiple lines."138(save-excursion139(goto-char end)140(beginning-of-line)141(while (< start (point))142(insert-before-markers prefix)143(forward-line -1))))144145(defun slime-tree-insert (tree prefix)146"Insert TREE prefixed with PREFIX at point."147(with-struct (slime-tree. print-fn kids collapsed-p start-mark end-mark) tree148(let ((line-start (line-beginning-position)))149(setf start-mark (point-marker))150(slime-tree-insert-decoration tree)151(funcall print-fn tree)152(slime-tree-indent-item start-mark (point) (concat prefix " "))153(add-text-properties line-start (point) (list 'slime-tree tree))154(set-marker-insertion-type start-mark t)155(when (and kids (not collapsed-p))156(terpri (current-buffer))157(slime-tree-insert-list kids prefix))158(setf (slime-tree.prefix tree) prefix)159(setf end-mark (point-marker)))))160161(defun slime-tree-at-point ()162(cond ((get-text-property (point) 'slime-tree))163(t (error "No tree at point"))))164165(defun slime-tree-delete (tree)166"Delete the region for TREE."167(delete-region (slime-tree.start-mark tree)168(slime-tree.end-mark tree)))169170(defun slime-tree-toggle (tree)171"Toggle the visibility of TREE's children."172(with-struct (slime-tree. collapsed-p start-mark end-mark prefix) tree173(setf collapsed-p (not collapsed-p))174(slime-tree-delete tree)175(insert-before-markers " ") ; move parent's end-mark176(backward-char 1)177(slime-tree-insert tree prefix)178(delete-char 1)179(goto-char start-mark)))180181(provide 'slime-compiler-notes-tree)182183184