branch: elpa/flamegraph
commit 1839b6daa19ffc15bff626671c42979f524ba55f
Author: Dmitry Gutov <[email protected]>
Commit: Dmitry Gutov <[email protected]>

    Support RET on code snippet lines
---
 flamegraph.el            | 38 ++++++++++++++++++++++++++++++--------
 test/flamegraph-tests.el | 23 +++++++++++++++++++++++
 2 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/flamegraph.el b/flamegraph.el
index a098c289e6..b3134a44a6 100644
--- a/flamegraph.el
+++ b/flamegraph.el
@@ -557,12 +557,33 @@ necessarily its definition."
       (string-trim-right (substring entry 0 (match-beginning 0)) "[ (:-]+")
     (flamegraph--entry-name entry)))
 
-(defun flamegraph--snippet-line (n marked)
+(defvar-keymap flamegraph--snippet-line-map
+  :doc "Keymap active on source snippet lines."
+  "RET" #'flamegraph--snippet-visit-source)
+
+(defun flamegraph--snippet-visit-source ()
+  "Visit the source line described by text properties at point."
+  (interactive)
+  (let ((path (get-text-property (point) 'flamegraph-source-path))
+        (line (get-text-property (point) 'flamegraph-source-line)))
+    (when (and path line)
+      (flamegraph--visit-file path line))))
+
+(defun flamegraph--snippet-line (path n marked)
   "Format buffer line N for the snippet, marking it when MARKED."
-  (format " %s %4d  %s"
-          (if marked "▸" " ")
-          n
-          (buffer-substring (line-beginning-position) (line-end-position))))
+  (let ((line (format " %s %4d  %s
+"
+                      (if marked "▸" " ")
+                      n
+                      (buffer-substring (line-beginning-position)
+                                        (line-end-position)))))
+    (add-text-properties
+     0 (length line)
+     `(keymap ,flamegraph--snippet-line-map
+       flamegraph-source-path ,path
+       flamegraph-source-line ,n)
+     line)
+    line))
 
 (defun flamegraph--source-snippet (path line &optional node shown context)
   "Return source context around LINE of PATH as a fontified string, or nil.
@@ -628,7 +649,8 @@ defaults to 4."
             (let ((prev nil) (out nil))
               (dolist (n keep)
                 (when (and prev (> n (1+ prev)))
-                  (push "      ⋯" out))
+                  (push "      ⋯
+" out))
                 (goto-char (point-min))
                 (forward-line (1- n))
                 (ignore-errors
@@ -643,9 +665,9 @@ defaults to 4."
                       (when (and (<= bol rb) (>= eol re))
                         (add-face-text-property
                          rb re (flamegraph--call-site-face w))))))
-                (push (flamegraph--snippet-line n (= n line)) out)
+                (push (flamegraph--snippet-line path n (= n line)) out)
                 (setq prev n))
-              (mapconcat #'identity (nreverse out) "\n"))))))))
+              (apply #'concat (nreverse out)))))))))
 
 (defun flamegraph--skip-through-p (entry)
   "Non-nil if ENTRY is a frame to descend through transparently when
diff --git a/test/flamegraph-tests.el b/test/flamegraph-tests.el
index 4601c9db3b..d118e64343 100644
--- a/test/flamegraph-tests.el
+++ b/test/flamegraph-tests.el
@@ -447,6 +447,29 @@ foo at 100% of outer is hot; bar at 10% is warm."
       (should (flamegraph-test--has-face s 'flamegraph-call-site-hot))
       (should (flamegraph-test--has-face s 'flamegraph-call-site-warm)))))
 
+(ert-deftest flamegraph-test-source-snippet-lines-ret-visits-source ()
+  "RET on a snippet source line, including the final EOL, visits that line."
+  (flamegraph-test--with-temp-source path
+      "(defun outer ()
+  (foo)
+  (bar))
+"
+    (let ((snippet (flamegraph--source-snippet path 2 nil))
+          visited)
+      (should snippet)
+      (cl-letf (((symbol-function 'flamegraph--visit-file)
+                 (lambda (p l) (setq visited (cons p l)))))
+        (with-temp-buffer
+          (insert snippet)
+          (goto-char (point-min))
+          (re-search-forward " 3  ")
+          (end-of-line)
+          (should-not (button-at (point)))
+          (let ((map (get-text-property (point) 'keymap)))
+            (should map)
+            (call-interactively (lookup-key map (kbd "RET")))))
+        (should (equal visited (cons path 3)))))))
+
 ;;; Calls-tree rendering — `flamegraph--insert-call-tree'
 
 (defun flamegraph-test--render-call-tree (node ref &optional shown-nodes)

Reply via email to