summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mendler <mail@daniel-mendler.de>2025-01-01 11:23:50 +0100
committerDaniel Mendler <mail@daniel-mendler.de>2025-03-02 18:00:20 +0100
commit1e93daa67d87ea7c4e85d076da3b3a85eaab2da9 (patch)
treed7794f1e2b12a7b249d43b1e6df8402d06d01c2a
parent4d7b5c9a7234f68f2b3a6eff4ef338a104df0384 (diff)
Drop support for 24.x in upcoming Compat 31
- Emacs 24.4 has been released over ten years ago. - seq and cl-defgeneric have been introduced in 25.1. - Emacs follows a major.minor versioning scheme from 25.1 on, where new APIs are only introduced at major version bumps, which fits to the Compat development model. - Python.el in Emacs, which depends on Compat, requires Emacs 26.1 now (commit eff5a3e43ba886074c3a2e007a2bced9bcb85f17). - Packages which want to support 24.4 can depend on Compat 30 or older.
-rw-r--r--.github/workflows/makefile.yml5
-rw-r--r--.github/workflows/seq-24.el496
-rw-r--r--Makefile3
-rw-r--r--NEWS.org2
-rw-r--r--README.md2
-rw-r--r--compat-25.el260
-rw-r--r--compat-26.el8
-rw-r--r--compat-30.el24
-rw-r--r--compat-macs.el2
-rw-r--r--compat-tests.el28
-rw-r--r--compat.el2
-rw-r--r--compat.texi287
12 files changed, 33 insertions, 1086 deletions
diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml
index f74d357..5c80dc7 100644
--- a/.github/workflows/makefile.yml
+++ b/.github/workflows/makefile.yml
@@ -19,15 +19,12 @@ jobs:
strategy:
matrix:
# See https://github.com/purcell/setup-emacs/blob/master/.github/workflows/test.yml
- emacs-version: [24.4, 24.5, 25.1, 25.2, 25.3, 26.1, 26.2, 26.3, 27.1, 27.2, 28.1, 28.2, 29.1, 29.2, 29.3, 29.4, 30.1] # release-snapshot, snapshot
+ emacs-version: [25.1, 25.2, 25.3, 26.1, 26.2, 26.3, 27.1, 27.2, 28.1, 28.2, 29.1, 29.2, 29.3, 29.4, 30.1] # release-snapshot, snapshot
steps:
- uses: actions/checkout@v4
- uses: purcell/setup-emacs@master
with:
version: ${{ matrix.emacs-version }}
- - name: Provide seq.el on Emacs 24
- if: ${{ startsWith(matrix.emacs-version, '24.') }}
- run: mv .github/workflows/seq-24.el seq.el
- name: Basic checks
run: make check
- name: Run interpreted tests
diff --git a/.github/workflows/seq-24.el b/.github/workflows/seq-24.el
deleted file mode 100644
index 78dfe4b..0000000
--- a/.github/workflows/seq-24.el
+++ /dev/null
@@ -1,496 +0,0 @@
-;;; seq.el --- seq.el implementation for Emacs 24.x -*- lexical-binding: t -*-
-
-;; Copyright (C) 2014-2020 Free Software Foundation, Inc.
-
-;; Author: Nicolas Petton <nicolas@petton.fr>
-;; Keywords: sequences
-
-;; Maintainer: emacs-devel@gnu.org
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Sequence-manipulation functions that complement basic functions
-;; provided by subr.el.
-;;
-;; All functions are prefixed with "seq-".
-;;
-;; All provided functions work on lists, strings and vectors.
-;;
-;; Functions taking a predicate or iterating over a sequence using a
-;; function as argument take the function as their first argument and
-;; the sequence as their second argument. All other functions take
-;; the sequence as their first argument.
-
-;;; Code:
-
-(defmacro seq-doseq (spec &rest body)
- "Loop over a sequence.
-Similar to `dolist' but can be applied to lists, strings, and vectors.
-
-Evaluate BODY with VAR bound to each element of SEQ, in turn.
-
-\(fn (VAR SEQ) BODY...)"
- (declare (indent 1) (debug ((symbolp form &optional form) body)))
- (let ((length (make-symbol "length"))
- (seq (make-symbol "seq"))
- (index (make-symbol "index")))
- `(let* ((,seq ,(cadr spec))
- (,length (if (listp ,seq) nil (seq-length ,seq)))
- (,index (if ,length 0 ,seq)))
- (while (if ,length
- (< ,index ,length)
- (consp ,index))
- (let ((,(car spec) (if ,length
- (prog1 (seq-elt ,seq ,index)
- (setq ,index (+ ,index 1)))
- (pop ,index))))
- ,@body)))))
-
-;; Implementation of `seq-let' compatible with Emacs<25.1.
-(defmacro seq-let (args sequence &rest body)
- "Bind the variables in ARGS to the elements of SEQUENCE then evaluate BODY.
-
-ARGS can also include the `&rest' marker followed by a variable
-name to be bound to the rest of SEQUENCE."
- (declare (indent 2) (debug t))
- (let ((seq-var (make-symbol "seq")))
- `(let* ((,seq-var ,sequence)
- ,@(seq--make-bindings args seq-var))
- ,@body)))
-
-(defun seq-drop (sequence n)
- "Return a subsequence of SEQUENCE without its first N elements.
-The result is a sequence of the same type as SEQUENCE.
-
-If N is a negative integer or zero, SEQUENCE is returned."
- (if (<= n 0)
- sequence
- (if (listp sequence)
- (seq--drop-list sequence n)
- (let ((length (seq-length sequence)))
- (seq-subseq sequence (min n length) length)))))
-
-(defun seq-take (sequence n)
- "Return a subsequence of SEQUENCE with its first N elements.
-The result is a sequence of the same type as SEQUENCE.
-
-If N is a negative integer or zero, an empty sequence is
-returned."
- (if (listp sequence)
- (seq--take-list sequence n)
- (seq-subseq sequence 0 (min (max n 0) (seq-length sequence)))))
-
-(defun seq-drop-while (predicate sequence)
- "Return a sequence from the first element for which (PREDICATE element) is nil in SEQUENCE.
-The result is a sequence of the same type as SEQUENCE."
- (if (listp sequence)
- (seq--drop-while-list predicate sequence)
- (seq-drop sequence (seq--count-successive predicate sequence))))
-
-(defun seq-take-while (predicate sequence)
- "Return the successive elements for which (PREDICATE element) is non-nil in SEQUENCE.
-The result is a sequence of the same type as SEQUENCE."
- (if (listp sequence)
- (seq--take-while-list predicate sequence)
- (seq-take sequence (seq--count-successive predicate sequence))))
-
-(defun seq-filter (predicate sequence)
- "Return a list of all the elements for which (PREDICATE element) is non-nil in SEQUENCE."
- (let ((exclude (make-symbol "exclude")))
- (delq exclude (seq-map (lambda (elt)
- (if (funcall predicate elt)
- elt
- exclude))
- sequence))))
-
-(defun seq-map-indexed (function sequence)
- "Return the result of applying FUNCTION to each element of SEQUENCE.
-Unlike `seq-map', FUNCTION takes two arguments: the element of
-the sequence, and its index within the sequence."
- (let ((index 0))
- (seq-map (lambda (elt)
- (prog1
- (funcall function elt index)
- (setq index (1+ index))))
- sequence)))
-
-(defun seq-remove (predicate sequence)
- "Return a list of all the elements for which (PREDICATE element) is nil in SEQUENCE."
- (seq-filter (lambda (elt) (not (funcall predicate elt)))
- sequence))
-
-(defun seq-reduce (function sequence initial-value)
- "Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE.
-
-Return the result of calling FUNCTION with INITIAL-VALUE and the
-first element of SEQUENCE, then calling FUNCTION with that result and
-the second element of SEQUENCE, then with that result and the third
-element of SEQUENCE, etc.
-
-If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called."
- (if (seq-empty-p sequence)
- initial-value
- (let ((acc initial-value))
- (seq-doseq (elt sequence)
- (setq acc (funcall function acc elt)))
- acc)))
-
-(defun seq-some (predicate sequence)
- "Return the first value for which if (PREDICATE element) is non-nil for in SEQUENCE."
- (catch 'seq--break
- (seq-doseq (elt sequence)
- (let ((result (funcall predicate elt)))
- (when result
- (throw 'seq--break result))))
- nil))
-
-(defun seq-find (predicate sequence &optional default)
- "Return the first element for which (PREDICATE element) is non-nil in SEQUENCE.
-If no element is found, return DEFAULT.
-
-Note that `seq-find' has an ambiguity if the found element is
-identical to DEFAULT, as it cannot be known if an element was
-found or not."
- (catch 'seq--break
- (seq-doseq (elt sequence)
- (when (funcall predicate elt)
- (throw 'seq--break elt)))
- default))
-
-(defun seq-every-p (predicate sequence)
- "Return non-nil if (PREDICATE element) is non-nil for all elements of the sequence SEQUENCE."
- (catch 'seq--break
- (seq-doseq (elt sequence)
- (or (funcall predicate elt)
- (throw 'seq--break nil)))
- t))
-
-(defun seq-count (predicate sequence)
- "Return the number of elements for which (PREDICATE element) is non-nil in SEQUENCE."
- (let ((count 0))
- (seq-doseq (elt sequence)
- (when (funcall predicate elt)
- (setq count (+ 1 count))))
- count))
-
-(defun seq-empty-p (sequence)
- "Return non-nil if the sequence SEQUENCE is empty, nil otherwise."
- (if (listp sequence)
- (null sequence)
- (= 0 (seq-length sequence))))
-
-(defun seq-sort (predicate sequence)
- "Return a sorted sequence comparing using PREDICATE the elements of SEQUENCE.
-The result is a sequence of the same type as SEQUENCE."
- (if (listp sequence)
- (sort (seq-copy sequence) predicate)
- (let ((result (seq-sort predicate (append sequence nil))))
- (seq-into result (type-of sequence)))))
-
-(defun seq-sort-by (function pred sequence)
- "Sort SEQUENCE using PRED as a comparison function.
-Elements of SEQUENCE are transformed by FUNCTION before being
-sorted. FUNCTION must be a function of one argument."
- (seq-sort (lambda (a b)
- (funcall pred
- (funcall function a)
- (funcall function b)))
- sequence))
-
-(defun seq-contains (sequence elt &optional testfn)
- "Return the first element in SEQUENCE that equals to ELT.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
- (seq-some (lambda (e)
- (funcall (or testfn #'equal) elt e))
- sequence))
-
-(defun seq-set-equal-p (sequence1 sequence2 &optional testfn)
- "Return non-nil if SEQUENCE1 and SEQUENCE2 contain the same elements, regardless of order.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
- (and (seq-every-p (lambda (item1) (seq-contains sequence2 item1 testfn)) sequence1)
- (seq-every-p (lambda (item2) (seq-contains sequence1 item2 testfn)) sequence2)))
-
-(defun seq-position (sequence elt &optional testfn)
- "Return the index of the first element in SEQUENCE that is equal to ELT.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
- (let ((index 0))
- (catch 'seq--break
- (seq-doseq (e sequence)
- (when (funcall (or testfn #'equal) e elt)
- (throw 'seq--break index))
- (setq index (1+ index)))
- nil)))
-
-(defun seq-uniq (sequence &optional testfn)
- "Return a list of the elements of SEQUENCE with duplicates removed.
-TESTFN is used to compare elements, or `equal' if TESTFN is nil."
- (let ((result '()))
- (seq-doseq (elt sequence)
- (unless (seq-contains result elt testfn)
- (setq result (cons elt result))))
- (nreverse result)))
-
-(defun seq-subseq (sequence start &optional end)
- "Return the subsequence of SEQUENCE from START to END.
-If END is omitted, it defaults to the length of the sequence.
-If START or END is negative, it counts from the end."
- (cond ((or (stringp sequence) (vectorp sequence)) (substring sequence start end))
- ((listp sequence)
- (let (len (errtext (format "Bad bounding indices: %s, %s" start end)))
- (and end (< end 0) (setq end (+ end (setq len (seq-length sequence)))))
- (if (< start 0) (setq start (+ start (or len (setq len (seq-length sequence))))))
- (when (> start 0)
- (setq sequence (nthcdr (1- start) sequence))
- (or sequence (error "%s" errtext))
- (setq sequence (cdr sequence)))
- (if end
- (let ((res nil))
- (while (and (>= (setq end (1- end)) start) sequence)
- (push (pop sequence) res))
- (or (= (1+ end) start) (error "%s" errtext))
- (nreverse res))
- (seq-copy sequence))))
- (t (error "Unsupported sequence: %s" sequence))))
-
-(defun seq-concatenate (type &rest seqs)
- "Concatenate, into a sequence of type TYPE, the sequences SEQS.
-TYPE must be one of following symbols: vector, string or list.
-
-\n(fn TYPE SEQUENCE...)"
- (pcase type
- (`vector (apply #'vconcat seqs))
- (`string (apply #'concat seqs))
- (`list (apply #'append (append seqs '(nil))))
- (_ (error "Not a sequence type name: %S" type))))
-
-(defun seq-mapcat (function sequence &optional type)
- "Concatenate the result of applying FUNCTION to each element of SEQUENCE.
-The result is a sequence of type TYPE, or a list if TYPE is nil."
- (apply #'seq-concatenate (or type 'list)
- (seq-map function sequence)))
-
-(defun seq-mapn (function sequence &rest seqs)
- "Like `seq-map' but FUNCTION is mapped over all SEQS.
-The arity of FUNCTION must match the number of SEQS, and the
-mapping stops on the shortest sequence.
-Return a list of the results.
-
-\(fn FUNCTION SEQS...)"
- (let ((result nil)
- (seqs (seq-map (lambda (s)
- (seq-into s 'list))
- (cons sequence seqs))))
- (while (not (memq nil seqs))
- (push (apply function (seq-map #'car seqs)) result)
- (setq seqs (seq-map #'cdr seqs)))
- (nreverse result)))
-
-(defun seq-partition (sequence n)
- "Return a list of the 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, nil is returned."
- (unless (< n 1)
- (let ((result '()))
- (while (not (seq-empty-p sequence))
- (push (seq-take sequence n) result)
- (setq sequence (seq-drop sequence n)))
- (nreverse result))))
-
-(defun seq-intersection (seq1 seq2 &optional testfn)
- "Return a list of the elements that appear in both SEQ1 and SEQ2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
- (seq-reduce (lambda (acc elt)
- (if (seq-contains seq2 elt testfn)
- (cons elt acc)
- acc))
- (seq-reverse seq1)
- '()))
-
-(defun seq-difference (seq1 seq2 &optional testfn)
- "Return a list of the elements that appear in SEQ1 but not in SEQ2.
-Equality is defined by TESTFN if non-nil or by `equal' if nil."
- (seq-reduce (lambda (acc elt)
- (if (not (seq-contains seq2 elt testfn))
- (cons elt acc)
- acc))
- (seq-reverse seq1)
- '()))
-
-(defun 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'."
- (seq-reduce
- (lambda (acc elt)
- (let* ((key (funcall function elt))
- (cell (assoc key acc)))
- (if cell
- (setcdr cell (push elt (cdr cell)))
- (push (list key elt) acc))
- acc))
- (seq-reverse sequence)
- nil))
-
-(defalias 'seq-reverse
- (if (ignore-errors (reverse [1 2]))
- #'reverse
- (lambda (sequence)
- "Return the reversed copy of list, vector, or string SEQUENCE.
-See also the function `nreverse', which is used more often."
- (let ((result '()))
- (seq-map (lambda (elt) (push elt result))
- sequence)
- (if (listp sequence)
- result
- (seq-into result (type-of sequence)))))))
-
-(defun seq-into (sequence type)
- "Convert the sequence SEQUENCE into a sequence of type TYPE.
-TYPE can be one of the following symbols: vector, string or list."
- (pcase type
- (`vector (seq--into-vector sequence))
- (`string (seq--into-string sequence))
- (`list (seq--into-list sequence))
- (_ (error "Not a sequence type name: %S" type))))
-
-(defun seq-min (sequence)
- "Return the smallest element of SEQUENCE.
-SEQUENCE must be a sequence of numbers or markers."
- (apply #'min (seq-into sequence 'list)))
-
-(defun seq-max (sequence)
- "Return the largest element of SEQUENCE.
-SEQUENCE must be a sequence of numbers or markers."
- (apply #'max (seq-into sequence 'list)))
-
-(defun seq-random-elt (sequence)
- "Return a random element from SEQUENCE.
-Signal an error if SEQUENCE is empty."
- (if (seq-empty-p sequence)
- (error "Sequence cannot be empty")
- (seq-elt sequence (random (seq-length sequence)))))
-
-(defun seq--drop-list (list n)
- "Return a list from LIST without its first N elements.
-This is an optimization for lists in `seq-drop'."
- (nthcdr n list))
-
-(defun seq--take-list (list n)
- "Return a list from LIST made of its first N elements.
-This is an optimization for lists in `seq-take'."
- (let ((result '()))
- (while (and list (> n 0))
- (setq n (1- n))
- (push (pop list) result))
- (nreverse result)))
-
-(defun seq--drop-while-list (predicate list)
- "Return a list from the first element for which (PREDICATE element) is nil in LIST.
-This is an optimization for lists in `seq-drop-while'."
- (while (and list (funcall predicate (car list)))
- (setq list (cdr list)))
- list)
-
-(defun seq--take-while-list (predicate list)
- "Return the successive elements for which (PREDICATE element) is non-nil in LIST.
-This is an optimization for lists in `seq-take-while'."
- (let ((result '()))
- (while (and list (funcall predicate (car list)))
- (push (pop list) result))
- (nreverse result)))
-
-(defun seq--count-successive (predicate sequence)
- "Return the number of successive elements for which (PREDICATE element) is non-nil in SEQUENCE."
- (let ((n 0)
- (len (seq-length sequence)))
- (while (and (< n len)
- (funcall predicate (seq-elt sequence n)))
- (setq n (+ 1 n)))
- n))
-
-;; Helper function for the Backward-compatible version of `seq-let'
-;; for Emacs<25.1.
-(defun seq--make-bindings (args sequence &optional bindings)
- "Return a list of bindings of the variables in ARGS to the elements of a sequence.
-if BINDINGS is non-nil, append new bindings to it, and return
-BINDINGS."
- (let ((index 0)
- (rest-marker nil))
- (seq-doseq (name args)
- (unless rest-marker
- (pcase name
- ((pred seqp)
- (setq bindings (seq--make-bindings (seq--elt-safe args index)
- `(seq--elt-safe ,sequence ,index)
- bindings)))
- (`&rest
- (progn (push `(,(seq--elt-safe args (1+ index))
- (seq-drop ,sequence ,index))
- bindings)
- (setq rest-marker t)))
- (_
- (push `(,name (seq--elt-safe ,sequence ,index)) bindings))))
- (setq index (1+ index)))
- bindings))
-
-(defun seq--elt-safe (sequence n)
- "Return element of SEQUENCE at the index N.
-If no element is found, return nil."
- (when (or (listp sequence)
- (and (sequencep sequence)
- (> (seq-length sequence) n)))
- (seq-elt sequence n)))
-
-(defun seq--activate-font-lock-keywords ()
- "Activate font-lock keywords for some symbols defined in seq."
- (font-lock-add-keywords 'emacs-lisp-mode
- '("\\<seq-doseq\\>" "\\<seq-let\\>")))
-
-(defalias 'seq-copy #'copy-sequence)
-(defalias 'seq-elt #'elt)
-(defalias 'seq-length #'length)
-(defalias 'seq-do #'mapc)
-(defalias 'seq-each #'seq-do)
-(defalias 'seq-map #'mapcar)
-(defalias 'seqp #'sequencep)
-
-(defun seq--into-list (sequence)
- "Concatenate the elements of SEQUENCE into a list."
- (if (listp sequence)
- sequence
- (append sequence nil)))
-
-(defun seq--into-vector (sequence)
- "Concatenate the elements of SEQUENCE into a vector."
- (if (vectorp sequence)
- sequence
- (vconcat sequence)))
-
-(defun seq--into-string (sequence)
- "Concatenate the elements of SEQUENCE into a string."
- (if (stringp sequence)
- sequence
- (concat sequence)))
-
-(unless (fboundp 'elisp--font-lock-flush-elisp-buffers)
- ;; In Emacs≥25, (via elisp--font-lock-flush-elisp-buffers and a few others)
- ;; we automatically highlight macros.
- (add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
-
-(provide 'seq)
-;;; seq.el ends here
diff --git a/Makefile b/Makefile
index 9da028f..8982558 100644
--- a/Makefile
+++ b/Makefile
@@ -40,8 +40,7 @@ endif
EMACS = emacs
MAKEINFO = makeinfo
-BYTEC = compat-25.elc \
- compat-26.elc \
+BYTEC = compat-26.elc \
compat-27.elc \
compat-28.elc \
compat-29.elc \
diff --git a/NEWS.org b/NEWS.org
index cc3f2bf..6145d6b 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -8,6 +8,8 @@
- compat-31: New functions =minusp= and =plusp=.
- compat-31: New macros =incf= and =decf=.
- compat-31: New function =color-blend=.
+- Drop support for Emacs 24.x. Emacs 25.1 is required now. In case
+ Emacs 24.x support is still needed, Compat 30 can be used.
* Release of "Compat" Version 30.0.2.0
diff --git a/README.md b/README.md
index 8c1eff2..4fd69db 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
COMPATibility Library for Emacs
===============================
This is the source of compat.el, the forwards-compatibility library for (GNU)
-Emacs Lisp, versions 24.4 and newer. The intended audience are package
+Emacs Lisp, versions 25.1 and newer. The intended audience are package
developers that are interested in using newer developments, without having to
break compatibility.
diff --git a/compat-25.el b/compat-25.el
deleted file mode 100644
index 51c4f06..0000000
--- a/compat-25.el
+++ /dev/null
@@ -1,260 +0,0 @@
-;;; compat-25.el --- Functionality added in Emacs 25.1 -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2021-2025 Free Software Foundation, Inc.
-
-;; 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
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Functionality added in Emacs 25.1, needed by older Emacs versions.
-
-;;; Code:
-
-(eval-when-compile (load "compat-macs.el" nil t t))
-
-(compat-version "25.1")
-
-;;;; Defined in alloc.c
-
-(compat-defun bool-vector (&rest objects) ;; <compat-tests:bool-vector>
- "Return a new bool-vector with specified arguments as elements.
-Allows any number of arguments, including zero.
-usage: (bool-vector &rest OBJECTS)"
- (let ((vec (make-bool-vector (length objects) nil))
- (i 0))
- (while objects
- (when (car objects)
- (aset vec i t))
- (setq objects (cdr objects)
- i (1+ i)))
- vec))
-
-;;;; Defined in editfns.c
-
-(compat-defalias format-message format) ;; <compat-tests:format-message>
-
-;;;; Defined in fileio.c
-
-(compat-defun directory-name-p (name) ;; <compat-tests:directory-name-p>
- "Return non-nil if NAME ends with a directory separator character."
- (eq (eval-when-compile
- (if (memq system-type '(cygwin windows-nt ms-dos))
- ?\\ ?/))
- (aref name (1- (length name)))))
-
-;;;; Defined in doc.c
-
-(compat-defvar text-quoting-style nil ;; <compat-tests:text-quoting-style>
- "Style to use for single quotes in help and messages.
-
-The value of this variable determines substitution of grave accents
-and apostrophes in help output (but not for display of Info
-manuals) and in functions like `message' and `format-message', but not
-in `format'.
-
-The value should be one of these symbols:
- `curve': quote with curved single quotes ‘like this’.
- `straight': quote with straight apostrophes \\='like this\\='.
- `grave': quote with grave accent and apostrophe \\=`like this\\=';
- i.e., do not alter the original quote marks.
- nil: like `curve' if curved single quotes are displayable,
- and like `grave' otherwise. This is the default.
-
-You should never read the value of this variable directly from a Lisp
-program. Use the function `text-quoting-style' instead, as that will
-compute the correct value for the current terminal in the nil case.")
-
-;;;; Defined in simple.el
-
-;; `save-excursion' behaved like `save-mark-and-excursion' before 25.1.
-(compat-defalias save-mark-and-excursion save-excursion) ;; <compat-tests:save-mark-and-excursion>
-
-(declare-function region-bounds nil) ;; Defined in compat-26.el
-(compat-defun region-noncontiguous-p () ;; <compat-tests:region-noncontiguous-p>
- "Return non-nil if the region contains several pieces.
-An example is a rectangular region handled as a list of
-separate contiguous regions for each line."
- (let ((bounds (region-bounds))) (and (cdr bounds) bounds)))
-
-;;;; Defined in subr.el
-
-(compat-defun string-greaterp (string1 string2) ;; <compat-tests:string-greaterp>
- "Return non-nil if STRING1 is greater than STRING2 in lexicographic order.
-Case is significant.
-Symbols are also allowed; their print names are used instead."
- (string-lessp string2 string1))
-
-(compat-defmacro with-file-modes (modes &rest body) ;; <compat-tests:with-file-modes>
- "Execute BODY with default file permissions temporarily set to MODES.
-MODES is as for `set-default-file-modes'."
- (declare (indent 1) (debug t))
- (let ((umask (make-symbol "umask")))
- `(let ((,umask (default-file-modes)))
- (unwind-protect
- (progn
- (set-default-file-modes ,modes)
- ,@body)
- (set-default-file-modes ,umask)))))
-
-(compat-defmacro if-let (spec then &rest else) ;; <compat-tests:if-let>
- "Bind variables according to SPEC and evaluate THEN or ELSE.
-Evaluate each binding in turn, as in `let*', stopping if a
-binding value is nil. If all are non-nil return the value of
-THEN, otherwise the last form in ELSE.
-
-Each element of SPEC is a list (SYMBOL VALUEFORM) that binds
-SYMBOL to the value of VALUEFORM. An element can additionally be
-of the form (VALUEFORM), which is evaluated and checked for nil;
-i.e. SYMBOL can be omitted if only the test result is of
-interest. It can also be of the form SYMBOL, then the binding of
-SYMBOL is checked for nil.
-
-As a special case, interprets a SPEC of the form \(SYMBOL SOMETHING)
-like \((SYMBOL SOMETHING)). This exists for backward compatibility
-with an old syntax that accepted only one binding."
- (declare (indent 2)
- (debug ([&or (symbolp form)
- (&rest [&or symbolp (symbolp form) (form)])]
- body)))
- (when (and (<= (length spec) 2) (not (listp (car spec))))
- ;; Adjust the single binding case
- (setq spec (list spec)))
- (let ((empty (make-symbol "s"))
- (last t) list)
- (dolist (var spec)
- (push `(,(if (cdr var) (car var) empty)
- (and ,last ,(if (cdr var) (cadr var) (car var))))
- list)
- (when (or (cdr var) (consp (car var)))
- (setq last (caar list))))
- `(let* ,(nreverse list)
- (if ,(caar list) ,then ,@else))))
-
-(compat-defmacro when-let (spec &rest body) ;; <compat-tests:when-let>
- "Bind variables according to SPEC and conditionally evaluate BODY.
-Evaluate each binding in turn, stopping if a binding value is nil.
-If all are non-nil, return the value of the last form in BODY.
-
-The variable list SPEC is the same as in `if-let'."
- (declare (indent 1) (debug if-let))
- (list 'if-let spec (macroexp-progn body)))
-
-;;;; Defined in subr-x.el
-
-(compat-defun hash-table-empty-p (hash-table) ;; <compat-tests:hash-table-empty-p>
- "Check whether HASH-TABLE is empty (has 0 elements)."
- (zerop (hash-table-count hash-table)))
-
-(compat-defmacro thread-first (&rest forms) ;; <compat-tests:thread-first>
- "Thread FORMS elements as the first argument of their successor.
-Example:
- (thread-first
- 5
- (+ 20)
- (/ 25)
- -
- (+ 40))
-Is equivalent to:
- (+ (- (/ (+ 5 20) 25)) 40)
-Note how the single `-' got converted into a list before
-threading."
- (declare (indent 1)
- (debug (form &rest [&or symbolp (sexp &rest form)])))
- (let ((body (car forms)))
- (dolist (form (cdr forms))
- (when (symbolp form)
- (setq form (list form)))
- (setq body (append (list (car form))
- (list body)
- (cdr form))))
- body))
-
-(compat-defmacro thread-last (&rest forms) ;; <compat-tests:thread-last>
- "Thread FORMS elements as the last argument of their successor.
-Example:
- (thread-last
- 5
- (+ 20)
- (/ 25)
- -
- (+ 40))
-Is equivalent to:
- (+ 40 (- (/ 25 (+ 20 5))))
-Note how the single `-' got converted into a list before
-threading."
- (declare (indent 1) (debug thread-first))
- (let ((body (car forms)))
- (dolist (form (cdr forms))
- (when (symbolp form)
- (setq form (list form)))
- (setq body (append form (list body))))
- body))
-
-;;;; Defined in macroexp.el
-
-(compat-defun macroexp-parse-body (body) ;; <compat-tests:macroexp-parse-body>
- "Parse a function BODY into (DECLARATIONS . EXPS)."
- (let ((decls ()))
- (while (and (cdr body)
- (let ((e (car body)))
- (or (stringp e)
- (memq (car-safe e)
- '(:documentation declare interactive cl-declare)))))
- (push (pop body) decls))
- (cons (nreverse decls) body)))
-
-(compat-defun macroexp-quote (v) ;; <compat-tests:macroexp-quote>
- "Return an expression E such that `(eval E)' is V.
-
-E is either V or (quote V) depending on whether V evaluates to
-itself or not."
- (if (and (not (consp v))
- (or (keywordp v)
- (not (symbolp v))
- (memq v '(nil t))))
- v
- (list 'quote v)))
-
-(compat-defun macroexpand-1 (form &optional environment) ;; <compat-tests:macroexpand-1>
- "Perform (at most) one step of macro expansion."
- (cond
- ((consp form)
- (let* ((head (car form))
- (env-expander (assq head environment)))
- (if env-expander
- (if (cdr env-expander)
- (apply (cdr env-expander) (cdr form))
- form)
- (if (not (and (symbolp head) (fboundp head)))
- form
- (let ((def (autoload-do-load (symbol-function head) head 'macro)))
- (cond
- ;; Follow alias, but only for macros, otherwise we may end up
- ;; skipping an important compiler-macro (e.g. cl--block-wrapper).
- ((and (symbolp def) (macrop def)) (cons def (cdr form)))
- ((not (consp def)) form)
- (t
- (if (eq 'macro (car def))
- (apply (cdr def) (cdr form))
- form))))))))
- (t form)))
-
-;;;; Defined in minibuffer.el
-
-(compat-defun completion--category-override (category tag) ;; <compat-tests:completion-metadata-get>
- "Return completion category override for CATEGORY and TAG."
- (assq tag (cdr (assq category completion-category-overrides))))
-
-(provide 'compat-25)
-;;; compat-25.el ends here
diff --git a/compat-26.el b/compat-26.el
index 9f5e199..92d1519 100644
--- a/compat-26.el
+++ b/compat-26.el
@@ -67,11 +67,7 @@ SEQUENCE may be a list, a vector, a boolean vector, or a string."
Value is a list of one or more cons cells of the form (START . END).
It will have more than one cons cell when the region is non-contiguous,
see `region-noncontiguous-p' and `extract-rectangle-bounds'."
- (if (eval-when-compile (< emacs-major-version 25))
- ;; FIXME: The `region-extract-function' of Emacs 24 has no support for the
- ;; bounds argument.
- (list (cons (region-beginning) (region-end)))
- (funcall region-extract-function 'bounds)))
+ (funcall region-extract-function 'bounds))
;;;; Defined in subr.el
@@ -108,7 +104,7 @@ If you just want to check `major-mode', use `derived-mode-p'."
(compat-defun alist-get (key alist &optional default remove testfn) ;; <compat-tests:alist-get>
"Handle optional argument TESTFN."
- :extended "25.1"
+ :extended t
(ignore remove)
(let ((x (if (not testfn)
(assq key alist)
diff --git a/compat-30.el b/compat-30.el
index 938cbcb..489ced7 100644
--- a/compat-30.el
+++ b/compat-30.el
@@ -387,7 +387,7 @@ The following arguments are defined:
For compatibility, the calling convention (sort SEQ LESSP) can also be used;
in this case, sorting is always done in-place."
:extended t
- (let ((in-place t) (reverse nil) (orig-seq seq))
+ (let ((in-place t) (reverse nil))
(when (or (not lessp) rest)
(setq
rest (if lessp (cons lessp rest) rest)
@@ -398,24 +398,10 @@ in this case, sorting is always done in-place."
(if key
(lambda (a b) (funcall < (funcall key a) (funcall key b)))
<))
- seq (if (or (and (eval-when-compile (< emacs-major-version 25)) (vectorp orig-seq))
- in-place)
- seq
- (copy-sequence seq))))
- ;; Emacs 24 does not support vectors. Convert to list.
- (when (and (eval-when-compile (< emacs-major-version 25)) (vectorp orig-seq))
- (setq seq (append seq nil)))
- (setq seq (if reverse
- (nreverse (sort (nreverse seq) lessp))
- (sort seq lessp)))
- ;; Emacs 24: Convert back to vector.
- (if (and (eval-when-compile (< emacs-major-version 25)) (vectorp orig-seq))
- (if in-place
- (cl-loop for i from 0 for x in seq
- do (aset orig-seq i x)
- finally return orig-seq)
- (apply #'vector seq))
- seq)))
+ seq (if in-place seq (copy-sequence seq))))
+ (if reverse
+ (nreverse (sort (nreverse seq) lessp))
+ (sort seq lessp))))
;;;; Defined in mule-cmds.el
diff --git a/compat-macs.el b/compat-macs.el
index c5567da..94f1806 100644
--- a/compat-macs.el
+++ b/compat-macs.el
@@ -103,7 +103,7 @@ REST are attributes and the function BODY."
(lambda (extended obsolete body)
(when (stringp extended)
(compat-macs--assert
- (and (version< extended compat-macs--version) (version< "24.4" extended))
+ (and (version< extended compat-macs--version) (version< "25.1" extended))
"Invalid :extended version %s for %s %s" extended type name)
(setq extended (version<= extended emacs-version)))
(compat-macs--strict (eq extended (fboundp name))
diff --git a/compat-tests.el b/compat-tests.el
index 7c67dc0..4c4b0c3 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -44,9 +44,8 @@
;; calling convention or behavior changed between Emacs versions.
;; The functions tested here are guaranteed to work on the Emacs versions
-;; tested by continuous integration. This includes 24.4, 24.5, 25.1, 25.2,
-;; 25.3, 26.1, 26.2, 26.3, 27.1, 27.2, 28.1, 28.2, 29.1 and the current
-;; Emacs master branch.
+;; tested by continuous integration. This includes the versions 25.x,
+;; 26.x, 27.x, 28.x, 29.x, 30.x and the current Emacs master branch.
;;; Code:
@@ -2890,12 +2889,10 @@
(ert-deftest compat-region-bounds ()
(should-error (region-bounds))
- ;; FIXME: On Emacs 24 `region-bounds' always returns a continuous region.
- (when (> emacs-major-version 24)
- (let ((region-extract-function #'ignore))
- (should-not (region-bounds)))
- (let ((region-extract-function (lambda (_) '((2 . 3) (6 . 7)))))
- (should-equal (region-bounds) '((2 . 3) (6 . 7)))))
+ (let ((region-extract-function #'ignore))
+ (should-not (region-bounds)))
+ (let ((region-extract-function (lambda (_) '((2 . 3) (6 . 7)))))
+ (should-equal (region-bounds) '((2 . 3) (6 . 7))))
(with-temp-buffer
(insert "abc\ndef\n")
(set-mark 2)
@@ -2903,9 +2900,8 @@
(should-equal (region-bounds) '((2 . 7)))))
(ert-deftest compat-region-noncontiguous-p ()
- (when (> emacs-major-version 24)
- (let ((region-extract-function (lambda (_) '((2 . 3) (6 . 7)))))
- (should (region-noncontiguous-p))))
+ (let ((region-extract-function (lambda (_) '((2 . 3) (6 . 7)))))
+ (should (region-noncontiguous-p)))
(with-temp-buffer
(insert "abc\ndef\n")
(set-mark 2)
@@ -2914,11 +2910,9 @@
(should-not (region-noncontiguous-p))
(should-not (use-region-noncontiguous-p))
(should (use-region-p))
- ;; FIXME: On Emacs 24 `region-bounds' always returns a continuous region.
- (when (> emacs-major-version 24)
- (let ((region-extract-function (lambda (_) '((2 . 3) (6 . 7)))))
- (should (region-noncontiguous-p))
- (should (use-region-noncontiguous-p))))))
+ (let ((region-extract-function (lambda (_) '((2 . 3) (6 . 7)))))
+ (should (region-noncontiguous-p))
+ (should (use-region-noncontiguous-p)))))
(ert-deftest compat-get-scratch-buffer-create ()
(should-equal "*scratch*" (buffer-name (get-scratch-buffer-create)))
diff --git a/compat.el b/compat.el
index 15af46c..def9869 100644
--- a/compat.el
+++ b/compat.el
@@ -6,7 +6,7 @@
;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht>
;; Version: 30.0.2.0
;; URL: https://github.com/emacs-compat/compat
-;; Package-Requires: ((emacs "24.4") (seq "2.23"))
+;; Package-Requires: ((emacs "25.1"))
;; Keywords: lisp, maint
;; This program is free software; you can redistribute it and/or modify
diff --git a/compat.texi b/compat.texi
index 55d05d1..6bb79ee 100644
--- a/compat.texi
+++ b/compat.texi
@@ -69,7 +69,6 @@ Introduction
Support
-* Emacs 25.1:: Compatibility support for Emacs 25.1
* Emacs 26.1:: Compatibility support for Emacs 26.1
* Emacs 27.1:: Compatibility support for Emacs 27.1
* Emacs 28.1:: Compatibility support for Emacs 28.1
@@ -97,7 +96,7 @@ for Emacs Lisp. By using Compat, an Elisp package does not have to
make the decision to either use new and useful functionality or
support old versions of Emacs.
-The library provides support back until Emacs 24.4. The intended
+The library provides support back until Emacs 25.1. The intended
audience are package developers that are interested in using newer
developments, without having to break compatibility.
@@ -110,10 +109,10 @@ mirrors the version of Emacs releases. The current version of Compat
corresponds to the current Emacs release.
@example
-;; Package-Requires: ((emacs "24.4") (compat "30.0.2.0"))
+;; Package-Requires: ((emacs "25.1") (compat "30.0.2.0"))
@end example
-There is no need to depend on @code{emacs 24.4} specifically. One can
+There is no need to depend on @code{emacs 25.1} specifically. One can
choose any newer version, if features not provided by Compat
necessitate it, for example bug fixes or UI improvements.
@@ -207,11 +206,11 @@ technical reasons. The scope is intentionally restricted in order to
limit the size of Compat and to ensure that the library stays
maintainable.
-Emacs version 24.4 is chosen as the oldest version supported by
-Compat, since Elisp has seen significant changes at that version.
-Since 24.4 Emacs major versions consistently bump the major version
-number. On the library level, subr-x was introduced in 24.4. Most
-popular Emacs packages already require 24.4 or even newer versions of
+Emacs version 25.1 is chosen as the oldest version supported by Compat,
+since Elisp has seen significant changes at that version. Since 25.1
+Emacs major versions consistently bump the major version number. On the
+library level, seq and generics were introduced in 25.1. Most popular
+Emacs packages already require 25.1 or even newer versions of
Emacs. Supporting for more historical Emacs versions would complicate
maintenance while only few packages and users would benefit.
@@ -306,7 +305,6 @@ This section goes into the features that Compat manages and doesn't
manage to provide for each Emacs version.
@menu
-* Emacs 25.1:: Compatibility support for Emacs 25.1
* Emacs 26.1:: Compatibility support for Emacs 26.1
* Emacs 27.1:: Compatibility support for Emacs 27.1
* Emacs 28.1:: Compatibility support for Emacs 28.1
@@ -315,275 +313,6 @@ manage to provide for each Emacs version.
* Emacs 31.1:: Compatibility support for Emacs 31.1
@end menu
-@node Emacs 25.1
-@section Emacs 25.1
-
-@subsection Added Definitions
-The following functions and macros are implemented in Emacs
-25.1. These functions are made available by Compat on Emacs versions
-older than 25.1.
-
-@c copied from lispref/help.texi
-@defopt text-quoting-style
-The value of this user option is a symbol that specifies the style
-Emacs should use for single quotes in the wording of help and
-messages. If the option's value is @code{curve}, the style is
-@t{‘like this’} with curved single quotes. If the value is
-@code{straight}, the style is @t{'like this'} with straight
-apostrophes. If the value is @code{grave}, quotes are not translated
-and the style is @t{`like this'} with grave accent and apostrophe, the
-standard style before Emacs version 25. The default value @code{nil}
-acts like @code{curve} if curved single quotes seem to be displayable,
-and like @code{grave} otherwise.
-
-This option is useful on platforms that have problems with curved
-quotes. You can customize it freely according to your personal
-preference.
-@end defopt
-
-@c based on lisp/simple.el
-@defun region-bounds
-Return the boundaries of the region. Value is a list of one or more
-cons cells of the form @code{(start . end)}. It will have more than
-one cons cell when the region is non-contiguous, see
-@code{region-noncontiguous-p} and @code{extract-rectangle-bounds}.
-@end defun
-
-@c based on lisp/simple.el
-@defun region-noncontiguous-p
-Return non-nil if the region contains several pieces. An example is a
-rectangular region handled as a list of separate contiguous regions
-for each line.
-@end defun
-
-@c copied from lispref/positions.texi
-@defmac save-mark-and-excursion body@dots{}
-This macro is like @code{save-excursion}, but also saves and restores
-the mark location and @code{mark-active}. This macro does what
-@code{save-excursion} did before Emacs 25.1.
-@end defmac
-
-@c copied from lispref/strings.texi
-@defun format-message string &rest objects
-This function acts like @code{format}, except it also converts any
-grave accents (@t{`}) and apostrophes (@t{'}) in @var{string} as per
-the value of @code{text-quoting-style}.
-
-Typically grave accent and apostrophe in the format translate to
-matching curved quotes, e.g., @t{"Missing `%s'"} might result in
-@t{"Missing ‘foo’"}. @xref{Text Quoting Style,,,elisp}, for how to
-influence or inhibit this translation.
-
-@ref{Formatting Strings,,,elisp}.
-@end defun
-
-@c copied from lispref/files.texi
-@defun directory-name-p filename
-This function returns non-@code{nil} if @var{filename} ends with a
-directory separator character. This is the forward slash @samp{/} on
-GNU and other POSIX-like systems; MS-Windows and MS-DOS recognize both
-the forward slash and the backslash @samp{\} as directory separators.
-
-@xref{Directory Names,,,elisp}.
-@end defun
-
-@c copied from lispref/strings.texi
-@defun string-greaterp string1 string2
-This function returns the result of comparing @var{string1} and
-@var{string2} in the opposite order, i.e., it is equivalent to calling
-@code{(string-lessp @var{string2} @var{string1})}.
-
-@xref{Text Comparison,,,elisp}.
-@end defun
-
-@c copied from lispref/files.texi
-@defmac with-file-modes mode body@dots{}
-This macro evaluates the @var{body} forms with the default permissions
-for new files temporarily set to @var{modes} (whose value is as for
-@code{set-file-modes} above). When finished, it restores the original
-default file permissions, and returns the value of the last form in
-@var{body}.
-
-This is useful for creating private files, for example.
-
-@xref{Changing Files,,,elisp}.
-@end defmac
-
-@c copied from lispref/lists.texi
-@defun alist-get key alist &optional default remove
-This function is similar to @code{assq}. It finds the first association
-@w{@code{(@var{key} . @var{value})}} by comparing @var{key} with
-@var{alist} elements, and, if found, returns the @var{value} of that
-association. If no association is found, the function returns
-@var{default}.
-
-This is a generalized variable (@pxref{Generalized Variables,,,elisp})
-that can be used to change a value with @code{setf}. When using it to
-set a value, optional argument @var{remove} non-@code{nil} means to
-remove @var{key}'s association from @var{alist} if the new value is
-@code{eql} to @var{default}.
-
-@ref{Association Lists,,,elisp}.
-@end defun
-
-@defmac if-let (bindings@dots{}) then &rest else@dots{}
-As with @code{let*}, @var{bindings} will consist of
-@code{(@var{symbol} @var{value-form})} entries that are evaluated and
-bound sequentially. If all @var{value-form} evaluate to
-non-@code{nil} values, then @var{then} is evaluated as were the case
-with a regular @code{let*} expression, with all the variables bound.
-If any @var{value-form} evaluates to @code{nil}, @var{else} is
-evaluated, without any bound variables.
-
-A binding may also optionally drop the @var{symbol}, and simplify to
-@code{(@var{value-form})} if only the test is of interest.
-
-For the sake of backwards compatibility, it is possible to write a
-single binding without a binding list:
-
-@example
-@group
-(if-let* (@var{symbol} (test)) foo bar)
-@equiv{}
-(if-let* ((@var{symbol} (test))) foo bar)
-@end group
-@end example
-@end defmac
-
-@defmac when-let (bindings@dots{}) &rest body
-As with @code{when}, if one is only interested in the case where all
-@var{bindings} are non-nil. Otherwise @var{bindings} are interpreted
-just as they are by @code{if-let*}.
-@end defmac
-
-@c based on lisp/subr-x.el
-@defun hash-table-empty hash-table
-Check whether @var{hash-table} is empty (has 0 elements).
-@end defun
-
-@c based on lisp/subr-x.el
-@defmac thread-first &rest forms
-Combine @var{forms} into a single expression by ``threading'' each
-element as the @emph{first} argument of their successor. Elements of
-@var{forms} can either be an list of an atom.
-
-For example, consider the threading expression and it's equivalent
-macro expansion:
-
-@example
-(thread-first
- 5
- (+ 20)
- (/ 25)
- -
- (+ 40))
-@equiv{}
-(+ (- (/ (+ 5 20) 25)) 40)
-@end example
-
-Note how the single @code{-} got converted into a list before threading.
-This example uses arithmetic functions, but @code{thread-first} is not
-restricted to arithmetic or side-effect free code.
-@end defmac
-
-@defmac thread-last &rest forms
-Combine @var{forms} into a single expression by ``threading'' each
-element as the @emph{last} argument of their successor. Elements of
-@var{forms} can either be an list of an atom.
-
-For example, consider the threading expression and it's equivalent
-macro expansion:
-
-@example
-(thread-first
- 5
- (+ 20)
- (/ 25)
- -
- (+ 40))
-@equiv{}
-(+ 40 (- (/ 25 (+ 20 5))))
-@end example
-
-Note how the single @code{-} got converted into a list before threading.
-This example uses arithmetic functions, but @code{thread-last} is not
-restricted to arithmetic or side-effect free code.
-@end defmac
-
-@c copied from lispref/macros.texi
-@defun macroexpand-1 form &optional environment
-This function expands macros like @code{macroexpand}, but it only
-performs one step of the expansion: if the result is another macro call,
-@code{macroexpand-1} will not expand it.
-
-@xref{Expansion,Expansion,,elisp}.
-@end defun
-
-@c based on lisp/emacs-lisp/macroexp.el
-@defun macroexp-quote e
-Return an expression @var{e} such that @code{(eval e)} is @var{v}.
-@end defun
-
-@c based on lisp/emacs-lisp/macroexp.el
-@defun macroexp-parse body
-Parse a function @var{body} into @code{(declarations . exps)}.
-@end defun
-
-@defun bool-vector &rest objects
-This function creates and returns a bool-vector whose elements are the
-arguments, @var{objects}.
-
-@xref{Bool-Vectors,,,elisp}.
-@end defun
-
-@subsection Missing Definitions
-Compat does not provide support for the following Lisp features
-implemented in 25.1:
-
-@itemize
-@item
-The function @code{macroexp-macroexpand}.
-@item
-The macro @code{macroexp-let2*}.
-@item
-The function @code{directory-files-recursively}.
-@item
-New @code{pcase} patterns.
-@item
-The hook @code{prefix-command-echo-keystrokes-functions} and
-@code{prefix-command-preserve-state-hook}.
-@item
-The hook @code{pre-redisplay-functions}.
-@item
-The function @code{make-process}.
-@item
-Support for the variable @code{inhibit-message}.
-@item
-The @code{define-inline} functionality.
-@item
-The functions @code{string-collate-lessp} and
-@code{string-collate-equalp}.
-@item
-The function @code{funcall-interactively}.
-@item
-The function @code{buffer-substring-with-bidi-context}.
-@item
-The function @code{font-info}.
-@item
-The function @code{default-font-width}.
-@item
-The function @code{window-font-height} and @code{window-font-width}.
-@item
-The function @code{window-max-chars-per-line}.
-@item
-The function @code{set-binary-mode}.
-@item
-The functions @code{bufferpos-to-filepos} and
-@code{filepos-to-bufferpos}.
-@item
-The @code{thunk} library.
-@end itemize
-
@node Emacs 26.1
@section Emacs 26.1