armindarvish / consult-gh

An Interactive interface for "GitHub CLI" client inside GNU Emacs using Consult

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issues should open in forge-topic-mode

agzam opened this issue · comments

If magit-forge is installed, an issue should be previewed and opened in forge-topic-mode. It can show the comments and other stuff and I think it integrates better with the existing tools like wandersoncferreira/code-review

Hmmm, that's an interesting idea, but I think then the repo needs to be added to forge-list. So let me do some tests and figure out how the workflow would work and I'll get back to this issue with some ideas.

Ouch... I think this is something I have tried to figure out before, but failed then and now I'm failing again. It doesn't seem very straightforward. Even if we consider for a moment that the repository has been added to the forge db (let's imagine it has), it still seems difficult to determine a forge-topic object solely based on a GitHub URL.

This is not working (just an example of what I'm trying):

(forge-visit-issue
 (forge-issue
  :repository (forge-get-repository "https://github.com/MYORG/REPO" nil t)
  :number 7993))

I still would love to figure it out, would be nice to have an Embark Action that can open an issue from e.g., bug-reference-mode marker or straight url-at-point.

I actually just got an initial version of this to work. I am going to try to add this as an extension only because the way forge is handling this is very complicated and it can break things really easily.

The issue is Forge is designed for "contributors" and not "viewers". So in that context, it makes sense to pull the data, put it in a sql database, etc. But in our case, we want to look at that topic and then dump all that data. Anyway, stay tuned, I may get it to work soon!

Ooof... what a rabbit hole. I figured it out. Here's the command I came up with.
You can ignore the bits related to bug-reference-mode.
bisect-github-url is a function that parses github url and returns a list with (:forge :org :repo :issue :pull ,etc.) It's a bit work-in-progress thing, so I'm not posting it here.

(defun forge-visit-topic-via-url (&optional url)
  "Opens Forge Topic buffer, based on GitHub URL."
  (interactive)
  (let* ((url (or url
                  (thing-at-point-url-at-point)
                  (when-let* ((o (car (overlays-at (point)))))
                    (overlay-get o 'bug-reference-url))))
         (parts (bisect-github-url url))
         (issue (plist-get parts :issue))
         (pr (plist-get parts :pull))
         (topic-num (string-to-number (or issue pr "")))
         (owner (plist-get parts :org))
         (repo-name (plist-get parts :repo))
         (repo-url (format "%s/%s/%s" (plist-get parts :forge) owner repo-name))
         (repo (or (ignore-errors (forge-get-repository repo-url t t))
                   (forge-get-repository repo-url nil 'create)))

         ;; This one is tricky:
         ;; - first, it tries to find the topic in forge db
         ;; - if that fails, it fetches the topic and updates the db
         ;;  - and then grabs the topic from the db
         ;;
         ;; Since fetching fns are async with a callback, have to wrap it into a deferred
         (topic
          (or
           (forge-get-topic repo topic-num)
           (deferred:sync!
            (deferred:$
             (deferred:next
              (lambda ()
                (let* ((d (deferred:new #'identity))
                       (fetch-fn (if issue 'ghub-fetch-issue
                                   'ghub-fetch-pullreq))
                       (update-fn (if issue 'forge--update-issue
                                    'forge--update-pullreq)))
                  (funcall
                   fetch-fn
                   owner repo-name topic-num
                   (lambda (data)
                     (funcall update-fn repo data nil)
                     (deferred:callback-post
                      d
                      (forge-get-topic repo topic-num))))
                  d))))))))
    ;; otherwise it complains for not running inside a git repo
    (cl-letf (((symbol-function #'magit-toplevel)
               (lambda () default-directory)))
      (forge-topic-setup-buffer topic))))

What a rabbit hole indeed. The more I look at this, the more I feel like "This is a bad idea!" 😂.

I have a first draft of the solution in forge branch. I won't be pushing this to "develop", until I do some more tests, and cover some more edge cases and add proper documentation as well.

Compared to your code:

  • Instead of deffered, I am using a while-loop, it's simpler and hopefully easier to maintain later. I added a custom variable consult-gh-forge-timeout-seconds, which is the max time, it tries to use forge and if it cannot load it, it reverts back to viewing issues in a normal emacs buffer (a.k.a. consult-gh-issue-view-action.
  • I am not using default-directory, instead I pass "/" as default-directory because otherwise, when you are inside a git directory, magit wants to refresh and asks if it should save files, etc.

If you want to use/test it, make sure you load "consult-gh" after forge. Then use this config:

(require 'consult-gh-forge)
(setq consult-gh-issue-action #'consult-gh-forge--issue-view-action)
(setq consult-gh-forge-timeout-seconds 10) ;; after the time-out it reverts back to consult-gh-issue-view

the more I feel like "This is a bad idea!"

Yeah, this stuff should be in magit/forge. I'll try to free up some time and see if I can make a PR there. I don't regret spending time to figure out that function though, it's super useful. I have a bunch of url converters, I use them to copy&paste links and very often they are GitHub urls. So, for example: I would grab a link from GitHub, and put it in my notes, but the link like github.com/org/project/issues/42 doesn't tell me anything, so I convert it into a more descriptive form. But then, when sharing context of my note with my colleague, I can't just send the org-mode link, it won't look nice in the chat, I have to convert it to markdown.

Now, with your package and this forge-visit-topic-via-url I can quickly find and preview issues and PRs - be that a raw url, or a markdown/org-mode link, or a bug-reference-mode label. Super cool.

the more I feel like "This is a bad idea!"

Yeah, this stuff should be in magit/forge. I'll try to free up some time and see if I can make a PR there. I don't regret spending time to figure out that function though, it's super useful. I have a bunch of url converters, I use them to copy&paste links and very often they are GitHub urls. So, for example: I would grab a link from GitHub, and put it in my notes, but the link like github.com/org/project/issues/42 doesn't tell me anything, so I convert it into a more descriptive form. But then, when sharing context of my note with my colleague, I can't just send the org-mode link, it won't look nice in the chat, I have to convert it to markdown.

Now, with your package and this forge-visit-topic-via-url I can quickly find and preview issues and PRs - be that a raw url, or a markdown/org-mode link, or a bug-reference-mode label. Super cool.

Great, I'm glad you like this! and yes, we are really hacking forge, to separate the magit ui features from the fetching and formatting content. I think this can be done either in forge or ghub package but I think that's a huge task given how interconnected the forge and magit packages are and given that it supports more than just GitHub!.

By the way, if all you need is to see the full thread for an issue (and not the forge folding ui, etc.), I just fixed the code, so consult-gh-issue--view shows the entire thread now. This is already in develop.

@agzam I updated the forge branch, now you can even edit issues (e.g. add comments) from forge! I am adding this comment from forge right now :D.

I am closing this now, since the forge branch merge achieves what is asked here.
There are other forge-related integration and ideas we can work on in the future, but we might as well open new issues when needed and close this one here.