ag91 / moldable-emacs

Adapting Emacs for moldable development
GNU General Public License v3.0
105 stars 8 forks source link

Show and tell: Xref to Org todo list #19

Closed alanz closed 1 year ago

alanz commented 2 years ago

I have been playing with moldable-emacs, and made a mold to convert xref results to an Org TODO list

The first part populates a Playground with the xref data

;; Following function is based on xref-query-replace-in-results
(defun me-get-xrefs ()
  "Run in the *xref* buffer, return the actual xrefs."
  (let* (item xrefs iter ret)
    (save-excursion
      (while (setq item (xref--search-property 'xref-item))
        (let ((pitem (list :summary (xref-item-summary item) :location (xref-item-location item)) ))
          (push pitem xrefs))))
    xrefs
    ))

(defun me-set-xref-self-for-playground ()
  "Set Playground `self' to xref list of locations."
  (when (and
         (s-starts-with-p "Playground" me-last-used-mold)
         (ignore-errors mold-data)
         (eq (plist-get mold-data :old-mode) 'xref--xref-buffer-mode))
    (setq-local self (with-current-buffer (plist-get mold-data :old-buffer)
                       (progn (goto-char (point-min))
                              (me-get-xrefs))))))
                       ;; (buffer-string)))))

;; the order is important: keep before me-set-self-mold-data, hence 91
(add-hook 'me-mold-after-hook #'me-set-xref-self-for-playground 91)

The next one converts it to a todo list

(me-register-mold
 :key "XrefToOrgTodos"
 :given (:fn (and
              (eq major-mode 'emacs-lisp-mode)))
 :then (:fn
        (let* ((tree self)
               (text (concat
                      "* Todo list [/]\n"
                      (s-join
                       "\n\n"
                       (--map
                        (format
                         "- [ ] [[elisp:%s][%s]]"
                         (format
                          "(progn (find-file-other-window \"%s\") (goto-char %s))"
                          (xref-location-group (plist-get it :location))
                          (marker-position (xref-location-marker (plist-get it :location))))
                         (s-truncate 100 (plist-get it :summary)))
                        tree)))))
          (with-current-buffer buffername
            (erase-buffer)
            (org-mode)
            (setq-local org-confirm-elisp-link-function nil)
            (insert text))))
 :docs "Transform an xref plist into an Org mode TODO list."
 :examples ())
ag91 commented 2 years ago

Thanks for sharing! How do I get into an xref--xref-buffer? Also, I would refine the :given clause so that your mold becomes usable only if self contains what you want, no? Now it is always available if your buffer is in emacs-lisp-mode

alanz commented 2 years ago

How do I get into an xref--xref-buffer?

For me it shows up if I either explicitly call lsp-find-references, or if I try to go to a definition (C-] in evil mode) and there is more than one target. It is the one called *xref*.

And I initially kept the preconditions wide because I was just trying to make the the thing work, it does need tightening up.

I would love to be able to set a field in the mold-data to identify the type of info in the self, so we can just check for that.

Which probably taps into something from #11 .

alanz commented 2 years ago

Here is an example

With the cursor on xref-location-group I hit C-] (evil-jump-to-tag) and got the *xref* buffer on the right.

image

ag91 commented 1 year ago

thanks again for this, closing it now