branch: externals/gnu-elpa commit cd18964ec3176ab99d626da4ca6ca7d4bf2389db Author: Stefan Monnier <monn...@iro.umontreal.ca> Commit: Stefan Monnier <monn...@iro.umontreal.ca>
* gnu-elpa-maint.el: Use a more compact gnu-elpa--autoloads-table The old table listed all the autoloaded functions. The new table only lists the prefixes needed to decide in which package to find the function. (gnu-elpa--single-pkg, gnu-elpa--prefixes): New functions. (gnu-elpa--make-features): Use them. * gnu-elpa-utils.el (gnu-elpa--package): Adjust lookup accordingly. * gnu-elpa-features.el: Update. --- gnu-elpa-features.el | 131 +++++++++++++++++++++++++++++++++++++++++++++------ gnu-elpa-maint.el | 43 +++++++++++++++-- gnu-elpa-utils.el | 8 ++-- gnu-elpa.el | 2 +- 4 files changed, 160 insertions(+), 24 deletions(-) diff --git a/gnu-elpa-features.el b/gnu-elpa-features.el index cf23086..7debb6e 100644 --- a/gnu-elpa-features.el +++ b/gnu-elpa-features.el @@ -928,10 +928,10 @@ CSV mode provides the following specific keyboard key bindings: (fn)" t nil) (darkroom-tentative-mode "Enters `darkroom-mode' when all other windows are deleted. -If called interactively, enable DarkRoom-Tentative mode if ARG is positive, and -disable it if ARG is zero or negative. If called from Lisp, -also enable the mode if ARG is omitted or nil, and toggle it -if ARG is `toggle'; disable the mode otherwise. +If called interactively, enable DarkRoom-Tentative mode if ARG is +positive, and disable it if ARG is zero or negative. If called +from Lisp, also enable the mode if ARG is omitted or nil, and +toggle it if ARG is `toggle'; disable the mode otherwise. (fn &optional ARG)" t nil) (darkroom-mode "Remove visual distractions and focus on writing. When this @@ -940,10 +940,10 @@ view. The buffer margins are set so that text is centered on screen. Text size is increased (display engine allowing) by `darkroom-text-scale-increase'. -If called interactively, enable Darkroom mode if ARG is positive, and -disable it if ARG is zero or negative. If called from Lisp, -also enable the mode if ARG is omitted or nil, and toggle it -if ARG is `toggle'; disable the mode otherwise. +If called interactively, enable Darkroom mode if ARG is positive, +and disable it if ARG is zero or negative. If called from Lisp, +also enable the mode if ARG is omitted or nil, and toggle it if +ARG is `toggle'; disable the mode otherwise. (fn &optional ARG)" t nil) (dbus-codegen-make-proxy "Create a new D-Bus proxy based on the introspection data. @@ -1964,6 +1964,18 @@ Use \\[describe-mode] for more info. (landmark-test-run "Run 100 Landmark games, each time saving the weights from the previous game. (fn)" t nil) + (leaf "Symplify your `.emacs' configuration for package NAME with ARGS. + +(fn NAME &rest ARGS)" nil t) + (leaf-expand "Expand `leaf' at point." t nil) + (leaf-create-issue-template "Create issue template buffer." t nil) + (leaf-pp "Output the pretty-printed representation of leaf SEXP. + +(fn SEXP)" nil nil) + (leaf-pp-to-string "Return format string of `leaf' SEXP like `pp-to-string'. + +(fn SEXP)" nil t) + (leaf-available-keywords "Return current available `leaf' keywords list." t nil) (lex-parse-re "Parse STRING as a regular expression. LEXER specifies the regexp syntax to use. It can be `ere', or `bre' and it defaults to `bre'. @@ -2122,10 +2134,10 @@ Called with a prefix prompt for the difficulty level. (fn &optional ARG)" t nil) (minimap-mode "Toggle minimap mode. -If called interactively, enable Minimap mode if ARG is positive, and -disable it if ARG is zero or negative. If called from Lisp, -also enable the mode if ARG is omitted or nil, and toggle it -if ARG is `toggle'; disable the mode otherwise. +If called interactively, enable Minimap mode if ARG is positive, +and disable it if ARG is zero or negative. If called from Lisp, +also enable the mode if ARG is omitted or nil, and toggle it if +ARG is `toggle'; disable the mode otherwise. (fn &optional ARG)" t nil) (mmm-add-classes "Add the submode classes CLASSES to `mmm-classes-alist'. @@ -3498,6 +3510,95 @@ At the moment, only `tiny-mapconcat' is supported. (transcribe-mode "Toggle transcribe-mode (fn &optional ARG)" t nil) + (define-infix-command "Define NAME as a transient infix command. + +ARGLIST is always ignored and reserved for future use. +DOCSTRING is the documentation string and is optional. + +The key-value pairs are mandatory. All transient infix commands +are equal to each other (but not eq), so it is meaningless to +define an infix command without also setting at least `:class' +and one other keyword (which it is depends on the used class, +usually `:argument' or `:variable'). + +Each key has to be a keyword symbol, either `:class' or a keyword +argument supported by the constructor of that class. The +`transient-switch' class is used if the class is not specified +explicitly. + +The function definitions is always: + + (lambda () + (interactive) + (let ((obj (transient-suffix-object))) + (transient-infix-set obj (transient-infix-read obj))) + (transient--show)) + +`transient-infix-read' and `transient-infix-set' are generic +functions. Different infix commands behave differently because +the concrete methods are different for different infix command +classes. In rare case the above command function might not be +suitable, even if you define your own infix command class. In +that case you have to use `transient-suffix-command' to define +the infix command and use t as the value of the `:transient' +keyword. + +(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)" nil t) + (define-suffix-command "Define NAME as a transient suffix command. + +ARGLIST are the arguments that the command takes. +DOCSTRING is the documentation string and is optional. + +These arguments can optionally be followed by key-value pairs. +Each key has to be a keyword symbol, either `:class' or a +keyword argument supported by the constructor of that class. +The `transient-suffix' class is used if the class is not +specified explicitly. + +The BODY must begin with an `interactive' form that matches +ARGLIST. The infix arguments are usually accessed by using +`transient-args' inside `interactive'. + +(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]... BODY...)" nil t) + (define-transient-command "Define NAME as a transient prefix command. + +ARGLIST are the arguments that command takes. +DOCSTRING is the documentation string and is optional. + +These arguments can optionally be followed by key-value pairs. +Each key has to be a keyword symbol, either `:class' or a keyword +argument supported by the constructor of that class. The +`transient-prefix' class is used if the class is not specified +explicitly. + +GROUPs add key bindings for infix and suffix commands and specify +how these bindings are presented in the popup buffer. At least +one GROUP has to be specified. See info node `(transient)Binding +Suffix and Infix Commands'. + +The BODY is optional. If it is omitted, then ARGLIST is also +ignored and the function definition becomes: + + (lambda () + (interactive) + (transient-setup \\='NAME)) + +If BODY is specified, then it must begin with an `interactive' +form that matches ARGLIST, and it must call `transient-setup'. +It may however call that function only when some condition is +satisfied; that is one of the reason why you might want to use +an explicit BODY. + +All transients have a (possibly nil) value, which is exported +when suffix commands are called, so that they can consume that +value. For some transients it might be necessary to have a sort +of secondary value, called a scope. Such a scope would usually +be set in the commands `interactive' form and has to be passed +to the setup function: + + (transient-setup \\='NAME nil nil :scope SCOPE) + +(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]... GROUP... [BODY...])" nil t) (global-undo-tree-mode "Toggle Undo-Tree mode in all buffers. With prefix ARG, enable Global Undo-Tree mode if ARG is positive; otherwise, disable it. If called from Lisp, enable the mode if @@ -3985,10 +4086,12 @@ in SKIP-SET-STRING. (xr-lint "Detect dubious practices and possible mistakes in RE-STRING. This includes uses of tolerated but discouraged constructs. Outright regexp syntax violations are signalled as errors. +If PURPOSE is `file', perform additional checks assuming that RE-STRING +is used to match a file name. Return a list of (OFFSET . COMMENT) where COMMENT applies at OFFSET in RE-STRING. -(fn RE-STRING)" nil nil) +(fn RE-STRING &optional PURPOSE)" nil nil) (xr-skip-set "Convert a skip set string argument to rx notation. SKIP-SET-STRING is interpreted according to the syntax of `skip-chars-forward' and `skip-chars-backward' and converted to @@ -4097,7 +4200,7 @@ Argument DIR2 right directory. (add-to-list 'auto-mode-alist '("\\.[Vv][Cc][Ff]\\'" . vcard-mode)) (add-to-list 'auto-mode-alist (cons (purecopy "\\.vcl\\'") 'vcl-mode)) (add-to-list 'auto-mode-alist '("\\.wy\\'" . wisitoken-grammar-mode)) -(defconst gnu-elpa--autoloads-table '(["ace-window" ace-window-display-mode ace-window ace-maximize-window ace-swap-window ace-delete-window ace-select-window] ["ack" pcomplete/ag pcomplete/ack ack] ["adaptive-wrap" adaptive-wrap-prefix-mode] ["adjust-parens" adjust-parens-mode] ["advice-patch" advice-patch] ["aggressive-indent" global-aggressive-indent-mode aggressive-indent-mode aggressive-indent-indent-region-and-on aggressive-indent-indent-defun] ["all" all] ["ampc" ampc ampc-on-p am [...] +(defconst gnu-elpa--autoloads-table '(("ace-" . "ace-window") ("ack" . "ack") ("adaptive-wrap-prefix-mode" . "adaptive-wrap") ("adjust-parens-mode" . "adjust-parens") ("advice-patch" . "advice-patch") ("aggressive-indent-" . "aggressive-indent") ("all" . "all") ("ampc" . "ampc") ("arbitools-mode" . "arbitools") ("aa2u" . "ascii-art-to-unicode") ("async-" . "async") ("aumix" . "aumix-mode") ("auto-correct-" . "auto-correct") ("auto-overlay" . "auto-overlays") ("pcomplete/a" . "ack") ("pro [...] ;; Local Variables: ;; no-byte-compile: t diff --git a/gnu-elpa-maint.el b/gnu-elpa-maint.el index e073b23..b106740 100644 --- a/gnu-elpa-maint.el +++ b/gnu-elpa-maint.el @@ -32,6 +32,7 @@ ;;; Code: (require 'map) +(require 'radix-tree) ;; FIXME: Skip those packages that aren't released, e.g. w3 and sm-c-mode @@ -134,6 +135,36 @@ ;; (:others . ,others) ))) +(defun gnu-elpa--single-pkg (subtree) + ;; Check to see if all the names inside `subtree' map to the + ;; same package. Return that package if yes, and nil otherwise. + (catch 'multiple + (let ((thepkg nil)) + (radix-tree-iter-mappings subtree + (lambda (_prefix pkg) + (cond + ((null thepkg) (setq thepkg pkg)) + ((eq thepkg pkg) nil) + (t (throw 'multiple nil))))) + thepkg))) + +(defun gnu-elpa--prefixes (tree) + (let ((todo nil) + (done nil)) + (radix-tree-iter-subtrees + tree (lambda (prefix subtree) + (push (cons prefix subtree) todo))) + (while todo + (pcase-let* ((`(,prefix . ,subtree) (pop todo)) + (thepkg (gnu-elpa--single-pkg subtree))) + (if thepkg (push (cons prefix thepkg) done) + ;; This same prefix is used by various packages, so we need + ;; to dig deeper. + (radix-tree-iter-subtrees + subtree (lambda (subprefix subtree) + (push (cons (concat prefix subprefix) subtree) todo)))))) + done)) + (defun gnu-elpa--make-features () (let (;; Make sure we can load this file without load-source-file-function. (coding-system-for-write 'emacs-internal)) @@ -164,14 +195,16 @@ ;; Don't edit this file, it's auto-generated by `gnu-elpa--make-features'! \n") - (let ((auto-table nil) + (let ((tree nil) (allforms nil)) (insert "(dolist (x '(") (dolist (pkg (gnu-elpa--pkgs)) - (pcase-let* (((map :autoloads :forms) (gnu-elpa--features-for-pkg pkg))) + (pcase-let* (((map :autoloads :forms) + (gnu-elpa--features-for-pkg pkg))) (when autoloads - (push (apply #'vector pkg (mapcar #'car autoloads)) - auto-table) + (dolist (autoload autoloads) + (setq tree (radix-tree-insert + tree (symbol-name (car autoload)) pkg))) (setf allforms (append forms allforms)) (dolist (x autoloads) (prin1 x (current-buffer)) @@ -186,7 +219,7 @@ ;; FIXME: Actually `gnu-elpa--autoloads-table' doesn't need to be ;; preloaded from `gnu-elpa-features' so it could be moved to ;; another file! - (prin1 `(defconst gnu-elpa--autoloads-table ',(nreverse auto-table)) + (prin1 `(defconst gnu-elpa--autoloads-table ',(gnu-elpa--prefixes tree)) (current-buffer))) ;; Use `\s' instead of a space character, so this code chunk is not ;; mistaken for an actual file-local section of gnu-elpa-maint.el. diff --git a/gnu-elpa-utils.el b/gnu-elpa-utils.el index 6f148b8..2b4a8cc 100644 --- a/gnu-elpa-utils.el +++ b/gnu-elpa-utils.el @@ -50,10 +50,10 @@ (defun gnu-elpa--package (func) "Return the package that provides function FUNC." - (let ((pkg nil)) - (dolist (pkg-desc gnu-elpa--autoloads-table) - (mapc (lambda (f) (if (eq f func) (setq pkg (aref pkg-desc 0)))) pkg-desc)) - pkg)) + (let ((thepkg nil)) + (pcase-dolist (`(,prefix . ,pkg) gnu-elpa--autoloads-table) + (if (string-prefix-p prefix (symbol-name func)) (setq thepkg pkg))) + thepkg)) (defun gnu-elpa--perform-autoload () "Prompt to install the package that provides the currently autoloaded function. diff --git a/gnu-elpa.el b/gnu-elpa.el index 088bc7f..a17f4ad 100644 --- a/gnu-elpa.el +++ b/gnu-elpa.el @@ -4,7 +4,7 @@ ;; Author: Stefan Monnier <monn...@iro.umontreal.ca> ;; Keywords: -;; Version: 1.0 +;; Version: 1.1 ;; 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