1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-12 00:50:43 -08:00

Merge branch 'master' into feature/igc

This commit is contained in:
Gerd Möllmann 2025-08-24 12:15:10 +02:00
commit 7d7ecea0eb
218 changed files with 6084 additions and 2921 deletions

View file

@ -286,6 +286,12 @@ This is used by `declare'.")
(list 'put (list 'quote name)
''edebug-form-spec (list 'quote spec)))))
(defalias 'byte-run--set-autoload-macro
#'(lambda (name _args spec)
(list 'function-put (list 'quote name)
''autoload-macro (list 'quote spec)))
"Handle autoload-macro declarations")
(defalias 'byte-run--set-no-font-lock-keyword
#'(lambda (name _args val)
(list 'function-put (list 'quote name)
@ -365,8 +371,13 @@ This is used by `declare'.")
(cons
(list 'debug #'byte-run--set-debug)
(cons
(list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword)
defun-declarations-alist))
;; macros can declare (autoload-macro expand) to request expansion
;; during autoload generation of forms calling them. See
;; `loaddefs-generate--make-autoload'.
(list 'autoload-macro #'byte-run--set-autoload-macro)
(cons
(list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword)
defun-declarations-alist)))
"List associating properties of macros to their macro expansion.
Each element of the list takes the form (PROP FUN) where FUN is a function.
For each (PROP . VALUES) in a macro's declaration, the FUN corresponding
@ -412,6 +423,8 @@ The return value is undefined.
(if declarations
(cons 'prog1 (cons def (car declarations)))
def))))))
;; Expand to defalias and related forms on autoload gen
(function-put 'defmacro 'autoload-macro 'expand) ; Since we cannot `declare' it
;; Now that we defined defmacro we can use it!
(defmacro defun (name arglist &rest body)
@ -424,7 +437,9 @@ INTERACTIVE is an optional `interactive' specification.
The return value is undefined.
\(fn NAME ARGLIST [DOCSTRING] [DECL] [INTERACTIVE] BODY...)"
(declare (doc-string 3) (indent 2))
(declare (doc-string 3) (indent 2)
;; Expand to defalias on autoload gen
(autoload-macro expand))
(or name (error "Cannot define '%s' as a function" name))
(if (null
(and (listp arglist)

View file

@ -3592,6 +3592,7 @@ This assumes the function has the `important-return-value' property."
(cl-nset-exclusive-or 1 2)
(cl-nreconc 1)
(cl-sort 1) (cl-stable-sort 1) (cl-merge 2 3)
(cl-fill 1) (cl-replace 1)
)))
(dolist (entry mutating-fns)
(put (car entry) 'mutates-arguments (cdr entry))))

View file

@ -230,9 +230,11 @@ SPECIALIZERS-FUNCTION takes as first argument a tag value TAG
(defmacro cl-defgeneric (name args &rest options-and-methods)
"Create a generic function NAME.
DOC-STRING is the base documentation for this class. A generic
function has no body, as its purpose is to decide which method body
is appropriate to use. Specific methods are defined with `cl-defmethod'.
With this implementation the ARGS are currently ignored.
function usually has no body, as its purpose is to decide which
method body is appropriate to use; ARGS are currently ignored if
there's no body. If BODY is present, it provides the default
implementation.
Specific implementation methods are defined with `cl-defmethod'.
OPTIONS-AND-METHODS currently understands:
- (:documentation DOCSTRING)
- (declare DECLARATIONS)
@ -258,7 +260,9 @@ DEFAULT-BODY, if present, is used as the body of a default method.
cl--generic-edebug-make-name in:method]
lambda-doc
def-body)]]
def-body)))
def-body))
;; Expand to defun and related forms on autoload definition
(autoload-macro expand))
(let* ((doc (if (stringp (car-safe options-and-methods))
(pop options-and-methods)))
(declarations nil)

View file

@ -396,7 +396,9 @@ more details.
[&optional ("interactive" interactive)]
def-body))
(doc-string 3)
(indent 2))
(indent 2)
;; expand to function definition on autoload gen
(autoload-macro expand))
`(defun ,name ,@(cl--transform-lambda (cons args body) name)))
;;;###autoload
@ -414,7 +416,9 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
[&optional ("interactive" interactive)]
def-body))
(doc-string 3)
(indent 2))
(indent 2)
;; expand (eventually) to function definition on autoload gen
(autoload-macro expand))
(require 'generator)
`(iter-defun ,name ,@(cl--transform-lambda (cons args body) name)))
@ -473,7 +477,8 @@ more details.
(declare (debug
(&define name cl-macro-list cl-declarations-or-string def-body))
(doc-string 3)
(indent 2))
(indent 2)
(autoload-macro expand)) ; expand to defmacro on autoload gen
`(defmacro ,name ,@(cl--transform-lambda (cons args body) name)))
(def-edebug-elem-spec 'cl-lambda-expr
@ -3087,7 +3092,9 @@ To see the documentation for a defined struct type, use
sexp])]
[&optional stringp]
;; All the above is for the following def-form.
&rest &or symbolp (symbolp &optional def-form &rest sexp))))
&rest &or symbolp (symbolp &optional def-form &rest sexp)))
;; expand to function definitions and related forms on autoload gen
(autoload-macro expand))
(let* ((name (if (consp struct) (car struct) struct))
(warning nil)
(opts (cdr-safe struct))

View file

@ -259,6 +259,7 @@ with empty strings removed."
(list minibuffer-visible-completions-map
map))
map))
(buffer (current-buffer))
input)
(minibuffer-with-setup-hook
(lambda ()
@ -282,6 +283,8 @@ with empty strings removed."
;; see completing_read in src/minibuf.c
(setq-local minibuffer-completion-confirm
(unless (eq require-match t) require-match))
(setq-local minibuffer--require-match require-match)
(setq-local minibuffer--original-buffer buffer)
(setq-local crm-completion-table table))
(setq input (read-from-minibuffer
(format-spec

View file

@ -222,10 +222,12 @@ INIT-VALUE LIGHTER KEYMAP.
(indent defun)
(debug (&define name string-or-null-p
[&optional [&not keywordp] sexp
&optional [&not keywordp] sexp
&optional [&not keywordp] sexp]
&optional [&not keywordp] sexp
&optional [&not keywordp] sexp]
[&rest [keywordp sexp]]
def-body)))
def-body))
;; expand to the command definition on autoload gen
(autoload-macro expand))
(let* ((last-message (make-symbol "last-message"))
(mode-name (symbol-name mode))
@ -488,7 +490,9 @@ after running the major mode's hook. However, MODE is not turned
on if the hook has explicitly disabled it.
\(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)"
(declare (doc-string 2) (indent defun))
(declare (doc-string 2) (indent defun)
;; expand to the minor-mode definition on autoload gen
(autoload-macro expand))
(let* ((global-mode-name (symbol-name global-mode))
(mode-name (symbol-name mode))
(pretty-name (easy-mmode-pretty-mode-name mode))
@ -499,8 +503,8 @@ on if the hook has explicitly disabled it.
(MODE-enable-in-buffer
(intern (concat global-mode-name "-enable-in-buffer")))
(minor-MODE-hook (intern (concat mode-name "-hook")))
(MODE-set-explicitly (intern (concat mode-name "-set-explicitly")))
(MODE-major-mode (intern (concat (symbol-name mode) "-major-mode")))
(MODE-set-explicitly (intern (concat mode-name "--set-explicitly")))
(MODE-major-mode (intern (concat global-mode-name "--major-mode")))
(MODE-predicate (intern (concat (replace-regexp-in-string
"-mode\\'" "" global-mode-name)
"-modes")))

View file

@ -593,7 +593,7 @@ OBJECT can be an instance or a class."
(defun find-class (symbol &optional errorp)
"Return the class that SYMBOL represents.
If there is no class, nil is returned if ERRORP is nil.
If ERRORP is non-nil, `wrong-argument-type' is signaled."
If ERRORP is non-nil, `wrong-type-argument' is signaled."
(let ((class (cl--find-class symbol)))
(cond
((eieio--class-p class) class)

View file

@ -813,7 +813,7 @@ This mainly sets up debugger-related bindings."
(letrec ((debugfun (lambda (err)
(ert--run-test-debugger test-execution-info
err debugfun))))
(handler-bind (((error quit) debugfun))
(handler-bind ((t debugfun))
(funcall (ert-test-body (ert--test-execution-info-test
test-execution-info))))))))
(ert-pass))

View file

@ -675,7 +675,8 @@ encapsulates the state of a computation that produces a sequence
of values. Callers can retrieve each value using `iter-next'."
(declare (indent defun)
(debug (&define name lambda-list lambda-doc &rest sexp))
(doc-string 3))
(doc-string 3)
(autoload-macro expand)) ; expand to the defun on autoload gen
(cl-assert lexical-binding)
(let* ((parsed-body (macroexp-parse-body body))
(declarations (car parsed-body))

View file

@ -135,7 +135,8 @@ After VARS is handled, BODY is evaluated in the new environment."
This is like `defmacro', but has several advantages.
See Info node `(elisp)Defining Functions' for more details."
;; FIXME: How can this work with CL arglists?
(declare (indent defun) (debug defun) (doc-string 3))
(declare (indent defun) (debug defun) (doc-string 3)
(autoload-macro expand)) ; expand to the defun on autoload gen
(let ((doc (if (stringp (car-safe body)) (list (pop body))))
(declares (if (eq (car-safe (car-safe body)) 'declare) (pop body)))
(cm-name (intern (format "%s--inliner" name)))

View file

@ -143,12 +143,37 @@ scanning for autoloads and will be in the `load-path'."
3)
form))
;; The following macros are known to define functions, and are treated
;; specially when encountered during autoload generation, translating
;; calls to them directly into appropriate (autoload function ...)
;; forms.
;;
;; An alternative to appearing on this list is for a macro to declare
;; (autoload-macro expand), so calls to it get expanded into more basic
;; forms during generation. Macros may be removed from this list once
;; they request such expansion and produce suitable output (e.g. by
;; employing :autoload-end to omit unneeded forms).
(defconst loaddefs--defining-macros
'( define-skeleton define-derived-mode define-compilation-mode
define-generic-mode define-globalized-minor-mode define-minor-mode
cl-defun defun* cl-defmacro defmacro* define-overloadable-function
transient-define-prefix transient-define-suffix transient-define-infix
transient-define-argument transient-define-group
;; Obsolete; keep until the alias is removed.
easy-mmode-define-global-mode
easy-mmode-define-minor-mode
define-global-minor-mode))
(defvar loaddefs--load-error-files nil)
(defun loaddefs-generate--make-autoload (form file &optional expansion)
"Turn FORM into an autoload or defvar for source file FILE.
Returns nil if FORM is not a special autoload form (i.e. a function definition
or macro definition or a defcustom).
If EXPANSION is non-nil, we're processing the macro expansion of an
expression, in which case we want to handle forms differently."
expression, in which case we want to handle forms differently.
Note that macros can request expansion by including `(autoload-macro
expand)' among their `declare' forms."
(let ((car (car-safe form)) expand)
(cond
((and expansion (eq car 'defalias))
@ -192,42 +217,58 @@ expression, in which case we want to handle forms differently."
(setq form (copy-sequence form))
(setcdr (memq :autoload-end form) nil))
(let ((exps (delq nil (mapcar (lambda (form)
(loaddefs-generate--make-autoload
form file expansion))
(unless (eq form :autoload-end)
(loaddefs-generate--make-autoload
form file expansion)))
(cdr form)))))
(when exps (cons 'progn exps)))))
;; For complex cases, try again on the macro-expansion.
((and (memq car '( define-globalized-minor-mode defun defmacro
define-minor-mode define-inline
cl-defun cl-defmacro cl-defgeneric
cl-defstruct pcase-defmacro iter-defun cl-iter-defun
;; Obsolete; keep until the alias is removed.
easy-mmode-define-global-mode
easy-mmode-define-minor-mode
define-global-minor-mode))
(macrop car)
(setq expand (let ((load-true-file-name file)
(load-file-name file))
(macroexpand form)))
(memq (car expand) '(progn prog1 defalias)))
;; For macros which request it, try again on their expansion.
((progn
;; If the car is an unknown symbol, we load the file first to
;; give packages a chance to define their macros.
(unless (or (not (symbolp car)) (fboundp car)
;; Special cases handled below
(memq car loaddefs--defining-macros)
(memq car '(defclass defcustom deftheme defgroup nil))
(assoc file load-history)
(member file loaddefs--load-error-files))
(let ((load-path (cons (file-name-directory file) load-path)))
(message "loaddefs-gen: loading file %s (for %s)" file car)
(condition-case e (load file)
(error
(push file loaddefs--load-error-files) ; do not attempt again
(warn "loaddefs-gen: load error\n\t%s" e)))))
(and (macrop car)
(eq 'expand (function-get car 'autoload-macro))
(setq expand (let ((load-true-file-name file)
(load-file-name file))
(macroexpand form)))
(or (and
;; Previously, macros defined in this list would not
;; see their expansions processed in place of
;; themselves if such an expansion did not yield a
;; `progn', `prog1' or `defalias' form. Not
;; reproducing these conditions results in the
;; omission of minor mode variables and suchlike in
;; loaddefs.el when only the defuns in the
;; macroexpansions are autoloaded.
(not (memq car '( define-globalized-minor-mode defun defmacro
define-minor-mode define-inline
cl-defun cl-defmacro cl-defgeneric
cl-defstruct pcase-defmacro iter-defun cl-iter-defun
;; Obsolete; keep until the alias is removed.
easy-mmode-define-global-mode
easy-mmode-define-minor-mode
define-global-minor-mode)))
(not (eq car (car expand))))
(memq (car expand) '(progn prog1 defalias)))))
;; Recurse on the expansion.
(loaddefs-generate--make-autoload expand file 'expansion))
;; For special function-like operators, use the `autoload' function.
((memq car '( define-skeleton define-derived-mode
define-compilation-mode define-generic-mode
define-globalized-minor-mode
define-minor-mode
cl-defun defun* cl-defmacro defmacro*
define-overloadable-function
transient-define-prefix transient-define-suffix
transient-define-infix transient-define-argument
transient-define-group
;; Obsolete; keep until the alias is removed.
easy-mmode-define-global-mode
easy-mmode-define-minor-mode
define-global-minor-mode))
;; For known special macros which define functions, use `autoload'
;; directly.
((memq car loaddefs--defining-macros)
(let* ((macrop (memq car '(defmacro cl-defmacro defmacro*)))
(name (nth 1 form))
(args (pcase car
@ -268,8 +309,8 @@ expression, in which case we want to handle forms differently."
t)
(and (eq (car-safe (car body)) 'interactive)
;; List of modes or just t.
(or (if (nthcdr 1 (car body))
(list 'quote (nthcdr 1 (car body)))
(or (if (nthcdr 2 (car body))
(list 'quote (nthcdr 2 (car body)))
t))))
,(if macrop ''macro nil)))))

View file

@ -350,7 +350,8 @@ The default implementation delegates to `map-apply'."
(cl-defgeneric map-filter (pred map)
"Return an alist of key/val pairs for which (PRED key val) is non-nil in MAP.
The default implementation delegates to `map-apply'."
The default implementation delegates to `map-apply'.
This does not modify MAP."
(delq nil (map-apply (lambda (key val)
(and (funcall pred key val)
(cons key val)))
@ -358,7 +359,8 @@ The default implementation delegates to `map-apply'."
(cl-defgeneric map-remove (pred map)
"Return an alist of the key/val pairs for which (PRED key val) is nil in MAP.
The default implementation delegates to `map-filter'."
The default implementation delegates to `map-filter'.
This does not modify MAP."
(map-filter (lambda (key val) (not (funcall pred key val)))
map))
@ -457,7 +459,8 @@ MAP may be of a type other than TYPE."
(defun map-merge (type &rest maps)
"Merge into a map of TYPE all the key/value pairs in MAPS.
See `map-into' for all supported values of TYPE."
See `map-into' for all supported values of TYPE.
This does not modify any of the MAPS."
(apply #'map--merge
(lambda (result key value)
(setf (map-elt result key) value)
@ -469,7 +472,8 @@ See `map-into' for all supported values of TYPE."
When two maps contain the same key, call FUNCTION on the two
values and use the value FUNCTION returns.
Each of MAPS can be an alist, plist, hash-table, or array.
See `map-into' for all supported values of TYPE."
See `map-into' for all supported values of TYPE.
This does not modify any of the MAPS."
(let ((not-found (list nil)))
(apply #'map--merge
(lambda (result key value)

View file

@ -995,18 +995,22 @@ Newer versions are always activated, regardless of FORCE."
This uses `tar-untar-buffer' from Tar mode. All files should
untar into a directory named DIR; otherwise, signal an error."
(tar-mode)
;; Make sure everything extracts into DIR.
(let ((regexp (concat "\\`" (regexp-quote (expand-file-name dir)) "/"))
(case-fold-search (file-name-case-insensitive-p dir)))
(dolist (tar-data tar-parse-info)
(let ((name (expand-file-name (tar-header-name tar-data))))
(or (string-match regexp name)
;; Tarballs created by some utilities don't list
;; directories with a trailing slash (Bug#13136).
(and (string-equal (expand-file-name dir) name)
(eq (tar-header-link-type tar-data) 5))
(error "Package does not untar cleanly into directory %s/" dir)))))
(tar-untar-buffer))
(unwind-protect
(progn
;; Make sure everything extracts into DIR.
(let ((regexp (concat "\\`" (regexp-quote (expand-file-name dir)) "/"))
(case-fold-search (file-name-case-insensitive-p dir)))
(dolist (tar-data tar-parse-info)
(let ((name (expand-file-name (tar-header-name tar-data))))
(or (string-match regexp name)
;; Tarballs created by some utilities don't list
;; directories with a trailing slash (Bug#13136).
(and (string-equal (expand-file-name dir) name)
(eq (tar-header-link-type tar-data) 5))
(error "Package does not untar cleanly into directory %s/"
dir)))))
(tar-untar-buffer))
(fundamental-mode))) ; free auxiliary tar-mode data
(defun package--alist-to-plist-args (alist)
(mapcar #'macroexp-quote
@ -2455,7 +2459,9 @@ directory."
(set-visited-file-name file)
(set-buffer-modified-p nil)
(when (string-match "\\.tar\\'" file) (tar-mode)))
(package-install-from-buffer)))
(unwind-protect
(package-install-from-buffer)
(fundamental-mode)))) ; free auxiliary data
;;;###autoload
(defun package-install-selected-packages (&optional noconfirm)

View file

@ -544,7 +544,9 @@ to this macro.
By convention, DOC should use \"EXPVAL\" to stand
for the result of evaluating EXP (first arg to `pcase').
\n(fn NAME ARGS [DOC] &rest BODY...)"
(declare (indent 2) (debug defun) (doc-string 3))
(declare (indent 2) (debug defun) (doc-string 3)
;; Expand to defun and related forms on autoload gen
(autoload-macro expand))
;; Add the function via `fsym', so that an autoload cookie placed
;; on a pcase-defmacro will cause the macro to be loaded on demand.
(let ((fsym (intern (format "%s--pcase-macroexpander" name)))

View file

@ -274,7 +274,8 @@ Value is a sequence of the same type as SEQUENCE."
(cl-defgeneric seq-sort (pred sequence)
"Sort SEQUENCE using PRED as the sorting comparison function.
The result is a sequence of the same type as SEQUENCE."
The result is a sequence of the same type as SEQUENCE. The sort
operates on a copy of SEQUENCE and does not modify SEQUENCE."
(let ((result (seq-sort pred (append sequence nil))))
(seq-into result (type-of sequence))))
@ -285,7 +286,8 @@ The result is a sequence of the same type as SEQUENCE."
(defun seq-sort-by (function pred sequence)
"Sort SEQUENCE transformed by FUNCTION using PRED as the comparison function.
Elements of SEQUENCE are transformed by FUNCTION before being
sorted. FUNCTION must be a function of one argument."
sorted. FUNCTION must be a function of one argument. The sort
operates on a copy of SEQUENCE and does not modify SEQUENCE."
(seq-sort (lambda (a b)
(funcall pred
(funcall function a)
@ -293,7 +295,8 @@ sorted. FUNCTION must be a function of one argument."
sequence))
(cl-defgeneric seq-reverse (sequence)
"Return a sequence with elements of SEQUENCE in reverse order."
"Return a sequence with elements of SEQUENCE in reverse order.
This does not modify SEQUENCE."
(let ((result '()))
(seq-map (lambda (elt)
(push elt result))
@ -307,6 +310,7 @@ sorted. FUNCTION must be a function of one argument."
(cl-defgeneric seq-concatenate (type &rest sequences)
"Concatenate SEQUENCES into a single sequence of type TYPE.
TYPE must be one of following symbols: `vector', `string' or `list'.
This does not modify any of the SEQUENCES.
\n(fn TYPE SEQUENCE...)"
(setq sequences (mapcar #'seq-into-sequence sequences))
@ -321,7 +325,9 @@ TYPE must be one of following symbols: `vector', `string' or `list'.
The default implementation is to signal an error if SEQUENCE is not a
sequence, specific functions should be implemented for new types
of sequence."
of sequence.
This does not modify SEQUENCE."
(unless (sequencep sequence)
(error "Cannot convert %S into a sequence" sequence))
sequence)
@ -329,7 +335,7 @@ of sequence."
(cl-defgeneric seq-into (sequence type)
"Concatenate the elements of SEQUENCE into a sequence of type TYPE.
TYPE can be one of the following symbols: `vector', `string' or
`list'."
`list'. This does not modify SEQUENCE."
(pcase type
(`vector (seq--into-vector sequence))
(`string (seq--into-string sequence))
@ -338,7 +344,8 @@ TYPE can be one of the following symbols: `vector', `string' or
;;;###autoload
(cl-defgeneric seq-filter (pred sequence)
"Return a list of all the elements in SEQUENCE for which PRED returns non-nil."
"Return a list of all the elements in SEQUENCE for which PRED returns non-nil.
This does not modify SEQUENCE."
(let ((exclude (make-symbol "exclude")))
(delq exclude (seq-map (lambda (elt)
(if (funcall pred elt)
@ -348,7 +355,8 @@ TYPE can be one of the following symbols: `vector', `string' or
;;;###autoload
(cl-defgeneric seq-remove (pred sequence)
"Return a list of all the elements in SEQUENCE for which PRED returns nil."
"Return a list of all the elements in SEQUENCE for which PRED returns nil.
This does not modify SEQUENCE."
(seq-filter (lambda (elt) (not (funcall pred elt)))
sequence))
@ -359,7 +367,8 @@ TYPE can be one of the following symbols: `vector', `string' or
N is the (zero-based) index of the element that should not be in
the result.
The result is a sequence of the same type as SEQUENCE."
The result is a sequence of the same type as SEQUENCE.
This does not modify SEQUENCE."
(seq-concatenate
(if (listp sequence) 'list (type-of sequence))
(seq-subseq sequence 0 n)
@ -376,7 +385,9 @@ third element of SEQUENCE, etc. FUNCTION will be called with
INITIAL-VALUE (and then the accumulated value) as the first
argument, and the elements from SEQUENCE as the second argument.
If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called."
If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called.
This does not modify SEQUENCE."
(if (seq-empty-p sequence)
initial-value
(let ((acc initial-value))
@ -411,7 +422,9 @@ If no such element is found, return DEFAULT.
Note that `seq-find' has an ambiguity if the found element is
identical to DEFAULT, as in that case it is impossible to know
whether an element was found or not."
whether an element was found or not.
This does not modify SEQUENCE."
(catch 'seq--break
(seq-doseq (elt sequence)
(when (funcall pred elt)
@ -485,7 +498,8 @@ The result is a list of (zero-based) indices."
;;;###autoload
(cl-defgeneric seq-uniq (sequence &optional testfn)
"Return a list of the elements of SEQUENCE with duplicates removed.
TESTFN is used to compare elements, and defaults to `equal'."
TESTFN is used to compare elements, and defaults to `equal'.
This does not modify SEQUENCE."
(let ((result '()))
(seq-doseq (elt sequence)
(unless (seq-contains-p result elt testfn)
@ -521,14 +535,16 @@ TESTFN is used to compare elements, and defaults to `equal'."
(cl-defgeneric seq-mapcat (function sequence &optional type)
"Concatenate the results of applying FUNCTION to each element of SEQUENCE.
The result is a sequence of type TYPE; TYPE defaults to `list'."
The result is a sequence of type TYPE; TYPE defaults to `list'.
This does not modify SEQUENCE."
(apply #'seq-concatenate (or type 'list)
(seq-map function sequence)))
(cl-defgeneric seq-partition (sequence n)
"Return list of elements of SEQUENCE grouped into sub-sequences of length N.
The last sequence may contain less than N elements. If N is a
negative integer or 0, the function returns nil."
negative integer or 0, the function returns nil.
This does not modify SEQUENCE."
(unless (< n 1)
(let ((result '()))
(while (not (seq-empty-p sequence))
@ -540,7 +556,8 @@ negative integer or 0, the function returns nil."
(cl-defgeneric seq-union (sequence1 sequence2 &optional testfn)
"Return a list of all the elements that appear in either SEQUENCE1 or SEQUENCE2.
\"Equality\" of elements is defined by the function TESTFN, which
defaults to `equal'."
defaults to `equal'.
This does not modify SEQUENCE1 or SEQUENCE2."
(let* ((accum (lambda (acc elt)
(if (seq-contains-p acc elt testfn)
acc
@ -553,7 +570,8 @@ defaults to `equal'."
(cl-defgeneric seq-intersection (sequence1 sequence2 &optional testfn)
"Return a list of all the elements that appear in both SEQUENCE1 and SEQUENCE2.
\"Equality\" of elements is defined by the function TESTFN, which
defaults to `equal'."
defaults to `equal'.
This does not modify SEQUENCE1 or SEQUENCE2."
(seq-reduce (lambda (acc elt)
(if (seq-contains-p sequence2 elt testfn)
(cons elt acc)
@ -564,7 +582,8 @@ defaults to `equal'."
(cl-defgeneric seq-difference (sequence1 sequence2 &optional testfn)
"Return list of all the elements that appear in SEQUENCE1 but not in SEQUENCE2.
\"Equality\" of elements is defined by the function TESTFN, which
defaults to `equal'."
defaults to `equal'.
This does not modify SEQUENCE1 or SEQUENCE2."
(seq-reduce (lambda (acc elt)
(if (seq-contains-p sequence2 elt testfn)
acc
@ -576,7 +595,7 @@ defaults to `equal'."
(cl-defgeneric seq-group-by (function sequence)
"Apply FUNCTION to each element of SEQUENCE.
Separate the elements of SEQUENCE into an alist using the results as
keys. Keys are compared using `equal'."
keys. Keys are compared using `equal'. This does not modify SEQUENCE."
(seq-reduce
(lambda (acc elt)
(let* ((key (funcall function elt))
@ -692,7 +711,7 @@ Signal an error if SEQUENCE is empty."
(defun seq-split (sequence length)
"Split SEQUENCE into a list of sub-sequences of at most LENGTH elements.
All the sub-sequences will be LENGTH long, except the last one,
which may be shorter."
which may be shorter. This does not modify SEQUENCE."
(when (< length 1)
(error "Sub-sequence length must be larger than zero"))
(let ((result nil)
@ -705,7 +724,8 @@ which may be shorter."
(nreverse result)))
(defun seq-keep (function sequence)
"Apply FUNCTION to SEQUENCE and return the list of all the non-nil results."
"Apply FUNCTION to SEQUENCE and return the list of all the non-nil results.
This does not modify SEQUENCE."
(delq nil (seq-map function sequence)))
(provide 'seq)

View file

@ -1131,6 +1131,9 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
:eval (seq-map-indexed (lambda (a i) (cons i a)) '(a b c)))
(seq-mapcat
:eval (seq-mapcat #'upcase '("a" "b" "c") 'string))
(seq-doseq
:no-eval (seq-doseq (a '("foo" "bar")) (insert a))
:eg-result ("foo" "bar"))
(seq-do
:no-eval (seq-do (lambda (a) (insert a)) '("foo" "bar"))
:eg-result ("foo" "bar"))

View file

@ -142,13 +142,14 @@ arguments and must return a list of the above form.")
(defvar-local tabulated-list-groups nil
"Groups displayed in the current Tabulated List buffer.
This should be either a function, or a list.
If a list, each element has the form (GROUP-NAME ENTRIES),
If a list, each element has the form (GROUP-NAME ENTRY1 ENTRY2 ...),
where:
- GROUP-NAME is a group name as a string, which is displayed
at the top line of each group.
- ENTRIES is a list described in `tabulated-list-entries'.
- ENTRY1, ENTRY2 and so on each have the same format as an element
of `tabulated-list-entries'.
If `tabulated-list-groups' is a function, it is called with no
arguments and must return a list of the above form.")

View file

@ -356,7 +356,7 @@ This function is called, by name, directly by the C code."
(defun run-at-time (time repeat function &rest args)
"Perform an action at time TIME.
Repeat the action every REPEAT seconds, if REPEAT is non-nil.
REPEAT may be an integer or floating point number.
REPEAT may be a non-negative integer or floating point number.
TIME should be one of:
- a string giving today's time like \"11:23pm\"
@ -386,10 +386,10 @@ This function returns a timer object which you can use in
`cancel-timer'."
(interactive "sRun at time: \nNRepeat interval: \naFunction: ")
(when (and repeat
(numberp repeat)
(< repeat 0))
(error "Invalid repetition interval"))
(unless (or (null repeat)
(and (numberp repeat)
(>= repeat 0)))
(error "Invalid repetition interval: %s" repeat))
(let ((timer (timer-create)))
;; Special case: nil means "now" and is useful when repeating.
@ -433,6 +433,7 @@ This function returns a timer object which you can use in
"Perform an action after a delay of SECS seconds.
Repeat the action every REPEAT seconds, if REPEAT is non-nil.
SECS and REPEAT may be integers or floating point numbers.
REPEAT, if non-nil, must be a non-negative number.
The action is to call FUNCTION with arguments ARGS.
This function returns a timer object which you can use in `cancel-timer'."