feat: add ghpr-list-prs

This commit is contained in:
Lucas Sta Maria 2025-08-22 22:48:35 +08:00
parent 28e18f7ecb
commit 8723768c9d
Signed by: lucas
GPG key ID: F07FB16A826E3B47
4 changed files with 119 additions and 1 deletions

View file

@ -23,6 +23,59 @@
;;; Code: ;;; Code:
(require 'auth-source)
(require 'request)
(require 'json)
(defun ghpr--get-token ()
"Retrieve GitHub authentication token from auth-sources.
Returns the token string if found, nil otherwise."
(auth-source-pick-first-password :host "api.github.com"))
(defun ghpr--parse-api-pr (pr)
"Parse a single pull request object, keeping only essential fields."
(let* ((get (lambda (field) (alist-get field pr)))
(base (get 'base))
(user (get 'user)))
`((url . ,(get 'url))
(id . ,(get 'id))
(diff_url . ,(get 'diff_url))
(patch_url . ,(get 'patch_url))
(number . ,(get 'number))
(state . ,(get 'state))
(locked . ,(get 'locked))
(title . ,(get 'title))
(body . ,(get 'body))
(username . ,(alist-get 'login user))
(base_sha . ,(alist-get 'sha base))
(merge_commit_sha . ,(get 'merge_commit_sha)))))
(defun ghpr--parse-api-pr-list (pr-list)
"Parse a list of pull request objects, keeping only essential fields."
(mapcar #'ghpr--parse-api-pr pr-list))
(defun ghpr--list-open-prs (repo-name)
"List open pull requests for REPO-NAME in owner/repo format.
Returns a list of pull request objects on success, nil on failure."
(let ((token (ghpr--get-token))
(url (format "https://api.github.com/repos/%s/pulls?state=open" repo-name))
(result nil))
(when token
(request url
:type "GET"
:headers `(("Accept" . "application/vnd.github+json")
("Authorization" . ,(format "Bearer %s" token))
("X-GitHub-Api-Version" . "2022-11-28"))
:parser 'json-read
:sync t
:success (cl-function
(lambda (&key data &allow-other-keys)
(setq result (ghpr--parse-api-pr-list data))))
:error (cl-function
(lambda (&key error-thrown &allow-other-keys)
(message "Error fetching pull requests: %s" error-thrown)))))
result))
(provide 'ghpr-api) (provide 'ghpr-api)
;;; ghpr-api.el ends here ;;; ghpr-api.el ends here

View file

@ -31,6 +31,16 @@
;;; Code: ;;; Code:
(require 'magit)
(defun ghpr--get-repo-name ()
"Get the GitHub repository name in owner/repo format from origin remote.
Returns nil if origin remote doesn't exist or is not a GitHub repository."
(when (magit-remote-p "origin")
(let ((origin-url (magit-get "remote.origin.url")))
(when (string-match "github\\.com[:/]\\([^/]+/[^/.]+\\)" origin-url)
(match-string 1 origin-url)))))
(provide 'ghpr-repo) (provide 'ghpr-repo)
;;; ghpr-repo.el ends here ;;; ghpr-repo.el ends here

34
ghpr-utils.el Normal file
View file

@ -0,0 +1,34 @@
;;; ghpr-utils.el --- Utility functions for ghpr -*- lexical-binding: t -*-
;; This file is not part of GNU Emacs
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Provides utility functions for ghpr.el.
;;; Code:
(defun ghpr--display-pr-item (pr)
"Displays a PR item for selection from the minibuffer."
(let* ((number (alist-get 'number pr))
(title (alist-get 'title pr))
(display-text (format "[#%s] %s" number title)))
(cons display-text pr)))
(provide 'ghpr-utils)
;;; ghpr-utils.el ends here

23
ghpr.el
View file

@ -3,7 +3,7 @@
;; Author: Lucas Sta Maria ;; Author: Lucas Sta Maria
;; Maintainer: Lucas Sta Maria ;; Maintainer: Lucas Sta Maria
;; Version: 0.1 ;; Version: 0.1
;; Package-Requires: (magit) ;; Package-Requires: (magit request)
;; Homepage: https://git.priime.dev/lucas/ghpr.el ;; Homepage: https://git.priime.dev/lucas/ghpr.el
;; Keywords: git ;; Keywords: git
@ -32,6 +32,27 @@
;;; Code: ;;; Code:
(require 'ghpr-api)
(require 'ghpr-repo)
(require 'ghpr-utils)
(defun ghpr-prs ()
"List and choose from the current repository's open PRs."
(interactive)
(let* ((repo-name (ghpr--get-repo-name))
(prs (and repo-name (ghpr--list-open-prs repo-name))))
(cond
((not repo-name)
(message "Not in a GitHub repository"))
((not prs)
(message "No open pull requests found"))
(t
(let* ((pr-items (mapcar #'ghpr--display-pr-item prs))
(selected-item (completing-read "Select PR: " pr-items nil t)))
(when selected-item
(let ((pr (cdr (assoc selected-item pr-items))))
pr)))))))
(provide 'ghpr) (provide 'ghpr)
;;; ghpr.el ends here ;;; ghpr.el ends here