summaryrefslogtreecommitdiff
path: root/admin
diff options
context:
space:
mode:
authorPhilip Kaludercic <philipk@posteo.net>2026-02-09 19:22:07 +0100
committerPhilip Kaludercic <philipk@posteo.net>2026-02-09 21:12:21 +0100
commit4a3640c3f82142f115c6a7a7e64a4869700d1f64 (patch)
tree6b720264ff6a9a416dbd38ba9c309f2e6700c8b9 /admin
parent1aabe135e644a5f8703cd6d6eac0402b728c9cd3 (diff)
Detect more package suggestions
* admin/scrape-elpa.el (scrape-elpa--safe-eval): Add new function. (scrape-elpa): Evaluate part of the matched expression to catch more entries. * etc/package-autosuggest.eld: Update database.
Diffstat (limited to 'admin')
-rw-r--r--admin/scrape-elpa.el60
1 files changed, 56 insertions, 4 deletions
diff --git a/admin/scrape-elpa.el b/admin/scrape-elpa.el
index f513dc36550..f3e9d7f8d0f 100644
--- a/admin/scrape-elpa.el
+++ b/admin/scrape-elpa.el
@@ -1,6 +1,6 @@
;;; scrape-elpa.el --- Collect ELPA package suggestions -*- lexical-binding: t; -*-
-;; Copyright (C) 2024 Free Software Foundation, Inc.
+;; Copyright (C) 2024, 2026 Free Software Foundation, Inc.
;; Author: Philip Kaludercic <philipk@posteo.net>
;; Keywords: tools
@@ -25,6 +25,39 @@
;;; Code:
+(require 'rx)
+
+(defun scrape-elpa--safe-eval (exp &optional vars)
+ "Manually evaluate EXP without potentially dangerous side-effects.
+The optional argument VARS may be an alist mapping symbols to values,
+used when evaluating variables. The evaluation function is not meant to
+be comprehensive, but just to handle the kinds of expressions that
+`scrape-elpa' expects to encounter."
+ (pcase-exhaustive exp
+ ;; special handling for macros
+ (`(rx . ,body) (rx-to-string `(: . ,body) t))
+ ;; quoting and quasi-quoting
+ (`',x x)
+ (`(purecopy ,x) x)
+ ((and (guard (eq '\` (car-safe exp))) (let `(,car . ,cdr) (cadr exp)))
+ (cons
+ (if (eq (car-safe car) '\,) (scrape-elpa--safe-eval (cadr car) vars) car)
+ (if (eq (car-safe cdr) '\,) (scrape-elpa--safe-eval (cadr cdr) vars) cdr)))
+ ;; supported functions
+ (`(cons ,car ,cdr)
+ (cons (scrape-elpa--safe-eval car vars)
+ (scrape-elpa--safe-eval cdr vars)))
+ (`(concat . ,args)
+ (apply #'concat (mapcar #'scrape-elpa--safe-eval args)))
+ ;; self-evaluating forms
+ ((pred macroexp-const-p) exp)
+ ;; variable evaluation
+ ((pred symbolp)
+ (let ((ent (assq exp vars)))
+ (if ent (cdr ent) (signal 'void-variable exp))))))
+
+(scrape-elpa--safe-eval '(cons "\\.go\\'" 'go-mode))
+
(defun scrape-elpa (&rest directories)
"Scrape autoload files in DIRECTORIES for package suggestions.
This file will automatically update \"package-autosuggest.eld\", but not
@@ -57,6 +90,7 @@ Please review the results before updating the autosuggest database!"
"Scraping files..."
(and-let* (((string-match "/\\([^/]+?\\)-autoloads\\.el\\'" file))
(pkg (intern (match-string 1 file)))
+ (vars (list '(#:nihil)))
(inhibit-message t))
(with-temp-buffer
(insert-file-contents file)
@@ -64,16 +98,34 @@ Please review the results before updating the autosuggest database!"
(while t
(dolist (exp (macroexp-unprogn (read (current-buffer))))
(pcase exp
+ (`(defconst ,(and (pred symbolp) var) ,val . ,_)
+ (catch 'ignore
+ (push
+ (cons var (condition-case err
+ (scrape-elpa--safe-eval val vars)
+ (t (message "Failed to evaluate %S: %S in %S" exp err vars)
+ (throw 'ignore nil))))
+ vars)))
(`(add-to-list
',(and (or 'interpreter-mode-alist
'magic-mode-alist
'auto-mode-alist)
variable)
- '(,(and (pred stringp) regexp) .
- ,(and (pred symbolp) mode)))
+ ,(let `(,(and (pred stringp) regexp) .
+ ,(and (pred symbolp) mode))
+ (condition-case err
+ (scrape-elpa--safe-eval _ vars)
+ (t (message "Failed to evaluate %S: %S in %S" exp err vars)
+ nil))))
(terpri)
(prin1 (append (list pkg variable regexp)
- (and (not (eq pkg mode)) (list mode))))))))
+ (and (not (eq pkg mode)) (list mode)))))
+ (`(add-to-list
+ ',(or 'interpreter-mode-alist
+ 'magic-mode-alist
+ 'auto-mode-alist)
+ _)
+ (_ (message "Skipped over %S" exp))))))
(end-of-file nil))))))
(insert "\n)\n")))