diff options
Diffstat (limited to 'lisp/package/package-misc.el')
| -rw-r--r-- | lisp/package/package-misc.el | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/lisp/package/package-misc.el b/lisp/package/package-misc.el new file mode 100644 index 00000000000..0432ab06f83 --- /dev/null +++ b/lisp/package/package-misc.el | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | ;;; package-misc.el --- Miscellaneous Packaging Functionality -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2025 Philip Kaludercic | ||
| 4 | |||
| 5 | ;; Author: Philip Kaludercic <philipk@posteo.net> | ||
| 6 | |||
| 7 | ;; This program is free software; you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; This program is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ;;; Commentary: | ||
| 21 | |||
| 22 | ;;; Code: | ||
| 23 | |||
| 24 | (require 'package-core) | ||
| 25 | |||
| 26 | (require 'macroexp) | ||
| 27 | |||
| 28 | (defun package--print-email-button (recipient) | ||
| 29 | "Insert a button whose action will send an email to RECIPIENT. | ||
| 30 | NAME should have the form (FULLNAME . EMAIL) where FULLNAME is | ||
| 31 | either a full name or nil, and EMAIL is a valid email address." | ||
| 32 | (when (car recipient) | ||
| 33 | (insert (car recipient))) | ||
| 34 | (when (and (car recipient) (cdr recipient)) | ||
| 35 | (insert " ")) | ||
| 36 | (when (cdr recipient) | ||
| 37 | (insert "<") | ||
| 38 | (insert-text-button (cdr recipient) | ||
| 39 | 'follow-link t | ||
| 40 | 'action (lambda (_) | ||
| 41 | (compose-mail | ||
| 42 | (format "%s <%s>" (car recipient) (cdr recipient))))) | ||
| 43 | (insert ">")) | ||
| 44 | (insert "\n")) | ||
| 45 | |||
| 46 | (declare-function ietf-drums-parse-address "ietf-drums" | ||
| 47 | (string &optional decode)) | ||
| 48 | |||
| 49 | (defun package-maintainers (pkg-desc &optional no-error) | ||
| 50 | "Return an email address for the maintainers of PKG-DESC. | ||
| 51 | The email address may contain commas, if there are multiple | ||
| 52 | maintainers. If no maintainers are found, an error will be | ||
| 53 | signaled. If the optional argument NO-ERROR is non-nil no error | ||
| 54 | will be signaled in that case." | ||
| 55 | (unless (package-desc-p pkg-desc) | ||
| 56 | (error "Invalid package description: %S" pkg-desc)) | ||
| 57 | (let* ((name (package-desc-name pkg-desc)) | ||
| 58 | (extras (package-desc-extras pkg-desc)) | ||
| 59 | (maint (alist-get :maintainer extras))) | ||
| 60 | (unless (listp (cdr maint)) | ||
| 61 | (setq maint (list maint))) | ||
| 62 | (cond | ||
| 63 | ((and (null maint) (null no-error)) | ||
| 64 | (user-error "Package `%s' has no explicit maintainer" name)) | ||
| 65 | ((and (not (progn | ||
| 66 | (require 'ietf-drums) | ||
| 67 | (ietf-drums-parse-address (cdar maint)))) | ||
| 68 | (null no-error)) | ||
| 69 | (user-error "Package `%s' has no maintainer address" name)) | ||
| 70 | (t | ||
| 71 | (with-temp-buffer | ||
| 72 | (mapc #'package--print-email-button maint) | ||
| 73 | (replace-regexp-in-string | ||
| 74 | "\n" ", " (string-trim | ||
| 75 | (buffer-substring-no-properties | ||
| 76 | (point-min) (point-max))))))))) | ||
| 77 | |||
| 78 | ;;;###autoload | ||
| 79 | (defun package-report-bug (desc) | ||
| 80 | "Prepare a message to send to the maintainers of a package. | ||
| 81 | DESC must be a `package-desc' object. | ||
| 82 | |||
| 83 | Of interest to package maintainers: By default, the command will use | ||
| 84 | `reporter-submit-bug-report' to generate a message buffer. If your | ||
| 85 | package has specific needs, you can set the symbol property | ||
| 86 | `package-report-bug-function' of the symbol designating your package | ||
| 87 | name. | ||
| 88 | " | ||
| 89 | (interactive (list (package--query-desc package-alist)) | ||
| 90 | package-menu-mode) | ||
| 91 | (let ((maint (package-maintainers desc)) | ||
| 92 | (name (symbol-name (package-desc-name desc))) | ||
| 93 | (pkgdir (package-desc-dir desc)) | ||
| 94 | vars) | ||
| 95 | (when pkgdir | ||
| 96 | (dolist-with-progress-reporter (group custom-current-group-alist) | ||
| 97 | "Scanning for modified user options..." | ||
| 98 | (when (and (car group) | ||
| 99 | (file-in-directory-p (car group) pkgdir)) | ||
| 100 | (dolist (ent (get (cdr group) 'custom-group)) | ||
| 101 | (when (and (custom-variable-p (car ent)) | ||
| 102 | (boundp (car ent)) | ||
| 103 | (not (eq (custom--standard-value (car ent)) | ||
| 104 | (default-toplevel-value (car ent))))) | ||
| 105 | (push (car ent) vars)))))) | ||
| 106 | (dlet ((reporter-prompt-for-summary-p t)) | ||
| 107 | (funcall (or (get name 'package-report-bug-function) | ||
| 108 | #'reporter-submit-bug-report) | ||
| 109 | maint name vars)))) | ||
| 110 | |||
| 111 | ;;;; Inferring package from current buffer | ||
| 112 | (defun package-read-from-string (str) | ||
| 113 | "Read a Lisp expression from STR. | ||
| 114 | Signal an error if the entire string was not used." | ||
| 115 | (pcase-let ((`(,expr . ,offset) (read-from-string str))) | ||
| 116 | (condition-case () | ||
| 117 | ;; The call to `ignore' suppresses a compiler warning. | ||
| 118 | (progn (ignore (read-from-string str offset)) | ||
| 119 | (error "Can't read whole string")) | ||
| 120 | (end-of-file expr)))) | ||
| 121 | |||
| 122 | |||
| 123 | (defun package--alist-to-plist-args (alist) | ||
| 124 | (mapcar #'macroexp-quote | ||
| 125 | (apply #'nconc | ||
| 126 | (mapcar (lambda (pair) (list (car pair) (cdr pair))) alist)))) | ||
| 127 | |||
| 128 | (provide 'package-misc) | ||
| 129 | ;;; package-misc.el ends here | ||