feat: add ghpr-review-mode

This commit is contained in:
Lucas Sta Maria 2025-08-23 00:31:04 +08:00
parent 30cfe3b7f3
commit 0179cd25ff
Signed by: lucas
GPG key ID: F07FB16A826E3B47
2 changed files with 90 additions and 0 deletions

View file

@ -75,6 +75,26 @@ Returns a list of pull request objects on success, nil on failure."
(message "Error fetching pull requests: %s" error-thrown))))) (message "Error fetching pull requests: %s" error-thrown)))))
result)) result))
(defun ghpr--get-diff-content (repo-name pr-number)
"Retrieve the diff contents for PR-NUMBER in REPO-NAME."
(let ((token (ghpr--get-token))
(url (format "https://api.github.com/repos/%s/pulls/%s" repo-name pr-number))
(result nil))
(when token
(request url
:type "GET"
:headers `(("Accept" . "application/vnd.github.diff")
("Authorization" . ,(format "Bearer %s" token))
("X-GitHub-Api-Version" . "2022-11-28"))
:sync t
:success (cl-function
(lambda (&key data &allow-other-keys)
(setq result data)))
:error (cl-function
(lambda (&key error-thrown &allow-other-keys)
(message "Error fetching diff: %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,76 @@
;;; Code: ;;; Code:
(require 'request)
(require 'ghpr-api)
(require 'ghpr-utils)
(defface ghpr-review-added-line
'((t (:background "green" :foreground "black")))
"Face for added lines in PR diff."
:group 'ghpr)
(defface ghpr-review-removed-line
'((t (:background "red" :foreground "black")))
"Face for removed lines in PR diff."
:group 'ghpr)
(defvar ghpr-review-font-lock-keywords
'(("^\\(> \\+[^+]\\)\\(.*\\)$"
(0 'ghpr-review-added-line t))
("^\\(> \\+\\)$" ; Handle line with just "> +"
(0 'ghpr-review-added-line t))
("^\\(> -[^-]\\)\\(.*\\)$"
(0 'ghpr-review-removed-line t))
("^\\(> -\\)$" ; Handle line with just "> -"
(0 'ghpr-review-removed-line t)))
"Font lock keywords for ghpr-review-mode.")
(define-derived-mode ghpr-review-mode text-mode "GHPR Review"
"Major mode for reviewing GitHub pull requests."
:group 'ghpr
(setq truncate-lines t)
(setq font-lock-defaults '(ghpr-review-font-lock-keywords t nil nil nil))
(font-lock-ensure))
(defun ghpr--prefix-line (line)
"Prefix the LINE with `> '."
(concat "> " line))
(defun ghpr--prefix-lines (text)
"Prefix every line in TEXT with `> '."
(let ((lines (split-string text "\n")))
(mapconcat #'ghpr--prefix-line lines "\n")))
(defun ghpr--open-pr/collect-contents (pr repo-name)
"Return a string of the title, body, and patch content separated by newlines."
(let* ((body (or (alist-get 'body pr) ""))
(number (alist-get 'number pr))
(content-parts (list (ghpr--pr-summary pr))))
(when (not (string-empty-p body))
(push body content-parts))
(let ((patch-content (ghpr--get-diff-content repo-name number)))
(when patch-content
(push patch-content content-parts)))
(mapconcat 'identity (reverse content-parts) "\n\n")))
(defun ghpr--open-pr/insert-contents (pr repo-name)
"Insert the contents of the pr into the current buffer."
(erase-buffer)
(let ((contents (ghpr--open-pr/collect-contents pr repo-name)))
(insert (ghpr--prefix-lines contents))))
(defun ghpr--open-pr (pr repo-name)
"Open a new buffer containing the body of the PR."
(let* ((number (alist-get 'number pr))
(buffer-name (format "*ghpr-pr-%s*" number))
(buffer (get-buffer-create buffer-name)))
(with-current-buffer buffer
(ghpr-review-mode)
(ghpr--open-pr/insert-contents pr repo-name)
(goto-char (point-min)))
(display-buffer buffer)))
(provide 'ghpr-review) (provide 'ghpr-review)
;;; ghpr-review.el ends here ;;; ghpr-review.el ends here