summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Voss <thomas.voss@humanwave.nl> 2025-06-13 14:57:02 +0200
committerThomas Voss <thomas.voss@humanwave.nl> 2025-06-13 14:57:02 +0200
commit64ed33f3d7dc64dd41d35f194279fcc868f907a5 (patch)
tree4cbe76484fda7bb790ec30df33a3902f42dbefb2
parent1b25bda0409dc045841875c1273e186b14e660b7 (diff)
emacs: Add GitHub integrationHEADmaster
-rw-r--r--.config/emacs/modules/mm-projects.el45
-rw-r--r--.config/emacs/site-lisp/gh.el39
2 files changed, 84 insertions, 0 deletions
diff --git a/.config/emacs/modules/mm-projects.el b/.config/emacs/modules/mm-projects.el
index 00342f5..71006d5 100644
--- a/.config/emacs/modules/mm-projects.el
+++ b/.config/emacs/modules/mm-projects.el
@@ -96,4 +96,49 @@ This is intended to be called interactively via
(require 'ansi-color)
(add-hook 'compilation-filter-hook #'ansi-color-compilation-filter))
+
+;;; GitHub Pull Requests
+
+(require 'gh)
+(keymap-global-set "C-c p" #'gh-create-pr)
+
+;; (defun mm-gh--get-labels ()
+;; (with-temp-buffer
+;; (call-process "gh" nil t nil "label" "list" "--json" "name")
+;; (goto-char (point-min))
+;; (let* ((data (json-parse-buffer))
+;; (labels (seq-map (lambda (x) (gethash "name" x)) data)))
+;; (sort labels
+;; :in-place t
+;; :lessp (lambda (x y)
+;; (let ((prefix-x-p (string-prefix-p "Sprint " x))
+;; (prefix-y-p (string-prefix-p "Sprint " y)))
+;; (cond
+;; ((and prefix-x-p prefix-y-p) (string> x y))
+;; (prefix-x-p t)
+;; (prefix-y-p nil)
+;; (:else (string< x y)))))))))
+
+;; (defun mm-gh-create-pr (title draftp labels)
+;; "Create a GitHub pull request using the gh CLI.
+;; If DRAFT is non-nil, the PR will be created as a draft.
+;; LABELS should be a comma-separated string of GitHub labels."
+;; (interactive
+;; (list
+;; (read-string (format-prompt "PR Title" nil))
+;; (y-or-n-p "Create as draft PR? ")
+;; (completing-read-multiple (format-prompt "PR Labels" nil)
+;; (mm-gh--get-labels))))
+;; (let* ((branch (car (vc-git-branches)))
+;; (title (format "%s %s" branch title))
+;; (flags `("--fill-verbose" "--title" ,title "--assignee" "@me"))
+;; (label-string (mapconcat #'identity labels ",")))
+;; (when draftp
+;; (setq flags (append flags '("--draft"))))
+;; (when labels
+;; (setq flags (append flags `("--label" ,label-string))))
+;; (with-temp-buffer
+;; (apply #'call-process "gh" nil t nil "pr" "create" flags)
+;; (message (buffer-string)))))
+
(provide 'mm-projects) \ No newline at end of file
diff --git a/.config/emacs/site-lisp/gh.el b/.config/emacs/site-lisp/gh.el
new file mode 100644
index 0000000..0461b18
--- /dev/null
+++ b/.config/emacs/site-lisp/gh.el
@@ -0,0 +1,39 @@
+;;; gh.el --- GitHub integration for Emacs -*- lexical-binding: t; -*-
+
+(defun gh-get-labels ()
+ "Return a list of labels in the current GitHub repository."
+ (with-temp-buffer
+ (call-process "gh" nil t nil "label" "list" "--sort" "name" "--json" "name")
+ (goto-char (point-min))
+ (seq-map (lambda (x) (gethash "name" x))
+ (json-parse-buffer))))
+
+;; TODO: Set title and body in a buffer like Magit
+(defun gh-create-pr (title &optional labels draftp)
+ "Create a GitHub pull request.
+If DRAFTP is non-nil, the PR will be created as a draft.
+
+LABELS is a list of labels. A list of available labels can be fetched
+via `gh-get-labels'."
+ (interactive
+ (list
+ (read-string (format-prompt "PR Title" nil))
+ (completing-read-multiple (format-prompt "PR Labels" nil)
+ (gh-get-labels))
+ (y-or-n-p "Create PR as a draft? ")))
+ (let* ((project (project-name (project-current)))
+ (flags `("--fill-verbose" "--assignee" "@me"))
+ (label-string (mapconcat #'identity labels ",")))
+ ;; TODO: Remove this
+ (when (string= project "blixem")
+ (setq title (format "%s %s" (car (vc-git-branches)) title)))
+ (setq flags (append flags `("--title" ,title)))
+ (when draftp
+ (setq flags (append flags '("--draft"))))
+ (when labels
+ (setq flags (append flags `("--label" ,label-string))))
+ (with-temp-buffer
+ (apply #'call-process "gh" nil t nil "pr" "create" flags)
+ (message (buffer-string)))))
+
+(provide 'gh) \ No newline at end of file