+++ /dev/null
-Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasignNOSPAMelpa.gnu.org> (trust undefined) created at 2025-04-02T11:05:03+0200 using EDDSA
\ No newline at end of file
+++ /dev/null
-#+link: compat-srht https://todo.sr.ht/~pkal/compat/
-#+link: compat-gh https://github.com/emacs-compat/compat/issues/
-#+options: toc:nil num:nil author:nil
-
-* Release of "Compat" Version 30.1.0.0
-
-- compat-30: Add oklab color functions.
-
-(Release <2025-04-02 Wed>)
-
-* Release of "Compat" Version 30.0.2.0
-
-- compat-30: Rename =trusted-files= to =trusted-content=.
-
-(Release <2025-01-04 Sat>)
-
-* Release of "Compat" Version 30.0.1.0
-
-- compat-30: New variable =untrusted-content=.
-- compat-30: New variable =trusted-files=.
-- compat-30: New function =trusted-content-p=.
-
-(Release <2024-12-15 Sun>)
-
-* Release of "Compat" Version 30.0.0.0
-
-- compat-28: Mark =subr-native-elisp-p= as obsolete (renamed in Emacs 30).
-- compat-30: New function =char-to-name=.
-- compat-30: New function =obarray-clear=.
-- compat-30: New function =interpreted-function-p=.
-- compat-30: New function =primitive-function-p=.
-- compat-30: New function =closurep=.
-- compat-30: Add extended function =sort= with keyword arguments.
-- compat-30: New function =value<=.
-- compat-30: Add extended =copy-tree= with support for copying records with
- non-nil optional second argument.
-- compat-30: New macro =static-if=.
-- compat-30: New alias =drop=.
-- compat-30: New function =merge-ordered-lists=.
-- compat-30: New variables =completion-lazy-hilit= and =completion-lazy-hilit-fn=
- and new function =completion-lazy-hilit=.
-- compat-30: New function =require-with-check=.
-- compat-30: New functions =find-buffer= and =get-truename-buffer=.
-- compat-30: Add extended =completion-metadata-get= with support for
- =completion-category-overrides= and =completion-extra-properties=.
-
-(Release <2024-07-08 Mon>)
-
-* Release of "Compat" Version 29.1.4.5
-
-- Minor optimization of ~plist-get~ and ~plist-put~.
-- Minor compatibility adjustments for the Emacs 30 development version.
-- A minimal version of =compat.el= will be part of Emacs 30. Emacs :core packages
- can directly ~(require 'compat)~ without the ~NOERROR~ flag. Furthermore Compat
- will not be installed unnecessarily. If a package depending on Emacs 25.1 and
- Compat 29.1 is installed on Emacs 30.1, Compat 29.1 will not be installed from
- ELPA, since Emacs 30.1 already provides the required functionality.
-
-(Release <2024-03-16 Sat>)
-
-* Release of "Compat" Version 29.1.4.4
-
-- Fix ~Package-Requires~ header in compat.el
-- Fix ~Maintainer~ header in compat.el
-
-(Release <2023-11-13 Mon>)
-
-* Release of "Compat" Version 29.1.4.3
-
-- compat-29: Add function =char-uppercase-p=.
-- compat-29: Add function =window-configuration-equal-p=.
-
-(Release <2023-11-04 Sat>)
-
-* Release of "Compat" Version 29.1.4.2
-
-- compat-28: Improve =make-separator-line= visuals on graphic displays.
-- compat-28: Add =native-comp-available-p=, which always returns nil.
-- compat-29: Add variable =lisp-directory=.
-
-(Release <2023-07-30 Sun>)
-
-* Release of "Compat" Version 29.1.4.1
-
-- compat-29: Add ~directory-abbrev-apply~.
-- compat-29: Add ~directory-abbrev-make-regexp~.
-
-(Release <2023-03-26 Sun>)
-
-* Release of "Compat" Version 29.1.4.0
-
-- compat-27: Drop obsolete ~compat-call dired-get-marked-files~.
-- compat-28: Add support for ~defcustom~ type ~natnum~.
-- compat-29: Add ~with-restriction~ and ~without-restriction~.
-- compat-29: Add ~cl-constantly~.
-- compat-29: Drop ~with-narrowing~ which was renamed to ~with-restriction~.
-- compat-28: Add support for ~defcustom~ type ~key~.
-
-(Release <2023-03-05 Sun>)
-
-* Release of "Compat" Version 29.1.3.4
-
-- Ensure that ~seq~ is required properly both at compile time and runtime, such
- that compilation of downstream packages works even if Compat itself is not
- compiled. Magit uses a complex continuous integration system, where Magit is
- compiled and tested, while the Compat dependency is not compiled.
-- compat-28: Add ~process-lines-handling-status~ and ~process-lines-ignore-status~.
-
-(Release <2023-02-11 Sat>)
-
-* Release of "Compat" Version 29.1.3.3
-
-- compat-27: Add ~with-suppressed-warnings~.
-- compat-29: Add ~cl-with-gensyms~ and ~cl-once-only~.
-- compat-29: Load ~seq~, which is preloaded on Emacs 29.
-
-(Release <2023-02-08 Wed>)
-
-* Release of "Compat" Version 29.1.3.2
-
-- compat-26: Add ~make-temp-file~ with optional argument TEXT.
-- compat-27: Mark ~compat-call dired-get-marked-files~ as obsolete. See the
- section limitations in the Compat manual.
-- compat-29: Add ~funcall-with-delayed-message~ and ~with-delayed-message~.
-- compat-29: Add ~ert-with-temp-file~ and ~ert-with-temp-directory~.
-- compat-29: Add ~set-transient-map~ with optional arguments MESSAGE and TIMEOUT.
-
-(Release <2023-02-01 Wed>)
-
-* Release of "Compat" Version 29.1.3.1
-
-- Fix regression, which prevented loading Compat in interpreted mode. We ensure
- that Compat works interpreted and byte compiled by running the entire test
- suite twice in the CI. See https://github.com/magit/magit/issues/4858 for the
- corresponding Magit issue.
-- compat-27: Add ~file-name-unquote~.
-- compat-28: Add ~mark-thing-at-mouse~.
-- compat-29: Replace ~string-lines~ with version from Emacs 29, support optional
- KEEP-NEWLINES argument.
-
-(Release <2023-01-25 Wed>)
-
-* Release of "Compat" Version 29.1.3.0
-
-- compat-25: Add ~hash-table-empty-p~.
-- compat-25: Add ~macroexp-parse-body~ and ~macroexp-quote~.
-- compat-25: Add ~region-noncontiguous-p~.
-- compat-25: Add ~save-mark-and-excursion~.
-- compat-26: Add ~read-answer~.
-- compat-26: Add ~region-bounds~.
-- compat-27: Add ~date-ordinal-to-time~.
-- compat-27: Add ~file-size-human-readable-iec~.
-- compat-27: Add ~major-mode-suspend~ and ~major-mode-restore~.
-- compat-27: Add ~make-decoded-time~.
-- compat-27: Add ~minibuffer-history-value~.
-- compat-27: Add ~read-char-from-minibuffer~.
-- compat-27: Add ~ring-resize~.
-- compat-28: Add ~color-dark-p~.
-- compat-28: Add ~directory-files-and-attributes~ with COUNT argument.
-- compat-28: Add ~text-quoting-style~.
-- compat-28: Add ~with-window-non-dedicated~.
-- compat-29: Add ~buffer-local-set-state~ and ~buffer-local-restore-state~.
-- compat-29: Add ~compiled-function-p~.
-- compat-29: Add ~count-sentences~.
-- compat-29: Add ~delete-line~.
-- compat-29: Add ~get-scratch-buffer-create~.
-- compat-29: Add ~list-of-strings-p~.
-- compat-29: Add ~plist-get~ generalized variable.
-- compat-29: Add ~plistp~.
-- compat-29: Add ~read-multiple-choice~ with LONG-FORM argument.
-- compat-29: Add ~readablep~.
-- compat-29: Add ~substitute-quotes~.
-- compat-29: Add ~use-region-beginning~, ~use-region-end~ and ~use-region-noncontiguous-p~.
-- compat-29: Add ~with-narrowing~.
-
-(Release <2023-01-22 Sun>)
-
-* Release of "Compat" Version 29.1.2.0
-
-- All compatibility functions are covered by tests!
-- Add links from compatibility definitions to tests.
-- BREAKING: Drop JSON parsing support (libjansson API, unused downstream).
-- BREAKING: Drop ~null-device~ (unused downstream).
-- BREAKING: Drop ~unlock-buffer~ (unused downstream).
-- compat-26: Add ~buffer-hash~.
-- compat-27: Add ~fixnump~ and ~bignump~.
-- compat-27: Add ~with-minibuffer-selected-window~.
-- compat-27: Add generalized variables for ~decoded-time-*~.
-- compat-28: Add ~macroexp-warn-and-return~.
-- compat-28: Add ~subr-native-elisp-p~.
-- compat-28: Add ~bounds-of-thing-at-mouse~.
-- compat-29: Add ~with-buffer-unmodified-if-unchanged~.
-- compat-29: Fix and test ~define-key~ with REMOVE argument.
-
-(Release <2023-01-16 Mon>)
-
-* Release of "Compat" Version 29.1.1.1
-
-- Add tests, 167 out of 203 definitions tested (82%).
-- compat-25: Improve algorithmic complexity of ~sort~.
-- compat-28: Add ~make-separator-line~.
-- compat-29: Minor fixes to ~keymap-*~ functions.
-- compat-29: Add ~with-memoization~.
-- compat-29: Add ~buttonize~ and ~buttonize-region~.
-
-(Release <2023-01-14 Sat>)
-
-* Release of "Compat" Version 29.1.1.0
-
-- The macros in ~compat-macs.el~ have been rewritten and simplified. The
- refactoring allows to further refine the criteria under which compatibility
- aliases, functions, macros and variables are installed.
-- Remove deprecated, prefixed compatibility functions.
-- Remove deprecated features ~compat-help~, ~compat-font-lock~ and ~compat-24~.
-- Compat uses runtime checks (~boundp~, ~fboundp~) to ensure that existing
- definitions are never overridden, when Compat is loaded on a newer Emacs than
- it was compiled on.
-- Compat compiles without byte compilation warnings on all supported Emacs
- versions. Warnings are treated as errors in the test suite.
-- Compat takes great care to remove unneeded definitions at compile time. On
- recent Emacs 29 the byte compiled files are empty and not loaded, such that
- Compat does not any cost to the Emacs process.
-- compat-26: Fix and test ~image-property~ setter.
-- compat-26: Fix and test ~read-multiple-choice~.
-- compat-28: Fix and test ~with-existing-directory~.
-- compat-28: Drop obsolete function ~make-directory-autoloads~.
-- compat-29: Drop broken functions ~string-pixel-width~ and
- ~buffer-text-pixel-size~. These functions had poor performance which lead to a
- downstream issue in the doom-modeline package. If a more efficient solution is
- possible, the function will be added back. See [[compat-gh:8]] for the bug report.
-- compat-29: Drop broken function ~string-limit~.
-- compat-29: Drop broken macro ~with-buffer-unmodified-if-unchanged~, which relied
- on ~buffer-hash~ which does not exist on all supported Emacs versions.
-- compat-29: Add ~pos-bol~ and ~pos-eol~.
-
-(Release <2023-01-07 Sat>)
-
-* Release of "Compat" Version 29.1.0.1
-
-- Add multiple new tests for existing APIs.
-- Fix bugs in compatibility functions: ~setq-local~, ~proper-list-p, prop-match-p~,
- ~file-name-concat~, ~replace-regexp-in-region~, ~replace-string-in-region~.
-- Add new Emacs 29 APIs. Some of them are still untested and may change. If you
- intend to use an Emacs 29 API please be careful and if possible contribute
- test cases. All untested functions are marked in the Compat code. Over time
- tests for all functions will be added gradually.
-- Add the macros ~compat-call~ and ~compat-function~ to call compatibility
- functions. Since Compat avoids overwriting already existing functions, we must
- define separate compatibility function definitions for functions which changed
- their calling convention or behavior. These compatibility definitions can be
- looked up using ~compat-function~ and called with ~compat-call~. For example ~assoc~
- can be called with a ~TESTFN~ since Emacs 26. In Emacs 25 and older the calling
- convention was ~(assoc KEY ALIST)~. In order to use the new calling convention
- you can use ~(compat-call assoc KEY ALIST TESTFN)~.
-- Deprecate all ~compat-*~ prefixed functions. Instead use the aforementioned
- ~compat-call~ or ~compat-function~ macros.
-- Deprecate ~compat-help.el~ and ~compat-font-lock.el.~
-- Development moved to GitHub.
-- BREAKING: Drop broken function ~func-arity~. Using ~func-arity~ is generally
- discouraged and the function is hard to implement properly due to all the
- various function types. There it is unlikely that the function will get
- reintroduced in Compat.
-- BREAKING: Drop broken function ~directory-files-recursively~. In case you need
- this function, a patch including tests is welcome.
-- BREAKING: Drop support for Emacs 24.3. Emacs 24.4 is required now. In case you
- still need Emacs 24.3 support, you can rely on Compat 28.1.2.2.
-
-(Release <2023-01-05 Thu>)
-
-* Release of "Compat" Version 28.1.2.2
-
-This is a minor release that hopes to address [[compat-srht:7]].
-
-(Release <2022-08-25 Thu>)
-
-* Release of "Compat" Version 28.1.2.1
-
-This is a minor release adding the following changes:
-
-- Add =derived-mode-p= defined in Emacs 27
-- Add =provided-mode-derived-p= defined in Emacs 27
-- Add =read-multiple-choice= defined in Emacs 26
-- Add =file-name-absolute-p= defined in Emacs 28
-
-The only other notable change is that the manual has been rewritten to
-include much more documentation that had been the case previously.
-
-(Release <2022-08-24 Wed>)
-
-* Release of "Compat" Version 28.1.2.0
-
-The main change of this release has been the major simplification of
-Compat's initialisation system, improving the situation around issues
-people had been reporting ([[compat-srht:4]], once again) with unconventional
-or unpopular packaging systems.
-
-In addition to this, the following functional changes have been made:
-
-- Fix =format-prompt= of an empty string as "default" argument
-- Add =decoded-time-period= defined in Emacs 28
-- Add =subr-primitive-p= defined in Emacs 28
-
-Minor improvements to manual are also part of this release.
-
-(Release <2022-07-18 Mon>)
-
-* Release of "Compat" Version 28.1.1.3
-
-This release just contains a hot-fix for an issue introduced in the
-last version, where compat.el raises an error during byte compilation.
-See [[compat-srht:4]].
-
-(Release <2022-06-19 Sun>)
-
-* Release of "Compat" Version 28.1.1.2
-
-Two main changes have necessitated a new patch release:
-
-1. Fix issues related to the loading of compat when uncompiled. See
- [[https://lists.sr.ht/~pkal/compat-devel/%3C20220530191000.2183047-1-jonas%40bernoul.li%3E][this thread]] for more details on the problem.
-2. Fix issues related to the loading of compat on old pre-releases
- (think of 28.0.50). See [[https://lists.sr.ht/~pkal/compat-devel/%3Cf8635d7d-e233-448f-b325-9e850363241c%40www.fastmail.com%3E][this thread]] for more details on the
- problem.
-
-(Released <2022-06-22 Wed>)
-
-* Release of "Compat" Version 28.1.1.1
-
-This is a minor release fixing a bug in =json-serialize=, that could
-cause unintended side-effects, not related to packages using Compat
-directly (see [[compat-srht:2]]).
-
-(Released <2022-05-05 Thu>)
-
-* Release of "Compat" Version 28.1.1.0
-
-This release mostly fixes a number of smaller bugs that were not
-identified as of 28.1.0.0. Nevertheless these warrant a version bump,
-as some of these changes a functional. These include:
-
-- The addition of the =file-attribute-*= accessor functions.
-- The addition of =file-attribute-collect=.
-- Improvements to the Texinfo manual (via Jonas Bernoulli's recent
- work on =ox-texinfo=). For the time being, the Texinfo file is
- maintained in the repository itself, next to the =MANUAL= file.
- This might change in the future.
-- Adding a prefix to =string-trim=, =string-trim-left= and
- =string-trim-right= (i.e. now =compat-string-trim=,
- =compat-string-trim-left= and =compat-string-trim-right=)
-- Improving the version inference used in the =compat-*= macros.
- This improves the compile-time optimisation that strips away
- functions that are known to be defined for a specific version.
-- The addition of generalised variable (=setf=) support for
- =compat-alist-get=.
-- The addition of =image-property= and generalised variable support
- for =image-property=.
-- The addition of the function =compat-executable-find=.
-- The addition of the function =compat-dired-get-marked-files=.
-- The addition of the function =exec-path=.
-- The addition of the function =make-lock-file-name=.
-- The addition of the function =null-device=.
-- The addition of the function =time-equal-p=.
-- The addition of the function =date-days-in-month=.
-- Handling out-of-directory byte compilation better.
-- Fixing the usage and edge-cases of =and-let*=.
-
-(Released <2022-04-22 Fri>)
+++ /dev/null
-;;; 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
+++ /dev/null
-;;; compat-26.el --- Functionality added in Emacs 26.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 26.1, needed by older Emacs versions.
-
-;;; Code:
-
-(eval-when-compile (load "compat-macs.el" nil t t))
-(compat-require compat-25 "25.1")
-
-(compat-version "26.1")
-
-;;;; Defined in fns.c
-
-(compat-defun buffer-hash (&optional buffer-or-name) ;; <compat-tests:buffer-hash>
- "Return a hash of the contents of BUFFER-OR-NAME.
-This hash is performed on the raw internal format of the buffer,
-disregarding any coding systems. If nil, use the current buffer.
-
-This function is useful for comparing two buffers running in the same
-Emacs, but is not guaranteed to return the same hash between different
-Emacs versions. It should be somewhat more efficient on larger
-buffers than `secure-hash' is, and should not allocate more memory.
-
-It should not be used for anything security-related. See
-`secure-hash' for these applications."
- (with-current-buffer (or buffer-or-name (current-buffer))
- (save-restriction
- (widen)
- (sha1 (current-buffer) (point-min) (point-max)))))
-
-(compat-defun mapcan (func sequence) ;; <compat-tests:mapcan>
- "Apply FUNC to each element of SEQUENCE.
-Concatenate the results by altering them (using `nconc').
-SEQUENCE may be a list, a vector, a boolean vector, or a string."
- (apply #'nconc (mapcar func sequence)))
-
-(compat-defun line-number-at-pos (&optional position absolute) ;; <compat-tests:line-number-at-pos>
- "Handle optional argument ABSOLUTE."
- :extended t
- (if absolute
- (save-restriction
- (widen)
- (line-number-at-pos position))
- (line-number-at-pos position)))
-
-;;;; Defined in simple.el
-
-(compat-defun region-bounds () ;; <compat-tests:region-bounds>
- "Return the boundaries of the region.
-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)))
-
-;;;; Defined in subr.el
-
-(compat-defun provided-mode-derived-p (mode &rest modes) ;; <compat-tests:provided-mode-derived-p>
- "Non-nil if MODE is derived from one of MODES.
-Uses the `derived-mode-parent' property of the symbol to trace backwards.
-If you just want to check `major-mode', use `derived-mode-p'."
- ;; If MODE is an alias, then look up the real mode function first.
- (let ((alias (symbol-function mode)))
- (when (and alias (symbolp alias))
- (setq mode alias)))
- (while
- (and
- (not (memq mode modes))
- (let* ((parent (get mode 'derived-mode-parent))
- (parentfn (symbol-function parent)))
- (setq mode (if (and parentfn (symbolp parentfn)) parentfn parent)))))
- mode)
-
-(compat-defun assoc (key alist &optional testfn) ;; <compat-tests:assoc>
- "Handle the optional TESTFN."
- :extended t
- (cond
- ((or (eq testfn #'eq)
- (and (not testfn) (or (symbolp key) (integerp key)))) ;; eq_comparable_value
- (assq key alist))
- ((or (eq testfn #'equal) (not testfn))
- (assoc key alist))
- (t
- (catch 'found
- (dolist (ent alist)
- (when (funcall testfn (car ent) key)
- (throw 'found ent)))))))
-
-(compat-defun alist-get (key alist &optional default remove testfn) ;; <compat-tests:alist-get>
- "Handle optional argument TESTFN."
- :extended "25.1"
- (ignore remove)
- (let ((x (if (not testfn)
- (assq key alist)
- (compat--assoc key alist testfn))))
- (if x (cdr x) default)))
-
-(compat-guard t ;; <compat-tests:alist-get-gv>
- (gv-define-expander compat--alist-get
- (lambda (do key alist &optional default remove testfn)
- (macroexp-let2 macroexp-copyable-p k key
- (gv-letplace (getter setter) alist
- (macroexp-let2 nil p `(compat--assoc ,k ,getter ,testfn)
- (funcall do (if (null default) `(cdr ,p)
- `(if ,p (cdr ,p) ,default))
- (lambda (v)
- (macroexp-let2 nil v v
- (let ((set-exp
- `(if ,p (setcdr ,p ,v)
- ,(funcall setter
- `(cons (setq ,p (cons ,k ,v))
- ,getter)))))
- `(progn
- ,(cond
- ((null remove) set-exp)
- ((or (eql v default)
- (and (eq (car-safe v) 'quote)
- (eq (car-safe default) 'quote)
- (eql (cadr v) (cadr default))))
- `(if ,p ,(funcall setter `(delq ,p ,getter))))
- (t
- `(cond
- ((not (eql ,default ,v)) ,set-exp)
- (,p ,(funcall setter
- `(delq ,p ,getter))))))
- ,v))))))))))
- (unless (get 'alist-get 'gv-expander)
- (put 'alist-get 'gv-expander (get 'compat--alist-get 'gv-expander))))
-
-(compat-defun string-trim-left (string &optional regexp) ;; <compat-tests:string-trim-left>
- "Handle optional argument REGEXP."
- :extended t
- (if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
- (substring string (match-end 0))
- string))
-
-(compat-defun string-trim-right (string &optional regexp) ;; <compat-tests:string-trim-right>
- "Handle optional argument REGEXP."
- :extended t
- (let ((i (string-match-p
- (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
- string)))
- (if i (substring string 0 i) string)))
-
-(compat-defun string-trim (string &optional trim-left trim-right) ;; <compat-tests:string-trim>
- "Handle optional arguments TRIM-LEFT and TRIM-RIGHT."
- :extended t
- (compat--string-trim-left
- (compat--string-trim-right
- string
- trim-right)
- trim-left))
-
-(compat-defun caaar (x) ;; <compat-tests:cXXXr>
- "Return the `car' of the `car' of the `car' of X."
- (declare (pure t))
- (car (car (car x))))
-
-(compat-defun caadr (x) ;; <compat-tests:cXXXr>
- "Return the `car' of the `car' of the `cdr' of X."
- (declare (pure t))
- (car (car (cdr x))))
-
-(compat-defun cadar (x) ;; <compat-tests:cXXXr>
- "Return the `car' of the `cdr' of the `car' of X."
- (declare (pure t))
- (car (cdr (car x))))
-
-(compat-defun caddr (x) ;; <compat-tests:cXXXr>
- "Return the `car' of the `cdr' of the `cdr' of X."
- (declare (pure t))
- (car (cdr (cdr x))))
-
-(compat-defun cdaar (x) ;; <compat-tests:cXXXr>
- "Return the `cdr' of the `car' of the `car' of X."
- (declare (pure t))
- (cdr (car (car x))))
-
-(compat-defun cdadr (x) ;; <compat-tests:cXXXr>
- "Return the `cdr' of the `car' of the `cdr' of X."
- (declare (pure t))
- (cdr (car (cdr x))))
-
-(compat-defun cddar (x) ;; <compat-tests:cXXXr>
- "Return the `cdr' of the `cdr' of the `car' of X."
- (declare (pure t))
- (cdr (cdr (car x))))
-
-(compat-defun cdddr (x) ;; <compat-tests:cXXXr>
- "Return the `cdr' of the `cdr' of the `cdr' of X."
- (declare (pure t))
- (cdr (cdr (cdr x))))
-
-(compat-defun caaaar (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `car' of the `car' of the `car' of X."
- (declare (pure t))
- (car (car (car (car x)))))
-
-(compat-defun caaadr (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `car' of the `car' of the `cdr' of X."
- (declare (pure t))
- (car (car (car (cdr x)))))
-
-(compat-defun caadar (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `car' of the `cdr' of the `car' of X."
- (declare (pure t))
- (car (car (cdr (car x)))))
-
-(compat-defun caaddr (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `car' of the `cdr' of the `cdr' of X."
- (declare (pure t))
- (car (car (cdr (cdr x)))))
-
-(compat-defun cadaar (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `cdr' of the `car' of the `car' of X."
- (declare (pure t))
- (car (cdr (car (car x)))))
-
-(compat-defun cadadr (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `cdr' of the `car' of the `cdr' of X."
- (declare (pure t))
- (car (cdr (car (cdr x)))))
-
-(compat-defun caddar (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `cdr' of the `cdr' of the `car' of X."
- (declare (pure t))
- (car (cdr (cdr (car x)))))
-
-(compat-defun cadddr (x) ;; <compat-tests:cXXXXr>
- "Return the `car' of the `cdr' of the `cdr' of the `cdr' of X."
- (declare (pure t))
- (car (cdr (cdr (cdr x)))))
-
-(compat-defun cdaaar (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `car' of the `car' of the `car' of X."
- (declare (pure t))
- (cdr (car (car (car x)))))
-
-(compat-defun cdaadr (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `car' of the `car' of the `cdr' of X."
- (declare (pure t))
- (cdr (car (car (cdr x)))))
-
-(compat-defun cdadar (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `car' of the `cdr' of the `car' of X."
- (declare (pure t))
- (cdr (car (cdr (car x)))))
-
-(compat-defun cdaddr (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `car' of the `cdr' of the `cdr' of X."
- (declare (pure t))
- (cdr (car (cdr (cdr x)))))
-
-(compat-defun cddaar (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `cdr' of the `car' of the `car' of X."
- (declare (pure t))
- (cdr (cdr (car (car x)))))
-
-(compat-defun cddadr (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `cdr' of the `car' of the `cdr' of X."
- (declare (pure t))
- (cdr (cdr (car (cdr x)))))
-
-(compat-defun cdddar (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `cdr' of the `cdr' of the `car' of X."
- (declare (pure t))
- (cdr (cdr (cdr (car x)))))
-
-(compat-defun cddddr (x) ;; <compat-tests:cXXXXr>
- "Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X."
- (declare (pure t))
- (cdr (cdr (cdr (cdr x)))))
-
-(compat-defvar gensym-counter 0 ;; <compat-tests:gensym>
- "Number used to construct the name of the next symbol created by `gensym'.")
-
-(compat-defun gensym (&optional prefix) ;; <compat-tests:gensym>
- "Return a new uninterned symbol.
-The name is made by appending `gensym-counter' to PREFIX.
-PREFIX is a string, and defaults to \"g\"."
- (let ((num (prog1 gensym-counter
- (setq gensym-counter
- (1+ gensym-counter)))))
- (make-symbol (format "%s%d" (or prefix "g") num))))
-
-(compat-defmacro if-let* (varlist then &rest else) ;; <compat-tests:if-let*>
- "Bind variables according to VARLIST and evaluate THEN or ELSE.
-This is like `if-let' but doesn't handle a VARLIST of the form
-\(SYMBOL SOMETHING) specially."
- (declare (indent 2)
- (debug ((&rest [&or symbolp (symbolp form) (form)])
- body)))
- (let ((empty (make-symbol "s"))
- (last t) list)
- (dolist (var varlist)
- (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* (varlist &rest body) ;; <compat-tests:when-let*>
- "Bind variables according to VARLIST and conditionally evaluate BODY.
-This is like `when-let' but doesn't handle a VARLIST of the form
-\(SYMBOL SOMETHING) specially."
- (declare (indent 1) (debug if-let*))
- (list 'if-let* varlist (macroexp-progn body)))
-
-(compat-defmacro and-let* (varlist &rest body) ;; <compat-tests:and-let*>
- "Bind variables according to VARLIST and conditionally evaluate BODY.
-Like `when-let*', except if BODY is empty and all the bindings
-are non-nil, then the result is non-nil."
- (declare (indent 1)
- (debug ((&rest [&or symbolp (symbolp form) (form)])
- body)))
- (let ((empty (make-symbol "s"))
- (last t) list)
- (dolist (var varlist)
- (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) ,(macroexp-progn (or body '(t)))))))
-
-;;;; Defined in files.el
-
-(compat-defvar mounted-file-systems ;; <compat-tests:mounted-file-systems>
- (eval-when-compile
- (if (memq system-type '(windows-nt cygwin))
- "^//[^/]+/"
- (concat
- "^" (regexp-opt '("/afs/" "/media/" "/mnt" "/net/" "/tmp_mnt/")))))
- "File systems that ought to be mounted.")
-
-(compat-defun file-local-name (file) ;; <compat-tests:file-local-name>
- "Return the local name component of FILE.
-This function removes from FILE the specification of the remote host
-and the method of accessing the host, leaving only the part that
-identifies FILE locally on the remote system.
-The returned file name can be used directly as argument of
-`process-file', `start-file-process', or `shell-command'."
- (or (file-remote-p file 'localname) file))
-
-(compat-defun temporary-file-directory () ;; <compat-tests:temporary-file-directory>
- "The directory for writing temporary files.
-In case of a remote `default-directory', this is a directory for
-temporary files on that remote host. If such a directory does
-not exist, or `default-directory' ought to be located on a
-mounted file system (see `mounted-file-systems'), the function
-returns `default-directory'.
-For a non-remote and non-mounted `default-directory', the value of
-the variable `temporary-file-directory' is returned."
- ;; NOTE: The handler may fail with an error, since the
- ;; `temporary-file-directory' handler was introduced in Emacs 26.
- (let ((handler (find-file-name-handler
- default-directory 'temporary-file-directory)))
- (or (and handler (ignore-errors (funcall handler 'temporary-file-directory)))
- (if-let ((remote (file-remote-p default-directory)))
- (concat remote "/tmp/") ;; FIXME: Guess /tmp on remote host
- (if (string-match mounted-file-systems default-directory)
- default-directory
- temporary-file-directory)))))
-
-(compat-defun make-temp-file (prefix &optional dir-flag suffix text) ;; <compat-tests:make-temp-file>
- "Handle optional argument TEXT."
- :extended t
- (let ((file (make-temp-file prefix dir-flag suffix)))
- (when text
- (with-temp-buffer
- (insert text)
- (write-region (point-min) (point-max) file)))
- file))
-
-(compat-defun make-nearby-temp-file (prefix &optional dir-flag suffix) ;; <compat-tests:make-nearby-temp-file>
- "Create a temporary file as close as possible to `default-directory'.
-If PREFIX is a relative file name, and `default-directory' is a
-remote file name or located on a mounted file systems, the
-temporary file is created in the directory returned by the
-function `temporary-file-directory'. Otherwise, the function
-`make-temp-file' is used. PREFIX, DIR-FLAG and SUFFIX have the
-same meaning as in `make-temp-file'."
- ;; NOTE: The handler may fail with an error, since the
- ;; `make-nearby-temp-file' handler was introduced in Emacs 26.
- (let ((handler (and (not (file-name-absolute-p default-directory))
- (find-file-name-handler
- default-directory 'make-nearby-temp-file))))
- (or (and handler (ignore-errors (funcall handler 'make-nearby-temp-file
- prefix dir-flag suffix)))
- (let ((temporary-file-directory (temporary-file-directory)))
- (make-temp-file prefix dir-flag suffix)))))
-
-(compat-defun file-attribute-type (attributes) ;; <compat-tests:file-attribute-getters>
- "The type field in ATTRIBUTES returned by `file-attributes'.
-The value is either t for directory, string (name linked to) for
-symbolic link, or nil."
- (nth 0 attributes))
-
-(compat-defun file-attribute-link-number (attributes) ;; <compat-tests:file-attribute-getters>
- "Return the number of links in ATTRIBUTES returned by `file-attributes'."
- (nth 1 attributes))
-
-(compat-defun file-attribute-user-id (attributes) ;; <compat-tests:file-attribute-getters>
- "The UID field in ATTRIBUTES returned by `file-attributes'.
-This is either a string or a number. If a string value cannot be
-looked up, a numeric value, either an integer or a float, is
-returned."
- (nth 2 attributes))
-
-(compat-defun file-attribute-group-id (attributes) ;; <compat-tests:file-attribute-getters>
- "The GID field in ATTRIBUTES returned by `file-attributes'.
-This is either a string or a number. If a string value cannot be
-looked up, a numeric value, either an integer or a float, is
-returned."
- (nth 3 attributes))
-
-(compat-defun file-attribute-access-time (attributes) ;; <compat-tests:file-attribute-getters>
- "The last access time in ATTRIBUTES returned by `file-attributes'.
-This a Lisp timestamp in the style of `current-time'."
- (nth 4 attributes))
-
-(compat-defun file-attribute-modification-time (attributes) ;; <compat-tests:file-attribute-getters>
- "The modification time in ATTRIBUTES returned by `file-attributes'.
-This is the time of the last change to the file's contents, and
-is a Lisp timestamp in the style of `current-time'."
- (nth 5 attributes))
-
-(compat-defun file-attribute-status-change-time (attributes) ;; <compat-tests:file-attribute-getters>
- "The status modification time in ATTRIBUTES returned by `file-attributes'.
-This is the time of last change to the file's attributes: owner
-and group, access mode bits, etc., and is a Lisp timestamp in the
-style of `current-time'."
- (nth 6 attributes))
-
-(compat-defun file-attribute-size (attributes) ;; <compat-tests:file-attribute-getters>
- "The integer size (in bytes) in ATTRIBUTES returned by `file-attributes'."
- (nth 7 attributes))
-
-(compat-defun file-attribute-modes (attributes) ;; <compat-tests:file-attribute-getters>
- "The file modes in ATTRIBUTES returned by `file-attributes'.
-This is a string of ten letters or dashes as in ls -l."
- (nth 8 attributes))
-
-(compat-defun file-attribute-inode-number (attributes) ;; <compat-tests:file-attribute-getters>
- "The inode number in ATTRIBUTES returned by `file-attributes'.
-It is a nonnegative integer."
- (nth 10 attributes))
-
-(compat-defun file-attribute-device-number (attributes) ;; <compat-tests:file-attribute-getters>
- "The file system device number in ATTRIBUTES returned by `file-attributes'.
-It is an integer."
- (nth 11 attributes))
-
-(compat-defun file-attribute-collect (attributes &rest attr-names) ;; <compat-tests:file-attribute-collect>
- "Return a sublist of ATTRIBUTES returned by `file-attributes'.
-ATTR-NAMES are symbols with the selected attribute names.
-
-Valid attribute names are: type, link-number, user-id, group-id,
-access-time, modification-time, status-change-time, size, modes,
-inode-number and device-number."
- (let ((idx '((type . 0)
- (link-number . 1)
- (user-id . 2)
- (group-id . 3)
- (access-time . 4)
- (modification-time . 5)
- (status-change-time . 6)
- (size . 7)
- (modes . 8)
- (inode-number . 10)
- (device-number . 11)))
- result)
- (while attr-names
- (let ((attr (pop attr-names)))
- (if (assq attr idx)
- (push (nth (cdr (assq attr idx))
- attributes)
- result)
- (error "Wrong attribute name '%S'" attr))))
- (nreverse result)))
-
-;;;; Defined in mouse.el
-
-(compat-defvar mouse-select-region-move-to-beginning nil ;; <compat-tests:thing-at-mouse>
- "Effect of selecting a region extending backward from double click.
-Nil means keep point at the position clicked (region end);
-non-nil means move point to beginning of region.")
-
-;;;; Defined in image.el
-
-(compat-defun image-property (image property) ;; <compat-tests:image-property>
- "Return the value of PROPERTY in IMAGE.
-Properties can be set with
-
- (setf (image-property IMAGE PROPERTY) VALUE)
-
-If VALUE is nil, PROPERTY is removed from IMAGE."
- :feature image
- (plist-get (cdr image) property))
-
-;;;; Defined in rmc.el
-
-(compat-defun read-multiple-choice (prompt choices) ;; <compat-tests:read-multiple-choice>
- "Ask user to select an entry from CHOICES, promting with PROMPT.
-This function allows to ask the user a multiple-choice question.
-
-CHOICES should be a list of the form (KEY NAME [DESCRIPTION]).
-KEY is a character the user should type to select the entry.
-NAME is a short name for the entry to be displayed while prompting
-\(if there's no room, it might be shortened).
-
-NOTE: This is a partial implementation of `read-multiple-choice', that
-among other things doesn't offer any help and ignores the
-optional DESCRIPTION field."
- (let ((options
- (mapconcat
- (lambda (opt)
- (format
- "[%s] %s"
- (key-description (string (car opt)))
- (cadr opt)))
- choices " "))
- choice)
- (setq prompt (concat prompt " (" options "): "))
- (while (not (setq choice (assq (read-event prompt) choices)))
- (message "Invalid choice")
- (sit-for 1))
- choice))
-
-(provide 'compat-26)
-;;; compat-26.el ends here
+++ /dev/null
-;;; compat-27.el --- Functionality added in Emacs 27.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 27.1, needed by older Emacs versions.
-
-;;; Code:
-
-(eval-when-compile (load "compat-macs.el" nil t t))
-(compat-require compat-26 "26.1")
-
-(compat-version "27.1")
-
-;;;; Defined in fns.c
-
-(compat-defun proper-list-p (object) ;; <compat-tests:proper-list-p>
- "Return OBJECT's length if it is a proper list, nil otherwise.
-A proper list is neither circular nor dotted (i.e., its last cdr
-is nil)."
- (if (eval-when-compile (< emacs-major-version 26))
- ;; On older Emacs than 26.1 use Tortoise and Hare algorithm
- (when (listp object)
- (catch 'cycle
- (let ((hare object) (tortoise object)
- (max 2) (q 2))
- (while (consp hare)
- (setq hare (cdr hare))
- (when (and (or (/= 0 (setq q (1- q)))
- (ignore
- (setq max (ash max 1)
- q max
- tortoise hare)))
- (eq hare tortoise))
- (throw 'cycle nil)))
- (and (null hare) (length object)))))
- ;; Errors on 26.1 and newer
- (and (listp object) (ignore-errors (length object)))))
-
-(compat-defun string-distance (string1 string2 &optional bytecompare) ;; <compat-tests:string-distance>
- "Return Levenshtein distance between STRING1 and STRING2.
-The distance is the number of deletions, insertions, and substitutions
-required to transform STRING1 into STRING2.
-If BYTECOMPARE is nil or omitted, compute distance in terms of characters.
-If BYTECOMPARE is non-nil, compute distance in terms of bytes.
-Letter-case is significant, but text properties are ignored."
- ;; https://en.wikipedia.org/wiki/Levenshtein_distance
- (let ((s1 (if bytecompare
- (encode-coding-string string1 'raw-text)
- (concat string1 "")))
- (s2 (if bytecompare
- (encode-coding-string string2 'raw-text)
- string2)))
- (let* ((len1 (length s1))
- (len2 (length s2))
- (column (make-vector (1+ len1) 0)))
- (dotimes (y len1)
- (setf (aref column (1+ y)) y))
- (dotimes (x len2)
- (setf (aref column 0) (1+ x))
- (let ((lastdiag x) olddiag)
- (dotimes (y len1)
- (setf olddiag (aref column (1+ y))
- (aref column (1+ y))
- (min (+ (if (= (aref s1 y) (aref s2 x)) 0 1)
- lastdiag)
- (1+ (aref column (1+ y)))
- (1+ (aref column y)))
- lastdiag olddiag))))
- (aref column len1))))
-
-;;;; Defined in window.c
-
-(compat-defun recenter (&optional arg redisplay) ;; <compat-tests:recenter>
- "Handle optional argument REDISPLAY."
- :extended t
- (recenter arg)
- (when (and redisplay recenter-redisplay)
- (redisplay)))
-
-;;;; Defined in keymap.c
-
-(compat-defun lookup-key (keymap key &optional accept-default) ;; <compat-tests:lookup-key>
- "Allow for KEYMAP to be a list of keymaps."
- :extended t
- (cond
- ((keymapp keymap)
- (lookup-key keymap key accept-default))
- ((listp keymap)
- (catch 'found
- (dolist (map keymap)
- (when-let ((fn (lookup-key map key accept-default)))
- (throw 'found fn)))))
- ((signal 'wrong-type-argument (list 'keymapp keymap)))))
-
-;;;; Defined in timefns.c
-
-(compat-defun time-equal-p (t1 t2) ;; <compat-tests:time-equal-p>
- "Return non-nil if time value T1 is equal to time value T2.
-A nil value for either argument stands for the current time.
-
-NOTE: This function is not as accurate as the actual `time-equal-p'."
- (cond
- ((eq t1 t2))
- ((and (consp t1) (consp t2))
- (equal t1 t2))
- (t
- ;; Due to inaccuracies and the relatively slow evaluating of
- ;; Emacs Lisp compared to C, we allow for slight inaccuracies
- ;; (less than a millisecond) when comparing time values.
- (< (abs (- (float-time t1) (float-time t2)))
- (if (and t1 t2) 1e-6 1e-5)))))
-
-;;;; Defined in subr.el
-
-(compat-defalias fixnump integerp) ;; <compat-tests:fixnump>
-(compat-defalias bignump ignore) ;; <compat-tests:bignump>
-
-(compat-defmacro setq-local (&rest pairs) ;; <compat-tests:setq-local>
- "Handle multiple assignments."
- :extended t
- (unless (zerop (mod (length pairs) 2))
- (error "PAIRS must have an even number of variable/value members"))
- (let (body)
- (while pairs
- (let* ((sym (pop pairs))
- (val (pop pairs)))
- (unless (symbolp sym)
- (error "Attempting to set a non-symbol: %s" (car pairs)))
- (push `(set (make-local-variable ',sym) ,val)
- body)))
- (cons 'progn (nreverse body))))
-
-(compat-defmacro ignore-error (condition &rest body) ;; <compat-tests:ignore-error>
- "Execute BODY; if the error CONDITION occurs, return nil.
-Otherwise, return result of last form in BODY.
-
-CONDITION can also be a list of error conditions."
- (declare (debug t) (indent 1))
- `(condition-case nil (progn ,@body) (,condition nil)))
-
-(compat-defmacro dolist-with-progress-reporter (spec reporter-or-message &rest body) ;; <compat-tests:dolist-with-progress-reporter>
- "Loop over a list and report progress in the echo area.
-Evaluate BODY with VAR bound to each car from LIST, in turn.
-Then evaluate RESULT to get return value, default nil.
-
-REPORTER-OR-MESSAGE is a progress reporter object or a string. In the latter
-case, use this string to create a progress reporter.
-
-At each iteration, print the reporter message followed by progress
-percentage in the echo area. After the loop is finished,
-print the reporter message followed by the word \"done\".
-
-\(fn (VAR LIST [RESULT]) REPORTER-OR-MESSAGE BODY...)"
- (declare (indent 2) (debug ((symbolp form &optional form) form body)))
- (let ((prep (make-symbol "--dolist-progress-reporter--"))
- (count (make-symbol "--dolist-count--"))
- (list (make-symbol "--dolist-list--")))
- `(let ((,prep ,reporter-or-message)
- (,count 0)
- (,list ,(cadr spec)))
- (when (stringp ,prep)
- (setq ,prep (make-progress-reporter ,prep 0 (length ,list))))
- (dolist (,(car spec) ,list)
- ,@body
- (progress-reporter-update ,prep (setq ,count (1+ ,count))))
- (progress-reporter-done ,prep)
- (or ,@(cdr (cdr spec)) nil))))
-
-(compat-defun flatten-tree (tree) ;; <compat-tests:flatten-tree>
- "Return a \"flattened\" copy of TREE.
-In other words, return a list of the non-nil terminal nodes, or
-leaves, of the tree of cons cells rooted at TREE. Leaves in the
-returned list are in the same order as in TREE.
-
-\(flatten-tree \\='(1 (2 . 3) nil (4 5 (6)) 7))
-=> (1 2 3 4 5 6 7)"
- (let (elems)
- (while (consp tree)
- (let ((elem (pop tree)))
- (while (consp elem)
- (push (cdr elem) tree)
- (setq elem (car elem)))
- (if elem (push elem elems))))
- (if tree (push tree elems))
- (nreverse elems)))
-
-(compat-defun xor (cond1 cond2) ;; <compat-tests:xor>
- "Return the boolean exclusive-or of COND1 and COND2.
-If only one of the arguments is non-nil, return it; otherwise
-return nil."
- (declare (pure t) (side-effect-free error-free))
- (cond ((not cond1) cond2)
- ((not cond2) cond1)))
-
-(compat-defvar regexp-unmatchable "\\`a\\`" ;; <compat-tests:regexp-unmatchable>
- "Standard regexp guaranteed not to match any string at all."
- :constant t)
-
-(compat-defun assoc-delete-all (key alist &optional test) ;; <compat-tests:assoc-delete-all>
- "Handle optional argument TEST."
- :extended "26.2"
- (unless test (setq test #'equal))
- (while (and (consp (car alist))
- (funcall test (caar alist) key))
- (setq alist (cdr alist)))
- (let ((tail alist) tail-cdr)
- (while (setq tail-cdr (cdr tail))
- (if (and (consp (car tail-cdr))
- (funcall test (caar tail-cdr) key))
- (setcdr tail (cdr tail-cdr))
- (setq tail tail-cdr))))
- alist)
-
-(compat-defvar major-mode--suspended nil ;; <compat-tests:major-mode-suspend>
- "Suspended major mode."
- :local permanent)
-
-(compat-defun major-mode-suspend () ;; <compat-tests:major-mode-suspend>
- "Exit current major mode, remembering it."
- (let* ((prev-major-mode (or major-mode--suspended
- (unless (eq major-mode 'fundamental-mode)
- major-mode))))
- (kill-all-local-variables)
- (setq-local major-mode--suspended prev-major-mode)))
-
-(compat-defun major-mode-restore (&optional avoided-modes) ;; <compat-tests:major-mode-suspend>
- "Restore major mode earlier suspended with `major-mode-suspend'.
-If there was no earlier suspended major mode, then fallback to `normal-mode',
-though trying to avoid AVOIDED-MODES."
- (if major-mode--suspended
- (funcall (prog1 major-mode--suspended
- (kill-local-variable 'major-mode--suspended)))
- (let ((auto-mode-alist
- (let ((alist (copy-sequence auto-mode-alist)))
- (dolist (mode avoided-modes)
- (setq alist (rassq-delete-all mode alist)))
- alist))
- (magic-fallback-mode-alist
- (let ((alist (copy-sequence magic-fallback-mode-alist)))
- (dolist (mode avoided-modes)
- (setq alist (rassq-delete-all mode alist)))
- alist)))
- (normal-mode))))
-
-(compat-defun read-char-from-minibuffer-insert-char () ;; <compat-tests:read-char-from-minibuffer>
- "Insert the character you type into the minibuffer and exit minibuffer.
-Discard all previous input before inserting and exiting the minibuffer."
- (interactive)
- (when (minibufferp)
- (delete-minibuffer-contents)
- (insert last-command-event)
- (exit-minibuffer)))
-
-(compat-defun read-char-from-minibuffer-insert-other () ;; <compat-tests:read-char-from-minibuffer>
- "Reject a disallowed character typed into the minibuffer.
-This command is intended to be bound to keys that users are not
-allowed to type into the minibuffer. When the user types any
-such key, this command discard all minibuffer input and displays
-an error message."
- (interactive)
- (when (minibufferp)
- (delete-minibuffer-contents)
- (ding)
- (discard-input)
- (minibuffer-message "Wrong answer")
- (sit-for 2)))
-
-(compat-defvar read-char-history nil ;; <compat-tests:read-char-from-minibuffer>
- "The default history for the `read-char-from-minibuffer' function.")
-
-(compat-defvar read-char-from-minibuffer-map ;; <compat-tests:read-char-from-minibuffer>
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-map)
- (define-key map [remap self-insert-command] #'read-char-from-minibuffer-insert-char)
- (define-key map [remap exit-minibuffer] #'read-char-from-minibuffer-insert-other)
- map)
- "Keymap for the `read-char-from-minibuffer' function.")
-
-(compat-defvar read-char-from-minibuffer-map-hash ;; <compat-tests:read-char-from-minibuffer>
- (make-hash-table :test 'equal)
- "Hash table of keymaps used by `read-char-from-minibuffer'."
- :constant t)
-
-(compat-defun read-char-from-minibuffer (prompt &optional chars history) ;; <compat-tests:read-char-from-minibuffer>
- "Read a character from the minibuffer, prompting for it with PROMPT.
-Like `read-char', but uses the minibuffer to read and return a character.
-Optional argument CHARS, if non-nil, should be a list of characters;
-the function will ignore any input that is not one of CHARS.
-Optional argument HISTORY, if non-nil, should be a symbol that
-specifies the history list variable to use for navigating in input
-history using \\`M-p' and \\`M-n', with \\`RET' to select a character from
-history.
-If you bind the variable `help-form' to a non-nil value
-while calling this function, then pressing `help-char'
-causes it to evaluate `help-form' and display the result.
-There is no need to explicitly add `help-char' to CHARS;
-`help-char' is bound automatically to `help-form-show'."
- (let* ((map (if (consp chars)
- (or (gethash (list help-form (cons help-char chars))
- read-char-from-minibuffer-map-hash)
- (let ((map (make-sparse-keymap))
- (msg help-form))
- (set-keymap-parent map read-char-from-minibuffer-map)
- ;; If we have a dynamically bound `help-form'
- ;; here, then the `C-h' (i.e., `help-char')
- ;; character should output that instead of
- ;; being a command char.
- (when help-form
- (define-key map (vector help-char)
- (lambda ()
- (interactive)
- (let ((help-form msg)) ; lexically bound msg
- (help-form-show)))))
- (dolist (char chars)
- (define-key map (vector char)
- #'read-char-from-minibuffer-insert-char))
- (define-key map [remap self-insert-command]
- #'read-char-from-minibuffer-insert-other)
- (puthash (list help-form (cons help-char chars))
- map read-char-from-minibuffer-map-hash)
- map))
- read-char-from-minibuffer-map))
- ;; Protect this-command when called from pre-command-hook (bug#45029)
- (this-command this-command)
- (result (read-from-minibuffer prompt nil map nil (or history t)))
- (char
- (if (> (length result) 0)
- ;; We have a string (with one character), so return the first one.
- (elt result 0)
- ;; The default value is RET.
- (when history (push "\r" (symbol-value history)))
- ?\r)))
- ;; Display the question with the answer.
- (message "%s%s" prompt (char-to-string char))
- char))
-
-;;;; Defined in simple.el
-
-(compat-guard (not (fboundp 'decoded-time-second)) ;; <compat-tests:decoded-time>
- (cl-defstruct (decoded-time
- (:constructor nil)
- (:copier nil)
- (:type list))
- (second nil :documentation "\
-This is an integer or a Lisp timestamp (TICKS . HZ) representing a nonnegative
-number of seconds less than 61. (If not less than 60, it is a leap second,
-which only some operating systems support.)")
- (minute nil :documentation "This is an integer between 0 and 59 (inclusive).")
- (hour nil :documentation "This is an integer between 0 and 23 (inclusive).")
- (day nil :documentation "This is an integer between 1 and 31 (inclusive).")
- (month nil :documentation "\
-This is an integer between 1 and 12 (inclusive). January is 1.")
- (year nil :documentation "This is a four digit integer.")
- (weekday nil :documentation "\
-This is a number between 0 and 6, and 0 is Sunday.")
- (dst -1 :documentation "\
-This is t if daylight saving time is in effect, nil if it is not
-in effect, and -1 if daylight saving information is not available.
-Also see `decoded-time-dst'.")
- (zone nil :documentation "\
-This is an integer indicating the UTC offset in seconds, i.e.,
-the number of seconds east of Greenwich.")))
-
-(compat-defun minibuffer-history-value () ;; <compat-tests:minibuffer-history-value>
- "Return the value of the minibuffer input history list.
-If `minibuffer-history-variable' points to a buffer-local variable and
-the minibuffer is active, return the buffer-local value for the buffer
-that was current when the minibuffer was activated."
- (buffer-local-value minibuffer-history-variable
- (window-buffer (minibuffer-selected-window))))
-
-;;;; Defined in minibuffer.el
-
-(compat-defmacro with-minibuffer-selected-window (&rest body) ;; <compat-tests:with-minibuffer-selected-window>
- "Execute the forms in BODY from the minibuffer in its original window.
-When used in a minibuffer window, select the window selected just before
-the minibuffer was activated, and execute the forms."
- (declare (indent 0) (debug t))
- `(when-let ((window (minibuffer-selected-window)))
- (with-selected-window window
- ,@body)))
-
-;;;; Defined in byte-run.el
-
-(compat-defmacro with-suppressed-warnings (_warnings &rest body) ;; <compat-tests:with-suppressed-warnings>
- "Like `progn', but prevents compiler WARNINGS in BODY.
-NOTE: The compatibility version behaves like `with-no-warnings'."
- `(with-no-warnings ,@body))
-
-;;;; Defined in image.el
-
-(compat-defun image--set-property (image property value) ;; <compat-tests:image-property>
- "Set PROPERTY in IMAGE to VALUE, internal use only."
- :extended "26.1"
- :feature image
- (if (null value)
- (while (cdr image)
- (if (eq (cadr image) property)
- (setcdr image (cdddr image))
- (setq image (cddr image))))
- (setcdr image (plist-put (cdr image) property value)))
- value)
-
-;; HACK: image--set-property was broken with an off-by-one error on Emacs 26.
-;; The bug was fixed in a4ad7bed187493c1c230f223b52c71f5c34f7c89. Therefore we
-;; override the gv expander until Emacs 27.1.
-(compat-guard ;; <compat-tests:image-property>
- (or (= emacs-major-version 26) (not (get 'image-property 'gv-expander)))
- :feature image
- (gv-define-setter image-property (value image prop)
- `(,(if (< emacs-major-version 26) 'image--set-property 'compat--image--set-property)
- ,image ,prop ,value)))
-
-;;;; Defined in files.el
-
-(compat-defun file-name-quoted-p (name &optional top) ;; <compat-tests:file-name-quoted-p>
- "Handle optional argument TOP."
- :extended "26.1"
- (let ((file-name-handler-alist (unless top file-name-handler-alist)))
- (string-prefix-p "/:" (file-local-name name))))
-
-(compat-defun file-name-quote (name &optional top) ;; <compat-tests:file-name-quote>
- "Handle optional argument TOP."
- :extended "26.1"
- (let* ((file-name-handler-alist (unless top file-name-handler-alist))
- (localname (file-local-name name)))
- (if (string-prefix-p "/:" localname)
- name
- (concat (file-remote-p name) "/:" localname))))
-
-(compat-defun file-name-unquote (name &optional top) ;; <compat-tests:file-name-unquote>
- "Handle optional argument TOP."
- :extended "26.1"
- (let* ((file-name-handler-alist (unless top file-name-handler-alist))
- (localname (file-local-name name)))
- (when (string-prefix-p "/:" localname)
- (setq localname (if (= (length localname) 2) "/" (substring localname 2))))
- (concat (file-remote-p name) localname)))
-
-(compat-defun file-size-human-readable (file-size &optional flavor space unit) ;; <compat-tests:file-size-human-readable>
- "Handle the optional arguments SPACE and UNIT."
- :extended t
- (let ((power (if (or (null flavor) (eq flavor 'iec))
- 1024.0
- 1000.0))
- (prefixes '("" "k" "M" "G" "T" "P" "E" "Z" "Y")))
- (while (and (>= file-size power) (cdr prefixes))
- (setq file-size (/ file-size power)
- prefixes (cdr prefixes)))
- (let* ((prefix (car prefixes))
- (prefixed-unit (if (eq flavor 'iec)
- (concat
- (if (string= prefix "k") "K" prefix)
- (if (string= prefix "") "" "i")
- (or unit "B"))
- (concat prefix unit))))
- (format (if (and (>= (mod file-size 1.0) 0.05)
- (< (mod file-size 1.0) 0.95))
- "%.1f%s%s"
- "%.0f%s%s")
- file-size
- (if (string= prefixed-unit "") "" (or space ""))
- prefixed-unit))))
-
-(compat-defun file-size-human-readable-iec (size) ;; <compat-tests:file-size-human-readable-iec>
- "Human-readable string for SIZE bytes, using IEC prefixes."
- (compat--file-size-human-readable size 'iec " "))
-
-(compat-defun exec-path () ;; <compat-tests:exec-path>
- "Return list of directories to search programs to run in remote subprocesses.
-The remote host is identified by `default-directory'. For remote
-hosts that do not support subprocesses, this returns nil.
-If `default-directory' is a local directory, this function returns
-the value of the variable `exec-path'."
- (let ((handler (find-file-name-handler default-directory 'exec-path)))
- ;; NOTE: The handler may fail since it was added in 27.1.
- (or (and handler (ignore-errors (funcall handler 'exec-path)))
- (if (file-remote-p default-directory)
- ;; FIXME: Just return some standard path on remote
- '("/bin" "/usr/bin" "/sbin" "/usr/sbin" "/usr/local/bin" "/usr/local/sbin")
- exec-path))))
-
-(compat-defun executable-find (command &optional remote) ;; <compat-tests:executable-find>
- "Handle optional argument REMOTE."
- :extended t
- (if (and remote (file-remote-p default-directory))
- (let ((res (locate-file
- command
- (mapcar
- (apply-partially
- #'concat (file-remote-p default-directory))
- (exec-path))
- exec-suffixes 'file-executable-p)))
- (when (stringp res) (file-local-name res)))
- (executable-find command)))
-
-(compat-defun make-empty-file (filename &optional parents) ;; <compat-tests:make-empty-file>
- "Create an empty file FILENAME.
-Optional arg PARENTS, if non-nil then creates parent dirs as needed."
- (when (and (file-exists-p filename) (null parents))
- (signal 'file-already-exists (list "File exists" filename)))
- (let ((paren-dir (file-name-directory filename)))
- (when (and paren-dir (not (file-exists-p paren-dir)))
- (make-directory paren-dir parents)))
- (write-region "" nil filename nil 0))
-
-;;;; Defined in regexp-opt.el
-
-(compat-defun regexp-opt (strings &optional paren) ;; <compat-tests:regexp-opt>
- "Handle an empty list of STRINGS."
- :extended t
- (if (null strings)
- (let ((re "\\`a\\`"))
- (cond ((null paren)
- (concat "\\(?:" re "\\)"))
- ((stringp paren)
- (concat paren re "\\)"))
- ((eq paren 'words)
- (concat "\\<\\(" re "\\)\\>"))
- ((eq paren 'symbols)
- (concat "\\_\\(<" re "\\)\\_>"))
- ((concat "\\(" re "\\)"))))
- (regexp-opt strings paren)))
-
-;;;; Defined in package.el
-
-(declare-function lm-header "lisp-mnt")
-(declare-function macroexp-file-name nil)
-
-(compat-defun package-get-version () ;; <compat-tests:package-get-version>
- "Return the version number of the package in which this is used.
-Assumes it is used from an Elisp file placed inside the top-level directory
-of an installed ELPA package.
-The return value is a string (or nil in case we can’t find it)."
- ;; No :feature since the function is autoloaded.
- ;; In a sense, this is a lie, but it does just what we want: precompute
- ;; the version at compile time and hardcodes it into the .elc file!
- (declare (pure t))
- ;; Hack alert!
- (let ((file (or (macroexp-file-name) buffer-file-name)))
- (cond
- ((null file) nil)
- ;; Packages are normally installed into directories named "<pkg>-<vers>",
- ;; so get the version number from there.
- ((string-match
- "/[^/]+-\\([0-9]\\(?:[0-9.]\\|pre\\|beta\\|alpha\\|snapshot\\)+\\)/[^/]+\\'"
- file)
- (match-string 1 file))
- ;; For packages run straight from the an elpa.git clone, there's no
- ;; "-<vers>" in the directory name, so we have to fetch the version
- ;; the hard way.
- ((let* ((pkgdir (file-name-directory file))
- (pkgname (file-name-nondirectory (directory-file-name pkgdir)))
- (mainfile (expand-file-name (concat pkgname ".el") pkgdir)))
- (when (file-readable-p mainfile)
- (require 'lisp-mnt)
- (with-temp-buffer
- (insert-file-contents mainfile)
- (or (lm-header "package-version")
- (lm-header "version")))))))))
-
-;;;; Defined in time-date.el
-
-(compat-defun make-decoded-time ;; <compat-tests:make-decoded-time>
- (&key second minute hour day month year (dst -1) zone)
- "Return a `decoded-time' structure with only the keywords given filled out."
- :feature time-date
- (list second minute hour day month year nil dst zone))
-
-(compat-defun date-days-in-month (year month) ;; <compat-tests:date-days-in-month>
- "The number of days in MONTH in YEAR."
- :feature time-date
- (unless (and (numberp month)
- (<= 1 month)
- (<= month 12))
- (error "Month %s is invalid" month))
- (if (= month 2)
- (if (date-leap-year-p year)
- 29
- 28)
- (if (memq month '(1 3 5 7 8 10 12))
- 31
- 30)))
-
-(compat-defun date-ordinal-to-time (year ordinal) ;; <compat-tests:date-ordinal-to-time>
- "Convert a YEAR/ORDINAL to the equivalent `decoded-time' structure.
-ORDINAL is the number of days since the start of the year, with
-January 1st being 1."
- (let ((month 1))
- (while (> ordinal (date-days-in-month year month))
- (setq ordinal (- ordinal (date-days-in-month year month))
- month (1+ month)))
- (list nil nil nil ordinal month year nil nil nil)))
-
-;;;; Defined in text-property-search.el
-
-(declare-function make-prop-match nil)
-(compat-guard (not (fboundp 'make-prop-match)) ;; <compat-tests:prop-match>
- (cl-defstruct (prop-match) beginning end value))
-
-(compat-defun text-property-search-forward ;; <compat-tests:text-property-search-forward>
- (property &optional value predicate not-current)
- "Search for the next region of text where PREDICATE is true.
-PREDICATE is used to decide whether a value of PROPERTY should be
-considered as matching VALUE.
-
-If PREDICATE is a function, it will be called with two arguments:
-VALUE and the value of PROPERTY. The function should return
-non-nil if these two values are to be considered a match.
-
-Two special values of PREDICATE can also be used:
-If PREDICATE is t, that means a value must `equal' VALUE to be
-considered a match.
-If PREDICATE is nil (which is the default value), a value will
-match if is not `equal' to VALUE. Furthermore, a nil PREDICATE
-means that the match region is ended if the value changes. For
-instance, this means that if you loop with
-
- (while (setq prop (text-property-search-forward \\='face))
- ...)
-
-you will get all distinct regions with non-nil `face' values in
-the buffer, and the `prop' object will have the details about the
-match. See the manual for more details and examples about how
-VALUE and PREDICATE interact.
-
-If NOT-CURRENT is non-nil, the function will search for the first
-region that doesn't include point and has a value of PROPERTY
-that matches VALUE.
-
-If no matches can be found, return nil and don't move point.
-If found, move point to the end of the region and return a
-`prop-match' object describing the match. To access the details
-of the match, use `prop-match-beginning' and `prop-match-end' for
-the buffer positions that limit the region, and
-`prop-match-value' for the value of PROPERTY in the region."
- (let* ((match-p
- (lambda (prop-value)
- (funcall
- (cond
- ((eq predicate t)
- #'equal)
- ((eq predicate nil)
- (lambda (val p-val)
- (not (equal val p-val))))
- (predicate))
- value prop-value)))
- (find-end
- (lambda (start)
- (let (end)
- (if (and value
- (null predicate))
- ;; This is the normal case: We're looking for areas where the
- ;; values aren't, so we aren't interested in sub-areas where the
- ;; property has different values, all non-matching value.
- (let ((ended nil))
- (while (not ended)
- (setq end (next-single-property-change (point) property))
- (if (not end)
- (progn
- (goto-char (point-max))
- (setq end (point)
- ended t))
- (goto-char end)
- (unless (funcall match-p (get-text-property (point) property))
- (setq ended t)))))
- ;; End this at the first place the property changes value.
- (setq end (next-single-property-change (point) property nil (point-max)))
- (goto-char end))
- (make-prop-match
- :beginning start
- :end end
- :value (get-text-property start property))))))
- (cond
- ;; No matches at the end of the buffer.
- ((eobp)
- nil)
- ;; We're standing in the property we're looking for, so find the
- ;; end.
- ((and (funcall match-p (get-text-property (point) property))
- (not not-current))
- (funcall find-end (point)))
- (t
- (let ((origin (point))
- (ended nil)
- pos)
- ;; Find the next candidate.
- (while (not ended)
- (setq pos (next-single-property-change (point) property))
- (if (not pos)
- (progn
- (goto-char origin)
- (setq ended t))
- (goto-char pos)
- (if (funcall match-p (get-text-property (point) property))
- (setq ended (funcall find-end (point)))
- ;; Skip past this section of non-matches.
- (setq pos (next-single-property-change (point) property))
- (unless pos
- (goto-char origin)
- (setq ended t)))))
- (and (not (eq ended t))
- ended))))))
-
-(compat-defun text-property-search-backward ;; <compat-tests:text-property-search-backward>
- (property &optional value predicate not-current)
- "Search for the previous region of text whose PROPERTY matches VALUE.
-
-Like `text-property-search-forward', which see, but searches backward,
-and if a matching region is found, place point at the start of the region."
- (let* ((match-p
- (lambda (prop-value)
- (funcall
- (cond
- ((eq predicate t)
- #'equal)
- ((eq predicate nil)
- (lambda (val p-val)
- (not (equal val p-val))))
- (predicate))
- value prop-value)))
- (find-end
- (lambda (start)
- (let (end)
- (if (and value
- (null predicate))
- ;; This is the normal case: We're looking for areas where the
- ;; values aren't, so we aren't interested in sub-areas where the
- ;; property has different values, all non-matching value.
- (let ((ended nil))
- (while (not ended)
- (setq end (previous-single-property-change (point) property))
- (if (not end)
- (progn
- (goto-char (point-min))
- (setq end (point)
- ended t))
- (goto-char (1- end))
- (unless (funcall match-p (get-text-property (point) property))
- (goto-char end)
- (setq ended t)))))
- ;; End this at the first place the property changes value.
- (setq end (previous-single-property-change
- (point) property nil (point-min)))
- (goto-char end))
- (make-prop-match
- :beginning end
- :end (1+ start)
- :value (get-text-property end property))))))
- (cond
- ;; We're at the start of the buffer; no previous matches.
- ((bobp)
- nil)
- ;; We're standing in the property we're looking for, so find the
- ;; end.
- ((funcall match-p (get-text-property (1- (point)) property))
- (let ((origin (point))
- (match (funcall find-end (1- (point)) property value predicate)))
- ;; When we want to ignore the current element, then repeat the
- ;; search if we haven't moved out of it yet.
- (if (and not-current
- (equal (get-text-property (point) property)
- (get-text-property origin property)))
- (text-property-search-backward property value predicate)
- match)))
- (t
- (let ((origin (point))
- (ended nil)
- pos)
- ;; Find the previous candidate.
- (while (not ended)
- (setq pos (previous-single-property-change (point) property))
- (if (not pos)
- (progn
- (goto-char origin)
- (setq ended t))
- (goto-char (1- pos))
- (if (funcall match-p (get-text-property (point) property))
- (setq ended
- (funcall find-end (point)))
- ;; Skip past this section of non-matches.
- (setq pos (previous-single-property-change (point) property))
- (unless pos
- (goto-char origin)
- (setq ended t)))))
- (and (not (eq ended t))
- ended))))))
-
-;;;; Defined in ring.el
-
-(compat-defun ring-resize (ring size) ;; <compat-tests:ring-resize>
- "Set the size of RING to SIZE.
-If the new size is smaller, then the oldest items in the ring are
-discarded."
- :feature ring
- (when (integerp size)
- (let ((length (ring-length ring))
- (new-vec (make-vector size nil)))
- (if (= length 0)
- (setcdr ring (cons 0 new-vec))
- (let* ((hd (car ring))
- (old-size (ring-size ring))
- (old-vec (cddr ring))
- (copy-length (min size length))
- (copy-hd (mod (+ hd (- length copy-length)) length)))
- (setcdr ring (cons copy-length new-vec))
- ;; If the ring is wrapped, the existing elements must be written
- ;; out in the right order.
- (dotimes (j copy-length)
- (aset new-vec j (aref old-vec (mod (+ copy-hd j) old-size))))
- (setcar ring 0))))))
-
-;;;; Defined in map-ynp.el
-
-(compat-version "26.2")
-
-(compat-defvar read-answer-short 'auto ;; <compat-tests:read-answer>
- "If non-nil, the `read-answer' function accepts single-character answers.
-If t, accept short (single key-press) answers to the question.
-If nil, require long answers. If `auto', accept short answers if
-`use-short-answers' is non-nil, or the function cell of `yes-or-no-p'
-is set to `y-or-n-p'.
-
-Note that this variable does not affect calls to the more
-commonly-used `yes-or-no-p' function; it only affects calls to
-the `read-answer' function. To control whether `yes-or-no-p'
-requires a long or a short answer, see the `use-short-answers'
-variable.")
-
-(compat-defun read-answer (question answers) ;; <compat-tests:read-answer>
- "Read an answer either as a complete word or its character abbreviation.
-Ask user a question and accept an answer from the list of possible answers.
-
-QUESTION should end in a space; this function adds a list of answers to it.
-
-ANSWERS is an alist with elements in the following format:
- (LONG-ANSWER SHORT-ANSWER HELP-MESSAGE)
-where
- LONG-ANSWER is a complete answer,
- SHORT-ANSWER is an abbreviated one-character answer,
- HELP-MESSAGE is a string describing the meaning of the answer.
-
-SHORT-ANSWER is not necessarily a single character answer. It can be
-also a function key like F1, a character event such as C-M-h, or
-a control character like C-h.
-
-Example:
- \\='((\"yes\" ?y \"perform the action\")
- (\"no\" ?n \"skip to the next\")
- (\"all\" ?! \"accept all remaining without more questions\")
- (\"help\" ?h \"show help\")
- (\"quit\" ?q \"exit\"))
-
-When `read-answer-short' is non-nil, accept short answers.
-
-Return a long answer even in case of accepting short ones.
-
-When `use-dialog-box' is t, pop up a dialog window to get user input."
- ;; NOTE: For simplicity we provide a primitive implementation based on
- ;; `read-multiple-choice', which does neither support long answers nor the the
- ;; gui dialog box.
- (cadr (read-multiple-choice
- (string-trim-right question)
- (delq nil
- (mapcar (lambda (x) (unless (equal "help" (car x))
- (list (cadr x) (car x) (caddr x))))
- answers)))))
-
-(provide 'compat-27)
-;;; compat-27.el ends here
+++ /dev/null
-;;; compat-28.el --- Functionality added in Emacs 28.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 28.1, needed by older Emacs versions.
-
-;;; Code:
-
-(eval-when-compile (load "compat-macs.el" nil t t))
-(compat-require compat-27 "27.1")
-
-(compat-version "28.1")
-
-;;;; Defined in comp.c
-
-(compat-defalias native-comp-available-p ignore) ;; <compat-tests:native-comp-available-p>
-
-;;;; Defined in fns.c
-
-;; FIXME Should handle multibyte regular expressions
-(compat-defun string-search (needle haystack &optional start-pos) ;; <compat-tests:string-search>
- "Search for the string NEEDLE in the string HAYSTACK.
-
-The return value is the position of the first occurrence of
-NEEDLE in HAYSTACK, or nil if no match was found.
-
-The optional START-POS argument says where to start searching in
-HAYSTACK and defaults to zero (start at the beginning).
-It must be between zero and the length of HAYSTACK, inclusive.
-
-Case is always significant and text properties are ignored.
-
-NOTE: Prior to Emacs 27 `string-match' has issues handling
-multibyte regular expressions. As the compatibility function
-for `string-search' is implemented via `string-match', these
-issues are inherited."
- (when (and start-pos (or (< (length haystack) start-pos)
- (< start-pos 0)))
- (signal 'args-out-of-range (list start-pos)))
- (let (case-fold-search)
- (string-match-p (regexp-quote needle) haystack start-pos)))
-
-(compat-defun length= (sequence length) ;; [[compat-tests:length=]]
- "Returns non-nil if SEQUENCE has a length equal to LENGTH."
- (cond
- ((null sequence) (zerop length))
- ((consp sequence)
- (and (null (nthcdr length sequence))
- (nthcdr (1- length) sequence)
- t))
- ((arrayp sequence)
- (= (length sequence) length))
- (t (signal 'wrong-type-argument (list 'sequencep sequence)))))
-
-(compat-defun length< (sequence length) ;; [[compat-tests:length<]]
- "Returns non-nil if SEQUENCE is shorter than LENGTH."
- (cond
- ((null sequence) (not (zerop length)))
- ((listp sequence)
- (null (nthcdr (1- length) sequence)))
- ((arrayp sequence)
- (< (length sequence) length))
- (t (signal 'wrong-type-argument (list 'sequencep sequence)))))
-
-(compat-defun length> (sequence length) ;; [[compat-tests:length>]]
- "Returns non-nil if SEQUENCE is longer than LENGTH."
- (cond
- ((listp sequence)
- (and (nthcdr length sequence) t))
- ((arrayp sequence)
- (> (length sequence) length))
- (t (signal 'wrong-type-argument (list 'sequencep sequence)))))
-
-;;;; Defined in fileio.c
-
-(compat-defun file-name-concat (directory &rest components) ;; <compat-tests:file-name-concat>
- "Append COMPONENTS to DIRECTORY and return the resulting string.
-Elements in COMPONENTS must be a string or nil.
-DIRECTORY or the non-final elements in COMPONENTS may or may not end
-with a slash -- if they don’t end with a slash, a slash will be
-inserted before contatenating."
- (let ((separator (eval-when-compile
- (if (memq system-type '(ms-dos windows-nt cygwin))
- "\\" "/")))
- (components (delq nil
- (mapcar (lambda (x) (and (not (equal "" x)) x))
- (cons directory components))))
- (result ""))
- (while components
- (let ((c (pop components)))
- (setq result (concat result c
- (and components
- (not (string-suffix-p separator c))
- separator)))))
- result))
-
-;;;; Defined in alloc.c
-
-(compat-defalias garbage-collect-maybe ignore) ;; <compat-tests:garbage-collect-maybe>
-
-;;;; Defined in characters.c
-
-(compat-defun string-width (string &optional from to) ;; <compat-tests:string-width>
- "Handle optional arguments FROM and TO."
- :extended t
- (let* ((len (length string))
- (from (or from 0))
- (to (or to len)))
- (if (and (= from 0) (= to len))
- (string-width string)
- (string-width (substring string from to)))))
-
-;;;; Defined in dired.c
-
-(compat-defun directory-files (directory &optional full match nosort count) ;; <compat-tests:directory-files>
- "Handle additional optional argument COUNT."
- :extended t
- (let ((files (directory-files directory full match nosort)))
- (when (natnump count)
- (setf (nthcdr count files) nil))
- files))
-
-(compat-defun directory-files-and-attributes (directory &optional full match nosort id-format count) ;; <compat-tests:directory-files-and-attributes>
- "Handle additional optional argument COUNT."
- :extended t
- (let ((files (directory-files-and-attributes directory full match nosort id-format)))
- (when (natnump count)
- (setf (nthcdr count files) nil))
- files))
-
-;;;; xfaces.c
-
-(compat-defun color-values-from-color-spec (spec) ;; <compat-tests:color-values-from-color-spec>
- "Parse color SPEC as a numeric color and return (RED GREEN BLUE).
-This function recognises the following formats for SPEC:
-
- #RGB, where R, G and B are hex numbers of equal length, 1-4 digits each.
- rgb:R/G/B, where R, G, and B are hex numbers, 1-4 digits each.
- rgbi:R/G/B, where R, G and B are floating-point numbers in [0,1].
-
-If SPEC is not in one of the above forms, return nil.
-
-Each of the 3 integer members of the resulting list, RED, GREEN,
-and BLUE, is normalized to have its value in [0,65535]."
- (let ((case-fold-search nil))
- (save-match-data
- (cond
- ((string-match
- ;; (rx bos "#"
- ;; (or (: (group-n 1 (= 1 hex)) (group-n 2 (= 1 hex)) (group-n 3 (= 1 hex)))
- ;; (: (group-n 1 (= 2 hex)) (group-n 2 (= 2 hex)) (group-n 3 (= 2 hex)))
- ;; (: (group-n 1 (= 3 hex)) (group-n 2 (= 3 hex)) (group-n 3 (= 3 hex)))
- ;; (: (group-n 1 (= 4 hex)) (group-n 2 (= 4 hex)) (group-n 3 (= 4 hex))))
- ;; eos)
- "\\`#\\(?:\\(?1:[[:xdigit:]]\\{1\\}\\)\\(?2:[[:xdigit:]]\\{1\\}\\)\\(?3:[[:xdigit:]]\\{1\\}\\)\\|\\(?1:[[:xdigit:]]\\{2\\}\\)\\(?2:[[:xdigit:]]\\{2\\}\\)\\(?3:[[:xdigit:]]\\{2\\}\\)\\|\\(?1:[[:xdigit:]]\\{3\\}\\)\\(?2:[[:xdigit:]]\\{3\\}\\)\\(?3:[[:xdigit:]]\\{3\\}\\)\\|\\(?1:[[:xdigit:]]\\{4\\}\\)\\(?2:[[:xdigit:]]\\{4\\}\\)\\(?3:[[:xdigit:]]\\{4\\}\\)\\)\\'"
- spec)
- (let ((max (1- (ash 1 (* (- (match-end 1) (match-beginning 1)) 4)))))
- (list (/ (* (string-to-number (match-string 1 spec) 16) 65535) max)
- (/ (* (string-to-number (match-string 2 spec) 16) 65535) max)
- (/ (* (string-to-number (match-string 3 spec) 16) 65535) max))))
- ((string-match
- ;; (rx bos "rgb:"
- ;; (group (** 1 4 hex)) "/"
- ;; (group (** 1 4 hex)) "/"
- ;; (group (** 1 4 hex))
- ;; eos)
- "\\`rgb:\\([[:xdigit:]]\\{1,4\\}\\)/\\([[:xdigit:]]\\{1,4\\}\\)/\\([[:xdigit:]]\\{1,4\\}\\)\\'"
- spec)
- (list (/ (* (string-to-number (match-string 1 spec) 16) 65535)
- (1- (ash 1 (* (- (match-end 1) (match-beginning 1)) 4))))
- (/ (* (string-to-number (match-string 2 spec) 16) 65535)
- (1- (ash 1 (* (- (match-end 2) (match-beginning 2)) 4))))
- (/ (* (string-to-number (match-string 3 spec) 16) 65535)
- (1- (ash 1 (* (- (match-end 3) (match-beginning 3)) 4))))))
- ;; The "RGBi" (RGB Intensity) specification is defined by
- ;; XCMS[0], see [1] for the implementation in Xlib.
- ;;
- ;; [0] https://www.nic.funet.fi/pub/X11/X11R4/DOCS/color/Xcms.text
- ;; [1] https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/master/src/xcms/LRGB.c#L1392
- ((string-match
- ;; (rx bos "rgbi:" (* space)
- ;; (group (? (or "-" "+"))
- ;; (or (: (+ digit) (? "." (* digit)))
- ;; (: "." (+ digit)))
- ;; (? "e" (? (or "-" "+")) (+ digit)))
- ;; "/" (* space)
- ;; (group (? (or "-" "+"))
- ;; (or (: (+ digit) (? "." (* digit)))
- ;; (: "." (+ digit)))
- ;; (? "e" (? (or "-" "+")) (+ digit)))
- ;; "/" (* space)
- ;; (group (? (or "-" "+"))
- ;; (or (: (+ digit) (? "." (* digit)))
- ;; (: "." (+ digit)))
- ;; (? "e" (? (or "-" "+")) (+ digit)))
- ;; eos)
- "\\`rgbi:[[:space:]]*\\([+-]?\\(?:[[:digit:]]+\\(?:\\.[[:digit:]]*\\)?\\|\\.[[:digit:]]+\\)\\(?:e[+-]?[[:digit:]]+\\)?\\)/[[:space:]]*\\([+-]?\\(?:[[:digit:]]+\\(?:\\.[[:digit:]]*\\)?\\|\\.[[:digit:]]+\\)\\(?:e[+-]?[[:digit:]]+\\)?\\)/[[:space:]]*\\([+-]?\\(?:[[:digit:]]+\\(?:\\.[[:digit:]]*\\)?\\|\\.[[:digit:]]+\\)\\(?:e[+-]?[[:digit:]]+\\)?\\)\\'"
- spec)
- (let ((r (round (* (string-to-number (match-string 1 spec)) 65535)))
- (g (round (* (string-to-number (match-string 2 spec)) 65535)))
- (b (round (* (string-to-number (match-string 3 spec)) 65535))))
- (when (and (<= 0 r) (<= r 65535)
- (<= 0 g) (<= g 65535)
- (<= 0 b) (<= b 65535))
- (list r g b))))))))
-
-;;;; Defined in simple.el
-
-(compat-defun make-separator-line (&optional length) ;; <compat-tests:make-separator-line>
- "Make a string appropriate for usage as a visual separator line.
-If LENGTH is nil, use the window width."
- (if (display-graphic-p)
- (if length
- (concat (propertize (make-string length ?\s) 'face '(:underline t)) "\n")
- (propertize "\n" 'face '(:extend t :height 0.1 :inverse-video t)))
- (concat (make-string (or length (1- (window-width))) ?-) "\n")))
-
-;;;; Defined in subr.el
-
-(compat-defun process-lines-handling-status (program status-handler &rest args) ;; <compat-tests:process-lines-handling-status>
- "Execute PROGRAM with ARGS, returning its output as a list of lines.
-If STATUS-HANDLER is non-nil, it must be a function with one
-argument, which will be called with the exit status of the
-program before the output is collected. If STATUS-HANDLER is
-nil, an error is signaled if the program returns with a non-zero
-exit status."
- (with-temp-buffer
- (let ((status (apply #'call-process program nil (current-buffer) nil args)))
- (if status-handler
- (funcall status-handler status)
- (unless (eq status 0)
- (error "%s exited with status %s" program status)))
- (goto-char (point-min))
- (let (lines)
- (while (not (eobp))
- (setq lines (cons (buffer-substring-no-properties
- (line-beginning-position)
- (line-end-position))
- lines))
- (forward-line 1))
- (nreverse lines)))))
-
-(compat-defun process-lines-ignore-status (program &rest args) ;; <compat-tests:process-lines-ignore-status>
- "Execute PROGRAM with ARGS, returning its output as a list of lines.
-The exit status of the program is ignored.
-Also see `process-lines'."
- (apply 'process-lines-handling-status program #'ignore args))
-
-;; FIXME Should handle multibyte regular expressions
-(compat-defun string-replace (fromstring tostring instring) ;; <compat-tests:string-replace>
- "Replace FROMSTRING with TOSTRING in INSTRING each time it occurs."
- (when (equal fromstring "")
- (signal 'wrong-length-argument '(0)))
- (let ((case-fold-search nil))
- (replace-regexp-in-string
- (regexp-quote fromstring)
- tostring instring
- t t)))
-
-(compat-defun always (&rest _arguments) ;; <compat-tests:always>
- "Do nothing and return t.
-This function accepts any number of ARGUMENTS, but ignores them.
-Also see `ignore'."
- t)
-
-(compat-defun insert-into-buffer (buffer &optional start end) ;; <compat-tests:insert-into-buffer>
- "Insert the contents of the current buffer into BUFFER.
-If START/END, only insert that region from the current buffer.
-Point in BUFFER will be placed after the inserted text."
- (let ((current (current-buffer)))
- (with-current-buffer buffer
- (insert-buffer-substring current start end))))
-
-(compat-defun replace-string-in-region (string replacement &optional start end) ;; <compat-tests:replace-string-in-region>
- "Replace STRING with REPLACEMENT in the region from START to END.
-The number of replaced occurrences are returned, or nil if STRING
-doesn't exist in the region.
-
-If START is nil, use the current point. If END is nil, use `point-max'.
-
-Comparisons and replacements are done with fixed case."
- (if start
- (when (< start (point-min))
- (error "Start before start of buffer"))
- (setq start (point)))
- (if end
- (when (> end (point-max))
- (error "End after end of buffer"))
- (setq end (point-max)))
- (save-excursion
- (goto-char start)
- (save-restriction
- (narrow-to-region start end)
- (let ((matches 0)
- (case-fold-search nil))
- (while (search-forward string nil t)
- (delete-region (match-beginning 0) (match-end 0))
- (insert replacement)
- (setq matches (1+ matches)))
- (and (not (zerop matches))
- matches)))))
-
-(compat-defun replace-regexp-in-region (regexp replacement &optional start end) ;; <compat-tests:replace-regexp-in-region>
- "Replace REGEXP with REPLACEMENT in the region from START to END.
-The number of replaced occurrences are returned, or nil if REGEXP
-doesn't exist in the region.
-
-If START is nil, use the current point. If END is nil, use `point-max'.
-
-Comparisons and replacements are done with fixed case.
-
-REPLACEMENT can use the following special elements:
-
- `\\&' in NEWTEXT means substitute original matched text.
- `\\N' means substitute what matched the Nth `\\(...\\)'.
- If Nth parens didn't match, substitute nothing.
- `\\\\' means insert one `\\'.
- `\\?' is treated literally."
- (if start
- (when (< start (point-min))
- (error "Start before start of buffer"))
- (setq start (point)))
- (if end
- (when (> end (point-max))
- (error "End after end of buffer"))
- (setq end (point-max)))
- (save-excursion
- (goto-char start)
- (save-restriction
- (narrow-to-region start end)
- (let ((matches 0)
- (case-fold-search nil))
- (while (re-search-forward regexp nil t)
- (replace-match replacement t)
- (setq matches (1+ matches)))
- (and (not (zerop matches))
- matches)))))
-
-(compat-defun buffer-local-boundp (symbol buffer) ;; <compat-tests:buffer-local-boundp>
- "Return non-nil if SYMBOL is bound in BUFFER.
-Also see `local-variable-p'."
- (condition-case nil
- (progn (buffer-local-value symbol buffer)
- t)
- (void-variable nil)))
-
-(compat-defmacro with-existing-directory (&rest body) ;; <compat-tests:with-existing-directory>
- "Execute BODY with `default-directory' bound to an existing directory.
-If `default-directory' is already an existing directory, it's not changed."
- (declare (indent 0) (debug t))
- `(let ((default-directory
- (or (catch 'quit
- (dolist (dir (list default-directory
- (expand-file-name "~/")
- temporary-file-directory
- (getenv "TMPDIR")
- "/tmp/"))
- (when (and dir (file-exists-p dir))
- (throw 'quit dir))))
- "/")))
- ,@body))
-
-(compat-defmacro dlet (binders &rest body) ;; <compat-tests:dlet>
- "Like `let' but using dynamic scoping."
- (declare (indent 1) (debug let))
- `(let (_)
- ,@(mapcar (lambda (binder)
- `(defvar ,(if (consp binder) (car binder) binder)))
- binders)
- (let ,binders ,@body)))
-
-(compat-defun ensure-list (object) ;; <compat-tests:ensure-list>
- "Return OBJECT as a list.
-If OBJECT is already a list, return OBJECT itself. If it's
-not a list, return a one-element list containing OBJECT."
- (if (listp object)
- object
- (list object)))
-
-(compat-defalias subr-primitive-p subrp) ;; <compat-tests:subr-primitive-p>
-
-;;;; Defined in data.c
-
-;; Renamed in Emacs 30 to `native-comp-function-p'.
-(compat-defalias subr-native-elisp-p ignore :obsolete t) ;; <compat-tests:obsolete-subr-native-elisp-p>
-
-;;;; Defined in subr-x.el
-
-(compat-defun string-clean-whitespace (string) ;; <compat-tests:string-clean-whitespace>
- "Clean up whitespace in STRING.
-All sequences of whitespaces in STRING are collapsed into a
-single space character, and leading/trailing whitespace is
-removed."
- (let ((blank "[[:blank:]\r\n]+"))
- (replace-regexp-in-string
- "^[[:blank:]\r\n]+\\|[[:blank:]\r\n]+$"
- ""
- (replace-regexp-in-string
- blank " " string))))
-
-(compat-defun string-fill (string length) ;; <compat-tests:string-fill>
- "Clean up whitespace in STRING.
-All sequences of whitespaces in STRING are collapsed into a
-single space character, and leading/trailing whitespace is
-removed."
- (with-temp-buffer
- (insert string)
- (goto-char (point-min))
- (let ((fill-column length)
- (adaptive-fill-mode nil))
- (fill-region (point-min) (point-max)))
- (buffer-string)))
-
-(compat-defun string-pad (string length &optional padding start) ;; <compat-tests:string-pad>
- "Pad STRING to LENGTH using PADDING.
-If PADDING is nil, the space character is used. If not nil, it
-should be a character.
-
-If STRING is longer than the absolute value of LENGTH, no padding
-is done.
-
-If START is nil (or not present), the padding is done to the end
-of the string, and if non-nil, padding is done to the start of
-the string."
- (unless (natnump length)
- (signal 'wrong-type-argument (list 'natnump length)))
- (let ((pad-length (- length (length string))))
- (if (< pad-length 0)
- string
- (concat (and start
- (make-string pad-length (or padding ?\s)))
- string
- (and (not start)
- (make-string pad-length (or padding ?\s)))))))
-
-(compat-defun string-chop-newline (string) ;; <compat-tests:string-chop-newline>
- "Remove the final newline (if any) from STRING."
- (if (and (>= (length string) 1) (= (aref string (1- (length string))) ?\n))
- (substring string 0 -1)
- string))
-
-(compat-defmacro named-let (name bindings &rest body) ;; <compat-tests:named-let>
- "Looping construct taken from Scheme.
-Like `let', bind variables in BINDINGS and then evaluate BODY,
-but with the twist that BODY can evaluate itself recursively by
-calling NAME, where the arguments passed to NAME are used
-as the new values of the bound variables in the recursive invocation."
- (declare (indent 2) (debug (symbolp (&rest (symbolp form)) body)))
- (let ((fargs (mapcar (lambda (b)
- (let ((var (if (consp b) (car b) b)))
- (make-symbol (symbol-name var))))
- bindings))
- (aargs (mapcar (lambda (b) (if (consp b) (cadr b))) bindings))
- rargs)
- (dotimes (i (length bindings))
- (let ((b (nth i bindings)))
- (push (list (if (consp b) (car b) b) (nth i fargs))
- rargs)
- (setf (if (consp b) (car b) b)
- (nth i fargs))))
- (letrec
- ((quit (make-symbol "quit")) (self (make-symbol "self"))
- (total-tco t)
- (macro (lambda (&rest args)
- (setq total-tco nil)
- `(funcall ,self . ,args)))
- ;; Based on `cl--self-tco':
- (tco-progn (lambda (exprs)
- (append
- (butlast exprs)
- (list (funcall tco (car (last exprs)))))))
- (tco (lambda (expr)
- (cond
- ((eq (car-safe expr) 'if)
- (append (list 'if
- (cadr expr)
- (funcall tco (nth 2 expr)))
- (funcall tco-progn (nthcdr 3 expr))))
- ((eq (car-safe expr) 'cond)
- (let ((conds (cdr expr)) body)
- (while conds
- (let ((branch (pop conds)))
- (push (cond
- ((cdr branch) ;has tail
- (funcall tco-progn branch))
- ((null conds) ;last element
- (list t (funcall tco (car branch))))
- ((progn
- branch)))
- body)))
- (cons 'cond (nreverse body))))
- ((eq (car-safe expr) 'or)
- (if (cddr expr)
- (let ((var (make-symbol "var")))
- `(let ((,var ,(cadr expr)))
- (if ,var ,(funcall tco var)
- ,(funcall tco (cons 'or (cddr expr))))))
- (funcall tco (cadr expr))))
- ((eq (car-safe expr) 'condition-case)
- (append (list 'condition-case (cadr expr) (nth 2 expr))
- (mapcar
- (lambda (handler)
- (cons (car handler)
- (funcall tco-progn (cdr handler))))
- (nthcdr 3 expr))))
- ((memq (car-safe expr) '(and progn))
- (cons (car expr) (funcall tco-progn (cdr expr))))
- ((memq (car-safe expr) '(let let*))
- (append (list (car expr) (cadr expr))
- (funcall tco-progn (cddr expr))))
- ((eq (car-safe expr) name)
- (let (sets (args (cdr expr)))
- (dolist (farg fargs)
- (push (list farg (pop args))
- sets))
- (cons 'setq (apply #'nconc (nreverse sets)))))
- (`(throw ',quit ,expr))))))
- (when-let ((tco-body (funcall tco (macroexpand-all (macroexp-progn body)))))
- (setq body `((catch ',quit
- (while t (let ,rargs ,@(macroexp-unprogn tco-body)))))))
- (let ((expand (macroexpand-all (macroexp-progn body) (list (cons name macro)))))
- (if total-tco
- `(let ,bindings ,expand)
- `(funcall
- (letrec ((,self (lambda ,fargs ,expand))) ,self)
- ,@aargs))))))
-
-;;;; Defined in files.el
-
-(compat-defun file-name-with-extension (filename extension) ;; <compat-tests:file-name-with-extension>
- "Set the EXTENSION of a FILENAME.
-The extension (in a file name) is the part that begins with the last \".\".
-
-Trims a leading dot from the EXTENSION so that either \"foo\" or
-\".foo\" can be given.
-
-Errors if the FILENAME or EXTENSION are empty, or if the given
-FILENAME has the format of a directory.
-
-See also `file-name-sans-extension'."
- (let ((extn (string-remove-prefix "." extension)))
- (cond
- ((string= filename "")
- (error "Empty filename"))
- ((string= extn "")
- (error "Malformed extension: %s" extension))
- ((directory-name-p filename)
- (error "Filename is a directory: %s" filename))
- (t
- (concat (file-name-sans-extension filename) "." extn)))))
-
-(compat-defun directory-empty-p (dir) ;; <compat-tests:directory-empty-p>
- "Return t if DIR names an existing directory containing no other files.
-Return nil if DIR does not name a directory, or if there was
-trouble determining whether DIR is a directory or empty.
-
-Symbolic links to directories count as directories.
-See `file-symlink-p' to distinguish symlinks."
- (and (file-directory-p dir)
- (null (directory-files dir nil directory-files-no-dot-files-regexp t))))
-
-(compat-defun file-modes-number-to-symbolic (mode &optional filetype) ;; <compat-tests:file-modes-number-to-symbolic>
- "Return a string describing a file's MODE.
-For instance, if MODE is #o700, then it produces `-rwx------'.
-FILETYPE if provided should be a character denoting the type of file,
-such as `?d' for a directory, or `?l' for a symbolic link and will override
-the leading `-' char."
- (string
- (or filetype
- (pcase (ash mode -12)
- ;; POSIX specifies that the file type is included in st_mode
- ;; and provides names for the file types but values only for
- ;; the permissions (e.g., S_IWOTH=2).
-
- ;; (#o017 ??) ;; #define S_IFMT 00170000
- (#o014 ?s) ;; #define S_IFSOCK 0140000
- (#o012 ?l) ;; #define S_IFLNK 0120000
- ;; (8 ??) ;; #define S_IFREG 0100000
- (#o006 ?b) ;; #define S_IFBLK 0060000
- (#o004 ?d) ;; #define S_IFDIR 0040000
- (#o002 ?c) ;; #define S_IFCHR 0020000
- (#o001 ?p) ;; #define S_IFIFO 0010000
- (_ ?-)))
- (if (zerop (logand 256 mode)) ?- ?r)
- (if (zerop (logand 128 mode)) ?- ?w)
- (if (zerop (logand 64 mode))
- (if (zerop (logand 2048 mode)) ?- ?S)
- (if (zerop (logand 2048 mode)) ?x ?s))
- (if (zerop (logand 32 mode)) ?- ?r)
- (if (zerop (logand 16 mode)) ?- ?w)
- (if (zerop (logand 8 mode))
- (if (zerop (logand 1024 mode)) ?- ?S)
- (if (zerop (logand 1024 mode)) ?x ?s))
- (if (zerop (logand 4 mode)) ?- ?r)
- (if (zerop (logand 2 mode)) ?- ?w)
- (if (zerop (logand 512 mode))
- (if (zerop (logand 1 mode)) ?- ?x)
- (if (zerop (logand 1 mode)) ?T ?t))))
-
-(compat-defun file-backup-file-names (filename) ;; <compat-tests:file-backup-file-names>
- "Return a list of backup files for FILENAME.
-The list will be sorted by modification time so that the most
-recent files are first."
- ;; `make-backup-file-name' will get us the right directory for
- ;; ordinary or numeric backups. It might create a directory for
- ;; backups as a side-effect, according to `backup-directory-alist'.
- (let* ((filename (file-name-sans-versions
- (make-backup-file-name (expand-file-name filename))))
- (dir (file-name-directory filename))
- files)
- (dolist (file (file-name-all-completions
- (file-name-nondirectory filename) dir))
- (let ((candidate (concat dir file)))
- (when (and (backup-file-name-p candidate)
- (string= (file-name-sans-versions candidate) filename))
- (push candidate files))))
- (sort files #'file-newer-than-file-p)))
-
-(compat-defun make-lock-file-name (filename) ;; <compat-tests:make-lock-file-name>
- "Make a lock file name for FILENAME.
-This prepends \".#\" to the non-directory part of FILENAME, and
-doesn't respect `lock-file-name-transforms', as Emacs 28.1 and
-onwards does."
- (expand-file-name
- (concat
- ".#" (file-name-nondirectory filename))
- (file-name-directory filename)))
-
-;;;; Defined in minibuffer.el
-
-(compat-defun format-prompt (prompt default &rest format-args) ;; <compat-tests:format-prompt>
- "Format PROMPT with DEFAULT.
-If FORMAT-ARGS is nil, PROMPT is used as a plain string. If
-FORMAT-ARGS is non-nil, PROMPT is used as a format control
-string, and FORMAT-ARGS are the arguments to be substituted into
-it. See `format' for details.
-
-If DEFAULT is a list, the first element is used as the default.
-If not, the element is used as is.
-
-If DEFAULT is nil or an empty string, no \"default value\" string
-is included in the return value."
- (concat
- (if (null format-args)
- prompt
- (apply #'format prompt format-args))
- (and default
- (or (not (stringp default))
- (> (length default) 0))
- (format " (default %s)"
- (if (consp default)
- (car default)
- default)))
- ": "))
-
-;;;; Defined in faces.el
-
-(compat-defvar color-luminance-dark-limit 0.325 ;; <compat-tests:color-dark-p>
- "The relative luminance below which a color is considered \"dark\".
-A \"dark\" color in this sense provides better contrast with white
-than with black; see `color-dark-p'.
-This value was determined experimentally."
- :constant t)
-
-(compat-defun color-dark-p (rgb) ;; <compat-tests:color-dark-p>
- "Whether RGB is more readable against white than black.
-RGB is a 3-element list (R G B), each component in the range [0,1].
-This predicate can be used both for determining a suitable (black or white)
-contrast color with RGB as background and as foreground."
- (unless (<= 0 (apply #'min rgb) (apply #'max rgb) 1)
- (error "RGB components %S not in [0,1]" rgb))
- ;; Compute the relative luminance after gamma-correcting (assuming sRGB),
- ;; and compare to a cut-off value determined experimentally.
- ;; See https://en.wikipedia.org/wiki/Relative_luminance for details.
- (let* ((sr (nth 0 rgb))
- (sg (nth 1 rgb))
- (sb (nth 2 rgb))
- ;; Gamma-correct the RGB components to linear values.
- ;; Use the power 2.2 as an approximation to sRGB gamma;
- ;; it should be good enough for the purpose of this function.
- (r (expt sr 2.2))
- (g (expt sg 2.2))
- (b (expt sb 2.2))
- (y (+ (* r 0.2126) (* g 0.7152) (* b 0.0722))))
- (< y color-luminance-dark-limit)))
-
-;;;; Defined in window.el
-
-(compat-defmacro with-window-non-dedicated (window &rest body) ;; <compat-tests:with-window-non-dedicated>
- "Evaluate BODY with WINDOW temporarily made non-dedicated.
-If WINDOW is nil, use the selected window. Return the value of
-the last form in BODY."
- (declare (indent 1) (debug t))
- (let ((window-dedicated-sym (gensym))
- (window-sym (gensym)))
- `(let* ((,window-sym (window-normalize-window ,window t))
- (,window-dedicated-sym (window-dedicated-p ,window-sym)))
- (set-window-dedicated-p ,window-sym nil)
- (unwind-protect
- (progn ,@body)
- (set-window-dedicated-p ,window-sym ,window-dedicated-sym)))))
-
-(compat-defun count-windows (&optional minibuf all-frames) ;; <compat-tests:count-windows>
- "Handle optional argument ALL-FRAMES."
- :extended t
- (if all-frames
- (let ((sum 0))
- (dolist (frame (frame-list))
- (with-selected-frame frame
- (setq sum (+ (count-windows minibuf) sum))))
- sum)
- (count-windows minibuf)))
-
-;;;; Defined in thingatpt.el
-
-(compat-defun thing-at-mouse (event thing &optional no-properties) ;; <compat-tests:thing-at-mouse>
- "Return the THING at mouse click.
-Like `thing-at-point', but tries to use the event
-where the mouse button is clicked to find a thing nearby."
- ;; No :feature specified, since the function is autoloaded.
- (save-excursion
- (mouse-set-point event)
- (thing-at-point thing no-properties)))
-
-(compat-defun bounds-of-thing-at-mouse (event thing) ;; <compat-tests:thing-at-mouse>
- "Determine start and end locations for THING at mouse click given by EVENT.
-Like `bounds-of-thing-at-point', but tries to use the position in EVENT
-where the mouse button is clicked to find the thing nearby."
- ;; No :feature specified, since the function is autoloaded.
- (save-excursion
- (mouse-set-point event)
- (bounds-of-thing-at-point thing)))
-
-;;;; Defined in mouse.el
-
-(compat-defun mark-thing-at-mouse (click thing) ;; <compat-tests:thing-at-mouse>
- "Activate the region around THING found near the mouse CLICK."
- (when-let ((bounds (bounds-of-thing-at-mouse click thing)))
- (goto-char (if mouse-select-region-move-to-beginning
- (car bounds) (cdr bounds)))
- (push-mark (if mouse-select-region-move-to-beginning
- (cdr bounds) (car bounds))
- t 'activate)))
-
-;;;; Defined in macroexp.el
-
-(compat-defun macroexp-warn-and-return (msg form &optional _category _compile-only _arg) ;; <compat-tests:macroexp-warn-and-return>
- "Return code equivalent to FORM labeled with warning MSG.
-CATEGORY is the category of the warning, like the categories that
-can appear in `byte-compile-warnings'.
-COMPILE-ONLY non-nil means no warning should be emitted if the code
-is executed without being compiled first.
-ARG is a symbol (or a form) giving the source code position for the message.
-It should normally be a symbol with position and it defaults to FORM."
- (macroexp--warn-and-return msg form))
-
-(compat-defun macroexp-file-name () ;; <compat-tests:macroexp-file-name>
- "Return the name of the file from which the code comes.
-Returns nil when we do not know.
-A non-nil result is expected to be reliable when called from a macro in order
-to find the file in which the macro's call was found, and it should be
-reliable as well when used at the top-level of a file.
-Other uses risk returning non-nil value that point to the wrong file."
- (let ((file (car (last current-load-list))))
- (or (if (stringp file) file)
- (bound-and-true-p byte-compile-current-file))))
-
-;;;; Defined in env.el
-
-(compat-defmacro with-environment-variables (variables &rest body) ;; <compat-tests:with-environment-variables>
- "Set VARIABLES in the environment and execute BODY.
-VARIABLES is a list of variable settings of the form (VAR VALUE),
-where VAR is the name of the variable (a string) and VALUE
-is its value (also a string).
-
-The previous values will be be restored upon exit."
- (declare (indent 1) (debug (sexp body)))
- (unless (consp variables)
- (error "Invalid VARIABLES: %s" variables))
- `(let ((process-environment (copy-sequence process-environment)))
- ,@(mapcar (lambda (elem)
- `(setenv ,(car elem) ,(cadr elem)))
- variables)
- ,@body))
-
-;;;; Defined in time-data.el
-
-(compat-defun decoded-time-period (time) ;; <compat-tests:decoded-time-period>
- "Interpret DECODED as a period and return its length in seconds.
-For computational purposes, years are 365 days long and months
-are 30 days long."
- :feature time-date
- (+ (if (consp (decoded-time-second time))
- (/ (float (car (decoded-time-second time)))
- (cdr (decoded-time-second time)))
- (or (decoded-time-second time) 0))
- (* (or (decoded-time-minute time) 0) 60)
- (* (or (decoded-time-hour time) 0) 60 60)
- (* (or (decoded-time-day time) 0) 60 60 24)
- (* (or (decoded-time-month time) 0) 60 60 24 30)
- (* (or (decoded-time-year time) 0) 60 60 24 365)))
-
-;;;; Defined in doc.c
-
-(compat-defun text-quoting-style () ;; <compat-tests:text-quoting-style>
- "Return the current effective text quoting style.
-If the variable `text-quoting-style' is `grave', `straight' or
-`curve', just return that value. If it is nil (the default), return
-`grave' if curved quotes cannot be displayed (for instance, on a
-terminal with no support for these characters), otherwise return
-`quote'. Any other value is treated as `grave'.
-
-Note that in contrast to the variable `text-quoting-style', this
-function will never return nil."
- (cond
- ((memq text-quoting-style '(grave straight curve))
- text-quoting-style)
- ((not text-quoting-style) 'grave)
- (t 'curve)))
-
-;;;; Defined in button.el
-
-;; Obsolete Alias since 29
-(compat-defalias button-buttonize buttonize :obsolete t) ;; <compat-tests:obsolete-button-buttonize>
-
-;;;; Defined in wid-edit.el
-
-(compat-guard t ;; <compat-tests:widget-natnum>
- :feature wid-edit
- (define-widget 'natnum 'restricted-sexp
- "A nonnegative integer."
- :tag "Integer (positive)"
- :value 0
- :type-error "This field should contain a nonnegative integer"
- :match-alternatives '(natnump)))
-
-(provide 'compat-28)
-;;; compat-28.el ends here
+++ /dev/null
-;;; compat-29.el --- Functionality added in Emacs 29.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 29.1, needed by older Emacs versions.
-
-;;; Code:
-
-(eval-when-compile (load "compat-macs.el" nil t t))
-(compat-require compat-28 "28.1")
-
-;; Preloaded in loadup.el
-(compat-require seq "29.1") ;; <compat-tests:seq>
-
-(compat-version "29.1")
-
-;;;; Defined in startup.el
-
-(compat-defvar lisp-directory ;; <compat-tests:lisp-directory>
- (file-truename
- (file-name-directory
- (locate-file "simple" load-path (get-load-suffixes))))
- "Directory where Emacs's own *.el and *.elc Lisp files are installed.")
-
-;;;; Defined in window.c
-
-(compat-defalias window-configuration-equal-p compare-window-configurations) ;; <compat-tests:window-configuration-equal-p>
-
-;;;; Defined in xdisp.c
-
-(compat-defun get-display-property (position prop &optional object properties) ;; <compat-tests:get-display-property>
- "Get the value of the `display' property PROP at POSITION.
-If OBJECT, this should be a buffer or string where the property is
-fetched from. If omitted, OBJECT defaults to the current buffer.
-
-If PROPERTIES, look for value of PROP in PROPERTIES instead of
-the properties at POSITION."
- (if properties
- (unless (listp properties)
- (signal 'wrong-type-argument (list 'listp properties)))
- (setq properties (get-text-property position 'display object)))
- (cond
- ((vectorp properties)
- (catch 'found
- (dotimes (i (length properties))
- (let ((ent (aref properties i)))
- (when (eq (car ent) prop)
- (throw 'found (cadr ent )))))))
- ((consp (car properties))
- (condition-case nil
- (cadr (assq prop properties))
- ;; Silently handle improper lists:
- (wrong-type-argument nil)))
- ((and (consp (cdr properties))
- (eq (car properties) prop))
- (cadr properties))))
-
-;;;; Defined in fns.c
-
-(compat-defun ntake (n list) ;; <compat-tests:ntake>
- "Modify LIST to keep only the first N elements.
-If N is zero or negative, return nil.
-If N is greater or equal to the length of LIST, return LIST unmodified.
-Otherwise, return LIST after truncating it."
- (and (> n 0) (let ((cons (nthcdr (1- n) list)))
- (when cons (setcdr cons nil))
- list)))
-
-(compat-defun take (n list) ;; <compat-tests:take>
- "Return the first N elements of LIST.
-If N is zero or negative, return nil.
-If N is greater or equal to the length of LIST, return LIST (or a copy)."
- (declare (pure t) (side-effect-free t))
- (let (copy)
- (while (and (< 0 n) list)
- (push (pop list) copy)
- (setq n (1- n)))
- (nreverse copy)))
-
-(compat-defun string-equal-ignore-case (string1 string2) ;; <compat-tests:string-equal-ignore-case>
- "Like `string-equal', but case-insensitive.
-Upper-case and lower-case letters are treated as equal.
-Unibyte strings are converted to multibyte for comparison."
- (declare (pure t) (side-effect-free t))
- (eq t (compare-strings string1 0 nil string2 0 nil t)))
-
-(compat-defun plist-get (plist prop &optional predicate) ;; <compat-tests:plist-get>
- "Handle optional argument PREDICATE."
- :extended t
- (pcase predicate
- ((or `nil `eq) (plist-get plist prop))
- (`equal (lax-plist-get plist prop))
- (_ (catch 'found
- (while (consp plist)
- (when (funcall predicate prop (car plist))
- (throw 'found (cadr plist)))
- (setq plist (cddr plist)))))))
-
-(compat-defun plist-put (plist prop val &optional predicate) ;; <compat-tests:plist-get>
- "Handle optional argument PREDICATE."
- :extended t
- (pcase predicate
- ((or `nil `eq) (plist-put plist prop val))
- (`equal (lax-plist-put plist prop val))
- (_ (catch 'found
- (let ((tail plist))
- (while (consp tail)
- (when (funcall predicate prop (car tail))
- (setcar (cdr tail) val)
- (throw 'found plist))
- (setq tail (cddr tail))))
- (nconc plist (list prop val))))))
-
-(compat-defun plist-member (plist prop &optional predicate) ;; <compat-tests:plist-get>
- "Handle optional argument PREDICATE."
- :extended t
- (pcase predicate
- ((or `nil `eq) (plist-member plist prop))
- (_ (catch 'found
- (while (consp plist)
- (when (funcall predicate prop (car plist))
- (throw 'found plist))
- (setq plist (cddr plist)))))))
-
-;;;; Defined in gv.el
-
-(compat-guard t ;; <compat-tests:plist-get-gv>
- (gv-define-expander compat--plist-get
- (lambda (do plist prop &optional predicate)
- (macroexp-let2 macroexp-copyable-p key prop
- (gv-letplace (getter setter) plist
- (macroexp-let2 nil p `(cdr (compat--plist-member ,getter ,key ,predicate))
- (funcall do
- `(car ,p)
- (lambda (val)
- `(if ,p
- (setcar ,p ,val)
- ,(funcall setter
- `(cons ,key (cons ,val ,getter)))))))))))
- (unless (get 'plist-get 'gv-expander)
- (put 'plist-get 'gv-expander (get 'compat--plist-get 'gv-expander))))
-
-;;;; Defined in editfns.c
-
-(compat-defun pos-bol (&optional n) ;; <compat-tests:pos-bol>
- "Return the position of the first character on the current line.
-With optional argument N, scan forward N - 1 lines first.
-If the scan reaches the end of the buffer, return that position.
-
-This function ignores text display directionality; it returns the
-position of the first character in logical order, i.e. the smallest
-character position on the logical line. See `vertical-motion' for
-movement by screen lines.
-
-This function does not move point. Also see `line-beginning-position'."
- (declare (side-effect-free t))
- (let ((inhibit-field-text-motion t))
- (line-beginning-position n)))
-
-(compat-defun pos-eol (&optional n) ;; <compat-tests:pos-bol>
- "Return the position of the last character on the current line.
-With argument N not nil or 1, move forward N - 1 lines first.
-If scan reaches end of buffer, return that position.
-
-This function ignores text display directionality; it returns the
-position of the last character in logical order, i.e. the largest
-character position on the line.
-
-This function does not move point. Also see `line-end-position'."
- (declare (side-effect-free t))
- (let ((inhibit-field-text-motion t))
- (line-end-position n)))
-
-;;;; Defined in subr.el
-
-(compat-defmacro with-delayed-message (_args &rest body) ;; <compat-tests:with-delayed-message>
- "Like `progn', but display MESSAGE if BODY takes longer than TIMEOUT seconds.
-The MESSAGE form will be evaluated immediately, but the resulting
-string will be displayed only if BODY takes longer than TIMEOUT seconds.
-
-NOTE: The compatibility function never displays the message,
-which is not problematic since the only effect of the function is
-to display a progress message to the user. Backporting this
-feature is not possible, since the implementation is directly
-baked into the Elisp interpreter.
-
-\(fn (timeout message) &rest body)"
- (declare (indent 1))
- (macroexp-progn body))
-
-(compat-defun funcall-with-delayed-message (timeout message function) ;; <compat-tests:with-delayed-message>
- "Like `funcall', but display MESSAGE if FUNCTION takes longer than TIMEOUT.
-TIMEOUT is a number of seconds, and can be an integer or a
-floating point number. If FUNCTION takes less time to execute
-than TIMEOUT seconds, MESSAGE is not displayed.
-
-NOTE: The compatibility function never displays the message,
-which is not problematic since the only effect of the function is
-to display a progress message to the user. Backporting this
-feature is not possible, since the implementation is directly
-baked into the Elisp interpreter."
- (ignore timeout message)
- (funcall function))
-
-(compat-defun string-lines (string &optional omit-nulls keep-newlines) ;; <compat-tests:string-lines>
- "Handle additional KEEP-NEWLINES argument."
- :extended "28.1"
- (if (equal string "")
- (if omit-nulls
- nil
- (list ""))
- (let ((lines nil)
- (start 0))
- (while (< start (length string))
- (let ((newline (string-search "\n" string start)))
- (if newline
- (progn
- (when (or (not omit-nulls)
- (not (= start newline)))
- (let ((line (substring string start
- (if keep-newlines
- (1+ newline)
- newline))))
- (when (not (and keep-newlines omit-nulls
- (equal line "\n")))
- (push line lines))))
- (setq start (1+ newline)))
- (if (zerop start)
- (push string lines)
- (push (substring string start) lines))
- (setq start (length string)))))
- (nreverse lines))))
-
-(compat-defun readablep (object) ;; <compat-tests:readablep>
- "Say whether OBJECT has a readable syntax.
-This means that OBJECT can be printed out and then read back
-again by the Lisp reader. This function returns nil if OBJECT is
-unreadable, and the printed representation (from `prin1') of
-OBJECT if it is readable."
- (declare (side-effect-free error-free))
- (ignore-errors (equal object (read (prin1-to-string object)))))
-
-(compat-defun buffer-local-restore-state (states) ;; <compat-tests:buffer-local-set-state>
- "Restore values of buffer-local variables recorded in STATES.
-STATES should be an object returned by `buffer-local-set-state'."
- (dolist (state states)
- (if (cadr state)
- (set (car state) (caddr state))
- (kill-local-variable (car state)))))
-
-(compat-defun buffer-local-set-state--get (pairs) ;; <compat-tests:buffer-local-set-state>
- "Internal helper function."
- (let ((states nil))
- (while pairs
- (push (list (car pairs)
- (and (boundp (car pairs))
- (local-variable-p (car pairs)))
- (and (boundp (car pairs))
- (symbol-value (car pairs))))
- states)
- (setq pairs (cddr pairs)))
- (nreverse states)))
-
-(compat-defmacro buffer-local-set-state (&rest pairs) ;; <compat-tests:buffer-local-set-state>
- "Like `setq-local', but allow restoring the previous state of locals later.
-This macro returns an object that can be passed to `buffer-local-restore-state'
-in order to restore the state of the local variables set via this macro.
-
-\(fn [VARIABLE VALUE]...)"
- (declare (debug setq))
- (unless (zerop (mod (length pairs) 2))
- (error "PAIRS must have an even number of variable/value members"))
- `(prog1
- (buffer-local-set-state--get ',pairs)
- (,(if (fboundp 'compat--setq-local) 'compat--setq-local 'setq-local)
- ,@pairs)))
-
-(compat-defun list-of-strings-p (object) ;; <compat-tests:list-of-strings-p>
- "Return t if OBJECT is nil or a list of strings."
- (declare (pure t) (side-effect-free t))
- (while (and (consp object) (stringp (car object)))
- (setq object (cdr object)))
- (null object))
-
-(compat-defun plistp (object) ;; <compat-tests:plistp>
- "Non-nil if and only if OBJECT is a valid plist."
- (let ((len (proper-list-p object)))
- (and len (zerop (% len 2)))))
-
-(compat-defun delete-line () ;; <compat-tests:delete-line>
- "Delete the current line."
- (delete-region (pos-bol) (pos-bol 2)))
-
-(compat-defmacro with-restriction (start end &rest rest) ;; <compat-tests:with-restriction>
- "Execute BODY with restrictions set to START and END.
-
-The current restrictions, if any, are restored upon return.
-
-When the optional :label LABEL argument is present, in which
-LABEL is a symbol, inside BODY, `narrow-to-region' and `widen'
-can be used only within the START and END limits. To gain access
-to other portions of the buffer, use `without-restriction' with the
-same LABEL argument.
-
-\(fn START END [:label LABEL] BODY)"
- (declare (indent 0) (debug t))
- `(save-restriction
- (narrow-to-region ,start ,end)
- ;; Locking is ignored
- ,@(if (eq (car rest) :label) (cddr rest) rest)))
-
-(compat-defmacro without-restriction (&rest rest) ;; <compat-tests:without-restriction>
- "Execute BODY without restrictions.
-
-The current restrictions, if any, are restored upon return.
-
-When the optional :label LABEL argument is present, the
-restrictions set by `with-restriction' with the same LABEL argument
-are lifted.
-
-\(fn [:label LABEL] BODY)"
- (declare (indent 0) (debug t))
- `(save-restriction
- (widen)
- ;; Locking is ignored
- ,@(if (eq (car rest) :label) (cddr rest) rest)))
-
-(compat-defmacro with-memoization (place &rest code) ;; <compat-tests:with-memoization>
- "Return the value of CODE and stash it in PLACE.
-If PLACE's value is non-nil, then don't bother evaluating CODE
-and return the value found in PLACE instead."
- (declare (indent 1))
- (gv-letplace (getter setter) place
- `(or ,getter
- ,(macroexp-let2 nil val (macroexp-progn code)
- `(progn
- ,(funcall setter val)
- ,val)))))
-
-(compat-defalias string-split split-string) ;; <compat-tests:string-split>
-
-(compat-defun compiled-function-p (object) ;; <compat-tests:compiled-function-p>
- "Return non-nil if OBJECT is a function that has been compiled.
-Does not distinguish between functions implemented in machine code
-or byte-code."
- (or (subrp object) (byte-code-function-p object)))
-
-(compat-defun function-alias-p (func &optional noerror) ;; <compat-tests:function-alias-p>
- "Return nil if FUNC is not a function alias.
-If FUNC is a function alias, return the function alias chain.
-
-If the function alias chain contains loops, an error will be
-signalled. If NOERROR, the non-loop parts of the chain is returned."
- (declare (side-effect-free t))
- (let ((chain nil)
- (orig-func func))
- (nreverse
- (catch 'loop
- (while (and (symbolp func)
- (setq func (symbol-function func))
- (symbolp func))
- (when (or (memq func chain)
- (eq func orig-func))
- (if noerror
- (throw 'loop chain)
- (signal 'cyclic-function-indirection (list orig-func))))
- (push func chain))
- chain))))
-
-(compat-defun buffer-match-p (condition buffer-or-name &optional arg) ;; <compat-tests:buffer-match-p>
- "Return non-nil if BUFFER-OR-NAME matches CONDITION.
-CONDITION is either:
-- the symbol t, to always match,
-- the symbol nil, which never matches,
-- a regular expression, to match a buffer name,
-- a predicate function that takes a buffer object and ARG as
- arguments, and returns non-nil if the buffer matches,
-- a cons-cell, where the car describes how to interpret the cdr.
- The car can be one of the following:
- * `derived-mode': the buffer matches if the buffer's major mode
- is derived from the major mode in the cons-cell's cdr.
- * `major-mode': the buffer matches if the buffer's major mode
- is eq to the cons-cell's cdr. Prefer using `derived-mode'
- instead when both can work.
- * `not': the cadr is interpreted as a negation of a condition.
- * `and': the cdr is a list of recursive conditions, that all have
- to be met.
- * `or': the cdr is a list of recursive condition, of which at
- least one has to be met."
- (letrec
- ((buffer (get-buffer buffer-or-name))
- (match
- (lambda (conditions)
- (catch 'match
- (dolist (condition conditions)
- (when (cond
- ((eq condition t))
- ((stringp condition)
- (string-match-p condition (buffer-name buffer)))
- ((functionp condition)
- (condition-case nil
- (funcall condition buffer)
- (wrong-number-of-arguments
- (funcall condition buffer arg))))
- ((eq (car-safe condition) 'major-mode)
- (eq
- (buffer-local-value 'major-mode buffer)
- (cdr condition)))
- ((eq (car-safe condition) 'derived-mode)
- (provided-mode-derived-p
- (buffer-local-value 'major-mode buffer)
- (cdr condition)))
- ((eq (car-safe condition) 'not)
- (not (funcall match (cdr condition))))
- ((eq (car-safe condition) 'or)
- (funcall match (cdr condition)))
- ((eq (car-safe condition) 'and)
- (catch 'fail
- (dolist (c (cdr condition))
- (unless (funcall match (list c))
- (throw 'fail nil)))
- t)))
- (throw 'match t)))))))
- (funcall match (list condition))))
-
-(compat-defun match-buffers (condition &optional buffers arg) ;; <compat-tests:match-buffers>
- "Return a list of buffers that match CONDITION.
-See `buffer-match' for details on CONDITION. By default all
-buffers are checked, this can be restricted by passing an
-optional argument BUFFERS, set to a list of buffers to check.
-ARG is passed to `buffer-match', for predicate conditions in
-CONDITION."
- (let (bufs)
- (dolist (buf (or buffers (buffer-list)))
- (when (buffer-match-p condition (get-buffer buf) arg)
- (push buf bufs)))
- bufs))
-
-(compat-defvar set-transient-map-timeout nil ;; <compat-tests:set-transient-map>
- "Timeout in seconds for deactivation of a transient keymap.
-If this is a number, it specifies the amount of idle time
-after which to deactivate the keymap set by `set-transient-map',
-thus overriding the value of the TIMEOUT argument to that function.")
-
-(compat-defvar set-transient-map-timer nil ;; <compat-tests:set-transient-map>
- "Timer for `set-transient-map-timeout'.")
-
-(declare-function format-spec "format-spec")
-(compat-defun set-transient-map (map &optional keep-pred on-exit message timeout) ;; <compat-tests:set-transient-map>
- "Handle the optional arguments MESSAGE and TIMEOUT."
- :extended t
- (unless (fboundp 'format-spec)
- (require 'format-spec))
- (let* ((timeout (or set-transient-map-timeout timeout))
- (message
- (when message
- (let (keys)
- (map-keymap (lambda (key cmd) (and cmd (push key keys))) map)
- (format-spec (if (stringp message) message "Repeat with %k")
- `((?k . ,(mapconcat
- (lambda (key)
- (substitute-command-keys
- (format "\\`%s'"
- (key-description (vector key)))))
- keys ", ")))))))
- (clearfun (make-symbol "clear-transient-map"))
- (exitfun
- (lambda ()
- (internal-pop-keymap map 'overriding-terminal-local-map)
- (remove-hook 'pre-command-hook clearfun)
- (when message (message ""))
- (when set-transient-map-timer (cancel-timer set-transient-map-timer))
- (when on-exit (funcall on-exit)))))
- (fset clearfun
- (lambda ()
- (with-demoted-errors "set-transient-map PCH: %S"
- (if (cond
- ((null keep-pred) nil)
- ((and (not (eq map (cadr overriding-terminal-local-map)))
- (memq map (cddr overriding-terminal-local-map)))
- t)
- ((eq t keep-pred)
- (let ((mc (lookup-key map (this-command-keys-vector))))
- (when (and mc (symbolp mc))
- (setq mc (or (command-remapping mc) mc)))
- (and mc (eq this-command mc))))
- (t (funcall keep-pred)))
- (when message (message "%s" message))
- (funcall exitfun)))))
- (add-hook 'pre-command-hook clearfun)
- (internal-push-keymap map 'overriding-terminal-local-map)
- (when timeout
- (when set-transient-map-timer (cancel-timer set-transient-map-timer))
- (setq set-transient-map-timer (run-with-idle-timer timeout nil exitfun)))
- (when message (message "%s" message))
- exitfun))
-
-;;;; Defined in simple.el
-
-(compat-defun char-uppercase-p (char) ;; <compat-tests:char-uppercase-p>
- "Return non-nil if CHAR is an upper-case character.
-If the Unicode tables are not yet available, e.g. during bootstrap,
-then gives correct answers only for ASCII characters."
- (cond ((unicode-property-table-internal 'lowercase)
- (characterp (get-char-code-property char 'lowercase)))
- ((and (>= char ?A) (<= char ?Z)))))
-
-(compat-defun use-region-noncontiguous-p () ;; <compat-tests:region-noncontiguous-p>
- "Return non-nil for a non-contiguous region if `use-region-p'."
- (and (use-region-p) (region-noncontiguous-p)))
-
-(compat-defun use-region-beginning () ;; <compat-tests:use-region>
- "Return the start of the region if `use-region-p'."
- (and (use-region-p) (region-beginning)))
-
-(compat-defun use-region-end () ;; <compat-tests:use-region>
- "Return the end of the region if `use-region-p'."
- (and (use-region-p) (region-end)))
-
-(compat-defun get-scratch-buffer-create () ;; <compat-tests:get-scratch-buffer-create>
- "Return the *scratch* buffer, creating a new one if needed."
- (or (get-buffer "*scratch*")
- (let ((scratch (get-buffer-create "*scratch*")))
- ;; Don't touch the buffer contents or mode unless we know that
- ;; we just created it.
- (with-current-buffer scratch
- (when initial-scratch-message
- (insert (substitute-command-keys initial-scratch-message))
- (set-buffer-modified-p nil))
- (funcall initial-major-mode))
- scratch)))
-
-;;;; Defined in subr-x.el
-
-(compat-defmacro with-buffer-unmodified-if-unchanged (&rest body) ;; <compat-tests:with-buffer-unmodified-if-unchanged>
- "Like `progn', but change buffer-modified status only if buffer text changes.
-If the buffer was unmodified before execution of BODY, and
-buffer text after execution of BODY is identical to what it was
-before, ensure that buffer is still marked unmodified afterwards.
-For example, the following won't change the buffer's modification
-status:
-
- (with-buffer-unmodified-if-unchanged
- (insert \"a\")
- (delete-char -1))
-
-Note that only changes in the raw byte sequence of the buffer text,
-as stored in the internal representation, are monitored for the
-purpose of detecting the lack of changes in buffer text. Any other
-changes that are normally perceived as \"buffer modifications\", such
-as changes in text properties, `buffer-file-coding-system', buffer
-multibyteness, etc. -- will not be noticed, and the buffer will still
-be marked unmodified, effectively ignoring those changes."
- (declare (debug t) (indent 0))
- (let ((hash (gensym))
- (buffer (gensym)))
- `(let ((,hash (and (not (buffer-modified-p))
- (buffer-hash)))
- (,buffer (current-buffer)))
- (prog1
- (progn
- ,@body)
- ;; If we didn't change anything in the buffer (and the buffer
- ;; was previously unmodified), then flip the modification status
- ;; back to "unchanged".
- (when (and ,hash (buffer-live-p ,buffer))
- (with-current-buffer ,buffer
- (when (and (buffer-modified-p)
- (equal ,hash (buffer-hash)))
- (restore-buffer-modified-p nil))))))))
-
-(compat-defun add-display-text-property (start end prop value ;; <compat-tests:add-display-text-property>
- &optional object)
- "Add display property PROP with VALUE to the text from START to END.
-If any text in the region has a non-nil `display' property, those
-properties are retained.
-
-If OBJECT is non-nil, it should be a string or a buffer. If nil,
-this defaults to the current buffer."
- (let ((sub-start start)
- (sub-end 0)
- disp)
- (while (< sub-end end)
- (setq sub-end (next-single-property-change sub-start 'display object
- (if (stringp object)
- (min (length object) end)
- (min end (point-max)))))
- (if (not (setq disp (get-text-property sub-start 'display object)))
- ;; No old properties in this range.
- (put-text-property sub-start sub-end 'display (list prop value)
- object)
- ;; We have old properties.
- (let ((vector nil))
- ;; Make disp into a list.
- (setq disp
- (cond
- ((vectorp disp)
- (setq vector t)
- (append disp nil))
- ((not (consp (car disp)))
- (list disp))
- (t
- disp)))
- ;; Remove any old instances.
- (when-let ((old (assoc prop disp)))
- (setq disp (delete old disp)))
- (setq disp (cons (list prop value) disp))
- (when vector
- (setq disp (vconcat disp)))
- ;; Finally update the range.
- (put-text-property sub-start sub-end 'display disp object)))
- (setq sub-start sub-end))))
-
-(compat-defmacro while-let (spec &rest body) ;; <compat-tests:while-let>
- "Bind variables according to SPEC and conditionally evaluate BODY.
-Evaluate each binding in turn, stopping if a binding value is nil.
-If all bindings are non-nil, eval BODY and repeat.
-
-The variable list SPEC is the same as in `if-let*'."
- (declare (indent 1) (debug if-let))
- (let ((done (gensym "done")))
- `(catch ',done
- (while t
- (if-let* ,spec
- (progn
- ,@body)
- (throw ',done nil))))))
-
-;;;; Defined in files.el
-
-(compat-defun directory-abbrev-make-regexp (directory) ;; <compat-tests:directory-abbrev-make-regexp>
- "Create a regexp to match DIRECTORY for `directory-abbrev-alist'."
- (let ((regexp
- ;; We include a slash at the end, to avoid spurious
- ;; matches such as `/usr/foobar' when the home dir is
- ;; `/usr/foo'.
- (concat "\\`" (regexp-quote directory) "\\(/\\|\\'\\)")))
- ;; The value of regexp could be multibyte or unibyte. In the
- ;; latter case, we need to decode it.
- (if (multibyte-string-p regexp)
- regexp
- (decode-coding-string regexp
- (if (eq system-type 'windows-nt)
- 'utf-8
- locale-coding-system)))))
-
-(compat-defun directory-abbrev-apply (filename) ;; <compat-tests:directory-abbrev-apply>
- "Apply the abbreviations in `directory-abbrev-alist' to FILENAME.
-Note that when calling this, you should set `case-fold-search' as
-appropriate for the filesystem used for FILENAME."
- (dolist (dir-abbrev directory-abbrev-alist filename)
- (when (string-match (car dir-abbrev) filename)
- (setq filename (concat (cdr dir-abbrev)
- (substring filename (match-end 0)))))))
-
-(compat-defun file-name-split (filename) ;; <compat-tests:file-name-split>
- "Return a list of all the components of FILENAME.
-On most systems, this will be true:
-
- (equal (string-join (file-name-split filename) \"/\") filename)"
- (let ((components nil))
- ;; If this is a directory file name, then we have a null file name
- ;; at the end.
- (when (directory-name-p filename)
- (push "" components)
- (setq filename (directory-file-name filename)))
- ;; Loop, chopping off components.
- (while (length> filename 0)
- (push (file-name-nondirectory filename) components)
- (let ((dir (file-name-directory filename)))
- (setq filename (and dir (directory-file-name dir)))
- ;; If there's nothing left to peel off, we're at the root and
- ;; we can stop.
- (when (and dir (equal dir filename))
- (push (if (equal dir "") ""
- ;; On Windows, the first component might be "c:" or
- ;; the like.
- (substring dir 0 -1))
- components)
- (setq filename nil))))
- components))
-
-(compat-defun file-attribute-file-identifier (attributes) ;; <compat-tests:file-attribute-getters>
- "The inode and device numbers in ATTRIBUTES returned by `file-attributes'.
-The value is a list of the form (INODENUM DEVICE), where DEVICE could be
-either a single number or a cons cell of two numbers.
-This tuple of numbers uniquely identifies the file."
- (nthcdr 10 attributes))
-
-(compat-defun file-name-parent-directory (filename) ;; <compat-tests:file-name-parent-directory>
- "Return the directory name of the parent directory of FILENAME.
-If FILENAME is at the root of the filesystem, return nil.
-If FILENAME is relative, it is interpreted to be relative
-to `default-directory', and the result will also be relative."
- (let* ((expanded-filename (expand-file-name filename))
- (parent (file-name-directory (directory-file-name expanded-filename))))
- (cond
- ;; filename is at top-level, therefore no parent
- ((or (null parent)
- ;; `equal' is enough, we don't need to resolve symlinks here
- ;; with `file-equal-p', also for performance
- (equal parent expanded-filename))
- nil)
- ;; filename is relative, return relative parent
- ((not (file-name-absolute-p filename))
- (file-relative-name parent))
- (t
- parent))))
-
-(compat-defvar file-has-changed-p--hash-table ;; <compat-tests:file-has-changed-p>
- (make-hash-table :test #'equal)
- "Internal variable used by `file-has-changed-p'.")
-
-(compat-defun file-has-changed-p (file &optional tag) ;; <compat-tests:file-has-changed-p>
- "Return non-nil if FILE has changed.
-The size and modification time of FILE are compared to the size
-and modification time of the same FILE during a previous
-invocation of `file-has-changed-p'. Thus, the first invocation
-of `file-has-changed-p' always returns non-nil when FILE exists.
-The optional argument TAG, which must be a symbol, can be used to
-limit the comparison to invocations with identical tags; it can be
-the symbol of the calling function, for example."
- (let* ((file (directory-file-name (expand-file-name file)))
- (remote-file-name-inhibit-cache t)
- (fileattr (file-attributes file 'integer))
- (attr (and fileattr
- (cons (file-attribute-size fileattr)
- (file-attribute-modification-time fileattr))))
- (sym (concat (symbol-name tag) "@" file))
- (cachedattr (gethash sym file-has-changed-p--hash-table)))
- (unless (equal attr cachedattr)
- (puthash sym attr file-has-changed-p--hash-table))))
-
-;;;; Defined in keymap.el
-
-(compat-defun key-valid-p (keys) ;; <compat-tests:key-valid-p>
- "Say whether KEYS is a valid key.
-A key is a string consisting of one or more key strokes.
-The key strokes are separated by single space characters.
-
-Each key stroke is either a single character, or the name of an
-event, surrounded by angle brackets. In addition, any key stroke
-may be preceded by one or more modifier keys. Finally, a limited
-number of characters have a special shorthand syntax.
-
-Here's some example key sequences.
-
- \"f\" (the key `f')
- \"S o m\" (a three key sequence of the keys `S', `o' and `m')
- \"C-c o\" (a two key sequence of the keys `c' with the control modifier
- and then the key `o')
- \"H-<left>\" (the key named \"left\" with the hyper modifier)
- \"M-RET\" (the \"return\" key with a meta modifier)
- \"C-M-<space>\" (the \"space\" key with both the control and meta modifiers)
-
-These are the characters that have shorthand syntax:
-NUL, RET, TAB, LFD, ESC, SPC, DEL.
-
-Modifiers have to be specified in this order:
-
- A-C-H-M-S-s
-
-which is
-
- Alt-Control-Hyper-Meta-Shift-super"
- (declare (pure t) (side-effect-free t))
- (let ((case-fold-search nil))
- (and
- (stringp keys)
- (string-match-p "\\`[^ ]+\\( [^ ]+\\)*\\'" keys)
- (save-match-data
- (catch 'exit
- (let ((prefixes
- "\\(A-\\)?\\(C-\\)?\\(H-\\)?\\(M-\\)?\\(S-\\)?\\(s-\\)?"))
- (dolist (key (split-string keys " "))
- ;; Every key might have these modifiers, and they should be
- ;; in this order.
- (when (string-match (concat "\\`" prefixes) key)
- (setq key (substring key (match-end 0))))
- (unless (or (and (= (length key) 1)
- ;; Don't accept control characters as keys.
- (not (< (aref key 0) ?\s))
- ;; Don't accept Meta'd characters as keys.
- (or (multibyte-string-p key)
- (not (<= 127 (aref key 0) 255))))
- (and (string-match-p "\\`<[-_A-Za-z0-9]+>\\'" key)
- ;; Don't allow <M-C-down>.
- (= (progn
- (string-match
- (concat "\\`<" prefixes) key)
- (match-end 0))
- 1))
- (string-match-p
- "\\`\\(NUL\\|RET\\|TAB\\|LFD\\|ESC\\|SPC\\|DEL\\)\\'"
- key))
- ;; Invalid.
- (throw 'exit nil)))
- t))))))
-
-(compat-defun keymap--check (key) ;; <compat-tests:keymap--check>
- "Signal an error if KEY doesn't have a valid syntax."
- (unless (key-valid-p key)
- (error "%S is not a valid key definition; see `key-valid-p'" key)))
-
-(compat-defun key-parse (keys) ;; <compat-tests:key-parse>
- "Convert KEYS to the internal Emacs key representation.
-See `kbd' for a descripion of KEYS."
- (declare (pure t) (side-effect-free t))
- ;; A pure function is expected to preserve the match data.
- (save-match-data
- (let ((case-fold-search nil)
- (len (length keys)) ; We won't alter keys in the loop below.
- (pos 0)
- (res []))
- (while (and (< pos len)
- (string-match "[^ \t\n\f]+" keys pos))
- (let* ((word-beg (match-beginning 0))
- (word-end (match-end 0))
- (word (substring keys word-beg len))
- (times 1)
- key)
- ;; Try to catch events of the form "<as df>".
- (if (string-match "\\`<[^ <>\t\n\f][^>\t\n\f]*>" word)
- (setq word (match-string 0 word)
- pos (+ word-beg (match-end 0)))
- (setq word (substring keys word-beg word-end)
- pos word-end))
- (when (string-match "\\([0-9]+\\)\\*." word)
- (setq times (string-to-number (substring word 0 (match-end 1))))
- (setq word (substring word (1+ (match-end 1)))))
- (cond ((string-match "^<<.+>>$" word)
- (setq key (vconcat (if (eq (key-binding [?\M-x])
- 'execute-extended-command)
- [?\M-x]
- (or (car (where-is-internal
- 'execute-extended-command))
- [?\M-x]))
- (substring word 2 -2) "\r")))
- ((and (string-match "^\\(\\([ACHMsS]-\\)*\\)<\\(.+\\)>$" word)
- (progn
- (setq word (concat (match-string 1 word)
- (match-string 3 word)))
- (not (string-match
- "\\<\\(NUL\\|RET\\|LFD\\|ESC\\|SPC\\|DEL\\)$"
- word))))
- (setq key (list (intern word))))
- ((or (equal word "REM") (string-match "^;;" word))
- (setq pos (string-match "$" keys pos)))
- (t
- (let ((orig-word word) (prefix 0) (bits 0))
- (while (string-match "^[ACHMsS]-." word)
- (setq bits (+ bits
- (cdr
- (assq (aref word 0)
- '((?A . ?\A-\0) (?C . ?\C-\0)
- (?H . ?\H-\0) (?M . ?\M-\0)
- (?s . ?\s-\0) (?S . ?\S-\0))))))
- (setq prefix (+ prefix 2))
- (setq word (substring word 2)))
- (when (string-match "^\\^.$" word)
- (setq bits (+ bits ?\C-\0))
- (setq prefix (1+ prefix))
- (setq word (substring word 1)))
- (let ((found (assoc word '(("NUL" . "\0") ("RET" . "\r")
- ("LFD" . "\n") ("TAB" . "\t")
- ("ESC" . "\e") ("SPC" . " ")
- ("DEL" . "\177")))))
- (when found (setq word (cdr found))))
- (when (string-match "^\\\\[0-7]+$" word)
- (let ((n 0))
- (dolist (ch (cdr (string-to-list word)))
- (setq n (+ (* n 8) ch -48)))
- (setq word (vector n))))
- (cond ((= bits 0)
- (setq key word))
- ((and (= bits ?\M-\0) (stringp word)
- (string-match "^-?[0-9]+$" word))
- (setq key (mapcar (lambda (x) (+ x bits))
- (append word nil))))
- ((/= (length word) 1)
- (error "%s must prefix a single character, not %s"
- (substring orig-word 0 prefix) word))
- ((and (/= (logand bits ?\C-\0) 0) (stringp word)
- ;; We used to accept . and ? here,
- ;; but . is simply wrong,
- ;; and C-? is not used (we use DEL instead).
- (string-match "[@-_a-z]" word))
- (setq key (list (+ bits (- ?\C-\0)
- (logand (aref word 0) 31)))))
- (t
- (setq key (list (+ bits (aref word 0)))))))))
- (when key
- (dolist (_ (number-sequence 1 times))
- (setq res (vconcat res key))))))
- res)))
-
-(compat-defun keymap-set (keymap key definition) ;; <compat-tests:defvar-keymap>
- "Set KEY to DEFINITION in KEYMAP.
-KEY is a string that satisfies `key-valid-p'.
-
-DEFINITION is anything that can be a key's definition:
- nil (means key is undefined in this keymap),
- a command (a Lisp function suitable for interactive calling),
- a string (treated as a keyboard macro),
- a keymap (to define a prefix key),
- a symbol (when the key is looked up, the symbol will stand for its
- function definition, which should at that time be one of the above,
- or another symbol whose function definition is used, etc.),
- a cons (STRING . DEFN), meaning that DEFN is the definition
- (DEFN should be a valid definition in its own right) and
- STRING is the menu item name (which is used only if the containing
- keymap has been created with a menu name, see `make-keymap'),
- or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
- or an extended menu item definition.
- (See info node `(elisp)Extended Menu Items'.)"
- (keymap--check key)
- (when (stringp definition)
- (keymap--check definition)
- (setq definition (key-parse definition)))
- (define-key keymap (key-parse key) definition))
-
-(compat-defun keymap-unset (keymap key &optional remove) ;; <compat-tests:keymap-unset>
- "Remove key sequence KEY from KEYMAP.
-KEY is a string that satisfies `key-valid-p'.
-
-If REMOVE, remove the binding instead of unsetting it. This only
-makes a difference when there's a parent keymap. When unsetting
-a key in a child map, it will still shadow the same key in the
-parent keymap. Removing the binding will allow the key in the
-parent keymap to be used."
- (keymap--check key)
- (compat--define-key keymap (key-parse key) nil remove))
-
-(compat-defun keymap-global-set (key command) ;; <compat-tests:keymap-global-set>
- "Give KEY a global binding as COMMAND.
-COMMAND is the command definition to use; usually it is
-a symbol naming an interactively-callable function.
-
-KEY is a string that satisfies `key-valid-p'.
-
-Note that if KEY has a local binding in the current buffer,
-that local binding will continue to shadow any global binding
-that you make with this function.
-
-NOTE: The compatibility version is not a command."
- (keymap-set (current-global-map) key command))
-
-(compat-defun keymap-local-set (key command) ;; <compat-tests:keymap-local-set>
- "Give KEY a local binding as COMMAND.
-COMMAND is the command definition to use; usually it is
-a symbol naming an interactively-callable function.
-
-KEY is a string that satisfies `key-valid-p'.
-
-The binding goes in the current buffer's local map, which in most
-cases is shared with all other buffers in the same major mode.
-
-NOTE: The compatibility version is not a command."
- (let ((map (current-local-map)))
- (unless map
- (use-local-map (setq map (make-sparse-keymap))))
- (keymap-set map key command)))
-
-(compat-defun keymap-global-unset (key &optional remove) ;; <compat-tests:keymap-global-unset>
- "Remove global binding of KEY (if any).
-KEY is a string that satisfies `key-valid-p'.
-
-If REMOVE (interactively, the prefix arg), remove the binding
-instead of unsetting it. See `keymap-unset' for details.
-
-NOTE: The compatibility version is not a command."
- (keymap-unset (current-global-map) key remove))
-
-(compat-defun keymap-local-unset (key &optional remove) ;; <compat-tests:keymap-local-unset>
- "Remove local binding of KEY (if any).
-KEY is a string that satisfies `key-valid-p'.
-
-If REMOVE (interactively, the prefix arg), remove the binding
-instead of unsetting it. See `keymap-unset' for details.
-
-NOTE: The compatibility version is not a command."
- (when (current-local-map)
- (keymap-unset (current-local-map) key remove)))
-
-(compat-defun keymap-substitute (keymap olddef newdef &optional oldmap prefix) ;; <compat-tests:keymap-substitute>
- "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF.
-In other words, OLDDEF is replaced with NEWDEF wherever it appears.
-Alternatively, if optional fourth argument OLDMAP is specified, we redefine
-in KEYMAP as NEWDEF those keys that are defined as OLDDEF in OLDMAP.
-
-If you don't specify OLDMAP, you can usually get the same results
-in a cleaner way with command remapping, like this:
- (define-key KEYMAP [remap OLDDEF] NEWDEF)
-\n(fn OLDDEF NEWDEF KEYMAP &optional OLDMAP)"
- ;; Don't document PREFIX in the doc string because we don't want to
- ;; advertise it. It's meant for recursive calls only. Here's its
- ;; meaning
-
- ;; If optional argument PREFIX is specified, it should be a key
- ;; prefix, a string. Redefined bindings will then be bound to the
- ;; original key, with PREFIX added at the front.
- (unless prefix
- (setq prefix ""))
- (let* ((scan (or oldmap keymap))
- (prefix1 (vconcat prefix [nil]))
- (key-substitution-in-progress
- (cons scan key-substitution-in-progress)))
- ;; Scan OLDMAP, finding each char or event-symbol that
- ;; has any definition, and act on it with hack-key.
- (map-keymap
- (lambda (char defn)
- (aset prefix1 (length prefix) char)
- (substitute-key-definition-key defn olddef newdef prefix1 keymap))
- scan)))
-
-(compat-defun keymap-set-after (keymap key definition &optional after) ;; <compat-tests:keymap-set-after>
- "Add binding in KEYMAP for KEY => DEFINITION, right after AFTER's binding.
-This is like `keymap-set' except that the binding for KEY is placed
-just after the binding for the event AFTER, instead of at the beginning
-of the map. Note that AFTER must be an event type (like KEY), NOT a command
-\(like DEFINITION).
-
-If AFTER is t or omitted, the new binding goes at the end of the keymap.
-AFTER should be a single event type--a symbol or a character, not a sequence.
-
-Bindings are always added before any inherited map.
-
-The order of bindings in a keymap matters only when it is used as
-a menu, so this function is not useful for non-menu keymaps."
- (keymap--check key)
- (when (eq after t) (setq after nil)) ; nil and t are treated the same
- (when (stringp after)
- (keymap--check after)
- (setq after (key-parse after)))
- ;; If we're binding this key to another key, then parse that other
- ;; key, too.
- (when (stringp definition)
- (keymap--check definition)
- (setq definition (key-parse definition)))
- (define-key-after keymap (key-parse key) definition
- after))
-
-(compat-defun keymap-lookup ;; <compat-tests:keymap-lookup>
- (keymap key &optional accept-default no-remap position)
- "Return the binding for command KEY.
-KEY is a string that satisfies `key-valid-p'.
-
-If KEYMAP is nil, look up in the current keymaps. If non-nil, it
-should either be a keymap or a list of keymaps, and only these
-keymap(s) will be consulted.
-
-The binding is probably a symbol with a function definition.
-
-Normally, `keymap-lookup' ignores bindings for t, which act as
-default bindings, used when nothing else in the keymap applies;
-this makes it usable as a general function for probing keymaps.
-However, if the optional second argument ACCEPT-DEFAULT is
-non-nil, `keymap-lookup' does recognize the default bindings,
-just as `read-key-sequence' does.
-
-Like the normal command loop, `keymap-lookup' will remap the
-command resulting from looking up KEY by looking up the command
-in the current keymaps. However, if the optional third argument
-NO-REMAP is non-nil, `keymap-lookup' returns the unmapped
-command.
-
-If KEY is a key sequence initiated with the mouse, the used keymaps
-will depend on the clicked mouse position with regard to the buffer
-and possible local keymaps on strings.
-
-If the optional argument POSITION is non-nil, it specifies a mouse
-position as returned by `event-start' and `event-end', and the lookup
-occurs in the keymaps associated with it instead of KEY. It can also
-be a number or marker, in which case the keymap properties at the
-specified buffer position instead of point are used."
- (keymap--check key)
- (when (and keymap position)
- (error "Can't pass in both keymap and position"))
- (if keymap
- (let ((value (lookup-key keymap (key-parse key) accept-default)))
- (if (and (not no-remap)
- (symbolp value))
- (or (command-remapping value) value)
- value))
- (key-binding (key-parse key) accept-default no-remap position)))
-
-(compat-defun keymap-local-lookup (keys &optional accept-default) ;; <compat-tests:keymap-local-lookup>
- "Return the binding for command KEYS in current local keymap only.
-KEY is a string that satisfies `key-valid-p'.
-
-The binding is probably a symbol with a function definition.
-
-If optional argument ACCEPT-DEFAULT is non-nil, recognize default
-bindings; see the description of `keymap-lookup' for more details
-about this."
- (when-let ((map (current-local-map)))
- (keymap-lookup map keys accept-default)))
-
-(compat-defun keymap-global-lookup (keys &optional accept-default _message) ;; <compat-tests:keymap-global-lookup>
- "Return the binding for command KEYS in current global keymap only.
-KEY is a string that satisfies `key-valid-p'.
-
-The binding is probably a symbol with a function definition.
-This function's return values are the same as those of `keymap-lookup'
-\(which see).
-
-If optional argument ACCEPT-DEFAULT is non-nil, recognize default
-bindings; see the description of `keymap-lookup' for more details
-about this.
-
-NOTE: The compatibility version is not a command."
- (keymap-lookup (current-global-map) keys accept-default))
-
-(compat-defun define-keymap (&rest definitions) ;; <compat-tests:defvar-keymap>
- "Create a new keymap and define KEY/DEFINITION pairs as key bindings.
-The new keymap is returned.
-
-Options can be given as keywords before the KEY/DEFINITION
-pairs. Available keywords are:
-
-:full If non-nil, create a chartable alist (see `make-keymap').
- If nil (i.e., the default), create a sparse keymap (see
- `make-sparse-keymap').
-
-:suppress If non-nil, the keymap will be suppressed (see `suppress-keymap').
- If `nodigits', treat digits like other chars.
-
-:parent If non-nil, this should be a keymap to use as the parent
- (see `set-keymap-parent').
-
-:keymap If non-nil, instead of creating a new keymap, the given keymap
- will be destructively modified instead.
-
-:name If non-nil, this should be a string to use as the menu for
- the keymap in case you use it as a menu with `x-popup-menu'.
-
-:prefix If non-nil, this should be a symbol to be used as a prefix
- command (see `define-prefix-command'). If this is the case,
- this symbol is returned instead of the map itself.
-
-KEY/DEFINITION pairs are as KEY and DEF in `keymap-set'. KEY can
-also be the special symbol `:menu', in which case DEFINITION
-should be a MENU form as accepted by `easy-menu-define'.
-
-\(fn &key FULL PARENT SUPPRESS NAME PREFIX KEYMAP &rest [KEY DEFINITION]...)"
- (declare (indent defun))
- (let (full suppress parent name prefix keymap)
- ;; Handle keywords.
- (while (and definitions
- (keywordp (car definitions))
- (not (eq (car definitions) :menu)))
- (let ((keyword (pop definitions)))
- (unless definitions
- (error "Missing keyword value for %s" keyword))
- (let ((value (pop definitions)))
- (pcase keyword
- (:full (setq full value))
- (:keymap (setq keymap value))
- (:parent (setq parent value))
- (:suppress (setq suppress value))
- (:name (setq name value))
- (:prefix (setq prefix value))
- (_ (error "Invalid keyword: %s" keyword))))))
-
- (when (and prefix
- (or full parent suppress keymap))
- (error "A prefix keymap can't be defined with :full/:parent/:suppress/:keymap keywords"))
-
- (when (and keymap full)
- (error "Invalid combination: :keymap with :full"))
-
- (let ((keymap (cond
- (keymap keymap)
- (prefix (define-prefix-command prefix nil name))
- (full (make-keymap name))
- (t (make-sparse-keymap name))))
- seen-keys)
- (when suppress
- (suppress-keymap keymap (eq suppress 'nodigits)))
- (when parent
- (set-keymap-parent keymap parent))
-
- ;; Do the bindings.
- (while definitions
- (let ((key (pop definitions)))
- (unless definitions
- (error "Uneven number of key/definition pairs"))
- (let ((def (pop definitions)))
- (if (eq key :menu)
- (easy-menu-define nil keymap "" def)
- (if (member key seen-keys)
- (error "Duplicate definition for key: %S %s" key keymap)
- (push key seen-keys))
- (keymap-set keymap key def)))))
- keymap)))
-
-(compat-defmacro defvar-keymap (variable-name &rest defs) ;; <compat-tests:defvar-keymap>
- "Define VARIABLE-NAME as a variable with a keymap definition.
-See `define-keymap' for an explanation of the keywords and KEY/DEFINITION.
-
-In addition to the keywords accepted by `define-keymap', this
-macro also accepts a `:doc' keyword, which (if present) is used
-as the variable documentation string.
-
-The `:repeat' keyword can also be specified; it controls the
-`repeat-mode' behavior of the bindings in the keymap. When it is
-non-nil, all commands in the map will have the `repeat-map'
-symbol property.
-
-More control is available over which commands are repeatable; the
-value can also be a property list with properties `:enter' and
-`:exit', for example:
-
- :repeat (:enter (commands ...) :exit (commands ...))
-
-`:enter' specifies the list of additional commands that only
-enter `repeat-mode'. When the list is empty, then only the
-commands defined in the map enter `repeat-mode'. Specifying a
-list of commands is useful when there are commands that have the
-`repeat-map' symbol property, but don't exist in this specific
-map.
-
-`:exit' is a list of commands that exit `repeat-mode'. When the
-list is empty, no commands in the map exit `repeat-mode'.
-Specifying a list of commands is useful when those commands exist
-in this specific map, but should not have the `repeat-map' symbol
-property.
-
-\(fn VARIABLE-NAME &key DOC FULL PARENT SUPPRESS NAME PREFIX KEYMAP REPEAT &rest [KEY DEFINITION]...)"
- (declare (indent 1))
- (let ((opts nil)
- doc repeat props)
- (while (and defs
- (keywordp (car defs))
- (not (eq (car defs) :menu)))
- (let ((keyword (pop defs)))
- (unless defs
- (error "Uneven number of keywords"))
- (cond
- ((eq keyword :doc) (setq doc (pop defs)))
- ((eq keyword :repeat) (setq repeat (pop defs)))
- (t (push keyword opts)
- (push (pop defs) opts)))))
- (unless (zerop (% (length defs) 2))
- (error "Uneven number of key/definition pairs: %s" defs))
-
- (let ((defs defs)
- key seen-keys)
- (while defs
- (setq key (pop defs))
- (pop defs)
- (unless (eq key :menu)
- (if (member key seen-keys)
- (error "Duplicate definition for key '%s' in keymap '%s'"
- key variable-name)
- (push key seen-keys)))))
-
- (when repeat
- (let ((defs defs)
- def)
- (dolist (def (plist-get repeat :enter))
- (push `(put ',def 'repeat-map ',variable-name) props))
- (while defs
- (pop defs)
- (setq def (pop defs))
- (when (and (memq (car def) '(function quote))
- (not (memq (cadr def) (plist-get repeat :exit))))
- (push `(put ,def 'repeat-map ',variable-name) props)))))
-
- (let ((defvar-form
- `(defvar ,variable-name
- (define-keymap ,@(nreverse opts) ,@defs)
- ,@(and doc (list doc)))))
- (if props
- `(progn
- ,defvar-form
- ,@(nreverse props))
- defvar-form))))
-
-;;;; Defined in keymap.c
-
-(compat-defun define-key (keymap key def &optional remove) ;; <compat-tests:define-key>
- "Handle optional argument REMOVE."
- :extended t
- (if (not remove)
- (define-key keymap key def)
- ;; Canonicalize key
- (setq key (key-parse (key-description key)))
- (define-key keymap key nil)
- ;; Split M-key in ESC key
- (setq key (mapcan (lambda (k)
- (if (and (integerp k) (/= (logand k ?\M-\0) 0))
- (list ?\e (logxor k ?\M-\0))
- (list k)))
- key))
- ;; Delete single keys directly
- (if (length= key 1)
- (delete key keymap)
- ;; Lookup submap and delete key from there
- (let ((submap (lookup-key keymap (vconcat (butlast key)))))
- (unless (keymapp submap)
- (error "Not a keymap for %s" key))
- (when (symbolp submap)
- (setq submap (symbol-function submap)))
- (delete (last key) submap)))
- def))
-
-;;;; Defined in help.el
-
-(compat-defun substitute-quotes (string) ;; <compat-tests:substitute-quotes>
- "Substitute quote characters for display.
-Each grave accent \\=` is replaced by left quote, and each
-apostrophe \\=' is replaced by right quote. Left and right quote
-characters are specified by `text-quoting-style'."
- (cond ((eq (text-quoting-style) 'curve)
- (string-replace "`" "‘"
- (string-replace "'" "’" string)))
- ((eq (text-quoting-style) 'straight)
- (string-replace "`" "'" string))
- (t string)))
-
-;;;; Defined in button.el
-
-(compat-defun button--properties (callback data help-echo) ;; <compat-tests:buttonize>
- "Helper function."
- (list 'font-lock-face 'button
- 'mouse-face 'highlight
- 'help-echo help-echo
- 'button t
- 'follow-link t
- 'category t
- 'button-data data
- 'keymap button-map
- 'action callback))
-
-(compat-defun buttonize (string callback &optional data help-echo) ;; <compat-tests:buttonize>
- "Make STRING into a button and return it.
-When clicked, CALLBACK will be called with the DATA as the
-function argument. If DATA isn't present (or is nil), the button
-itself will be used instead as the function argument.
-
-If HELP-ECHO, use that as the `help-echo' property.
-
-Also see `buttonize-region'."
- (let ((string
- (apply #'propertize string
- (button--properties callback data help-echo))))
- ;; Add the face to the end so that it can be overridden.
- (add-face-text-property 0 (length string) 'button t string)
- string))
-
-(compat-defun buttonize-region (start end callback &optional data help-echo) ;; <compat-tests:buttonize-region>
- "Make the region between START and END into a button.
-When clicked, CALLBACK will be called with the DATA as the
-function argument. If DATA isn't present (or is nil), the button
-itself will be used instead as the function argument.
-
-If HELP-ECHO, use that as the `help-echo' property.
-
-Also see `buttonize'."
- (add-text-properties start end (button--properties callback data help-echo))
- (add-face-text-property start end 'button t))
-
-;;;; Defined in rmc.el
-
-(compat-defun read-multiple-choice ;; <compat-tests:read-multiple-choice>
- (prompt choices &optional _help-str _show-help long-form)
- "Handle LONG-FORM argument."
- :extended t
- (if (not long-form)
- (read-multiple-choice prompt choices)
- (let ((answer
- (completing-read
- (concat prompt " ("
- (mapconcat #'identity (mapcar #'cadr choices) "/")
- ") ")
- (mapcar #'cadr choices) nil t)))
- (catch 'found
- (dolist (c choices)
- (when (equal answer (cadr c))
- (throw 'found c)))))))
-
-;;;; Defined in paragraphs.el
-
-(compat-defun count-sentences (start end) ;; <compat-tests:count-sentences>
- "Count sentences in current buffer from START to END."
- (let ((sentences 0)
- (inhibit-field-text-motion t))
- (save-excursion
- (save-restriction
- (narrow-to-region start end)
- (goto-char (point-min))
- (while (ignore-errors (forward-sentence))
- (setq sentences (1+ sentences)))
- (when (/= (skip-chars-backward " \t\n") 0)
- (setq sentences (1- sentences)))
- sentences))))
-
-;;;; Defined in cl-lib.el
-
-(compat-defun cl-constantly (value) ;; <compat-tests:cl-constantly>
- "Return a function that takes any number of arguments, but returns VALUE."
- :feature cl-lib
- (lambda (&rest _) value))
-
-;;;; Defined in cl-macs.el
-
-(compat-defmacro cl-with-gensyms (names &rest body) ;; <compat-tests:cl-with-gensyms>
- "Bind each of NAMES to an uninterned symbol and evaluate BODY."
- ;; No :feature since macro is autoloaded
- (declare (debug (sexp body)) (indent 1))
- `(let ,(cl-loop for name in names collect
- `(,name (gensym (symbol-name ',name))))
- ,@body))
-
-(compat-defmacro cl-once-only (names &rest body) ;; <compat-tests:cl-once-only>
- "Generate code to evaluate each of NAMES just once in BODY.
-
-This macro helps with writing other macros. Each of names is
-either (NAME FORM) or NAME, which latter means (NAME NAME).
-During macroexpansion, each NAME is bound to an uninterned
-symbol. The expansion evaluates each FORM and binds it to the
-corresponding uninterned symbol.
-
-For example, consider this macro:
-
- (defmacro my-cons (x)
- (cl-once-only (x)
- \\=`(cons ,x ,x)))
-
-The call (my-cons (pop y)) will expand to something like this:
-
- (let ((g1 (pop y)))
- (cons g1 g1))
-
-The use of `cl-once-only' ensures that the pop is performed only
-once, as intended.
-
-See also `macroexp-let2'."
- ;; No :feature since macro is autoloaded
- (declare (debug (sexp body)) (indent 1))
- (setq names (mapcar #'ensure-list names))
- (let ((our-gensyms (cl-loop for _ in names collect (gensym))))
- `(let ,(cl-loop for sym in our-gensyms collect `(,sym (gensym)))
- `(let ,(list
- ,@(cl-loop for name in names for gensym in our-gensyms
- for to-eval = (or (cadr name) (car name))
- collect ``(,,gensym ,,to-eval)))
- ,(let ,(cl-loop for name in names for gensym in our-gensyms
- collect `(,(car name) ,gensym))
- ,@body)))))
-
-;;;; Defined in ert-x.el
-
-(compat-defmacro ert-with-temp-file (name &rest body) ;; <compat-tests:ert-with-temp-file>
- "Bind NAME to the name of a new temporary file and evaluate BODY.
-Delete the temporary file after BODY exits normally or
-non-locally. NAME will be bound to the file name of the temporary
-file.
-
-The following keyword arguments are supported:
-
-:prefix STRING If non-nil, pass STRING to `make-temp-file' as
- the PREFIX argument. Otherwise, use the value of
- `ert-temp-file-prefix'.
-
-:suffix STRING If non-nil, pass STRING to `make-temp-file' as the
- SUFFIX argument. Otherwise, use the value of
- `ert-temp-file-suffix'; if the value of that
- variable is nil, generate a suffix based on the
- name of the file that `ert-with-temp-file' is
- called from.
-
-:text STRING If non-nil, pass STRING to `make-temp-file' as
- the TEXT argument.
-
-:buffer SYMBOL Open the temporary file using `find-file-noselect'
- and bind SYMBOL to the buffer. Kill the buffer
- after BODY exits normally or non-locally.
-
-:coding CODING If non-nil, bind `coding-system-for-write' to CODING
- when executing BODY. This is handy when STRING includes
- non-ASCII characters or the temporary file must have a
- specific encoding or end-of-line format.
-
-See also `ert-with-temp-directory'."
- :feature ert-x
- (declare (indent 1) (debug (symbolp body)))
- (cl-check-type name symbol)
- (let (keyw prefix suffix directory text extra-keywords buffer coding)
- (while (keywordp (setq keyw (car body)))
- (setq body (cdr body))
- (pcase keyw
- (:prefix (setq prefix (pop body)))
- (:suffix (setq suffix (pop body)))
- ;; This is only for internal use by `ert-with-temp-directory'
- ;; and is therefore not documented.
- (:directory (setq directory (pop body)))
- (:text (setq text (pop body)))
- (:buffer (setq buffer (pop body)))
- (:coding (setq coding (pop body)))
- (_ (push keyw extra-keywords) (pop body))))
- (when extra-keywords
- (error "Invalid keywords: %s" (mapconcat #'symbol-name extra-keywords " ")))
- (let ((temp-file (make-symbol "temp-file"))
- (prefix (or prefix "emacs-test-"))
- (suffix (or suffix
- (thread-last
- (file-name-base (or (macroexp-file-name) buffer-file-name))
- (replace-regexp-in-string (rx string-start
- (group (+? not-newline))
- (regexp "-?tests?")
- string-end)
- "\\1")
- (concat "-")))))
- `(let* ((coding-system-for-write ,(or coding coding-system-for-write))
- (,temp-file (,(if directory 'file-name-as-directory 'identity)
- (,(if (fboundp 'compat--make-temp-file)
- 'compat--make-temp-file 'make-temp-file)
- ,prefix ,directory ,suffix ,text)))
- (,name ,(if directory
- `(file-name-as-directory ,temp-file)
- temp-file))
- ,@(when buffer
- (list `(,buffer (find-file-literally ,temp-file)))))
- (unwind-protect
- (progn ,@body)
- (ignore-errors
- ,@(when buffer
- (list `(with-current-buffer ,buffer
- (set-buffer-modified-p nil))
- `(kill-buffer ,buffer))))
- (ignore-errors
- ,(if directory
- `(delete-directory ,temp-file :recursive)
- `(delete-file ,temp-file))))))))
-
-(compat-defmacro ert-with-temp-directory (name &rest body) ;; <compat-tests:ert-with-temp-directory>
- "Bind NAME to the name of a new temporary directory and evaluate BODY.
-Delete the temporary directory after BODY exits normally or
-non-locally.
-
-NAME is bound to the directory name, not the directory file
-name. (In other words, it will end with the directory delimiter;
-on Unix-like systems, it will end with \"/\".)
-
-The same keyword arguments are supported as in
-`ert-with-temp-file' (which see), except for :text."
- :feature ert-x
- (declare (indent 1) (debug (symbolp body)))
- (let ((tail body) keyw)
- (while (keywordp (setq keyw (car tail)))
- (setq tail (cddr tail))
- (pcase keyw (:text (error "Invalid keyword for directory: :text")))))
- `(ert-with-temp-file ,name
- :directory t
- ,@body))
-
-;;;; Defined in wid-edit.el
-
-(compat-guard (not (fboundp 'widget-key-validate)) ;; <compat-tests:widget-key>
- :feature wid-edit
- (defvar widget-key-prompt-value-history nil
- "History of input to `widget-key-prompt-value'.")
- (define-widget 'key 'editable-field
- "A key sequence."
- :prompt-value 'widget-field-prompt-value
- :match 'widget-key-valid-p
- :format "%{%t%}: %v"
- :validate 'widget-key-validate
- :keymap widget-key-sequence-map
- :help-echo "C-q: insert KEY, EVENT, or CODE; RET: enter value"
- :tag "Key")
- (defun widget-key-valid-p (_widget value)
- (key-valid-p value))
- (defun widget-key-validate (widget)
- (unless (and (stringp (widget-value widget))
- (key-valid-p (widget-value widget)))
- (widget-put widget :error (format "Invalid key: %S"
- (widget-value widget)))
- widget)))
-
-(provide 'compat-29)
-;;; compat-29.el ends here
+++ /dev/null
-;;; compat-30.el --- Functionality added in Emacs 30 -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2023-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 30, needed by older Emacs versions.
-
-;;; Code:
-
-(eval-when-compile (load "compat-macs.el" nil t t))
-(compat-require compat-29 "29.1")
-
-(compat-version "29.3")
-(compat-defvar untrusted-content nil ;; <compat-tests:untrusted-content>
- "Non-nil means that current buffer originated from an untrusted source.
-Email clients and some other modes may set this non-nil to mark the
-buffer contents as untrusted.
-
-This variable might be subject to change without notice."
- :local permanent)
-
-(compat-version "30.1")
-
-;;;; Defined in lread.c
-
-(compat-defun obarray-clear (ob) ;; <compat-tests:obarray-clear>
- "Remove all symbols from obarray OB."
- (fillarray ob 0))
-
-;;;; Defined in buffer.c
-
-(compat-defun find-buffer (variable value) ;; <compat-tests:find-buffer>
- "Return the buffer with buffer-local VARIABLE equal to VALUE.
-If there is no such live buffer, return nil."
- (cl-loop for buffer the buffers
- if (equal (buffer-local-value variable buffer) value)
- return buffer))
-
-(compat-defun get-truename-buffer (filename) ;; <compat-tests:get-truename-buffer>
- "Return the buffer with `file-truename' equal to FILENAME (a string).
-If there is no such live buffer, return nil.
-See also `find-buffer-visiting'."
- (find-buffer 'buffer-file-truename filename))
-
-;;;; Defined in files.el
-
-(compat-defvar trusted-content nil ;; <compat-tests:trusted-content>
- "List of files and directories whose content we trust.
-Be extra careful here since trusting means that Emacs might execute the
-code contained within those files and directories without an explicit
-request by the user.
-One important case when this might happen is when `flymake-mode' is
-enabled (for example, when it is added to a mode hook).
-Each element of the list should be a string:
-- If it ends in \"/\", it is considered as a directory name and means that
- Emacs should trust all the files whose name has this directory as a prefix.
-- else it is considered as a file name.
-Use abbreviated file names. For example, an entry \"~/mycode\" means
-that Emacs will trust all the files in your directory \"mycode\".
-This variable can also be set to `:all', in which case Emacs will trust
-all files, which opens a gaping security hole."
- :risky t)
-
-(compat-defun trusted-content-p () ;; <compat-tests:trusted-content-p>
- "Return non-nil if we trust the contents of the current buffer.
-Here, \"trust\" means that we are willing to run code found inside of it.
-See also `trusted-content'."
- (and (not untrusted-content)
- (or
- (eq trusted-content :all)
- (and
- buffer-file-truename
- (with-demoted-errors "trusted-content-p: %S"
- (let ((exists (file-exists-p buffer-file-truename)))
- (or
- (if (and exists user-init-file)
- (file-equal-p buffer-file-truename user-init-file)
- (equal buffer-file-truename user-init-file))
- (let ((file (abbreviate-file-name buffer-file-truename))
- (trusted nil))
- (dolist (tf trusted-content)
- (when (or (if exists (file-equal-p tf file) (equal tf file))
- (and (string-suffix-p "/" tf)
- (string-prefix-p tf file)))
- (setq trusted t)))
- trusted))))))))
-
-(compat-defun require-with-check (feature &optional filename noerror) ;; <compat-tests:require-with-check>
- "If FEATURE is not already loaded, load it from FILENAME.
-This is like `require' except if FEATURE is already a member of the list
-`features’, then check if it was provided by a different file than the
-one that is about to be loaded now (presumably because `load-path' has
-been changed since FILENAME was loaded). If that is the case, either
-signal an error (the default), or forcibly reload the new file (if
-NOERROR is equal to `reload'), or otherwise emit a warning."
- (let ((lh load-history)
- (res (require feature filename (if (eq noerror 'reload) nil noerror))))
- ;; If the `feature' was not yet provided, `require' just loaded the right
- ;; file, so we're done.
- (when (and res (eq lh load-history))
- ;; If `require' did nothing, we need to make sure that was warranted.
- (let* ((fn (locate-file (or filename (symbol-name feature))
- load-path (get-load-suffixes) nil
- )) ;; load-prefer-newer
- ;; We used to look for `fn' in `load-history' with `assoc'
- ;; which works in most cases, but in some cases (e.g. when
- ;; `load-prefer-newer' is set) `locate-file' can return a
- ;; different file than the file that `require' would load,
- ;; so the file won't be found in `load-history' even though
- ;; we did load "it". (bug#74040)
- ;; So use a "permissive" search which doesn't pay attention to
- ;; differences between file extensions.
- (prefix (if (string-match
- (concat (regexp-opt (get-load-suffixes)) "\\'") fn)
- (concat (substring fn 0 (match-beginning 0)) ".")
- fn))
- (lh load-history))
- (while (and lh (let ((file (car-safe (car lh))))
- (not (and file (string-prefix-p prefix file)))))
- (setq lh (cdr lh)))
- (cond
- (lh nil) ;We loaded the right file.
- ((eq noerror 'reload) (load fn nil 'nomessage))
- ((and fn (memq feature features))
- (funcall (if noerror #'warn #'error)
- "Feature `%S' is now provided by a different file %s"
- feature fn))
- (fn
- (funcall (if noerror #'warn #'error)
- "Could not load file %s" fn))
- (t
- (funcall (if noerror #'warn #'error)
- "Could not locate file %s in load path"
- (or filename (symbol-name feature)))))))
- res))
-
-;;;; Defined in minibuffer.el
-
-(compat-defun completion--metadata-get-1 (metadata prop) ;; <compat-tests:completion-metadata-get>
- "Helper function.
-See for `completion-metadata-get' for METADATA and PROP arguments."
- (or (alist-get prop metadata)
- (plist-get completion-extra-properties
- (or (get prop 'completion-extra-properties--keyword)
- (put prop 'completion-extra-properties--keyword
- (intern (concat ":" (symbol-name prop))))))))
-
-(compat-defun completion-metadata-get (metadata prop) ;; <compat-tests:completion-metadata-get>
- "Get property PROP from completion METADATA.
-If the metadata specifies a completion category, the variables
-`completion-category-overrides' and
-`completion-category-defaults' take precedence for
-category-specific overrides. If the completion metadata does not
-specify the property, the `completion-extra-properties' plist is
-consulted. Note that the keys of the
-`completion-extra-properties' plist are keyword symbols, not
-plain symbols."
- :extended t
- (if-let ((cat (and (not (eq prop 'category))
- (completion--metadata-get-1 metadata 'category)))
- (over (completion--category-override cat prop)))
- (cdr over)
- (completion--metadata-get-1 metadata prop)))
-
-(compat-defvar completion-lazy-hilit nil ;; <compat-tests:completion-lazy-hilit>
- "If non-nil, request lazy highlighting of completion candidates.
-
-Lisp programs (a.k.a. \"front ends\") that present completion
-candidates may opt to bind this variable to a non-nil value when
-calling functions (such as `completion-all-completions') which
-produce completion candidates. This tells the underlying
-completion styles that they do not need to fontify (i.e.,
-propertize with the `face' property) completion candidates in a
-way that highlights the matching parts. Then it is the front end
-which presents the candidates that becomes responsible for this
-fontification. The front end does that by calling the function
-`completion-lazy-hilit' on each completion candidate that is to be
-displayed to the user.
-
-Note that only some completion styles take advantage of this
-variable for optimization purposes. Other styles will ignore the
-hint and fontify eagerly as usual. It is still safe for a
-front end to call `completion-lazy-hilit' in these situations.
-
-To author a completion style that takes advantage of this variable,
-see `completion-lazy-hilit-fn' and `completion-pcm--hilit-commonality'.")
-
-(compat-defvar completion-lazy-hilit-fn nil ;; <compat-tests:completion-lazy-hilit>
- "Fontification function set by lazy-highlighting completions styles.
-When a given style wants to enable support for `completion-lazy-hilit'
-\(which see), that style should set this variable to a function of one
-argument. It will be called with each completion candidate, a string, to
-be displayed to the user, and should destructively propertize these
-strings with the `face' property.")
-
-(compat-defun completion-lazy-hilit (str) ;; <compat-tests:completion-lazy-hilit>
- "Return a copy of completion candidate STR that is `face'-propertized.
-See documentation of the variable `completion-lazy-hilit' for more
-details."
- (if (and completion-lazy-hilit completion-lazy-hilit-fn)
- (funcall completion-lazy-hilit-fn (copy-sequence str))
- str))
-
-;;;; Defined in color.el
-
-(compat-defun color-oklab-to-xyz (l a b) ;; <compat-tests:color-oklab-to-xyz>
- "Convert the OkLab color represented by L A B to CIE XYZ.
-Oklab is a perceptual color space created by Björn Ottosson
-<https://bottosson.github.io/posts/oklab/>. It has the property that
-changes in the hue and saturation of a color can be made while maintaining
-the same perceived lightness."
- :feature color
- (let ((ll (expt (+ (* 1.0 l) (* 0.39633779 a) (* 0.21580376 b)) 3))
- (mm (expt (+ (* 1.00000001 l) (* -0.10556134 a) (* -0.06385417 b)) 3))
- (ss (expt (+ (* 1.00000005 l) (* -0.08948418 a) (* -1.29148554 b)) 3)))
- (list (+ (* ll 1.22701385) (* mm -0.55779998) (* ss 0.28125615))
- (+ (* ll -0.04058018) (* mm 1.11225687) (* ss -0.07167668))
- (+ (* ll -0.07638128) (* mm -0.42148198) (* ss 1.58616322)))))
-
-(compat-defun color-xyz-to-oklab (x y z) ;; <compat-tests:color-xyz-to-oklab>
- "Convert the CIE XYZ color represented by X Y Z to Oklab."
- :feature color
- (let ((ll (+ (* x 0.8189330101) (* y 0.3618667424) (* z -0.1288597137)))
- (mm (+ (* x 0.0329845436) (* y 0.9293118715) (* z 0.0361456387)))
- (ss (+ (* x 0.0482003018) (* y 0.2643662691) (* z 0.6338517070))))
- (let*
- ((cube-root (lambda (f)
- (if (< f 0)
- (- (expt (- f) (/ 1.0 3.0)))
- (expt f (/ 1.0 3.0)))))
- (lll (funcall cube-root ll))
- (mmm (funcall cube-root mm))
- (sss (funcall cube-root ss)))
- (list (+ (* lll 0.2104542553) (* mmm 0.7936177850) (* sss -0.0040720468))
- (+ (* lll 1.9779984951) (* mmm -2.4285922050) (* sss 0.4505937099))
- (+ (* lll 0.0259040371) (* mmm 0.7827717662) (* sss -0.8086757660))))))
-
-(compat-defun color-oklab-to-srgb (l a b) ;; <compat-tests:color-oklab-to-srgb>
- "Convert the Oklab color represented by L A B to sRGB."
- :feature color
- (apply #'color-xyz-to-srgb (color-oklab-to-xyz l a b)))
-
-(compat-defun color-srgb-to-oklab (r g b) ;; <compat-tests:color-srgb-to-oklab>
- "Convert the sRGB color R G B to Oklab."
- :feature color
- (apply #'color-xyz-to-oklab (color-srgb-to-xyz r g b)))
-
-;;;; Defined in subr.el
-
-(compat-defmacro static-if (condition then-form &rest else-forms) ;; <compat-tests:static-if>
- "A conditional compilation macro.
-Evaluate CONDITION at macro-expansion time. If it is non-nil,
-expand the macro to THEN-FORM. Otherwise expand it to ELSE-FORMS
-enclosed in a `progn' form. ELSE-FORMS may be empty."
- (declare (indent 2) (debug (sexp sexp &rest sexp)))
- (if (eval condition lexical-binding)
- then-form
- (cons 'progn else-forms)))
-
-(compat-defun closurep (object) ;; <compat-tests:closurep>
- "Return t if OBJECT is a function of type closure."
- (declare (side-effect-free error-free))
- (eq (car-safe object) 'closure))
-
-(compat-defalias interpreted-function-p closurep) ;; <compat-tests:closurep>
-
-(compat-defun primitive-function-p (object) ;; <compat-tests:primitive-function-p>
- "Return t if OBJECT is a built-in primitive function.
-This excludes special forms, since they are not functions."
- (declare (side-effect-free error-free))
- (and (subrp object)
- (not (or (with-no-warnings (subr-native-elisp-p object))
- (special-form-p object)))))
-
-(compat-defalias drop nthcdr) ;; <compat-tests:drop>
-
-(compat-defun merge-ordered-lists (lists &optional error-function) ;; <compat-tests:merge-ordered-lists>
- "Merge LISTS in a consistent order.
-LISTS is a list of lists of elements.
-Merge them into a single list containing the same elements (removing
-duplicates), obeying their relative positions in each list.
-The order of the (sub)lists determines the final order in those cases where
-the order within the sublists does not impose a unique choice.
-Equality of elements is tested with `eql'.
-
-If a consistent order does not exist, call ERROR-FUNCTION with
-a remaining list of lists that we do not know how to merge.
-It should return the candidate to use to continue the merge, which
-has to be the head of one of the lists.
-By default we choose the head of the first list."
- (let ((result '()))
- (setq lists (remq nil lists))
- (while (cdr (setq lists (delq nil lists)))
- (let* ((next nil)
- (tail lists))
- (while tail
- (let ((candidate (caar tail))
- (other-lists lists))
- (while other-lists
- (if (not (memql candidate (cdr (car other-lists))))
- (setq other-lists (cdr other-lists))
- (setq candidate nil)
- (setq other-lists nil)))
- (if (not candidate)
- (setq tail (cdr tail))
- (setq next candidate)
- (setq tail nil))))
- (unless next
- (setq next (funcall (or error-function #'caar) lists))
- (unless (funcall
- (eval-when-compile (if (fboundp 'compat--assoc) 'compat--assoc 'assoc))
- next lists #'eql)
- (error "Invalid candidate returned by error-function: %S" next)))
- (push next result)
- (setq lists
- (mapcar (lambda (l) (if (eql (car l) next) (cdr l) l))
- lists))))
- (if (null result) (car lists)
- (append (nreverse result) (car lists)))))
-
-(compat-defun copy-tree (tree &optional vectors-and-records) ;; <compat-tests:copy-tree>
- "Handle copying records when optional arg is non-nil."
- :extended t
- (declare (side-effect-free error-free))
- (if (fboundp 'recordp)
- (if (consp tree)
- (let (result)
- (while (consp tree)
- (let ((newcar (car tree)))
- (if (or (consp (car tree))
- (and vectors-and-records
- (or (vectorp (car tree)) (recordp (car tree)))))
- (setq newcar (compat--copy-tree (car tree) vectors-and-records)))
- (push newcar result))
- (setq tree (cdr tree)))
- (nconc (nreverse result)
- (if (and vectors-and-records (or (vectorp tree) (recordp tree)))
- (compat--copy-tree tree vectors-and-records)
- tree)))
- (if (and vectors-and-records (or (vectorp tree) (recordp tree)))
- (let ((i (length (setq tree (copy-sequence tree)))))
- (while (>= (setq i (1- i)) 0)
- (aset tree i (compat--copy-tree (aref tree i) vectors-and-records)))
- tree)
- tree))
- (copy-tree tree vectors-and-records)))
-
-;;;; Defined in fns.c
-
-(compat-defun value< (a b) ;; <compat-tests:value<>
- "Return non-nil if A precedes B in standard value order.
-A and B must have the same basic type.
-Numbers are compared with <.
-Strings and symbols are compared with string-lessp.
-Lists, vectors, bool-vectors and records are compared lexicographically.
-Markers are compared lexicographically by buffer and position.
-Buffers and processes are compared by name.
-Other types are considered unordered and the return value will be ‘nil’."
- (cond
- ((or (and (numberp a) (numberp b))
- (and (markerp a) (markerp b)))
- (< a b))
- ((or (and (stringp a) (stringp b))
- (and (symbolp a) (symbolp b)))
- (string< a b))
- ((and (listp a) (listp b))
- (while (and (consp a) (consp b) (equal (car a) (car b)))
- (setq a (cdr a) b (cdr b)))
- (cond
- ((not b) nil)
- ((not a) t)
- ((and (consp a) (consp b)) (value< (car a) (car b)))
- (t (value< a b))))
- ((and (vectorp a) (vectorp b))
- (let* ((na (length a))
- (nb (length b))
- (n (min na nb))
- (i 0))
- (while (and (< i n) (equal (aref a i) (aref b i)))
- (cl-incf i))
- (if (< i n) (value< (aref a i) (aref b i)) (< n nb))))
- ((and (bufferp a) (bufferp b))
- ;; `buffer-name' is nil for killed buffers.
- (setq a (buffer-name a)
- b (buffer-name b))
- (cond
- ((and a b) (string< a b))
- (b t)))
- ((and (processp a) (processp b))
- (string< (process-name a) (process-name b)))
- ;; TODO Add support for more types here.
- ;; Other values of equal type are considered unordered (return value nil).
- ((eq (type-of a) (type-of b)) nil)
- ;; Different types.
- (t (error "value< type mismatch: %S %S" a b))))
-
-(compat-defun sort (seq &optional lessp &rest rest) ;; <compat-tests:sort>
- "Sort function with support for keyword arguments.
-The following arguments are defined:
-
-:key FUNC -- FUNC is a function that takes a single element from SEQ and
- returns the key value to be used in comparison. If absent or nil,
- `identity' is used.
-
-:lessp FUNC -- FUNC is a function that takes two arguments and returns
- non-nil if the first element should come before the second.
- If absent or nil, `value<' is used.
-
-:reverse BOOL -- if BOOL is non-nil, the sorting order implied by FUNC is
- reversed. This does not affect stability: equal elements still retain
- their order in the input sequence.
-
-:in-place BOOL -- if BOOL is non-nil, SEQ is sorted in-place and returned.
- Otherwise, a sorted copy of SEQ is returned and SEQ remains unmodified;
- this is the default.
-
-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))
- (when (or (not lessp) rest)
- (setq
- rest (if lessp (cons lessp rest) rest)
- in-place (plist-get rest :in-place)
- reverse (plist-get rest :reverse)
- lessp (let ((key (plist-get rest :key))
- (< (or (plist-get rest :lessp) #'value<)))
- (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)))
-
-;;;; Defined in mule-cmds.el
-
-(compat-defun char-to-name (char) ;; <compat-tests:char-to-name>
- "Return the Unicode name for CHAR, if it has one, else nil.
-Return nil if CHAR is not a character."
- (and (characterp char)
- (or (get-char-code-property char 'name)
- (get-char-code-property char 'old-name))))
-
-(provide 'compat-30)
-;;; compat-30.el ends here
+++ /dev/null
-;;; compat-autoloads.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*-
-;; Generated by the `loaddefs-generate' function.
-
-;; This file is part of GNU Emacs.
-
-;;; Code:
-
-(add-to-list 'load-path (or (and load-file-name (directory-file-name (file-name-directory load-file-name))) (car load-path)))
-
-
-\f
-;;; Generated autoloads from compat.el
-
-(register-definition-prefixes "compat" '("compat-"))
-
-\f
-;;; Generated autoloads from compat-macs.el
-
-(register-definition-prefixes "compat-macs" '("compat-"))
-\f
-;;; End of scraped data
-
-(provide 'compat-autoloads)
-
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; no-native-compile: t
-;; coding: utf-8-emacs-unix
-;; End:
-
-;;; compat-autoloads.el ends here
+++ /dev/null
-;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: 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:
-
-;; WARNING: This file provides *internal* macros. The macros are used
-;; by Compat to facilitate the definition of compatibility functions,
-;; compatibility macros and compatibility variables. The
-;; `compat-macs' feature should never be loaded at runtime in your
-;; Emacs and will only be used during byte compilation. Every
-;; definition provided here is internal, may change any time between
-;; Compat releases and must not be used by other packages.
-
-;;; Code:
-
-;; We always require subr-x at compile time for the fboundp check
-;; since definitions have been moved around. The cl-lib macros are
-;; needed by compatibility definitions.
-(require 'subr-x)
-(require 'cl-lib)
-
-(defvar compat-macs--version nil
- "Version of the currently defined compatibility definitions.")
-
-(defun compat-macs--strict (cond &rest error)
- "Assert strict COND, otherwise fail with ERROR."
- (when (bound-and-true-p compat-strict)
- (apply #'compat-macs--assert cond error)))
-
-(defun compat-macs--assert (cond &rest error)
- "Assert COND, otherwise fail with ERROR."
- (unless cond (apply #'error error)))
-
-(defun compat-macs--docstring (type name docstring)
- "Format DOCSTRING for NAME of TYPE.
-Prepend compatibility notice to the actual documentation string."
- (with-temp-buffer
- (insert
- (format
- "[Compatibility %s for `%s', defined in Emacs %s. \
-See (compat) Emacs %s' for more details.]\n\n%s"
- type name compat-macs--version compat-macs--version docstring))
- (let ((fill-column 80))
- (fill-region (point-min) (point-max)))
- (buffer-string)))
-
-(defun compat-macs--check-attributes (attrs preds)
- "Check ATTRS given PREDS predicate plist and return rest."
- (while (keywordp (car attrs))
- (compat-macs--assert (cdr attrs) "Attribute list length is odd")
- (compat-macs--assert (let ((p (plist-get preds (car attrs))))
- (and p (or (eq p t) (funcall p (cadr attrs)))))
- "Invalid attribute %s" (car attrs))
- (setq attrs (cddr attrs)))
- attrs)
-
-(defun compat-macs--guard (attrs preds fun)
- "Guard compatibility definition generation.
-The version constraints specified by ATTRS are checked. PREDS is
-a plist of predicates for arguments which are passed to FUN."
- (declare (indent 2))
- (compat-macs--assert compat-macs--version "No `compat-version' was declared")
- (let* ((body (compat-macs--check-attributes
- attrs `(,@preds :feature symbolp)))
- (feature (plist-get attrs :feature))
- (attrs `(:body ,body ,@attrs))
- args)
- ;; Require feature at compile time
- (when feature
- (compat-macs--assert (not (eq feature 'subr-x)) "Invalid feature subr-x")
- (require feature))
- ;; The current Emacs must be older than the currently declared version.
- (when (version< emacs-version compat-macs--version)
- (while preds
- (push (plist-get attrs (car preds)) args)
- (setq preds (cddr preds)))
- (setq body (apply fun (nreverse args)))
- (if (and feature body)
- `(with-eval-after-load ',feature ,@body)
- (macroexp-progn body)))))
-
-(defun compat-macs--defun (type name arglist docstring rest)
- "Define function NAME of TYPE with ARGLIST and DOCSTRING.
-REST are attributes and the function BODY."
- (compat-macs--guard
- rest (list :extended (lambda (x) (or (booleanp x) (version-to-list x)))
- :obsolete (lambda (x) (or (booleanp x) (stringp x)))
- :body t)
- (lambda (extended obsolete body)
- (when (stringp extended)
- (compat-macs--assert
- (and (version< extended compat-macs--version) (version< "24.4" extended))
- "Invalid :extended version %s for %s %s" extended type name)
- (setq extended (version<= extended emacs-version)))
- (compat-macs--strict (eq extended (fboundp name))
- "Wrong :extended flag for %s %s" type name)
- ;; Remove unsupported declares. It might be possible to set these
- ;; properties otherwise. That should be looked into and implemented
- ;; if it is the case.
- (when (and (listp (car-safe body)) (eq (caar body) 'declare) (<= emacs-major-version 25))
- (setcar body (assq-delete-all 'pure (assq-delete-all
- 'side-effect-free (car body)))))
- ;; Use `:extended' name if the function is already defined.
- (let* ((defname (if (and extended (fboundp name))
- (intern (format "compat--%s" name))
- name))
- (def `(,(if (memq '&key arglist)
- (if (eq type 'macro) 'cl-defmacro 'cl-defun)
- (if (eq type 'macro) 'defmacro 'defun))
- ,defname ,arglist
- ,(compat-macs--docstring type name docstring)
- ,@body)))
- `(,@(if (eq defname name)
- ;; An additional fboundp check is performed at runtime to make
- ;; sure that we never redefine an existing definition if Compat
- ;; is loaded on a newer Emacs version. Declare the function,
- ;; such that the byte compiler does not complain about possibly
- ;; missing functions at runtime. The warnings are generated due
- ;; to the fboundp check.
- `((declare-function ,name nil)
- (unless (fboundp ',name) ,def))
- (list def))
- ,@(when obsolete
- `((make-obsolete
- ',defname ,(if (stringp obsolete) obsolete "No substitute")
- ,compat-macs--version))))))))
-
-(defmacro compat-guard (cond &rest rest)
- "Guard definition with a runtime COND and a version check.
-The runtime condition must make sure that no definition is
-overridden. REST is an attribute plist followed by the definition
-body. The attributes specify the conditions under which the
-definition is generated.
-
-- :feature :: Wrap the definition with `with-eval-after-load' for
- the given feature."
- (declare (debug ([&rest keywordp sexp] def-body))
- (indent 1))
- (compat-macs--guard rest '(:body t)
- (lambda (body)
- (compat-macs--assert body "The guarded body is empty")
- (if (eq cond t)
- body
- (compat-macs--strict (eval cond t) "Guard %S failed" cond)
- `((when ,cond ,@body))))))
-
-(defmacro compat-defalias (name def &rest attrs)
- "Define compatibility alias NAME as DEF.
-ATTRS is a plist of attributes, which specify the conditions
-under which the definition is generated.
-
-- :obsolete :: Mark the alias as obsolete if t.
-
-- :feature :: See `compat-guard'."
- (declare (debug (name symbolp [&rest keywordp sexp])))
- (compat-macs--guard attrs '(:obsolete booleanp)
- (lambda (obsolete)
- (compat-macs--strict (not (fboundp name)) "%s already defined" name)
- ;; The fboundp check is performed at runtime to make sure that we never
- ;; redefine an existing definition if Compat is loaded on a newer Emacs
- ;; version.
- `((unless (fboundp ',name)
- (defalias ',name ',def
- ,(compat-macs--docstring 'function name
- (get name 'function-documentation)))
- ,@(when obsolete
- `((make-obsolete ',name ',def ,compat-macs--version))))))))
-
-(defmacro compat-defun (name arglist docstring &rest rest)
- "Define compatibility function NAME with arguments ARGLIST.
-The function must be documented in DOCSTRING. REST is an
-attribute plist followed by the function body. The attributes
-specify the conditions under which the definition is generated.
-
-- :extended :: Mark the function as extended if t. The function
- must be called explicitly via `compat-call'. This attribute
- should be used for functions which extend already existing
- functions, e.g., functions which changed their calling
- convention or their behavior. The value can also be a version
- string, which specifies the Emacs version when the original
- version of the function was introduced.
-
-- :obsolete :: Mark the function as obsolete if t, can be a
- string describing the obsoletion.
-
-- :feature :: See `compat-guard'."
- (declare (debug (&define name (&rest symbolp)
- stringp
- [&rest keywordp sexp]
- def-body))
- (doc-string 3) (indent 2))
- (compat-macs--defun 'function name arglist docstring rest))
-
-(defmacro compat-defmacro (name arglist docstring &rest rest)
- "Define compatibility macro NAME with arguments ARGLIST.
-The macro must be documented in DOCSTRING. REST is an attribute
-plist followed by the macro body. See `compat-defun' for
-details."
- (declare (debug compat-defun) (doc-string 3) (indent 2))
- (compat-macs--defun 'macro name arglist docstring rest))
-
-(defmacro compat-defvar (name initval docstring &rest attrs)
- "Define compatibility variable NAME with initial value INITVAL.
-The variable must be documented in DOCSTRING. ATTRS is a plist
-of attributes, which specify the conditions under which the
-definition is generated.
-
-- :constant :: Mark the variable as constant if t.
-
-- :risky :: Mark the variable as risky if t.
-
-- :local :: Make the variable buffer-local if t. If the value is
- `permanent' make the variable additionally permanently local.
-
-- :obsolete :: Mark the variable as obsolete if t, can be a
- string describing the obsoletion.
-
-- :feature :: See `compat-guard'."
- (declare (debug (name form stringp [&rest keywordp sexp]))
- (doc-string 3) (indent 2))
- (compat-macs--guard
- attrs (list :constant #'booleanp
- :risky #'booleanp
- :local (lambda (x) (memq x '(nil t permanent)))
- :obsolete (lambda (x) (or (booleanp x) (stringp x))))
- (lambda (constant risky local obsolete)
- (compat-macs--strict (not (boundp name)) "%s already defined" name)
- (compat-macs--assert (not (and constant local)) "Both :constant and :local")
- (compat-macs--assert (not (and local risky)) "Both :risky and :local")
- ;; The boundp check is performed at runtime to make sure that we never
- ;; redefine an existing definition if Compat is loaded on a newer Emacs
- ;; version.
- `((defvar ,name)
- (unless (boundp ',name)
- (,(if constant 'defconst 'defvar)
- ,name ,initval
- ,(compat-macs--docstring 'variable name docstring))
- ,@(when obsolete
- `((make-obsolete-variable
- ',name ,(if (stringp obsolete) obsolete "No substitute")
- ,compat-macs--version))))
- ,@(and local `((make-variable-buffer-local ',name)))
- ,@(and risky `((put ',name 'risky-local-variable t)))
- ,@(and (eq local 'permanent) `((put ',name 'permanent-local t)))))))
-
-(defmacro compat-version (version)
- "Set the Emacs version that is currently being handled to VERSION."
- (setq compat-macs--version version)
- nil)
-
-(defmacro compat-require (feature version)
- "Require FEATURE if the Emacs version is less than VERSION."
- (when (version< emacs-version version)
- (require feature)
- `(require ',feature)))
-
-(provide 'compat-macs)
-;;; compat-macs.el ends here
+++ /dev/null
-;; Generated package description from .el -*- compatno-byte-compile: t -*-
-(define-package "compat" "30.1.0.0" "Emacs Lisp Compatibility Library" '((emacs "24.4") (seq "2.23")) :commit "7179960b7c82a7cca6bac60d79dd7fe09ae390a0" :authors '(("Philip Kaludercic" . "philipkNOSPAMposteo.net") ("Daniel Mendler" . "mailNOSPAMdaniel-mendler.de")) :maintainer '("Compat Development" . "~pkal/compat-develNOSPAMlists.sr.ht") :keywords '("lisp" "maint") :url "https://github.com/emacs-compat/compat")
+++ /dev/null
-;;; compat.el --- Emacs Lisp Compatibility Library -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2021-2025 Free Software Foundation, Inc.
-
-;; Author: Philip Kaludercic <philipkNOSPAMposteo.net>, Daniel Mendler <mailNOSPAMdaniel-mendler.de>
-;; Maintainer: Compat Development <~pkal/compat-develNOSPAMlists.sr.ht>
-;; Version: 30.1.0.0
-;; URL: https://github.com/emacs-compat/compat
-;; Package-Requires: ((emacs "24.4") (seq "2.23"))
-;; Keywords: lisp, maint
-
-;; 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:
-
-;; Compat is the Elisp forwards compatibility library, which provides
-;; definitions introduced in newer Emacs versions. The definitions
-;; are only installed if necessary for your current Emacs version. If
-;; Compat is compiled on a recent version of Emacs, all of the
-;; definitions are disabled at compile time, such that no negative
-;; performance impact is incurred. The provided compatibility
-;; implementations of functions and macros are at least subsets of the
-;; actual implementations. Be sure to read the documentation string
-;; and the Compat manual.
-;;
-;; Not every function provided in newer versions of Emacs is provided
-;; here. Some depend on new features from the C core, others cannot
-;; be implemented to a meaningful degree. Please consult the Compat
-;; manual for details regarding the usage of the Compat library and
-;; the provided functionality.
-
-;; The main audience for this library are not regular users, but
-;; package maintainers. Therefore no commands, user-facing modes or
-;; user options are implemented here.
-
-;;; Code:
-
-;; Ensure that the newest compatibility layer is required at compile
-;; time and runtime, but only if needed.
-(eval-when-compile
- (defmacro compat--maybe-require ()
- (when (version< emacs-version "30.1")
- (require 'compat-30)
- '(require 'compat-30))))
-(compat--maybe-require)
-
-;;;; Macros for extended compatibility function calls
-
-(defmacro compat-function (fun)
- "Return compatibility function symbol for FUN.
-
-If the Emacs version provides a sufficiently recent version of
-FUN, the symbol FUN is returned itself. Otherwise the macro
-returns the symbol of a compatibility function which supports the
-behavior and calling convention of the current stable Emacs
-version. For example Compat 29.1 will provide compatibility
-functions which implement the behavior and calling convention of
-Emacs 29.1.
-
-See also `compat-call' to directly call compatibility functions."
- (let ((compat (intern (format "compat--%s" fun))))
- `#',(if (fboundp compat) compat fun)))
-
-(defmacro compat-call (fun &rest args)
- "Call compatibility function or macro FUN with ARGS.
-
-A good example function is `plist-get' which was extended with an
-additional predicate argument in Emacs 29.1. The compatibility
-function, which supports this additional argument, can be
-obtained via (compat-function plist-get) and called
-via (compat-call plist-get plist prop predicate). It is not
-possible to directly call (plist-get plist prop predicate) on
-Emacs older than 29.1, since the original `plist-get' function
-does not yet support the predicate argument. Note that the
-Compat library never overrides existing functions.
-
-See also `compat-function' to lookup compatibility functions."
- (let ((compat (intern (format "compat--%s" fun))))
- `(,(if (fboundp compat) compat fun) ,@args)))
-
-(provide 'compat)
-;;; compat.el ends here
+++ /dev/null
-This is docdzgy5X.info, produced by makeinfo version 6.8 from
-compat.texi.
-
-Copyright © 2022-2025 Free Software Foundation, Inc.
-
- Permission is granted to copy, distribute and/or modify this
- document under the terms of the GNU Free Documentation License,
- Version 1.3 or any later version published by the Free Software
- Foundation; with no Invariant Sections, with the Front-Cover Texts
- being “A GNU Manual,” and with the Back-Cover Texts as in (a)
- below. A copy of the license is included in the section entitled
- “GNU Free Documentation License.”
-
- (a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
- modify this GNU manual.”
-
-INFO-DIR-SECTION Emacs
-START-INFO-DIR-ENTRY
-* Compat: (compat). Compatibility Library for Emacs Lisp.
-END-INFO-DIR-ENTRY
-
-\1f
-File: docdzgy5X.info, Node: Top, Next: Introduction, Up: (dir)
-
-"Compat" Manual
-***************
-
-This manual documents the usage of the "Compat" Emacs lisp library, the
-forward-compatibility library for Emacs Lisp, corresponding to version
-30.1.0.0.
-
- Copyright © 2022-2025 Free Software Foundation, Inc.
-
- Permission is granted to copy, distribute and/or modify this
- document under the terms of the GNU Free Documentation License,
- Version 1.3 or any later version published by the Free Software
- Foundation; with no Invariant Sections, with the Front-Cover Texts
- being “A GNU Manual,” and with the Back-Cover Texts as in (a)
- below. A copy of the license is included in the section entitled
- “GNU Free Documentation License.”
-
- (a) The FSF’s Back-Cover Text is: “You have the freedom to copy and
- modify this GNU manual.”
-
-* Menu:
-
-* Introduction::
-* Support::
-* Development::
-* Function Index::
-* Variable Index::
-
-— The Detailed Node Listing —
-
-Introduction
-
-* Overview::
-* Usage::
-* Limitations::
-
-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
-* Emacs 29.1:: Compatibility support for Emacs 29.1
-* Emacs 30.1:: Compatibility support for Emacs 30.1
-
-
-\1f
-File: docdzgy5X.info, Node: Introduction, Next: Support, Prev: Top, Up: Top
-
-1 Introduction
-**************
-
-* Menu:
-
-* Overview::
-* Usage::
-* Limitations::
-
-\1f
-File: docdzgy5X.info, Node: Overview, Next: Usage, Up: Introduction
-
-1.1 Overview
-============
-
-The objective of Compat is to provide "forwards compatibility" library
-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
-audience are package developers that are interested in using newer
-developments, without having to break compatibility.
-
-\1f
-File: docdzgy5X.info, Node: Usage, Next: Limitations, Prev: Overview, Up: Introduction
-
-1.2 Usage
-=========
-
-The intended use-case for this library is for package developers to add
-as a dependency in the header. The version of the Compat library
-mirrors the version of Emacs releases. The current version of Compat
-corresponds to the current Emacs release.
-
- ;; Package-Requires: ((emacs "24.4") (compat "30.1.0.0"))
-
- There is no need to depend on ‘emacs 24.4’ specifically. One can
-choose any newer version, if features not provided by Compat necessitate
-it, for example bug fixes or UI improvements.
-
- In any file where compatibility forms are used, a
-
- (require 'compat)
-
- should be added early on. This will load all necessary Compat
-definitions. Compat loads the ‘seq’ library which is preloaded by
-default on Emacs 29. Note that if Compat is installed on a recent
-version of Emacs, all of the definitions are disabled at compile time,
-such that no negative performance impact is incurred.
-
- A minimal version of Compat will be present in Emacs version 30 and
-newer. Packages which are part of Emacs itself and want to take
-advantage of Compat, can also use ‘(require 'compat)’. The advantage of
-the inclusion of a minimal Compat in Emacs is that Compat will not be
-installed if you require a version older or equal than the current Emacs
-version. For example, if a package depending on Emacs 25.1 and Compat
-29.1 is installed on Emacs 30.1, Compat will not be pulled in as
-dependency, since Emacs 30.1 already provides the required
-functionality.
-
- Compat provides replacement functions with extended functionality for
-functions that are already defined, e.g., ‘sort’ or ‘assoc’. These
-functions may have changed their calling convention (additional optional
-arguments) or may have changed their behavior. These functions must be
-looked up explicitly with ‘compat-function’ or called explicitly with
-‘compat-call’. We call them “Extended Definitions”. In contrast, newly
-“Added Definitions” can be called as usual. The Compat manual
-explicitly documents the calling convention of each compatibility
-function.
-
- (compat-call assoc key alist testfn) ;; Call extended `assoc'
- (mapcan fun seq) ;; Call newly added `mapcan'
-
- -- Macro: compat-call fun &rest args
- This macro calls the compatibility function FUN with ARGS. Many
- functions provided by Compat can be called directly without this
- macro. However in the case where Compat provides an alternative
- version of an existing function, the function call has to go
- through ‘compat-call’. This happens for example when the calling
- convention of a function has changed.
-
- -- Macro: compat-function fun
- This macro returns the compatibility function symbol for FUN. See
- ‘compat-call’ for a more convenient macro to directly call
- compatibility functions.
-
- If Compat is used in Emacs core packages, the macros ‘compat-call’
-and ‘compat-function’ will be available in Emacs version 30 and newer.
-
- The macros ‘compat-call’ and ‘compat-function’ are introduced by
-Compat, since Compat does not advise or override existing functions.
-Generally Compat is written in defensive style which is supposed to
-reduce potential breakage, and to increase the chances of staying binary
-compatible across releases. The extensive test coverage ensures that we
-can maintain high quality, which is crucial for Compat which is not
-restricted to a namespace like usual libraries.
-
- If you intend to use a compatibility function in your code it is
-recommended that you take a look at the test suite ‘compat-tests.el’.
-There you can see the supported calling conventions, which are
-guaranteed to work on the supported Emacs versions. We ensure this
-using continuous integration. All functions provided by Compat are
-covered by the test suite. There is a link to the corresponding test on
-the first line of each definition.
-
- You may want to subscribe to the compat-announce
-(https://lists.sr.ht/~pkal/compat-announce) mailing list to be notified
-when new versions are released or relevant changes are made. We also
-provide a development mailing list
-(https://lists.sr.ht/~pkal/compat-devel) (~pkal/compat-develNOSPAMlists.sr.ht
-<~pkal/compat-develNOSPAMlists.sr.ht>).
-
-\1f
-File: docdzgy5X.info, Node: Limitations, Prev: Usage, Up: Introduction
-
-1.3 Limitations
-===============
-
-The Compat library has a number of limitations. Complete backwards
-compatibility cannot be provided due to the scope of Compat and for
-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.
-Supporting for more historical Emacs versions would complicate
-maintenance while only few packages and users would benefit.
-
- Below we list a number of reasons why certain functionality cannot be
-provided. Note that in some special cases exceptions can be made and
-functions can still be added to Compat even if they satisfy the criteria
-from the list. In case you miss functionality which you think should
-belong here, a *note report: Development. would be much appreciated.
-
- • The additional functionality is a command or a user-facing minor or
- major mode. Compat is limited to functionality on the “library
- level”. Generally functions provided by Compat are
- non-interactive, such that the user interface (M-x) is unaffected
- by the presence of Compat.
-
- • The function is not useful for package authors or not intended to
- be used by packages, but is only useful on the configuration level.
- The macro ‘setopt’ is such an example.
-
- • Private (double dashed) functions are not ported back. If Compat
- includes some private functions, they are meant purely for internal
- usage.
-
- • The added or extended function belongs to the “application level”
- and not the “library level”. Features which are not preloaded
- often belong to the “application level”. Application examples are
- programming modes or modes like Dired, IRC and Gnus. If these
- modes are extended with new functions, these are not ported back.
-
- • An existing function or macro was extended by some new
- functionality. To support these cases, the function or macro would
- have to be advised. Since this is invasive and adds significant
- overhead, even when the new feature is not used, Compat does not
- use advices. As a compromise, compatibility functions and macros
- with a changed calling convention or behavior can be accessed via
- the ‘compat-function’ and ‘compat-call’ macros. In this manual we
- call such definitions “Extended Definitions”. An example is the
- function ‘plist-get’. Note that extended functions are subject to
- closer scrutiny, since their usage via ‘compat-call’ is not
- completely painless. If a particular extended function does not
- see much usage or the extension yields only marginal benefits, we
- may not provide it as part of Compat.
-
- • Bug fixes are usually not ported back as part of Compat. Sometimes
- library functions show wrong behavior for edge cases. In those
- cases Compat could in principle provide a compatibility function
- which is invoked via ‘compat-call’. Such extended definitions
- would increase the maintenance burden of Compat. At the same time
- the benefits would be small given that Compat does not override
- existing definitions.
-
- • The definition belongs to an Emacs core package, which is also
- distributed via ELPA. Compat does not have to provide backward
- compatibility for core packages since the updated package can be
- installed directly from ELPA. Examples include the libraries xref,
- project, seq, map and transient.
-
- • New functionality depends on an entire new, non-trivial core
- library, which is infeasible to duplicate within Compat. If a
- backport of such a library is required, the preferred approach is
- to either release the library separately on GNU ELPA as a core
- package or as a separately maintained GNU ELPA package. An example
- is the iso8601 library.
-
- • New functionality was implemented in the C core, or depends on
- external libraries that cannot be reasonably duplicated in the
- scope of a compatibility library. Sometimes new functions on the C
- level rely on internal data structures, which we cannot access,
- rendering a backport impossible. For example a missing libxml or
- libtreesitter cannot be emulated.
-
- • The semantics of Elisp changed on a deep level. For example the
- addition of big integer support in Emacs 27.1 cannot be replicated
- on the level of Compat.
-
-\1f
-File: docdzgy5X.info, Node: Support, Next: Development, Prev: Introduction, Up: Top
-
-2 Support
-*********
-
-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
-* Emacs 29.1:: Compatibility support for Emacs 29.1
-* Emacs 30.1:: Compatibility support for Emacs 30.1
-
-\1f
-File: docdzgy5X.info, Node: Emacs 25.1, Next: Emacs 26.1, Up: Support
-
-2.1 Emacs 25.1
-==============
-
-2.1.1 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.
-
- -- User Option: 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 ‘curve’, the style is ‘like
- this’ with curved single quotes. If the value is ‘straight’, the
- style is 'like this' with straight apostrophes. If the value is
- ‘grave’, quotes are not translated and the style is `like this'
- with grave accent and apostrophe, the standard style before Emacs
- version 25. The default value ‘nil’ acts like ‘curve’ if curved
- single quotes seem to be displayable, and like ‘grave’ otherwise.
-
- This option is useful on platforms that have problems with curved
- quotes. You can customize it freely according to your personal
- preference.
-
- -- Function: region-bounds
- Return the boundaries of the region. 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’.
-
- -- Function: 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.
-
- -- Macro: save-mark-and-excursion body...
- This macro is like ‘save-excursion’, but also saves and restores
- the mark location and ‘mark-active’. This macro does what
- ‘save-excursion’ did before Emacs 25.1.
-
- -- Function: format-message string &rest objects
- This function acts like ‘format’, except it also converts any grave
- accents (`) and apostrophes (') in STRING as per the value of
- ‘text-quoting-style’.
-
- Typically grave accent and apostrophe in the format translate to
- matching curved quotes, e.g., "Missing `%s'" might result in
- "Missing ‘foo’". *Note (elisp)Text Quoting Style::, for how to
- influence or inhibit this translation.
-
- *note (elisp)Formatting Strings::.
-
- -- Function: directory-name-p filename
- This function returns non-‘nil’ if FILENAME ends with a directory
- separator character. This is the forward slash ‘/’ on GNU and
- other POSIX-like systems; MS-Windows and MS-DOS recognize both the
- forward slash and the backslash ‘\’ as directory separators.
-
- *Note (elisp)Directory Names::.
-
- -- Function: string-greaterp string1 string2
- This function returns the result of comparing STRING1 and STRING2
- in the opposite order, i.e., it is equivalent to calling
- ‘(string-lessp STRING2 STRING1)’.
-
- *Note (elisp)Text Comparison::.
-
- -- Macro: with-file-modes mode body...
- This macro evaluates the BODY forms with the default permissions
- for new files temporarily set to MODES (whose value is as for
- ‘set-file-modes’ above). When finished, it restores the original
- default file permissions, and returns the value of the last form in
- BODY.
-
- This is useful for creating private files, for example.
-
- *Note (elisp)Changing Files::.
-
- -- Function: alist-get key alist &optional default remove
- This function is similar to ‘assq’. It finds the first association
- ‘(KEY . VALUE)’ by comparing KEY with ALIST elements, and, if
- found, returns the VALUE of that association. If no association is
- found, the function returns DEFAULT.
-
- This is a generalized variable (*note (elisp)Generalized
- Variables::) that can be used to change a value with ‘setf’. When
- using it to set a value, optional argument REMOVE non-‘nil’ means
- to remove KEY’s association from ALIST if the new value is ‘eql’ to
- DEFAULT.
-
- *note (elisp)Association Lists::.
-
- -- Macro: if-let (bindings...) then &rest else...
- As with ‘let*’, BINDINGS will consist of ‘(SYMBOL VALUE-FORM)’
- entries that are evaluated and bound sequentially. If all
- VALUE-FORM evaluate to non-‘nil’ values, then THEN is evaluated as
- were the case with a regular ‘let*’ expression, with all the
- variables bound. If any VALUE-FORM evaluates to ‘nil’, ELSE is
- evaluated, without any bound variables.
-
- A binding may also optionally drop the SYMBOL, and simplify to
- ‘(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:
-
- (if-let* (SYMBOL (test)) foo bar)
- ≡
- (if-let* ((SYMBOL (test))) foo bar)
-
- -- Macro: when-let (bindings...) &rest body
- As with ‘when’, if one is only interested in the case where all
- BINDINGS are non-nil. Otherwise BINDINGS are interpreted just as
- they are by ‘if-let*’.
-
- -- Function: hash-table-empty hash-table
- Check whether HASH-TABLE is empty (has 0 elements).
-
- -- Macro: thread-first &rest forms
- Combine FORMS into a single expression by “threading” each element
- as the _first_ argument of their successor. Elements of FORMS can
- either be an list of an atom.
-
- For example, consider the threading expression and it’s equivalent
- macro expansion:
-
- (thread-first
- 5
- (+ 20)
- (/ 25)
- -
- (+ 40))
- ≡
- (+ (- (/ (+ 5 20) 25)) 40)
-
- Note how the single ‘-’ got converted into a list before threading.
- This example uses arithmetic functions, but ‘thread-first’ is not
- restricted to arithmetic or side-effect free code.
-
- -- Macro: thread-last &rest forms
- Combine FORMS into a single expression by “threading” each element
- as the _last_ argument of their successor. Elements of FORMS can
- either be an list of an atom.
-
- For example, consider the threading expression and it’s equivalent
- macro expansion:
-
- (thread-first
- 5
- (+ 20)
- (/ 25)
- -
- (+ 40))
- ≡
- (+ 40 (- (/ 25 (+ 20 5))))
-
- Note how the single ‘-’ got converted into a list before threading.
- This example uses arithmetic functions, but ‘thread-last’ is not
- restricted to arithmetic or side-effect free code.
-
- -- Function: macroexpand-1 form &optional environment
- This function expands macros like ‘macroexpand’, but it only
- performs one step of the expansion: if the result is another macro
- call, ‘macroexpand-1’ will not expand it.
-
- *Note Expansion: (elisp)Expansion.
-
- -- Function: macroexp-quote e
- Return an expression E such that ‘(eval e)’ is V.
-
- -- Function: macroexp-parse body
- Parse a function BODY into ‘(declarations . exps)’.
-
- -- Function: bool-vector &rest objects
- This function creates and returns a bool-vector whose elements are
- the arguments, OBJECTS.
-
- *Note (elisp)Bool-Vectors::.
-
-2.1.2 Missing Definitions
--------------------------
-
-Compat does not provide support for the following Lisp features
-implemented in 25.1:
-
- • The function ‘macroexp-macroexpand’.
- • The macro ‘macroexp-let2*’.
- • The function ‘directory-files-recursively’.
- • New ‘pcase’ patterns.
- • The hook ‘prefix-command-echo-keystrokes-functions’ and
- ‘prefix-command-preserve-state-hook’.
- • The hook ‘pre-redisplay-functions’.
- • The function ‘make-process’.
- • Support for the variable ‘inhibit-message’.
- • The ‘define-inline’ functionality.
- • The functions ‘string-collate-lessp’ and ‘string-collate-equalp’.
- • The function ‘funcall-interactively’.
- • The function ‘buffer-substring-with-bidi-context’.
- • The function ‘font-info’.
- • The function ‘default-font-width’.
- • The function ‘window-font-height’ and ‘window-font-width’.
- • The function ‘window-max-chars-per-line’.
- • The function ‘set-binary-mode’.
- • The functions ‘bufferpos-to-filepos’ and ‘filepos-to-bufferpos’.
- • The ‘thunk’ library.
-
-\1f
-File: docdzgy5X.info, Node: Emacs 26.1, Next: Emacs 27.1, Prev: Emacs 25.1, Up: Support
-
-2.2 Emacs 26.1
-==============
-
-2.2.1 Added Definitions
------------------------
-
-The following functions and macros are implemented in Emacs 26.1. These
-functions are made available by Compat on Emacs versions older than
-26.1.
-
- -- Function: assoc-delete-all key alist
- This function is like ‘assq-delete-all’ except that it uses ‘equal’
- to compare elements.
-
- -- Function: read-answer question answers
- This function prompts the user with text in QUESTION, which should
- end in the ‘SPC’ character. The function includes in the prompt
- the possible responses in ANSWERS by appending them to the end of
- QUESTION. The possible responses are provided in ANSWERS as an
- alist whose elements are of the following form:
-
- (LONG-ANSWER SHORT-ANSWER HELP-MESSAGE)
-
- where LONG-ANSWER is the complete text of the user response, a
- string; SHORT-ANSWER is a short form of the same response, a single
- character or a function key; and HELP-MESSAGE is the text that
- describes the meaning of the answer. If the variable
- ‘read-answer-short’ is non-‘nil’, the prompt will show the short
- variants of the possible answers and the user is expected to type
- the single characters/keys shown in the prompt; otherwise the
- prompt will show the long variants of the answers, and the user is
- expected to type the full text of one of the answers and end by
- pressing <RET>. If ‘use-dialog-box’ is non-‘nil’, and this
- function was invoked by mouse events, the question and the answers
- will be displayed in a GUI dialog box.
-
- The function returns the text of the LONG-ANSWER selected by the
- user, regardless of whether long or short answers were shown in the
- prompt and typed by the user.
-
- Here is an example of using this function:
-
- (let ((read-answer-short t))
- (read-answer "Foo "
- '(("yes" ?y "perform the action")
- ("no" ?n "skip to the next")
- ("all" ?! "perform for the rest without more questions")
- ("help" ?h "show help")
- ("quit" ?q "exit"))))
-
- -- Function: mapcan function sequence
- This function applies FUNCTION to each element of SEQUENCE, like
- ‘mapcar’, but instead of collecting the results into a list, it
- returns a single list with all the elements of the results (which
- must be lists), by altering the results (using ‘nconc’; *note
- (elisp)Rearrangement::). Like with ‘mapcar’, SEQUENCE can be of
- any type except a char-table.
-
- ;; Contrast this: (mapcar #'list '(a b c d)) ⇒ ((a) (b) (c)
- (d)) ;; with this: (mapcan #'list '(a b c d)) ⇒ (a b c d)
-
- *Note (elisp)Mapping Functions::.
-
- -- Function: cXXXr
- -- Function: cXXXXr
- *Note (elisp)List Elements::.
-
- -- Function: gensym &optional prefix
- This function returns a symbol using ‘make-symbol’, whose name is
- made by appending ‘gensym-counter’ to PREFIX and incrementing that
- counter, guaranteeing that no two calls to this function will
- generate a symbol with the same name. The prefix defaults to
- ‘"g"’.
-
- -- Variable: gensym-counter
- See ‘gensym’.
-
- -- Function: buffer-hash &optional buffer-or-name
- Return a hash of BUFFER-OR-NAME. If ‘nil’, this defaults to the
- current buffer. As opposed to ‘secure-hash’, this function
- computes the hash based on the internal representation of the
- buffer, disregarding any coding systems. It’s therefore only
- useful when comparing two buffers running in the same Emacs, and is
- not guaranteed to return the same hash between different Emacs
- versions. It should be somewhat more efficient on larger buffers
- than ‘secure-hash’ is, and should not allocate more memory.
-
- -- Macro: file-name-unquote name
- This macro removes the quotation prefix ‘/:’ from the file NAME, if
- any. If NAME is a remote file name, the local part of NAME is
- unquoted.
-
- -- Function: file-name-quoted-p name
- This macro returns non-‘nil’, when NAME is quoted with the prefix
- ‘/:’. If NAME is a remote file name, the local part of NAME is
- checked.
-
- *Note (elisp)File Name Expansion::.
-
- -- Function: file-name-quote name
- This macro adds the quotation prefix ‘/:’ to the file NAME. For a
- local file NAME, it prefixes NAME with ‘/:’. If NAME is a remote
- file name, the local part of NAME (*note (elisp)Magic File Names::)
- is quoted. If NAME is already a quoted file name, NAME is returned
- unchanged.
-
- (substitute-in-file-name (compat-call file-name-quote "bar/~/foo")) ⇒
- "/:bar/~/foo"
-
- (substitute-in-file-name (compat-call file-name-quote "/ssh:host:bar/~/foo"))
- ⇒ "/ssh:host:/:bar/~/foo"
-
- The macro cannot be used to suppress file name handlers from magic
- file names (*note (elisp)Magic File Names::).
-
- *Note (elisp)File Name Expansion::.
-
- -- Function: make-nearby-temp-file prefix &optional dir-flag suffix
- This function is similar to ‘make-temp-file’, but it creates a
- temporary file as close as possible to ‘default-directory’. If
- PREFIX is a relative file name, and ‘default-directory’ is a remote
- file name or located on a mounted file systems, the temporary file
- is created in the directory returned by the function
- ‘temporary-file-directory’. Otherwise, the function
- ‘make-temp-file’ is used. PREFIX, DIR-FLAG and SUFFIX have the
- same meaning as in ‘make-temp-file’.
-
- (let ((default-directory "/ssh:remotehost:")) (make-nearby-temp-file
- "foo")) ⇒ "/ssh:remotehost:/tmp/foo232J6v"
-
- -- Variable: mounted-file-systems
- A regular expression matching files names that are probably on a
- mounted file system.
-
- -- Function: temporary-file-directory
- The directory for writing temporary files via
- ‘make-nearby-temp-file’. In case of a remote ‘default-directory’,
- this is a directory for temporary files on that remote host. If
- such a directory does not exist, or ‘default-directory’ ought to be
- located on a mounted file system (see ‘mounted-file-systems’), the
- function returns ‘default-directory’. For a non-remote and
- non-mounted ‘default-directory’, the value of the variable
- ‘temporary-file-directory’ is returned.
-
- *Note (elisp)Unique File Names::.
-
- -- Macro: if-let* (bindings...) then &rest else
- ‘if-let*’ is mostly equivalent to ‘if-let’, with the exception that
- the legacy ‘(if (VAR (test)) foo bar)’ syntax is not permitted.
-
- -- Macro: when-let* (bindings...) then &rest else
- ‘when-let*’ is mostly equivalent to ‘when-let’, with the exception
- that the legacy ‘(when-let (VAR (test)) foo bar)’ syntax is not
- permitted.
-
- -- Macro: and-let* (bindings...) &rest body
- A combination of LET* and AND, analogous to ‘when-let*’. If all
- BINDINGS are non-‘nil’ and BODY is ‘nil’, then the result of the
- ‘and-let*’ form will be the last value bound in BINDINGS.
-
- **Please Note:** The implementation provided by Compat does not
- include a bug that was observed with Emacs 26 (see
- <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31840>).
-
- -- Function: file-local-name filename
- This function returns the _local part_ of FILENAME. This is the
- part of the file’s name that identifies it on the remote host, and
- is typically obtained by removing from the remote file name the
- parts that specify the remote host and the method of accessing it.
- For example:
-
- (file-local-name "/ssh:USER@HOST:/foo/bar") ⇒
- "/foo/bar"
-
- For a remote FILENAME, this function returns a file name which
- could be used directly as an argument of a remote process (*note
- (elisp)Asynchronous Processes::, and *note (elisp)Synchronous
- Processes::), and as the program to run on the remote host. If
- FILENAME is local, this function returns it unchanged.
-
- *Note (elisp)Magic File Names::.
-
- -- Function: read-multiple-choice prompt choices
- Ask user a multiple choice question. PROMPT should be a string
- that will be displayed as the prompt.
-
- CHOICES is an alist where the first element in each entry is a
- character to be entered, the second element is a short name for the
- entry to be displayed while prompting (if there’s room, it might be
- shortened), and the third, optional entry is a longer explanation
- that will be displayed in a help buffer if the user requests more
- help.
-
- See *note Reading One Event: (elisp)Reading One Event.
-
- -- Function: image-property
- Defined in ‘image.el’.
-
- This function can also be used as a generalised variable.
-
- -- Function: file-attribute-type
- Return the field _type_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-link-number
- Return the field _link-number_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-user-id
- Return the field _user-id_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-group-id
- Return the field _group-id_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-access-time
- Return the field _access-time_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-modification-time
- Return the field _modification-time_ as generated by
- ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-status-change-time
- Return the field _modification-time_ as generated by
- ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-size
- Return the field _size_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-modes
- Return the field _modes_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-inode-number
- Return the field _inode-number_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-device-number
- Return the field _device-number_ as generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-attribute-collect attributes &rest attr-names
- Filter the file attributes ATTRIBUTES, as generated by
- ‘file-attributes’, according to ATTR-NAMES.
-
- Valid attribute names for ATTR-NAMES are: type, link-number,
- user-id, group-id, access-time, modification-time,
- status-change-time, size, modes, inode-number and device-number.
-
- (file-attributes ".") ⇒ (t 1 1000 1000 (25329 18215 325481 96000) (25325 15364 530263 840000) (25325 15364 530263 840000) 788 "drwxr-xr-x" t 137819 40)
- (file-attribute-collect (file-attributes ".") 'type 'modes
- 'inode-number) ⇒ (t "drwxr-xr-x" 137819)
-
-2.2.2 Extended Definitions
---------------------------
-
-These functions must be called explicitly via ‘compat-call’, since their
-calling convention or behavior was extended in Emacs 26.1:
-
- -- Function: compat-call make-temp-file prefix &optional dir-flag
- suffix text
- This function creates a temporary file and returns its name. Emacs
- creates the temporary file’s name by adding to PREFIX some random
- characters that are different in each Emacs job. The result is
- guaranteed to be a newly created file, containing TEXT if that’s
- given as a string and empty otherwise. On MS-DOS, this function
- can truncate PREFIX to fit into the 8+3 file-name limits. If
- PREFIX is a relative file name, it is expanded against
- ‘temporary-file-directory’.
-
- The compatibility version adds support for handling the optional
- argument TEXT.
-
- (make-temp-file "foo")
- ⇒ "/tmp/foo232J6v"
-
- When ‘make-temp-file’ returns, the file has been created and is
- empty. At that point, you should write the intended contents into
- the file.
-
- If DIR-FLAG is non-‘nil’, ‘make-temp-file’ creates an empty
- directory instead of an empty file. It returns the file name, not
- the directory name, of that directory. *Note (elisp)Directory
- Names::.
-
- If SUFFIX is non-‘nil’, ‘make-temp-file’ adds it at the end of the
- file name.
-
- If TEXT is a string, ‘make-temp-file’ inserts it in the file.
-
- To prevent conflicts among different libraries running in the same
- Emacs, each Lisp program that uses ‘make-temp-file’ should have its
- own PREFIX. The number added to the end of PREFIX distinguishes
- between the same application running in different Emacs jobs.
- Additional added characters permit a large number of distinct names
- even in one Emacs job.
-
- -- Function: compat-call assoc key alist &optional testfn
- This function returns the first association for KEY in ALIST,
- comparing KEY against the alist elements using TESTFN if it is a
- function, and ‘equal’ otherwise (*note (elisp)Equality
- Predicates::). If TESTFN is a function, it is called with two
- arguments: the CAR of an element from ALIST and KEY. The function
- returns ‘nil’ if no association in ALIST has a CAR equal to KEY, as
- tested by TESTFN.
-
- *Note (elisp)Association Lists::.
-
- The compatibility version adds support for handling the optional
- argument TESTFN.
-
- -- Function: compat-call line-number-at-pos &optional pos absolute
- This function returns the line number in the current buffer
- corresponding to the buffer position POS. If POS is ‘nil’ or
- omitted, the current buffer position is used. If ABSOLUTE is
- ‘nil’, the default, counting starts at ‘(point-min)’, so the value
- refers to the contents of the accessible portion of the
- (potentially narrowed) buffer. If ABSOLUTE is non-‘nil’, ignore
- any narrowing and return
-
- *Note (elisp)Text Lines::.
-
- The compatibility version adds support for handling the optional
- argument ABSOLUTE.
-
- -- Function: compat-call alist-get key alist &optional default remove
- testfn
- *Note (elisp)Association Lists::. This function is similar to
- ‘assq’. It finds the first association ‘(KEY . VALUE)’ by
- comparing KEY with ALIST elements, and, if found, returns the VALUE
- of that association. If no association is found, the function
- returns DEFAULT. Comparison of KEY against ALIST elements uses the
- function specified by TESTFN, defaulting to ‘eq’.
-
- *Note (elisp)Association Lists::.
-
- The compatibility version handles the optional argument TESTFN. It
- can also be used as a *note Generalized Variables:
- (elisp)generalised variable.
-
- -- Function: compat-call string-trim-left string &optional regexp
- Remove the leading text that matches REGEXP from STRING. REGEXP
- defaults to ‘[ \t\n\r]+’.
-
- *Note (elisp)Creating Strings::.
-
- The compatibility version handles the optional argument REGEXP.
-
- -- Function: compat-call string-trim-right string &optional regexp
- Remove the trailing text that matches REGEXP from STRING. REGEXP
- defaults to ‘[ \t\n\r]+’.
-
- *Note (elisp)Creating Strings::.
-
- The compatibility version handles the optional argument REGEXP.
-
- -- Function: compat-call string-trim string &optional trim-left
- trim-right
- Remove the leading text that matches TRIM-LEFT and trailing text
- that matches TRIM-RIGHT from STRING. Both regexps default to ‘[
- \t\n\r]+’.
-
- *Note (elisp)Creating Strings::.
-
- The compatibility version handles the optional arguments TRIM-LEFT
- and TRIM-RIGHT.
-
-2.2.3 Missing Definitions
--------------------------
-
-Compat does not provide support for the following Lisp features
-implemented in 26.1:
-
- • The function ‘func-arity’.
- • The function ‘secure-hash-algorithms’.
- • The function ‘gnutls-available-p’.
- • Support for records and record functions.
- • The function ‘mapbacktrace’.
- • The function ‘file-name-case-insensitive-p’.
- • The additional elements of ‘parse-partial-sexp’.
- • The function ‘add-variable-watcher’.
- • The function ‘undo-amalgamate-change-group’.
- • The function ‘char-from-name’
- • Signalling errors when ‘length’ or ‘member’ deal with list cycles.
- • The function ‘frame-list-z-order’.
- • The function ‘frame-restack’.
- • All changes related to ‘display-buffer’.
- • The function ‘window-swap-states’.
- • The function ‘string-version-lessp’.
- • The ‘xdg’ library.
- • The ‘svg’ library (published separately as a :core package).
-
-\1f
-File: docdzgy5X.info, Node: Emacs 27.1, Next: Emacs 28.1, Prev: Emacs 26.1, Up: Support
-
-2.3 Emacs 27.1
-==============
-
-2.3.1 Added Definitions
------------------------
-
-The following functions and macros are implemented in Emacs 27.1. These
-functions are made available by Compat on Emacs versions older than
-27.1.
-
- -- Function: major-mode-suspend
- This function works like ‘fundamental-mode’, in that it kills all
- buffer-local variables, but it also records the major mode in
- effect, so that it could subsequently be restored. This function
- and ‘major-mode-restore’ (described next) are useful when you need
- to put a buffer under some specialized mode other than the one
- Emacs chooses for it automatically, but would also like to be able
- to switch back to the original mode later.
-
- -- Function: major-mode-restore &optional avoided-modes
- This function restores the major mode recorded by
- ‘major-mode-suspend’. If no major mode was recorded, this function
- calls ‘normal-mode’, but tries to force it not to choose any modes
- in AVOIDED-MODES, if that argument is non-‘nil’.
-
- -- Function: ring-resize ring size
- Set the size of RING to SIZE. If the new size is smaller, then the
- oldest items in the ring are discarded.
-
- -- Function: minibuffer-history-value
- Return the value of the minibuffer input history list. If
- MINIBUFFER-HISTORY-VARIABLE points to a buffer-local variable and
- the minibuffer is active, return the buffer-local value for the
- buffer that was current when the minibuffer was activated."
-
- -- Macro: with-minibuffer-selected-window &rest body
- Execute the forms in BODY from the minibuffer in its original
- window. When used in a minibuffer window, select the window
- selected just before the minibuffer was activated, and execute the
- forms.
-
- -- Function: read-char-from-minibuffer prompt &optional chars history
- This function uses the minibuffer to read and return a single
- character. Optionally, it ignores any input that is not a member
- of CHARS, a list of accepted characters. The HISTORY argument
- specifies the history list symbol to use; if it is omitted or
- ‘nil’, this function doesn’t use the history.
-
- If you bind ‘help-form’ to a non-‘nil’ value while calling
- ‘read-char-from-minibuffer’, then pressing ‘help-char’ causes it to
- evaluate ‘help-form’ and display the result.
-
- -- Function: bignump object
- This predicate tests whether its argument is a large integer, and
- returns ‘t’ if so, ‘nil’ otherwise. Unlike small integers, large
- integers can be ‘=’ or ‘eql’ even if they are not ‘eq’.
-
- -- Function: fixnump object
- This predicate tests whether its argument is a small integer, and
- returns ‘t’ if so, ‘nil’ otherwise. Small integers can be compared
- with ‘eq’.
-
- -- Special Form: with-suppressed-warnings warnings body...
- In execution, this is equivalent to ‘(progn BODY...)’, but the
- compiler does not issue warnings for the specified conditions in
- BODY. WARNINGS is an association list of warning symbols and
- function/variable symbols they apply to. For instance, if you wish
- to call an obsolete function called ‘foo’, but want to suppress the
- compilation warning, say:
-
- (with-suppressed-warnings ((obsolete foo))
- (foo ...))
-
- -- Function: proper-list-p object
- This function returns the length of OBJECT if it is a proper list,
- ‘nil’ otherwise (*note (elisp)Cons Cells::). In addition to
- satisfying ‘listp’, a proper list is neither circular nor dotted.
-
- (proper-list-p '(a b c)) ⇒ 3
- (proper-list-p '(a b . c)) ⇒ nil
-
- *Note (elisp)List-related Predicates::.
-
- -- Function: string-distance string1 string2 &optional bytecompare
- This function returns the _Levenshtein distance_ between the source
- string STRING1 and the target string STRING2. The Levenshtein
- distance is the number of single-character changes—deletions,
- insertions, or replacements—required to transform the source string
- into the target string; it is one possible definition of the _edit
- distance_ between strings.
-
- Letter-case of the strings is significant for the computed
- distance, but their text properties are ignored. If the optional
- argument BYTECOMPARE is non-‘nil’, the function calculates the
- distance in terms of bytes instead of characters. The byte-wise
- comparison uses the internal Emacs representation of characters, so
- it will produce inaccurate results for multibyte strings that
- include raw bytes (*note (elisp)Text Representations::); make the
- strings unibyte by encoding them (*note (elisp)Explicit Encoding::)
- if you need accurate results with raw bytes.
-
- *Note (elisp)Text Comparison::.
-
- -- Macro: ignore-errors body...
- This construct executes BODY, ignoring any errors that occur during
- its execution. If the execution is without error, ‘ignore-errors’
- returns the value of the last form in BODY; otherwise, it returns
- ‘nil’.
-
- Here’s the example at the beginning of this subsection rewritten
- using ‘ignore-errors’:
-
- (ignore-errors (delete-file filename))
-
- *Note (elisp)Handling Errors::.
-
- -- Macro: dolist-with-progress-reporter (var count [result])
- reporter-or-message body...
- This is another convenience macro that works the same way as
- ‘dolist’ does, but also reports loop progress using the functions
- described above. As in ‘dotimes-with-progress-reporter’,
- ‘reporter-or-message’ can be a progress reporter or a string. You
- can rewrite the previous example with this macro as follows:
-
- (dolist-with-progress-reporter (k (number-sequence 0 500)) "Collecting
- some mana for Emacs..." (sit-for 0.01))
-
- *Note (elisp)Progress::.
-
- -- Function: flatten-tree tree
- This function returns a “flattened” copy of TREE, that is, a list
- containing all the non-‘nil’ terminal nodes, or leaves, of the tree
- of cons cells rooted at TREE. Leaves in the returned list are in
- the same order as in TREE.
-
- (flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7)) ⇒(1 2 3 4 5 6 7)
-
- *Note (elisp)Building Lists::.
-
- -- Function: xor condition1 condition2
- This function returns the boolean exclusive-or of CONDITION1 and
- CONDITION2. That is, ‘xor’ returns ‘nil’ if either both arguments
- are ‘nil’, or both are non-‘nil’. Otherwise, it returns the value
- of that argument which is non-‘nil’.
-
- Note that in contrast to ‘or’, both arguments are always evaluated.
-
- *Note (elisp)Combining Conditions::.
-
- -- Variable: regexp-unmatchable
- This variable contains a regexp that is guaranteed not to match any
- string at all. It is particularly useful as default value for
- variables that may be set to a pattern that actually matches
- something.
-
- *Note (elisp)Regexp Functions::
-
- -- Function: decoded-time-second time
- Return the SECONDS field of a ‘decoded-time’ record TIME. It can
- also be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-minute time
- Return the MINUTE field of a ‘decoded-time’ record TIME. It can
- also be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-hour time
- Return the HOUR field of a ‘decoded-time’ record TIME. It can also
- be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-day time
- Return the DAY field of a ‘decoded-time’ record TIME. It can also
- be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-month time
- Return the MONTH field of a ‘decoded-time’ record TIME. It can
- also be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-year time
- Return the YEAR field of a ‘decoded-time’ record TIME. It can also
- be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-weekday time
- Return the WEEKDAY field of a ‘decoded-time’ record TIME. It can
- also be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: decoded-time-dst time
- Return the DST (daylight saving time indicator) field of a
- ‘decoded-time’ record TIME. It can also be used as a *note
- Generalized Variables: (elisp)generalised variable.
-
- -- Function: decoded-time-zone time
- Return the ZONE field of a ‘decoded-time’ record TIME. It can also
- be used as a *note Generalized Variables: (elisp)generalised
- variable.
-
- -- Function: package-get-version
- Return the version number of the package in which this is used.
-
- -- Function: time-equal-p t1 t2
- This returns ‘t’ if the two time values T1 and T2 are equal.
-
- *Note (elisp)Time Calculations::.
-
- -- Function: date-days-in-month year month
- Return the number of days in MONTH in YEAR. For instance, February
- 2020 has 29 days.
-
- *Note (elisp)Time Calculations::. This function requires the
- ‘time-date’ feature to be loaded.
-
- -- Function: date-ordinal-to-time year ordinal
- Convert a YEAR/ORDINAL to the equivalent decoded-time structure.
- ORDINAL is the number of days since the start of the year, with
- January 1st being 1.
-
- *Note (elisp)Time Calculations::. This function requires the
- ‘time-date’ feature to be loaded.
-
- -- User Option: exec-path
- The value of this variable is a list of directories to search for
- programs to run in subprocesses. Each element is either the name
- of a directory (i.e., a string), or ‘nil’, which stands for the
- default directory (which is the value of ‘default-directory’).
- *Note executable-find: (elisp)Locating Files, for the details of
- this search.
-
- The value of ‘exec-path’ is used by ‘call-process’ and
- ‘start-process’ when the PROGRAM argument is not an absolute file
- name.
-
- Generally, you should not modify ‘exec-path’ directly. Instead,
- ensure that your ‘PATH’ environment variable is set appropriately
- before starting Emacs. Trying to modify ‘exec-path’ independently
- of ‘PATH’ can lead to confusing results.
-
- *Note (elisp)Subprocess Creation::.
-
- -- Function: provided-mode-derived-p mode &rest modes
- This function returns non-‘nil’ if MODE is derived from any of the
- major modes given by the symbols MODES.
-
- -- Function: file-size-human-readable-iec size
- Human-readable string for SIZE bytes, using IEC prefixes.
-
- -- Function: make-empty-file filename &optional parents
- This function creates an empty file named FILENAME. As
- ‘make-directory’, this function creates parent directories if
- PARENTS is non-‘nil’. If FILENAME already exists, this function
- signals an error.
-
- -- Function: text-property-search-forward prop &optional value
- predicate not-current
- Search for the next region that has text property PROP set to VALUE
- according to PREDICATE.
-
- This function is modeled after ‘search-forward’ and friends in that
- it moves point, but it returns a structure that describes the match
- instead of returning it in ‘match-beginning’ and friends.
-
- If the text property can’t be found, the function returns ‘nil’.
- If it’s found, point is placed at the end of the region that has
- this text property match, and a ‘prop-match’ structure is returned.
-
- PREDICATE can either be ‘t’ (which is a synonym for ‘equal’), ‘nil’
- (which means “not equal”), or a predicate that will be called with
- two parameters: The first is VALUE, and the second is the value of
- the text property we’re inspecting.
-
- If NOT-CURRENT, if point is in a region where we have a match, then
- skip past that and find the next instance instead.
-
- The ‘prop-match’ structure has the following accessors:
- ‘prop-match-beginning’ (the start of the match), ‘prop-match-end’
- (the end of the match), and ‘prop-match-value’ (the value of
- PROPERTY at the start of the match).
-
- In the examples below, imagine that you’re in a buffer that looks
- like this:
-
- This is a bold and here's bolditalic and this is the end.
-
- That is, the “bold” words are the ‘bold’ face, and the “italic”
- word is in the ‘italic’ face.
-
- With point at the start:
-
- (while (setq match (text-property-search-forward 'face 'bold t))
- (push (buffer-substring (prop-match-beginning match)
- (prop-match-end match))
- words))
-
- This will pick out all the words that use the ‘bold’ face.
-
- (while (setq match (text-property-search-forward 'face nil t))
- (push (buffer-substring (prop-match-beginning match)
- (prop-match-end match))
- words))
-
- This will pick out all the bits that have no face properties, which
- will result in the list ‘("This is a " "and here's " "and this is
- the end")’ (only reversed, since we used ‘push’).
-
- (while (setq match (text-property-search-forward 'face nil nil))
- (push (buffer-substring (prop-match-beginning match)
- (prop-match-end match))
- words))
-
- This will pick out all the regions where ‘face’ is set to
- something, but this is split up into where the properties change,
- so the result here will be ‘("bold" "bold" "italic")’.
-
- For a more realistic example where you might use this, consider
- that you have a buffer where certain sections represent URLs, and
- these are tagged with ‘shr-url’.
-
- (while (setq match (text-property-search-forward 'shr-url nil nil))
- (push (prop-match-value match) urls))
-
- This will give you a list of all those URLs.
-
- *Note (Property Search)elisp::.
-
- -- Function: text-property-search-backward prop &optional value
- predicate not-current
- This is just like ‘text-property-search-forward’, but searches
- backward instead. Point is placed at the beginning of the matched
- region instead of the end, though.
-
- *Note (Property Search)elisp::.
-
-2.3.2 Extended Definitions
---------------------------
-
-These functions must be called explicitly via ‘compat-call’, since their
-calling convention or behavior was extended in Emacs 27.1:
-
- -- Function: compat-call recenter &optional count redisplay
- This function scrolls the text in the selected window so that point
- is displayed at a specified vertical position within the window.
- It does not move point with respect to the text.
-
- *Note (elisp)Textual Scrolling::.
-
- This compatibility version adds support for the optional argument
- REDISPLAY.
-
- -- Function: compat-call lookup-key keymap key &optional
- accept-defaults
- This function returns the definition of KEY in KEYMAP. If the
- string or vector KEY is not a valid key sequence according to the
- prefix keys specified in KEYMAP, it must be too long and have extra
- events at the end that do not fit into a single key sequence. Then
- the value is a number, the number of events at the front of KEY
- that compose a complete key.
-
- *Note (elisp)Low-Level Key Binding::.
-
- This compatibility version allows for KEYMAP to be a list of
- keymaps, instead of just a singular keymap.
-
- -- Macro: compat-call setq-local &rest pairs
- PAIRS is a list of variable and value pairs. This macro creates a
- buffer-local binding in the current buffer for each of the
- variables, and gives them a buffer-local value. It is equivalent
- to calling ‘make-local-variable’ followed by ‘setq’ for each of the
- variables. The variables should be unquoted symbols.
-
- (setq-local var1 "value1"
- var2 "value2")
-
- *Note (elisp)Creating Buffer-Local::.
-
- This compatibility version allows for more than one variable to be
- set at once, as can be done with ‘setq’.
-
- -- Function: compat-call regexp-opt strings &optional paren
- This function returns an efficient regular expression that will
- match any of the strings in the list STRINGS. This is useful when
- you need to make matching or searching as fast as possible—for
- example, for Font Lock mode.
-
- *Note (elisp)Regexp Functions::.
-
- The compatibility version of this functions handles the case where
- STRINGS in an empty list. In that case, a regular expression is
- generated that never matches anything (see ‘regexp-unmatchable’).
-
- -- Function: compat-call file-size-human-readable file-size &optional
- flavor space unit
- Return a string with a human readable representation of FILE-SIZE.
-
- The optional second argument FLAVOR controls the units and the
- display format. If FLAVOR is...
-
- • ‘si’, each kilobyte is 1000 bytes and the produced suffixes
- are ‘k’, ‘M’, ‘G’, ‘T’, etc.
- • ‘iec’, each kilobyte is 1024 bytes and the produced suffixes
- are ‘KiB’, ‘MiB’, ‘GiB’, ‘TiB’, etc.
- • ‘nil’ or omitted, each kilobyte is 1024 bytes and the produced
- suffixes are ‘k’, ‘M’, ‘G’, ‘T’, etc.
-
- The compatibility version handles the optional third (SPACE) and
- forth (UNIT) arguments. The argument SPACE can be a string that is
- placed between the number and the unit. The argument UNIT
- determines the unit to use. By default it will be an empty string,
- unless FLAVOR is ‘iec’, in which case it will be ‘B’.
-
- -- Function: compat-call assoc-delete-all key alist &optional test
- This function is like ‘assq-delete-all’ except that it accepts an
- optional argument TEST, a predicate function to compare the keys in
- ALIST. If omitted or ‘nil’, TEST defaults to ‘equal’. As
- ‘assq-delete-all’, this function often modifies the original list
- structure of ALIST.
-
- *Note (elisp)Association Lists::.
-
- This compatibility version handles the optional third (TESTFN)
- argument.
-
- -- Function: compat-call executable-find program &optional remote
- This function searches for the executable file of the named PROGRAM
- and returns the absolute file name of the executable, including its
- file-name extensions, if any. It returns ‘nil’ if the file is not
- found. The function searches in all the directories in
- ‘exec-path’, and tries all the file-name extensions in
- ‘exec-suffixes’ (*note (elisp)Subprocess Creation::).
-
- If REMOTE is non-‘nil’, and ‘default-directory’ is a remote
- directory, PROGRAM is searched on the respective remote host.
-
- *Note (elisp)Locating Files::.
-
- This compatibility version adds support to handle the optional
- second (REMOTE) argument.
-
-2.3.3 Missing Definitions
--------------------------
-
-Compat does not provide support for the following Lisp features
-implemented in 27.1:
-
- • The functions ‘base64url-encode-*’.
- • The function ‘decoded-time-add’.
- • The function ‘decoded-time-set-defaults’.
- • The function ‘time-convert’.
- • The macro ‘benchmark-progn’.
- • Support for ‘condition-case’ to handle t.
- • The function ‘file-system-info’.
- • The function ‘group-name’.
- • The function ‘face-extend-p’ and ‘set-face-extend’.
- • Additional ‘format-spec’ modifiers.
- • Support for additional body forms for
- ‘define-globalized-minor-mode’.
- • The macro ‘with-connection-local-variables’ and related
- functionality.
- • The ‘iso8601’ library.
- • The ‘exif’ library.
- • The ‘image-converter’ library.
-
-\1f
-File: docdzgy5X.info, Node: Emacs 28.1, Next: Emacs 29.1, Prev: Emacs 27.1, Up: Support
-
-2.4 Emacs 28.1
-==============
-
-2.4.1 Added Definitions
------------------------
-
-The following functions and macros are implemented in Emacs 28.1. These
-functions are made available by Compat on Emacs versions older than
-28.1.
-
- The ‘defcustom’ type ‘natnum’ introduced in Emacs 28.1 is made
-available by Compat.
-
- -- Function: process-lines-ignore-status program &rest args
- This function is just like ‘process-lines’, but does not signal an
- error if PROGRAM exits with a non-zero exit status.
-
- -- Function: process-lines-handling-status program status-handler &rest
- args
- Execute PROGRAM with ARGS, returning its output as a list of lines.
- If STATUS-HANDLER is non-nil, it must be a function with one
- argument, which will be called with the exit status of the program
- before the output is collected. If STATUS-HANDLER is nil, an error
- is signaled if the program returns with a non-zero exit status.
-
- -- Function: text-quoting-style
- You should not read the value of the variable ‘text-quoting-style’
- directly. Instead, use this function with the same name to
- dynamically compute the correct quoting style on the current
- terminal in the ‘nil’ case described above.
-
- -- Function: string-search needle haystack &optional start-pos
- Return the position of the first instance of NEEDLE in HAYSTACK,
- both of which are strings. If START-POS is non-‘nil’, start
- searching from that position in NEEDLE. Return ‘nil’ if no match
- was found. This function only considers the characters in the
- strings when doing the comparison; text properties are ignored.
- Matching is always case-sensitive.
-
- -- Function: length= sequence length
- Return non-‘nil’ if the length of SEQUENCE is equal to LENGTH.
-
- -- Function: length< sequence length
- Return non-‘nil’ if SEQUENCE is shorter than LENGTH. This may be
- more efficient than computing the length of SEQUENCE if SEQUENCE is
- a long list.
-
- -- Function: length> sequence length
- Return non-‘nil’ if SEQUENCE is longer than LENGTH.
-
- -- Function: file-name-concat directory &rest components
- Concatenate COMPONENTS to DIRECTORY, inserting a slash before the
- components if DIRECTORY or the preceding component didn’t end with
- a slash.
-
- (file-name-concat "/tmp" "foo") ⇒ "/tmp/foo"
-
- A DIRECTORY or components that are ‘nil’ or the empty string are
- ignored—they are filtered out first and do not affect the results
- in any way.
-
- This is almost the same as using ‘concat’, but DIRNAME (and the
- non-final components) may or may not end with slash characters, and
- this function will not double those characters.
-
- -- Function: garbage-collect-maybe factor
- Suggest to run garbage collection, if _enough_ data has been
- allocated. This is determined by the positive numerical argument
- FACTOR, that would proportionally increase the likelihood of
- garbage collection taking place.
-
- This compatibility function does nothing and ignores any
- suggestion.
-
- -- Function: string-replace from-string to-string in-string
- This function replaces all occurrences of FROM-STRING with
- TO-STRING in IN-STRING and returns the result. It may return one
- of its arguments unchanged, a constant string or a new string.
- Case is significant, and text properties are ignored.
-
- -- Function: always &rest arguments
- This function ignores any ARGUMENTS and returns ‘t’.
-
- *Note (elisp)Calling Functions::.
-
- -- Function: make-separator-line &optional length
- Make a string appropriate for usage as a visual separator line. If
- LENGTH is nil, use the window width.
-
- -- Function: insert-into-buffer to-buffer &optional start end
- This is like ‘insert-buffer-substring’, but works in the opposite
- direction: The text is copied from the current buffer into
- TO-BUFFER. The block of text is copied to the current point in
- TO-BUFFER, and point (in that buffer) is advanced to after the end
- of the copied text. Is ‘start’/‘end’ is ‘nil’, the entire text in
- the current buffer is copied over.
-
- *Note (elisp)Insertion::.
-
- -- Function: replace-string-in-region string replacement &optional
- start end
- This function works similarly to ‘replace-regexp-in-region’, but
- searches for, and replaces, literal STRINGs instead of regular
- expressions.
-
- -- Function: replace-regexp-in-string regexp rep string &optional
- fixedcase literal subexp start
- This function copies STRING and searches it for matches for REGEXP,
- and replaces them with REP. It returns the modified copy. If
- START is non-‘nil’, the search for matches starts at that index in
- STRING, and the returned value does not include the first START
- characters of STRING. To get the whole transformed string,
- concatenate the first START characters of STRING with the return
- value.
-
- This function uses ‘replace-match’ to do the replacement, and it
- passes the optional arguments FIXEDCASE, LITERAL and SUBEXP along
- to ‘replace-match’.
-
- Instead of a string, REP can be a function. In that case,
- ‘replace-regexp-in-string’ calls REP for each match, passing the
- text of the match as its sole argument. It collects the value REP
- returns and passes that to ‘replace-match’ as the replacement
- string. The match data at this point are the result of matching
- REGEXP against a substring of STRING.
-
- -- Function: buffer-local-boundp variable buffer
- This returns non-‘nil’ if there’s either a buffer-local binding of
- VARIABLE (a symbol) in buffer BUFFER, or VARIABLE has a global
- binding.
-
- *Note (elisp)Creating Buffer-Local::.
-
- -- Macro: with-existing-directory body...
- This macro ensures that ‘default-directory’ is bound to an existing
- directory before executing BODY. If ‘default-directory’ already
- exists, that’s preferred, and otherwise some other directory is
- used. This macro can be useful, for instance, when calling an
- external command that requires that it’s running in a directory
- that exists. The chosen directory is not guaranteed to be
- writable.
-
- *Note (elisp)Testing Accessibility::.
-
- -- Macro: dlet (bindings...) forms...
- This special form is like ‘let’, but it binds all variables
- dynamically. This is rarely useful—you usually want to bind normal
- variables lexically, and special variables (i.e., variables that
- are defined with ‘defvar’) dynamically, and this is what ‘let’
- does.
-
- ‘dlet’ can be useful when interfacing with old code that assumes
- that certain variables are dynamically bound (*note (elisp)Dynamic
- Binding::), but it’s impractical to ‘defvar’ these variables.
- ‘dlet’ will temporarily make the bound variables special, execute
- the forms, and then make the variables non-special again.
-
- *Note (elisp)Local Variables::.
-
- -- Function: ensure-list object
- This function returns OBJECT as a list. If OBJECT is already a
- list, the function returns it; otherwise, the function returns a
- one-element list containing OBJECT.
-
- This is usually useful if you have a variable that may or may not
- be a list, and you can then say, for instance:
-
- (dolist (elem (ensure-list foo))
- (princ elem))
-
- *Note (elisp)Building Lists::.
-
- -- Function: string-clean-whitespace string
- Clean up the whitespace in STRING by collapsing stretches of
- whitespace to a single space character, as well as removing all
- whitespace from the start and the end of STRING.
-
- *Note (elisp)Creating Strings::.
-
- -- Function: string-fill string length
- Attempt to Word-wrap STRING so that no lines are longer than
- LENGTH. Filling is done on whitespace boundaries only. If there
- are individual words that are longer than LENGTH, these will not be
- shortened.
-
- *Note (elisp)Creating Strings::.
-
- -- Function: string-lines string &optional omit-nulls
- Split STRING into a list of strings on newline boundaries. If the
- optional argument OMIT-NULLS is non-‘nil’, remove empty lines from
- the results. Note that this function returns trailing newlines on
- Emacs 28, use ‘compat-call string-lines’ instead if you want
- consistent behavior.
-
- -- Function: string-pad string length &optional padding start
- Pad STRING to be of the given LENGTH using PADDING as the padding
- character. PADDING defaults to the space character. If STRING is
- longer than LENGTH, no padding is done. If START is ‘nil’ or
- omitted, the padding is appended to the characters of STRING, and
- if it’s non-‘nil’, the padding is prepended to STRING’s characters.
-
- *Note (elisp)Creating Strings::.
-
- -- Function: string-chop-newline string
- Remove the final newline, if any, from STRING.
-
- *Note (elisp)Creating Strings::.
-
- -- Macro: named-let name bindings &rest body
- This special form is a looping construct inspired from the Scheme
- language. It is similar to ‘let’: It binds the variables in
- BINDINGS, and then evaluates BODY. However, ‘named-let’ also binds
- NAME to a local function whose formal arguments are the variables
- in BINDINGS and whose body is BODY. This allows BODY to call
- itself recursively by calling NAME, where the arguments passed to
- NAME are used as the new values of the bound variables in the
- recursive invocation.
-
- Recursive calls to NAME that occur in _tail positions_ in BODY are
- guaranteed to be optimized as _tail calls_, which means that they
- will not consume any additional stack space no matter how deeply
- the recursion runs. Such recursive calls will effectively jump to
- the top of the loop with new values for the variables.
-
- *Note (elisp)Local Variables::.
-
- -- Function: file-name-with-extension filename extension
- This function returns FILENAME with its extension set to EXTENSION.
- A single leading dot in the EXTENSION will be stripped if there is
- one. For example:
-
- (file-name-with-extension "file" "el")
- ⇒ "file.el"
- (file-name-with-extension "file" ".el")
- ⇒ "file.el"
- (file-name-with-extension "file.c" "el")
- ⇒ "file.el"
-
- Note that this function will error if FILENAME or EXTENSION are
- empty, or if the FILENAME is shaped like a directory (i.e., if
- ‘directory-name-p’ returns non-‘nil’).
-
- *Note File Name Components: (elisp)File Name Components.
-
- -- Function: directory-empty-p directory
- This utility function returns ‘t’ if given DIRECTORY is an
- accessible directory and it does not contain any files, i.e., is an
- empty directory. It will ignore ‘.’ and ‘..’ on systems that
- return them as files in a directory.
-
- Symbolic links to directories count as directories. See
- FILE-SYMLINK-P to distinguish symlinks.
-
- *Note (elisp)Contents of Directories::.
-
- -- Function: format-prompt prompt default &rest format-args
- Format PROMPT with default value DEFAULT according to the
- ‘minibuffer-default-prompt-format’ variable.
-
- ‘minibuffer-default-prompt-format’ is a format string (defaulting
- to ‘" (default %s)"’ that says how the “default” bit in prompts
- like ‘"Local filename (default somefile): "’ are to be formatted.
-
- To allow the users to customize how this is displayed, code that
- prompts the user for a value (and has a default) should look
- something along the lines of this code snippet:
-
- (read-file-name
- (format-prompt "Local filename" file)
- nil file)
-
- If FORMAT-ARGS is ‘nil’, PROMPT is used as a literal string. If
- FORMAT-ARGS is non-‘nil’, PROMPT is used as a format control
- string, and PROMPT and FORMAT-ARGS are passed to ‘format’ (*note
- (elisp)Formatting Strings::).
-
- ‘minibuffer-default-prompt-format’ can be ‘""’, in which case no
- default values are displayed.
-
- If DEFAULT is ‘nil’, there is no default value, and therefore no
- “default value” string is included in the result value. If DEFAULT
- is a non-‘nil’ list, the first element of the list is used in the
- prompt.
-
- *Note (elisp)Text from Minibuffer::.
-
- -- Function: thing-at-mouse event thing &optional no-properties
- Mouse-EVENT equivalent of ‘thing-at-point’. THING can be ‘symbol’,
- ‘list’, ‘sexp’, ‘filename’, ‘url’, ... among other things.
-
- When NO-PROPERTIES has a non-‘nil’ value, any text properties that
- might have been present in the buffer are stripped away.
-
- -- Function: bounds-of-thing-at-mouse event thing
- Determine start and end locations for THING at mouse click given by
- EVENT. Like ‘bounds-of-thing-at-point’, but tries to use the
- position in EVENT where the mouse button is clicked to find the
- thing nearby.
-
- -- Function: mark-thing-at-mouse click thing
- Activate the region around THING found near the mouse CLICK.
-
- -- Function: macroexp-file-name
- Return the name of the file in which the code is currently being
- evaluated, or ‘nil’ if it cannot be determined.
-
- -- Function: macroexp-warn-and-return msg form &optional category
- compile-only arg
- Return code equivalent to ‘form’ labeled with warning ‘msg’.
-
- -- Macro: with-environment-variables variables body...
- This macro sets the environment variables according to VARIABLES
- temporarily when executing BODY. The previous values are restored
- when the form finishes. The argument VARIABLES should be a list of
- pairs of strings of the form ‘(VAR VALUE)’, where VAR is the name
- of the environment variable and VALUE is that variable’s value.
-
- (with-environment-variables (("LANG" "C")
- ("LANGUAGE" "en_US:en"))
- (call-process "ls" nil t))
-
- *Note System Environment: (elisp)System Environment.
-
- -- Function: color-dark-p rgb
- Whether RGB is more readable against white than black. RGB is a
- 3-element list (R G B), each component in the range [0,1]. This
- predicate can be used both for determining a suitable (black or
- white) contrast color with RGB as background and as foreground.
-
- -- Function: color-values-from-color-spec spec
- Convert the textual color specification SPEC to a color triple
- ‘(RED GREEN blue)’. Each of RED, GREEN and ‘blue’ is a integer
- value between 0 and 65535.
-
- The specification SPEC can be one of the following
- • ‘#RGB’, where R, G and B are hex numbers of equal length, 1-4
- digits each.
- • ‘rgb:R/G/B’, where R, G, and B are hex numbers, 1-4 digits
- each.
- • ‘rgbi:R/G/B’, where R, G and B are floating-point numbers in
- [0,1].
-
- -- Function: file-modes-number-to-symbolic modes
- This function converts a numeric file mode specification in MODES
- into the equivalent symbolic form.
-
- *Note Changing Files: (elisp)Changing Files.
-
- -- Function: file-backup-file-names filename
- This function returns a list of all the backup file names for
- FILENAME, or ‘nil’ if there are none. The files are sorted by
- modification time, descending, so that the most recent files are
- first.
-
- *Note (elisp)Backup Names::.
-
- -- Function: make-lock-file-name filename
- Return a string containing a lock file name for FILENAME, obeying
- ‘lock-file-name-transforms’.
-
- -- Function: decoded-time-period time
- Interpret TIME as a period and return its length in seconds. For
- computational purposes, years are 365 days long and months are 30
- days long.
-
- -- Function: subr-primitive-p object
- Return ‘t’ if OBJECT is a primitive, built-in function. On systems
- with native compilation ‘subrp’ does not distinguish between
- built-in functions and functions that have been compiled. If
- native compilation is not available, this function behaves
- identically to ‘subrp’.
-
- -- Function: native-comp-available-p
- This function returns non-‘nil’ if the running Emacs process has
- the native-compilation support compiled into it. On systems that
- load ‘libgccjit’ dynamically, it also makes sure that library is
- available and can be loaded. Lisp programs that need to know up
- front whether native-compilation is available should use this
- predicate.
-
- -- Macro: with-window-non-dedicated window &rest body
- Evaluate BODY with WINDOW temporarily made non-dedicated. If
- WINDOW is nil, use the selected window. Return the value of the
- last form in BODY.
-
-2.4.2 Extended Definitions
---------------------------
-
-These functions must be called explicitly via ‘compat-call’, since their
-calling convention or behavior was extended in Emacs 28.1:
-
- -- Function: compat-call string-width string &optional from to
- This function returns the width in columns of the string STRING, if
- it were displayed in the current buffer and the selected window.
- Optional arguments FROM and TO specify the substring of STRING to
- consider, and are interpreted as in ‘substring’ (*note
- (elisp)Creating Strings::).
-
- The return value is an approximation: it only considers the values
- returned by ‘char-width’ for the constituent characters, always
- takes a tab character as taking ‘tab-width’ columns, ignores
- display properties and fonts, etc.
-
- *Note (elisp)Size of Displayed Text::.
-
- This compatibility version handles the optional arguments FROM and
- TO.
-
- -- Function: compat-call count-windows
- Return the number of live windows on the selected frame.
-
- The optional argument MINIBUF specifies whether the minibuffer
- window is included in the count.
-
- If ALL-FRAMES is non-‘nil’, count the windows in all frames instead
- just the selected frame.
-
- This compatibility version handles the optional argument
- ALL-FRAMES.
-
-2.4.3 Missing Definitions
--------------------------
-
-Compat does not provide support for the following Lisp features
-implemented in 28.1:
-
- • Support for ‘interactive’ or ‘declare’ to list applicable modes.
- • Support for ‘:interactive’ argument to ‘define-minor-mode’ and
- ‘define-derived-mode’.
- • Support for ‘:predicate’ argument to
- ‘define-globalized-minor-mode’.
- • Support for the ‘:success’ handler of ‘condition-case’.
- • The function ‘benchmark-call’.
- • Additional Edebug keywords.
- • The libjansson JSON APIs, e.g., ‘json-parse-string’.
- • The macro ‘pcase-setq’.
- • The function ‘custom-add-choice’.
- • The functions ‘dom-print’ and ‘dom-remove-attribute’.
- • The function ‘dns-query-asynchronous’.
- • The function ‘get-locale-names’.
- • The functions ‘mail-header-parse-addresses-lax’ and
- ‘mail-header-parse-address-lax’.
- • The function ‘num-processors’.
- • The function ‘object-intervals’.
- • The function ‘require-theme’.
- • The function ‘syntax-class-to-char’.
- • The function ‘path-separator’.
- • The function ‘null-device’.
- • The function ‘macroexp-compiling-p’.
- • The function ‘split-string-shell-command’.
- • The function ‘string-limit’.
- • The functions ‘innermost-minibuffer-p’ and
- ‘minibuffer-innermost-command-loop-p’.
- • The function ‘max-mini-window-lines’.
- • The function ‘lock-file’ and ‘unlock-file’.
- • The ‘multisession’ library.
-
-\1f
-File: docdzgy5X.info, Node: Emacs 29.1, Next: Emacs 30.1, Prev: Emacs 28.1, Up: Support
-
-2.5 Emacs 29.1
-==============
-
-2.5.1 Added Definitions
------------------------
-
-The following functions and macros are implemented in Emacs 29.1. These
-functions are made available by Compat on Emacs versions older than
-29.1. Note that due to upstream changes, it might happen that there
-will be the need for changes, so use these functions with care.
-
- The ‘defcustom’ type ‘key’ introduced in Emacs 29.1 is made available
-by Compat.
-
- -- Variable: untrusted-content
- Non-nil means that current buffer originated from an untrusted
- source. Email clients and some other modes may set this non-nil to
- mark the buffer contents as untrusted. This variable might be
- subject to change without notice.
-
- -- Variable: lisp-directory
- This variable holds a string naming the directory which holds
- Emacs’s own ‘*.el’ and ‘*.elc’ files. This is usually the place
- where those files are located in the Emacs installation tree,
- unless Emacs is run from its build directory in which case it
- points to the ‘lisp’ subdirectory in the source directory from
- which Emacs was built.
-
- -- Function: count-sentences start end
- Count sentences in current buffer from START to END.
-
- -- Function: readablep object
- This predicate says whether OBJECT has “readable syntax”, i.e., it
- can be written out and then read back by the Emacs Lisp reader. If
- it can’t, this function returns ‘nil’; if it can, this function
- returns a printed representation (via ‘prin1’).
-
- -- Function: substitute-quotes string
- This function works like ‘substitute-command-keys’, but only
- replaces quote characters.
-
- -- Function: get-scratch-buffer-create
- Return the *scratch* buffer, creating a new one if needed.
-
- -- Function: use-region-noncontiguous-p
- Return non-nil for a non-contiguous region if ‘use-region-p’.
-
- -- Function: use-region-end
- Return the end of the region if ‘use-region-p’.
-
- -- Function: use-region-beginning
- Return the start of the region if ‘use-region-p’.
-
- -- Macro: buffer-local-set-state variable value...
- Minor modes often set buffer-local variables that affect some
- features in Emacs. When a minor mode is switched off, the mode is
- expected to restore the previous state of these variables. This
- convenience macro helps with doing that: It works much like
- ‘setq-local’, but returns an object that can be used to restore
- these values back to their previous values/states (using the
- companion function ‘buffer-local-restore-state’).
-
- -- Function: delete-line
- Delete the current line.
-
- -- Function: list-of-strings-p object
- Return ‘t’ if OBJECT is ‘nil’ or a list of strings.
-
- -- Function: plistp object
- Non-nil if and only if OBJECT is a valid plist.
-
- -- Macro: with-memoization PLACE CODE...
- This macro provides a simple way to do memoization. CODE is
- evaluated and then stashed in PLACE. If PLACE’s value is
- non-‘nil’, return that value instead of evaluating CODE.
-
- -- Special Form: with-restriction start end [:label label] body
- This special form saves the current bounds of the accessible
- portion of the buffer, sets the accessible portion to start at
- START and end at END, evaluates the BODY forms, and restores the
- saved bounds. In that case it is equivalent to
-
- (save-restriction
- (narrow-to-region start end)
- body)
-
- When the optional argument LABEL, a symbol, is present, the
- narrowing is “labeled”. A labeled narrowing differs from a
- non-labeled one in several ways:
-
- • During the evaluation of the BODY form, ‘narrow-to-region’ and
- ‘widen’ can be used only within the START and END limits.
-
- • To lift the restriction introduced by ‘with-restriction’ and
- gain access to other portions of the buffer, use
- ‘without-restriction’ with the same LABEL argument. (Another
- way to gain access to other portions of the buffer is to use
- an indirect buffer (*note (elisp)Indirect Buffers::).)
-
- • Labeled narrowings can be nested.
-
- • Labeled narrowings can only be used in Lisp programs: they are
- never visible on display, and never interfere with narrowings
- set by the user.
-
- If you use ‘with-restriction’ with the optional LABEL argument, we
- recommend documenting the LABEL in the doc strings of the functions
- which use it, so that other Lisp programs your code calls could
- lift the labeled narrowing if and when it needs.
-
- -- Special Form: without-restriction [:label label] body
- This special form saves the current bounds of the accessible
- portion of the buffer, widens the buffer, evaluates the BODY forms,
- and restores the saved bounds. In that case it is equivalent to
-
- (save-restriction
- (widen)
- body)
-
- When the optional argument LABEL is present, the narrowing set by
- ‘with-restriction’ with the same LABEL argument is lifted.
-
- -- Function: pos-bol &optional count
- Like ‘line-beginning-position’, but ignores fields (and is more
- efficient).
-
- -- Function: pos-eol &optional count
- Like ‘line-end-position’, but ignores fields (and is more
- efficient).
-
- -- Function: char-uppercase-p char
- Return non-‘nil’ if CHAR is an uppercase character according to
- Unicode.
-
- -- Macro: with-delayed-message (timeout message) body...
- Sometimes it’s unclear whether an operation will take a long time
- to execute or not, or it can be inconvenient to implement a
- progress reporter. This macro can be used in those situations.
-
- (with-delayed-message (2 (format "Gathering data for %s" entry))
- (setq data (gather-data entry)))
-
- In this example, if the body takes more than two seconds to
- execute, the message will be displayed. If it takes a shorter time
- than that, the message won’t be displayed. In either case, the
- body is evaluated as normally, and the return value of the final
- element in the body is the return value of the macro.
-
- The MESSAGE element is evaluated before BODY, and is always
- evaluated, whether the message is displayed or not.
-
- -- Function: funcall-with-delayed-message timeout message function
- Like ‘funcall’, but display MESSAGE if FUNCTION takes longer than
- TIMEOUT. TIMEOUT is a number of seconds, and can be an integer or
- a floating point number.
-
- If FUNCTION takes less time to execute than TIMEOUT seconds,
- MESSAGE is not displayed.
-
- -- Function: buttonize string callback &optional data help-echo
- Sometimes it’s more convenient to make a string into a button
- without inserting it into a buffer immediately, for instance when
- creating data structures that may then, later, be inserted into a
- buffer. This function makes STRING into such a string, and
- CALLBACK will be called when the user clicks on the button. The
- optional DATA parameter will be used as the parameter when CALLBACK
- is called. If ‘nil’, the button is used as the parameter instead.
-
- -- Function: buttonize-region start end callback &optional data
- help-echo
- Make the region between START and END into a button. When clicked,
- CALLBACK will be called with the DATA as the function argument. If
- DATA isn’t present (or is nil), the button itself will be used
- instead as the function argument. If HELP-ECHO, use that as the
- help-echo property.
-
- -- Function: get-display-property position prop &optional object
- properties
- This convenience function can be used to get a specific display
- property, no matter whether the ‘display’ property is a vector, a
- list or a simple property. This is like ‘get-text-property’ (*note
- Examining Properties: (elisp)Examining Properties.), but works on
- the ‘display’ property only.
-
- POSITION is the position in the buffer or string to examine, and
- PROP is the ‘display’ property to return. The optional OBJECT
- argument should be either a string or a buffer, and defaults to the
- current buffer. If the optional PROPERTIES argument is non-‘nil’,
- it should be a ‘display’ property, and in that case, POSITION and
- OBJECT are ignored. (This can be useful if you’ve already gotten
- the ‘display’ property with ‘get-char-property’, for instance
- (*note Examining Properties: (elisp)Examining Properties.).
-
- -- Function: add-display-text-property start end prop value &optional
- object
- Add display property PROP with VALUE to the text from START to END.
- If any text in the region has a non-nil ‘display’ property, those
- properties are retained.
-
- If OBJECT is non-‘nil’, it should be a string or a buffer. If
- ‘nil’, this defaults to the current buffer.
-
- -- Function: take n list
- This function returns the N first elements of LIST. Essentially,
- it returns the part of LIST that ‘nthcdr’ skips.
-
- ‘take’ returns LIST if shorter than N elements; it returns ‘nil’ if
- N is zero or negative.
-
- (take 3 '(a b c d))
- ⇒ (a b c)
- (take 10 '(a b c d))
- ⇒ (a b c d)
- (take 0 '(a b c d))
- ⇒ nil
-
- -- Function: ntake n list
- This is a version of ‘take’ that works by destructively modifying
- the list structure of the argument. That makes it faster, but the
- original value of LIST may be lost.
-
- ‘ntake’ returns LIST unmodified if shorter than N elements; it
- returns ‘nil’ if N is zero or negative. Otherwise, it returns LIST
- truncated to its first N elements.
-
- This means that it is usually a good idea to use the return value
- and not just rely on the truncation effect unless N is known to be
- positive.
-
- -- Function: compiled-function-p object
- This function returns ‘t’ if OBJECT is a function object that is
- not in the form of ELisp source code but something like machine
- code or byte code instead. More specifically it returns ‘t’ if the
- function is built-in, or byte-compiled, or natively-compiled, or a
- function loaded from a dynamic module.
-
- -- Function: function-alias-p object &optional noerror
- Checks whether OBJECT is a function alias. If it is, it returns a
- list of symbols representing the function alias chain, else ‘nil’.
- For instance, if ‘a’ is an alias for ‘b’, and ‘b’ is an alias for
- ‘c’:
-
- (function-alias-p 'a)
- ⇒ (b c)
-
- If there’s a loop in the definitions, an error will be signalled.
- If NOERROR is non-‘nil’, the non-looping parts of the chain is
- returned instead.
-
- -- Function: string-equal-ignore-case string1 string2
- ‘string-equal-ignore-case’ compares strings ignoring case
- differences, like ‘char-equal’ when ‘case-fold-search’ is ‘t’.
-
- *Note (elisp)Text Comparison::.
-
- -- Function: string-split string &optional separators omit-nulls trim
- ‘string-split’ is an alias for the function ‘split-string’. The
- name follows the convention of other string functions.
-
- *Note (elisp)Creating Strings::.
-
- -- Function: buffer-match-p condition buffer-or-name &optional arg
- This function checks if a buffer designated by ‘buffer-or-name’
- satisfies a ‘condition’. Optional third argument ARG is passed to
- the predicate function in CONDITION. A condition can be one of the
- following:
- • A string, interpreted as a regular expression. The buffer
- satisfies the condition if the regular expression matches the
- buffer name.
- • A predicate function, which should return non-‘nil’ if the
- buffer matches. If the function expects one argument, it is
- called with BUFFER-OR-NAME as the argument; if it expects 2
- arguments, the first argument is BUFFER-OR-NAME and the second
- is ARG (or ‘nil’ if ARG is omitted).
- • A cons-cell ‘(OPER . EXPR)’ where OPER is one of
- ‘not’
- Satisfied if EXPR doesn’t satisfy ‘buffer-match-p’ with
- the same buffer and ‘arg’.
- ‘or’
- Satisfied if EXPR is a list and _any_ condition in EXPR
- satisfies ‘buffer-match-p’, with the same buffer and
- ‘arg’.
- ‘and’
- Satisfied if EXPR is a list and _all_ conditions in EXPR
- satisfy ‘buffer-match-p’, with the same buffer and ‘arg’.
- ‘derived-mode’
- Satisfied if the buffer’s major mode derives from EXPR.
- ‘major-mode’
- Satisfied if the buffer’s major mode is equal to EXPR.
- Prefer using ‘derived-mode’ instead when both can work.
- • t Satisfied by any buffer. A convenient alternative to ‘""’
- (empty string), ‘(and)’ (empty conjunction) or ‘always’.
-
- *Note (elisp)Buffer List::.
-
- -- Function: match-buffers condition &optional buffers arg
- This function returns a list of all buffers that satisfy a
- ‘condition’, as defined for ‘buffer-match-p’. By default all
- buffers are considered, but this can be restricted via the second
- optional ‘buffer-list’ argument. Optional third argument ARG will
- be used by CONDITION in the same way as ‘buffer-match-p’ does.
-
- *Note (elisp)Buffer List::.
-
- -- Function: string-glyph-split string
- When character compositions are in effect, sequence of characters
- can be composed for display to form _grapheme clusters_, for
- example to display accented characters, or ligatures, or Emoji, or
- when complex text shaping requires that for some scripts. When
- that happens, characters no longer map in a simple way to display
- columns, and display layout decisions with such strings, such as
- truncating too wide strings, can be a complex job. This function
- helps in performing such jobs: it splits up its argument STRING
- into a list of substrings, where each substring produces a single
- grapheme cluster that should be displayed as a unit. Lisp programs
- can then use this list to construct visually-valid substrings of
- STRING which will look correctly on display, or compute the width
- of any substring of STRING by adding the width of its constituents
- in the returned list, etc.
-
- For instance, if you want to display a string without the first
- glyph, you can say:
-
- (apply #'insert (cdr (string-glyph-split string))))
-
- *Note (elisp)Size of Displayed Text::.
-
- -- Macro: with-buffer-unmodified-if-unchanged &rest body...
- Evaluate BODY like ‘progn’, but change buffer-modified status only
- if buffer text changes. If the buffer was unmodified before
- execution of BODY, and buffer text after execution of BODY is
- identical to what it was before, ensure that buffer is still marked
- unmodified afterwards.
-
- Note that only changes in the raw byte sequence of the buffer text,
- as stored in the internal representation, are monitored for the
- purpose of detecting the lack of changes in buffer text. Any other
- changes that are normally perceived as "buffer modifications", such
- as changes in text properties, ‘buffer-file-coding-system’, buffer
- multibyteness, etc. – will not be noticed, and the buffer will
- still be marked unmodified, effectively ignoring those changes.
-
- -- Function: file-attribute-file-identifier
- Return the fields ‘(inodenum device)’ as a list from attributes
- generated by ‘file-attributes’.
-
- *Note (elisp)File Attributes::.
-
- -- Function: file-name-split filename
- This function splits a file name into its components, and can be
- thought of as the inverse of ‘string-join’ with the appropriate
- directory separator. For example,
-
- (file-name-split "/tmp/foo.txt")
- ⇒ ("" "tmp" "foo.txt")
- (string-join (file-name-split "/tmp/foo.txt") "/")
- ⇒ "/tmp/foo.txt"
-
- -- Function: file-name-parent-directory filename
- This function returns the directory name of the parent directory of
- FILENAME. If FILENAME is at the root directory of the filesystem,
- it returns ‘nil’. A relative FILENAME is assumed to be relative to
- ‘default-directory’, and the return value will also be relative in
- that case. If the return value is non-‘nil’, it ends in a slash.
-
- *Note (elisp)Directory Names::.
-
- -- Function: file-has-changed-p file &optional tag
- This function returns non-‘nil’ if the time stamp of FILENAME has
- changed since the last call. When called for the first time for
- some FILENAME, it records the last modification time and size of
- the file, and returns non-‘nil’ when FILENAME exists. Thereafter,
- when called for the same FILENAME, it compares the current time
- stamp and size with the recorded ones, and returns non-‘nil’ only
- if either the time stamp or the size (or both) are different. This
- is useful when a Lisp program wants to re-read a file whenever it
- changes. With an optional argument TAG, which must be a symbol,
- the size and modification time comparisons are limited to calls
- with the same tag.
-
- *Note (elisp)File Attributes::.
-
- -- Function: directory-abbrev-make-regexp directory
- Create a regexp to match DIRECTORY for ‘directory-abbrev-alist’.
-
- -- Function: directory-abbrev-apply filename
- Apply the abbreviations in ‘directory-abbrev-alist’ to FILENAME.
- Note that when calling this, you should set ‘case-fold-search’ as
- appropriate for the filesystem used for FILENAME.
-
- -- Function: key-valid-p keys
- Say whether KEYS is a valid key. A key is a string consisting of
- one or more key strokes. The key strokes are separated by single
- space characters.
-
- Each key stroke is either a single character, or the name of an
- event, surrounded by angle brackets. In addition, any key stroke
- may be preceded by one or more modifier keys. Finally, a limited
- number of characters have a special shorthand syntax.
-
- Here’s some example key sequences.
-
- ‘f’
- The key ‘f’.
- ‘S o m’
- A three key sequence of the keys ‘S’, ‘o’ and ‘m’.
- ‘C-c o’
- A two key sequence of the keys ‘c’ with the control modifier
- and then the key ‘o’.
- ‘H-<left>’
- The key named "left" with the hyper modifier.
- ‘M-RET’
- The "return" key with a meta modifier.
- ‘C-M-<space>’
- The "space" key with both the control and meta modifiers.
-
- These are the characters that have shorthand syntax: ‘NUL’, ‘RET’,
- ‘TAB’, ‘LFD’, ‘ESC’, ‘SPC’, ‘DEL’.
-
- Modifiers have to be specified in this order
- Alt (A)-Control (C)-Hyper (H)-Meta (M)-Shift (s)-Super (s)
-
- -- Function: key-parse keys
- Convert KEYS to the internal Emacs key representation. See
- ‘key-valid-p’ for a description of valid key sequences. Examples
- include ‘f’, ‘C-c C-c’, ‘H-<left>’, ‘M-RET’ or ‘C-M-<return>’.
-
- -- Function: keymap-set keymap key definition
- This function sets the binding for KEY in KEYMAP. (If KEY is more
- than one event long, the change is actually made in another keymap
- reached from KEYMAP.) The argument BINDING can be any Lisp object,
- but only certain types are meaningful. (For a list of meaningful
- types, see *note (elisp)Key Lookup::.) The value returned by
- ‘keymap-set’ is BINDING.
-
- If KEY is ‘<t>’, this sets the default binding in KEYMAP. When an
- event has no binding of its own, the Emacs command loop uses the
- keymap’s default binding, if there is one.
-
- Every prefix of KEY must be a prefix key (i.e., bound to a keymap)
- or undefined; otherwise an error is signaled. If some prefix of
- KEY is undefined, then ‘keymap-set’ defines it as a prefix key so
- that the rest of KEY can be defined as specified.
-
- If there was previously no binding for KEY in KEYMAP, the new
- binding is added at the beginning of KEYMAP. The order of bindings
- in a keymap makes no difference for keyboard input, but it does
- matter for menu keymaps (*note (elisp)Menu Keymaps::).
-
- *Note (elisp)Changing Key Bindings::.
-
- -- Function: keymap-global-set key command
- This function sets the binding of KEY in the current global map to
- BINDING.
-
- (keymap-global-set KEY BINDING)
- ≡
- (keymap-set (current-global-map) KEY BINDING)
-
- *Note (elisp)Key Binding Commands::.
-
- -- Function: keymap-local-set key command
- This function sets the binding of KEY in the current local keymap
- to BINDING.
-
- (keymap-local-set KEY BINDING)
- ≡
- (keymap-set (current-local-map) KEY BINDING)
-
- *Note (elisp)Key Binding Commands::.
-
- -- Function: keymap-global-unset key &optional remove
- This function removes the binding of KEY from the current global
- map.
-
- One use of this function is in preparation for defining a longer
- key that uses KEY as a prefix—which would not be allowed if KEY has
- a non-prefix binding. For example:
-
- (keymap-global-unset "C-l")
- ⇒ nil
- (keymap-global-set "C-l C-l" 'redraw-display)
- ⇒ nil
-
- *Note (elisp)Key Binding Commands::.
-
- -- Function: keymap-local-unset key &optional remove
- This function removes the binding of KEY from the current local
- map.
-
- *Note (elisp)Key Binding Commands::.
-
- -- Function: keymap-substitute keymap olddef newdef &optional oldmap
- prefix
- Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as
- OLDDEF. In other words, OLDDEF is replaced with NEWDEF wherever it
- appears. Alternatively, if optional fourth argument OLDMAP is
- specified, we redefine in KEYMAP as NEWDEF those keys that are
- defined as OLDDEF in OLDMAP.
-
- -- Function: keymap-lookup keymap key &optional accept-default no-remap
- position
- This function returns the definition of KEY in KEYMAP. All the
- other functions described in this chapter that look up keys use
- ‘keymap-lookup’. Here are examples:
-
- (keymap-lookup (current-global-map) "C-x C-f")
- ⇒ find-file
- (keymap-lookup (current-global-map) "C-x C-f 1 2 3 4 5")
- ⇒ 2
-
- *Note (elisp)Functions for Key Lookup::.
-
- -- Function: keymap-local-lookup keys &optional accept-default
- Like ‘keymap-lookup’, but restricting the search for commands bound
- to KEYS to the current local keymap.
-
- -- Function: keymap-global-lookup keys &optional accept-default
- Like ‘keymap-lookup’, but restricting the search for commands bound
- to KEYS to the current global keymap.
-
- -- Function: define-keymap &rest definitions
- You can create a keymap with the functions described above, and
- then use ‘keymap-set’ (*note (elisp)Changing Key Bindings::) to
- specify key bindings in that map. When writing modes, however, you
- frequently have to bind a large number of keys at once, and using
- ‘keymap-set’ on them all can be tedious and error-prone. Instead
- you can use ‘define-keymap’, which creates a keymap and binds a
- number of keys. Here’s a very basic example:
-
- (define-keymap
- "n" #'forward-line
- "f" #'previous-line
- "C-c C-c" #'quit-window)
-
- This function creates a new sparse keymap, defines the keystrokes
- in PAIRS, and returns the new keymap.
-
- PAIRS is a list of alternating key bindings and key definitions, as
- accepted by ‘keymap-set’. In addition, the key can be the special
- symbol ‘:menu’, in which case the definition should be a menu
- definition as accepted by ‘easy-menu-define’ (*note (elisp)Easy
- Menu::). Here’s a brief example of this usage:
-
- (define-keymap :full t
- "g" #'eww-reload
- :menu '("Eww"
- ["Exit" quit-window t]
- ["Reload" eww-reload t]))
-
- A number of keywords can be used before the key/definition pairs to
- change features of the new keymap. If any of the feature keywords
- is missing from the ‘define-keymap’ call, the default value for
- that feature is ‘nil’. Here’s a list of the available feature
- keywords:
-
- ‘:full’
- If non-‘nil’, create a char-table keymap (as from
- ‘make-keymap’) instead of a sparse keymap (as from
- ‘make-sparse-keymap’ (*note (elisp)Creating Keymaps::). A
- sparse keymap is the default.
-
- ‘:parent’
- If non-‘nil’, the value should be a keymap to use as the
- parent (*note (elisp)Inheritance and Keymaps::).
-
- ‘:keymap’
- If non-‘nil’, the value should be a keymap. Instead of
- creating a new keymap, the specified keymap is modified
- instead.
-
- ‘:suppress’
- If non-‘nil’, the keymap will be suppressed with
- ‘suppress-keymap’ (*note (elisp)Changing Key Bindings::). By
- default, digits and the minus sign are exempt from
- suppressing, but if the value is ‘nodigits’, this suppresses
- digits and minus-sign like it does with other characters.
-
- ‘:name’
- If non-‘nil’, the value should be a string to use as the menu
- for the keymap if you use it as a menu with ‘x-popup-menu’
- (*note (elisp)Pop-Up Menus::).
-
- ‘:prefix’
- If non-‘nil’, the value should be a symbol to be used as a
- prefix command (*note (elisp)Prefix Keys::). If this is the
- case, this symbol is returned by ‘define-keymap’ instead of
- the map itself.
-
- -- Function: defvar-keymap (variable-name &rest defs)
- By far, the most common thing to do with a keymap is to bind it to
- a variable. This is what virtually all modes do—a mode called
- ‘foo’ almost always has a variable called ‘foo-mode-map’.
-
- This macro defines NAME as a variable, passes OPTIONS and PAIRS to
- ‘define-keymap’, and uses the result as the default value for the
- variable.
-
- OPTIONS is like the keywords in ‘define-keymap’, but there’s an
- additional ‘:doc’ keyword that provides the doc string for the
- defined variable.
-
- Here’s an example:
-
- (defvar-keymap eww-textarea-map
- :parent text-mode-map
- "RET" #'forward-line
- "TAB" #'shr-next-link)
-
- -- Macro: while-let spec then-forms...
- Like ‘when-let’, but repeat until a binding in SPEC is ‘nil’. The
- return value is always ‘nil’.
-
- This is comparable to ‘and-let*’.
-
- -- Function: window-configuration-equal-p config1 config2
- This function says whether two window configurations have the same
- window layout, but ignores the values of point and the saved
- scrolling positions—it can return ‘t’ even if those aspects differ.
-
- -- Macro: ert-with-temp-file name &rest body
- Bind NAME to the name of a new temporary file and evaluate BODY.
- Delete the temporary file after BODY exits normally or non-locally.
- NAME will be bound to the file name of the temporary file. See the
- docstring for supported keyword arguments.
-
- -- Macro: ert-with-temp-directory name &rest body
- Bind NAME to the name of a new temporary directory and evaluate
- BODY. Delete the temporary directory after BODY exits normally or
- non-locally.
-
- NAME is bound to the directory name, not the directory file name.
- (In other words, it will end with the directory delimiter; on
- Unix-like systems, it will end with "/".)
-
- The same keyword arguments are supported as in ‘ert-with-temp-file’
- (which see), except for ‘:text’.
-
- -- Function: cl-constantly value
- Return a function that takes any number of arguments, but returns
- VALUE.
-
- -- Macro: cl-with-gensyms names... body
- This macro expands to code that executes BODY with each of the
- variables in NAMES bound to a fresh uninterned symbol, or “gensym”,
- in Common Lisp parlance. For macros requiring more than one
- gensym, use of ‘cl-with-gensyms’ shortens the code and renders
- one’s intentions clearer. Compare:
-
- (defmacro my-macro (foo)
- (let ((bar (gensym "bar"))
- (baz (gensym "baz"))
- (quux (gensym "quux")))
- `(let ((,bar (+ ...)))
- ...)))
-
- (defmacro my-macro (foo)
- (cl-with-gensyms (bar baz quux)
- `(let ((,bar (+ ...)))
- ...)))
-
- -- Macro: cl-once-only ((variable form)...) body
- This macro is primarily to help the macro programmer ensure that
- forms supplied by the user of the macro are evaluated just once by
- its expansion even though the result of evaluating the form is to
- occur more than once. Less often, this macro is used to ensure
- that forms supplied by the macro programmer are evaluated just
- once.
-
- Each VARIABLE may be used to refer to the result of evaluating FORM
- in BODY. ‘cl-once-only’ binds each VARIABLE to a fresh uninterned
- symbol during the evaluation of BODY. Then, ‘cl-once-only’ wraps
- the final expansion in code to evaluate each FORM and bind the
- result to the corresponding uninterned symbol. Thus, when the
- macro writer substitutes the value for VARIABLE into the expansion
- they are effectively referring to the result of evaluating FORM,
- rather than FORM itself. Another way to put this is that each
- VARIABLE is bound to an expression for the (singular) result of
- evaluating FORM.
-
- The most common case is where VARIABLE is one of the arguments to
- the macro being written, so ‘(variable variable)’ may be
- abbreviated to just ‘variable’.
-
- For example, consider this macro:
-
- (defmacro my-list (x y &rest forms)
- (let ((x-result (gensym))
- (y-result (gensym)))
- `(let ((,x-result ,x)
- (,y-result ,y))
- (list ,x-result ,y-result ,x-result ,y-result
- (progn ,@forms))))
-
- In a call like ‘(my-list (pop foo) ...)’ the intermediate binding
- to ‘x-result’ ensures that the ‘pop’ is not done twice. But as a
- result the code is rather complex: the reader must keep track of
- how ‘x-result’ really just means the first parameter of the call to
- the macro, and the required use of multiple gensyms to avoid
- variable capture by ‘(progn ,@forms)’ obscures things further.
- ‘cl-once-only’ takes care of these details:
-
- (defmacro my-list (x y &rest forms)
- (cl-once-only (x y)
- `(list ,x ,y ,x ,y
- (progn ,@forms))))
-
-2.5.2 Extended Definitions
---------------------------
-
-These functions must be called explicitly via ‘compat-call’, since their
-calling convention or behavior was extended in Emacs 29.1:
-
- -- Function: compat-call set-transient-map keymap &optional keep-pred
- on-exit message timeout
- This function adds KEYMAP as a “transient” keymap, which takes
- precedence over other keymaps for one (or more) subsequent keys.
-
- Normally, KEYMAP is used just once, to look up the very next key.
- If the optional argument KEEP-PRED is ‘t’, the map stays active as
- long as the user types keys defined in KEYMAP; when the user types
- a key that is not in KEYMAP, the transient keymap is deactivated
- and normal key lookup continues for that key.
-
- The KEEP-PRED argument can also be a function. In that case, the
- function is called with no arguments, prior to running each
- command, while KEYMAP is active; it should return non-‘nil’ if
- KEYMAP should stay active.
-
- The optional argument ON-EXIT, if non-‘nil’, specifies a function
- that is called, with no arguments, after KEYMAP is deactivated.
-
- The optional argument MESSAGE specifies the message to display
- after activating the transient map. If MESSAGE is a string, it is
- the format string for the message, and any ‘%k’ specifier in that
- string is replaced with the list of keys from the transient map.
- Any other non-‘nil’ value of MESSAGE stands for the default message
- format ‘Repeat with %k’.
-
- If the optional argument TIMEOUT is non-‘nil’, it should be a
- number that specifies how many seconds of idle time to wait before
- deactivating KEYMAP. The value of the variable
- ‘set-transient-map-timeout’, if non-‘nil’, overrides the value of
- this argument.
-
- This function works by adding and removing KEYMAP from the variable
- ‘overriding-terminal-local-map’, which takes precedence over all
- other active keymaps (*note (Searching Keymaps)elisp::).
-
- -- Function: compat-call string-lines string &optional omit-nulls
- keep-newlines
- Split STRING into a list of strings on newline boundaries. If the
- optional argument OMIT-NULLS is non-‘nil’, remove empty lines from
- the results. If the optional argument KEEP-NEWLINES is non-‘nil’,
- don’t remove the trailing newlines from the result strings.
-
- *Note (elisp)Creating Strings::.
-
- -- Function: compat-call define-key
- This function is like ‘keymap-set’ (*note (elisp)Changing Key
- Bindings::, but understands only the legacy key syntaxes.
-
- In addition, this function also has a REMOVE argument. If it is
- non-‘nil’, the definition will be removed. This is almost the same
- as setting the definition to ‘nil’, but makes a difference if the
- KEYMAP has a parent, and KEY is shadowing the same binding in the
- parent. With REMOVE, subsequent lookups will return the binding in
- the parent, whereas with a ‘nil’ definition the lookups will return
- ‘nil’.
-
- *Note (elisp)Low-Level Key Binding::.
-
- This compatibility version handles the optional argument REMOVE.
-
- -- Function: compat-call plist-get plist prop &optional predicate
- This returns the value of the PROPERTY property stored in the
- property list PLIST. Comparisons are done with PREDICATE, and
- defaults to ‘eq’. It accepts a malformed PLIST argument. If
- PROPERTY is not found in the PLIST, it returns ‘nil’.
-
- *Note (elisp)Plist Access::.
-
- This compatibility version handles the optional argument PREDICATE.
- This is a generalized variable (*note (elisp)Generalized
- Variables::) that can be used to change a value with ‘setf’.
-
- -- Function: compat-call plist-put plist prop val &optional predicate
- This stores VALUE as the value of the PROPERTY property in the
- property list PLIST. Comparisons are done with PREDICATE, and
- defaults to ‘eq’. It may modify PLIST destructively, or it may
- construct a new list structure without altering the old. The
- function returns the modified property list, so you can store that
- back in the place where you got PLIST.
-
- *Note (elisp)Plist Access::.
-
- This compatibility version handles the optional argument PREDICATE.
-
- -- Function: compat-call plist-member plist prop &optional predicate
- This returns non-‘nil’ if PLIST contains the given PROPERTY.
- Comparisons are done with PREDICATE, and defaults to ‘eq’. Unlike
- ‘plist-get’, this allows you to distinguish between a missing
- property and a property with the value ‘nil’. The value is
- actually the tail of PLIST whose ‘car’ is PROPERTY.
-
- *Note (elisp)Plist Access::.
-
- This compatibility version handles the optional argument PREDICATE.
-
-2.5.3 Missing Definitions
--------------------------
-
-Compat does not provide support for the following Lisp features
-implemented in 29.1:
-
- • The function ‘imagep’.
- • The function ‘image-at-point-p’.
- • The function ‘function-documentation’.
- • The macro ‘with-undo-amalgamate’.
- • The function ‘string-glyph-split’.
- • The function ‘string-limit’.
- • The function ‘string-pixel-width’ and ‘buffer-text-pixel-size’.
- • The function ‘minibuffer-lazy-highlight-setup’.
- • The function ‘pp-emacs-lisp-code’.
- • The function ‘bidi-string-strip-control-characters’.
- • The native function ‘current-cpu-time’.
- • The functions ‘xdg-state-home’, ‘xdg-current-desktop’ and
- ‘xdg-session-type’.
- • The macro ‘setopt’.
- • The ‘oclosure’ library.
- • The ‘textsec’ library.
- • The ‘range’ library.
- • The ‘string-edit’ library.
- • The ‘vtable’ library.
- • The ‘pixel-fill’ library.
- • Support for symbols with position information.
-
-\1f
-File: docdzgy5X.info, Node: Emacs 30.1, Prev: Emacs 29.1, Up: Support
-
-2.6 Emacs 30.1
-==============
-
-2.6.1 Added Definitions
------------------------
-
-The following functions and macros are implemented in Emacs 30.1. These
-functions are made available by Compat on Emacs versions older than
-30.1. Note that due to upstream changes, it might happen that there
-will be the need for changes, so use these functions with care.
-
- -- Variable: trusted-content
- List of files and directories whose content we trust. Be extra
- careful here since trusting means that Emacs might execute the code
- contained within those files and directories without an explicit
- request by the user. One important case when this might happen is
- when ‘flymake-mode’ is enabled (for example, when it is added to a
- mode hook). Each element of the list should be a string: - If it
- ends in "/", it is considered as a directory name and means that
- Emacs should trust all the files whose name has this directory as a
- prefix. - else it is considered as a file name. Use abbreviated
- file names. For example, an entry "~/mycode" means that Emacs will
- trust all the files in your directory "mycode". This variable can
- also be set to ‘:all’, in which case Emacs will trust all files,
- which opens a gaping security hole.
-
- -- Function: trusted-content-p
- Return non-nil if we trust the contents of the current buffer.
- Here, "trust" means that we are willing to run code found inside of
- it. See also ‘trusted-content’.
-
- -- Function: color-oklab-to-xyz l a b
- Convert the OkLab color represented by L A B to CIE XYZ. Oklab is a
- perceptual color space created by Björn Ottosson
- <https://bottosson.github.io/posts/oklab/>. It has the property
- that changes in the hue and saturation of a color can be made while
- maintaining the same perceived lightness.
-
- -- Function: color-xyz-to-oklab x y z
- Convert the CIE XYZ color represented by X Y Z to Oklab.
-
- -- Function: color-oklab-to-srgb l a b
- Convert the Oklab color represented by L A B to sRGB.
-
- -- Function: color-srgb-to-oklab r g b
- Convert the sRGB color R G B to Oklab.
-
- -- Function: char-to-name char
- This function returns the Unicode name of CHAR. It returns ‘nil’
- if CHAR is not a character or has no Unicode name.
-
- -- Function: obarray-clear obarray
- This function removes all symbols from OBARRAY.
-
- -- Function: closurep object
- This function returns ‘t’ if OBJECT is a closure, which is a
- particular kind of function object. Currently closures are used
- for all byte-code functions and all interpreted functions.
-
- -- Function: interpreted-function-p object
- This function returns ‘t’ if OBJECT is an interpreted function.
-
- -- Function: primitive-function-p object
- Return ‘t’ if OBJECT is a built-in primitive function. This
- excludes special forms, since they are not functions.
-
- -- Function: value< a b
- This function returns non-‘nil’ if A comes before B in the standard
- sorting order; this means that it returns ‘nil’ when B comes before
- A, or if they are equal or unordered.
-
- The arguments A and B must have the same type. Specifically:
-
- • Numbers are compared using ‘<’.
- • Strings are compared using ‘string<’ and symbols are compared
- by comparing their names as strings.
- • Conses, lists, vectors and records are compared
- lexicographically. This means that the two sequences are
- compared element-wise from left to right until they differ,
- and the result is then that of ‘value<’ on the first pair of
- differing elements. If one sequence runs out of elements
- before the other, the shorter sequence comes before the
- longer.
- • Markers are compared first by buffer, then by position.
- • Buffers and processes are compared by comparing their names as
- strings. Dead buffers (whose name is ‘nil’) will compare
- before any live buffer.
- • Other types are considered unordered and the return value will
- be ‘nil’.
-
- Examples:
- (value< -4 3.5) ⇒ t
- (value< "dog" "cat") ⇒ nil
- (value< 'yip 'yip) ⇒ nil
- (value< '(3 2) '(3 2 0)) ⇒ t
- (value< [3 2 "a"] [3 2 "b"]) ⇒ t
-
- Note that ‘nil’ is treated as either a symbol or an empty list,
- depending on what it is compared against:
-
- (value< nil '(0)) ⇒ t
- (value< 'nib nil) ⇒ t
-
- There is no limit to the length of sequences (lists, vectors and so
- on) that can be compared, but ‘value<’ may fail with an error if
- used to compare circular or deeply nested data structures.
-
- -- Function: drop n list
- This function is an alias for ‘nthcdr’. It returns the Nth CDR of
- LIST. In other words, it skips past the first N links of LIST and
- returns what follows.
-
- -- Function: get-truename-buffer filename
- Return the buffer with ‘file-truename’ equal to FILENAME (a
- string). If there is no such live buffer, return nil. See also
- ‘find-buffer-visiting’.
-
- -- Function: find-buffer variable value
- Return the buffer with buffer-local VARIABLE equal to VALUE. If
- there is no such live buffer, return nil.
-
- -- Function: require-with-check feature &optional filename noerror
- This function works like ‘require’, except if FEATURE is already
- loaded (i.e. is already a member of the list in ‘features’, see
- below). If FEATURE is already loaded, this function checks if
- FEATURE was provided by a file different from FILENAME, and if so,
- it by default signals an error. If the value of the optional
- argument NOERROR is ‘reload’, the function doesn’t signal an error,
- but instead forcibly reloads FILENAME; if NOERROR is some other
- non-‘nil’ value, the function emits a warning about FEATURE being
- already provided by another file.
-
- -- Function: merge-ordered-lists lists &optional error-function
- Merge LISTS in a consistent order. LISTS is a list of lists of
- elements. Merge them into a single list containing the same
- elements (removing duplicates), obeying their relative positions in
- each list. The order of the (sub)lists determines the final order
- in those cases where the order within the sublists does not impose
- a unique choice. Equality of elements is tested with ‘eql’.
-
- If a consistent order does not exist, call ERROR-FUNCTION with a
- remaining list of lists that we do not know how to merge. It
- should return the candidate to use to continue the merge, which has
- to be the head of one of the lists. By default we choose the head
- of the first list.
-
- -- Variable: completion-lazy-hilit
- If non-nil, request lazy highlighting of completion candidates.
-
- Lisp programs (a.k.a. "front ends") that present completion
- candidates may opt to bind this variable to a non-nil value when
- calling functions (such as ‘completion-all-completions’) which
- produce completion candidates. This tells the underlying
- completion styles that they do not need to fontify (i.e.,
- propertize with the ‘face’ property) completion candidates in a way
- that highlights the matching parts. Then it is the front end which
- presents the candidates that becomes responsible for this
- fontification. The front end does that by calling the function
- ‘completion-lazy-hilit’ on each completion candidate that is to be
- displayed to the user.
-
- Note that only some completion styles take advantage of this
- variable for optimization purposes. Other styles will ignore the
- hint and fontify eagerly as usual. It is still safe for a front
- end to call ‘completion-lazy-hilit’ in these situations.
-
- To author a completion style that takes advantage of this variable,
- see ‘completion-lazy-hilit-fn’ and
- ‘completion-pcm--hilit-commonality’.
-
- -- Variable: completion-lazy-hilit-fn
- Fontification function set by lazy-highlighting completions styles.
- When a given style wants to enable support for
- ‘completion-lazy-hilit’ (which see), that style should set this
- variable to a function of one argument. It will be called with
- each completion candidate, a string, to be displayed to the user,
- and should destructively propertize these strings with the ‘face’
- property.
-
- -- Function: completion-lazy-hilit str
- Return a copy of completion candidate STR that is face-propertized.
- See documentation of the variable ‘completion-lazy-hilit’ for more
- details.
-
- -- Macro: static-if condition then-form else-forms...
- Test CONDITION at macro-expansion time. If its value is non-‘nil’,
- expand the macro to THEN-FORM, otherwise expand it to ELSE-FORMS
- enclosed in a ‘progn’. ELSE-FORMS may be empty.
-
- Here is an example of its use from CC Mode, which prevents a
- ‘defadvice’ form being compiled in newer versions of Emacs:
- (static-if (boundp 'comment-line-break-function)
- (progn)
- (defvar c-inside-line-break-advice nil)
- (defadvice indent-new-comment-line (around c-line-break-advice
- activate preactivate)
- "Call `c-indent-new-comment-line' if in CC Mode."
- (if (or c-inside-line-break-advice
- (not c-buffer-is-cc-mode))
- ad-do-it
- (let ((c-inside-line-break-advice t))
- (c-indent-new-comment-line (ad-get-arg 0))))))
-
-2.6.2 Extended Definitions
---------------------------
-
-These functions must be called explicitly via ‘compat-call’, since their
-calling convention or behavior was extended in Emacs 30.1:
-
- -- Function: compat-call sort sequence &rest keyword-args
- This function sorts SEQUENCE, which must be a list or vector, and
- returns a sorted sequence of the same type. The sort is stable,
- which means that elements with equal sort keys maintain their
- relative order. It takes the following optional keyword arguments:
-
- ‘:key KEYFUNC’
- Use KEYFUNC, a function that takes a single element from
- SEQUENCE and returns its key value, to generate the keys used
- in comparison. If this argument is absent or if KEYFUNC is
- ‘nil’ then ‘identity’ is assumed; that is, the elements
- themselves are used as sorting keys.
-
- ‘:lessp PREDICATE’
- Use PREDICATE to order the keys. PREDICATE is a function that
- takes two sort keys as arguments and returns non-‘nil’ if the
- first should come before the second. If this argument is
- absent or PREDICATE is ‘nil’, then ‘value<’ is used, which is
- applicable to many different Lisp types and generally sorts in
- ascending order.
-
- For consistency, any predicate must obey the following rules:
- • It must be “antisymmetric”: it cannot both order A before
- B and B before A.
- • It must be “transitive”: if it orders A before B and B
- before C, then it must also order A before C.
-
- ‘:reverse FLAG’
- If FLAG is non-‘nil’, the sorting order is reversed. With the
- default ‘:lessp’ predicate this means sorting in descending
- order.
-
- ‘:in-place FLAG’
- If FLAG is non-‘nil’, then SEQUENCE is sorted in-place
- (destructively) and returned. If ‘nil’, or if this argument
- is not given, a sorted copy of the input is returned and
- SEQUENCE itself remains unmodified. In-place sorting is
- slightly faster, but the original sequence is lost.
-
- If the default behaviour is not suitable for your needs, it is
- usually easier and faster to supply a new ‘:key’ function than a
- different ‘:lessp’ predicate. For example, consider sorting these
- strings:
-
- (setq numbers '("one" "two" "three" "four" "five" "six"))
- (sort numbers)
- ⇒ ("five" "four" "one" "six" "three" "two")
-
- You can sort the strings by length instead by supplying a different
- key function:
-
- (sort numbers :key #'length)
- ⇒ ("one" "two" "six" "four" "five" "three")
-
- Note how strings of the same length keep their original order,
- thanks to the sorting stability. Now suppose you want to sort by
- length, but use the string contents to break ties. The easiest way
- is to specify a key function that transforms an element to a value
- that is sorted this way. Since ‘value<’ orders compound objects
- (conses, lists, vectors and records) lexicographically, you could
- do:
-
- (sort numbers :key (lambda (x) (cons (length x) x)))
- ⇒ ("one" "six" "two" "five" "four" "three")
-
- because ‘(3 . "six")’ is ordered before ‘(3 . "two")’ and so on.
-
- For compatibility with previous versions of Emacs, the ‘sort’
- function can also be called using the fixed two-argument form:
-
- (sort SEQUENCE PREDICATE)
-
- where PREDICATE is the ‘:lessp’ argument. When using this form,
- sorting is always done in-place.
-
- -- Function: compat-call completion-metadata-get metadata prop
- Get property PROP from completion METADATA. If the metadata
- specifies a completion category, the variables
- ‘completion-category-overrides’ and ‘completion-category-defaults’
- take precedence for category-specific overrides. If the completion
- metadata does not specify the property, the
- ‘completion-extra-properties’ plist is consulted. Note that the
- keys of the ‘completion-extra-properties’ plist are keyword
- symbols, not plain symbols.
-
- -- Function: compat-call copy-tree tree &optional vectors-and-records
- This function returns a copy of the tree TREE. If TREE is a cons
- cell, this makes a new cons cell with the same CAR and CDR, then
- recursively copies the CAR and CDR in the same way.
-
- Normally, when TREE is anything other than a cons cell, ‘copy-tree’
- simply returns TREE. However, if VECTORS-AND-RECORDS is non-‘nil’,
- it copies vectors and records too (and operates recursively on
- their elements). The TREE argument must not contain cycles.
-
-2.6.3 Missing Definitions
--------------------------
-
-Compat does not provide support for the following Lisp features
-implemented in 30.1:
-
-\1f
-File: docdzgy5X.info, Node: Development, Next: Function Index, Prev: Support, Up: Top
-
-3 Development
-*************
-
-Compat is developed on GitHub.
-
- Bug reports, patches and comments are best sent to the issue tracker
-(https://github.com/emacs-compat/compat/issues). These may include
-issues in the compatibility code, missing definitions or performance
-issues. We also provide a development mailing list
-(https://lists.sr.ht/~pkal/compat-devel) (~pkal/compat-develNOSPAMlists.sr.ht
-<~pkal/compat-develNOSPAMlists.sr.ht>).
-
- Please note that as a GNU ELPA package, Compat requires contributors
-to have signed the FSF copyright assignment
-(https://www.gnu.org/software/emacs/manual/html_node/emacs/Copyright-Assignment.html),
-before any non-trivial contribution (roughly 15 lines of code) can be
-applied.
-
- It is important that you provide tests when you contribute new
-functionality. Compat has 100% test coverage by the test suite. We use
-continuous integration to check if patches preserve existing
-functionality.
-
- Development for the currently stable Emacs version happens in the
-main branch of the Compat Git repository. ELPA-devel nightly builds are
-created from this branch. New features, which are not yet ready to be
-merged directly into the main branch, are developed in feature branches.
-Furthermore the Git repository has a branch emacs-<version> where the
-development for the upcoming Emacs release takes place. This branch is
-separate from the main branch since the new functionality should not be
-made available (neither via ELPA nor ELPA-devel) before the new Emacs
-version has been reasonably stabilized, e.g., around the time when the
-Emacs version branch is created in the Emacs repository on Savannah.
-
-\1f
-File: docdzgy5X.info, Node: Function Index, Next: Variable Index, Prev: Development, Up: Top
-
-Appendix A Function Index
-*************************
-
-\0\b[index\0\b]
-* Menu:
-
-* add-display-text-property: Emacs 29.1. (line 196)
-* alist-get: Emacs 25.1. (line 82)
-* always: Emacs 28.1. (line 83)
-* and-let*: Emacs 26.1. (line 158)
-* assoc-delete-all: Emacs 26.1. (line 13)
-* bignump: Emacs 27.1. (line 55)
-* bool-vector: Emacs 25.1. (line 177)
-* bounds-of-thing-at-mouse: Emacs 28.1. (line 296)
-* buffer-hash: Emacs 26.1. (line 80)
-* buffer-local-boundp: Emacs 28.1. (line 129)
-* buffer-local-restore-state: Emacs 29.1. (line 56)
-* buffer-local-set-state: Emacs 29.1. (line 56)
-* buffer-match-p: Emacs 29.1. (line 264)
-* buttonize: Emacs 29.1. (line 162)
-* buttonize-region: Emacs 29.1. (line 171)
-* char-to-name: Emacs 30.1. (line 50)
-* char-uppercase-p: Emacs 29.1. (line 133)
-* cl-constantly: Emacs 29.1. (line 641)
-* cl-once-only: Emacs 29.1. (line 664)
-* cl-with-gensyms: Emacs 29.1. (line 645)
-* closurep: Emacs 30.1. (line 57)
-* color-dark-p: Emacs 28.1. (line 326)
-* color-oklab-to-srgb: Emacs 30.1. (line 44)
-* color-oklab-to-xyz: Emacs 30.1. (line 34)
-* color-srgb-to-oklab: Emacs 30.1. (line 47)
-* color-values-from-color-spec: Emacs 28.1. (line 332)
-* color-xyz-to-oklab: Emacs 30.1. (line 41)
-* compat-call: Usage. (line 50)
-* compat-call alist-get: Emacs 26.1. (line 344)
-* compat-call assoc: Emacs 26.1. (line 316)
-* compat-call assoc-delete-all: Emacs 27.1. (line 417)
-* compat-call completion-metadata-get: Emacs 30.1. (line 287)
-* compat-call copy-tree: Emacs 30.1. (line 297)
-* compat-call count-windows: Emacs 28.1. (line 411)
-* compat-call define-key: Emacs 29.1. (line 761)
-* compat-call executable-find: Emacs 27.1. (line 429)
-* compat-call file-size-human-readable: Emacs 27.1. (line 397)
-* compat-call line-number-at-pos: Emacs 26.1. (line 330)
-* compat-call lookup-key: Emacs 27.1. (line 356)
-* compat-call make-temp-file: Emacs 26.1. (line 278)
-* compat-call plist-get: Emacs 29.1. (line 777)
-* compat-call plist-member: Emacs 29.1. (line 801)
-* compat-call plist-put: Emacs 29.1. (line 789)
-* compat-call recenter: Emacs 27.1. (line 346)
-* compat-call regexp-opt: Emacs 27.1. (line 385)
-* compat-call set-transient-map: Emacs 29.1. (line 716)
-* compat-call setq-local: Emacs 27.1. (line 370)
-* compat-call sort: Emacs 30.1. (line 212)
-* compat-call string-lines: Emacs 29.1. (line 752)
-* compat-call string-trim: Emacs 26.1. (line 375)
-* compat-call string-trim-left: Emacs 26.1. (line 359)
-* compat-call string-trim-right: Emacs 26.1. (line 367)
-* compat-call string-width: Emacs 28.1. (line 394)
-* compat-function: Usage. (line 58)
-* compiled-function-p: Emacs 29.1. (line 232)
-* completion-lazy-hilit: Emacs 30.1. (line 182)
-* count-sentences: Emacs 29.1. (line 31)
-* cXXXr: Emacs 26.1. (line 66)
-* cXXXXr: Emacs 26.1. (line 67)
-* date-days-in-month: Emacs 27.1. (line 213)
-* date-ordinal-to-time: Emacs 27.1. (line 220)
-* decoded-time-day: Emacs 27.1. (line 175)
-* decoded-time-dst: Emacs 27.1. (line 195)
-* decoded-time-hour: Emacs 27.1. (line 170)
-* decoded-time-minute: Emacs 27.1. (line 165)
-* decoded-time-month: Emacs 27.1. (line 180)
-* decoded-time-period: Emacs 28.1. (line 363)
-* decoded-time-second: Emacs 27.1. (line 160)
-* decoded-time-weekday: Emacs 27.1. (line 190)
-* decoded-time-year: Emacs 27.1. (line 185)
-* decoded-time-zone: Emacs 27.1. (line 200)
-* define-keymap: Emacs 29.1. (line 524)
-* defvar-keymap: Emacs 29.1. (line 592)
-* delete-line: Emacs 29.1. (line 65)
-* directory-abbrev-apply: Emacs 29.1. (line 388)
-* directory-abbrev-make-regexp: Emacs 29.1. (line 385)
-* directory-empty-p: Emacs 28.1. (line 247)
-* directory-name-p: Emacs 25.1. (line 56)
-* dlet: Emacs 28.1. (line 147)
-* dolist-with-progress-reporter: Emacs 27.1. (line 119)
-* drop: Emacs 30.1. (line 110)
-* ensure-list: Emacs 28.1. (line 162)
-* ert-with-temp-directory: Emacs 29.1. (line 629)
-* ert-with-temp-file: Emacs 29.1. (line 623)
-* file-attribute-access-time: Emacs 26.1. (line 223)
-* file-attribute-collect: Emacs 26.1. (line 260)
-* file-attribute-device-number: Emacs 26.1. (line 255)
-* file-attribute-file-identifier: Emacs 29.1. (line 345)
-* file-attribute-group-id: Emacs 26.1. (line 218)
-* file-attribute-inode-number: Emacs 26.1. (line 250)
-* file-attribute-link-number: Emacs 26.1. (line 208)
-* file-attribute-modes: Emacs 26.1. (line 245)
-* file-attribute-modification-time: Emacs 26.1. (line 228)
-* file-attribute-size: Emacs 26.1. (line 240)
-* file-attribute-status-change-time: Emacs 26.1. (line 234)
-* file-attribute-type: Emacs 26.1. (line 203)
-* file-attribute-user-id: Emacs 26.1. (line 213)
-* file-backup-file-names: Emacs 28.1. (line 351)
-* file-has-changed-p: Emacs 29.1. (line 370)
-* file-local-name: Emacs 26.1. (line 167)
-* file-modes-number-to-symbolic: Emacs 28.1. (line 345)
-* file-name-concat: Emacs 28.1. (line 53)
-* file-name-parent-directory: Emacs 29.1. (line 361)
-* file-name-quote: Emacs 26.1. (line 102)
-* file-name-quoted-p: Emacs 26.1. (line 95)
-* file-name-split: Emacs 29.1. (line 351)
-* file-name-unquote: Emacs 26.1. (line 90)
-* file-name-with-extension: Emacs 28.1. (line 229)
-* file-size-human-readable-iec: Emacs 27.1. (line 251)
-* find-buffer: Emacs 30.1. (line 120)
-* fixnump: Emacs 27.1. (line 60)
-* flatten-tree: Emacs 27.1. (line 132)
-* format-message: Emacs 25.1. (line 44)
-* format-prompt: Emacs 28.1. (line 258)
-* funcall-with-delayed-message: Emacs 29.1. (line 154)
-* function-alias-p: Emacs 29.1. (line 239)
-* garbage-collect-maybe: Emacs 28.1. (line 68)
-* gensym: Emacs 26.1. (line 70)
-* get-display-property: Emacs 29.1. (line 179)
-* get-scratch-buffer-create: Emacs 29.1. (line 44)
-* get-truename-buffer: Emacs 30.1. (line 115)
-* hash-table-empty: Emacs 25.1. (line 119)
-* if-let: Emacs 25.1. (line 96)
-* if-let*: Emacs 26.1. (line 149)
-* ignore-errors: Emacs 27.1. (line 106)
-* image-property: Emacs 26.1. (line 198)
-* insert-into-buffer: Emacs 28.1. (line 92)
-* interpreted-function-p: Emacs 30.1. (line 62)
-* key-parse: Emacs 29.1. (line 425)
-* key-valid-p: Emacs 29.1. (line 393)
-* keymap-global-lookup: Emacs 29.1. (line 520)
-* keymap-global-set: Emacs 29.1. (line 454)
-* keymap-global-unset: Emacs 29.1. (line 474)
-* keymap-local-lookup: Emacs 29.1. (line 516)
-* keymap-local-set: Emacs 29.1. (line 464)
-* keymap-local-unset: Emacs 29.1. (line 489)
-* keymap-lookup: Emacs 29.1. (line 503)
-* keymap-set: Emacs 29.1. (line 430)
-* keymap-substitute: Emacs 29.1. (line 495)
-* length<: Emacs 28.1. (line 45)
-* length=: Emacs 28.1. (line 42)
-* length>: Emacs 28.1. (line 50)
-* list-of-strings-p: Emacs 29.1. (line 68)
-* macroexp-file-name: Emacs 28.1. (line 305)
-* macroexp-parse: Emacs 25.1. (line 174)
-* macroexp-quote: Emacs 25.1. (line 171)
-* macroexp-warn-and-return: Emacs 28.1. (line 309)
-* macroexpand-1: Emacs 25.1. (line 164)
-* major-mode-restore: Emacs 27.1. (line 22)
-* major-mode-suspend: Emacs 27.1. (line 13)
-* make-empty-file: Emacs 27.1. (line 254)
-* make-lock-file-name: Emacs 28.1. (line 359)
-* make-nearby-temp-file: Emacs 26.1. (line 120)
-* make-separator-line: Emacs 28.1. (line 88)
-* mapcan: Emacs 26.1. (line 53)
-* mark-thing-at-mouse: Emacs 28.1. (line 302)
-* match-buffers: Emacs 29.1. (line 298)
-* merge-ordered-lists: Emacs 30.1. (line 135)
-* minibuffer-history-value: Emacs 27.1. (line 32)
-* named-let: Emacs 28.1. (line 211)
-* native-comp-available-p: Emacs 28.1. (line 375)
-* ntake: Emacs 29.1. (line 219)
-* obarray-clear: Emacs 30.1. (line 54)
-* package-get-version: Emacs 27.1. (line 205)
-* plistp: Emacs 29.1. (line 71)
-* pos-bol: Emacs 29.1. (line 125)
-* pos-eol: Emacs 29.1. (line 129)
-* primitive-function-p: Emacs 30.1. (line 65)
-* process-lines-handling-status: Emacs 28.1. (line 20)
-* process-lines-ignore-status: Emacs 28.1. (line 16)
-* proper-list-p: Emacs 27.1. (line 76)
-* provided-mode-derived-p: Emacs 27.1. (line 247)
-* read-answer: Emacs 26.1. (line 17)
-* read-char-from-minibuffer: Emacs 27.1. (line 44)
-* read-multiple-choice: Emacs 26.1. (line 185)
-* readablep: Emacs 29.1. (line 34)
-* region-bounds: Emacs 25.1. (line 28)
-* region-noncontiguous-p: Emacs 25.1. (line 34)
-* replace-regexp-in-string: Emacs 28.1. (line 108)
-* replace-string-in-region: Emacs 28.1. (line 102)
-* require-with-check: Emacs 30.1. (line 124)
-* ring-resize: Emacs 27.1. (line 28)
-* save-mark-and-excursion: Emacs 25.1. (line 39)
-* static-if: Emacs 30.1. (line 187)
-* string-chop-newline: Emacs 28.1. (line 206)
-* string-clean-whitespace: Emacs 28.1. (line 175)
-* string-distance: Emacs 27.1. (line 86)
-* string-equal-ignore-case: Emacs 29.1. (line 252)
-* string-fill: Emacs 28.1. (line 182)
-* string-glyph-split: Emacs 29.1. (line 307)
-* string-greaterp: Emacs 25.1. (line 64)
-* string-lines: Emacs 28.1. (line 190)
-* string-pad: Emacs 28.1. (line 197)
-* string-replace: Emacs 28.1. (line 77)
-* string-search: Emacs 28.1. (line 34)
-* string-split: Emacs 29.1. (line 258)
-* subr-primitive-p: Emacs 28.1. (line 368)
-* substitute-quotes: Emacs 29.1. (line 40)
-* take: Emacs 29.1. (line 205)
-* temporary-file-directory: Emacs 26.1. (line 137)
-* text-property-search-backward: Emacs 27.1. (line 332)
-* text-property-search-forward: Emacs 27.1. (line 260)
-* text-quoting-style: Emacs 28.1. (line 28)
-* thing-at-mouse: Emacs 28.1. (line 289)
-* thread-first: Emacs 25.1. (line 122)
-* thread-last: Emacs 25.1. (line 143)
-* time-equal-p: Emacs 27.1. (line 208)
-* trusted-content-p: Emacs 30.1. (line 29)
-* use-region-beginning: Emacs 29.1. (line 53)
-* use-region-end: Emacs 29.1. (line 50)
-* use-region-noncontiguous-p: Emacs 29.1. (line 47)
-* value<: Emacs 30.1. (line 69)
-* when-let: Emacs 25.1. (line 114)
-* when-let*: Emacs 26.1. (line 153)
-* while-let: Emacs 29.1. (line 612)
-* window-configuration-equal-p: Emacs 29.1. (line 618)
-* with-buffer-unmodified-if-unchanged: Emacs 29.1. (line 330)
-* with-delayed-message: Emacs 29.1. (line 137)
-* with-environment-variables: Emacs 28.1. (line 313)
-* with-existing-directory: Emacs 28.1. (line 136)
-* with-file-modes: Emacs 25.1. (line 71)
-* with-memoization: Emacs 29.1. (line 74)
-* with-minibuffer-selected-window: Emacs 27.1. (line 38)
-* with-restriction: Emacs 29.1. (line 79)
-* with-suppressed-warnings: Emacs 27.1. (line 65)
-* with-window-non-dedicated: Emacs 28.1. (line 383)
-* without-restriction: Emacs 29.1. (line 113)
-* xor: Emacs 27.1. (line 142)
-
-\1f
-File: docdzgy5X.info, Node: Variable Index, Prev: Function Index, Up: Top
-
-Appendix B Variable Index
-*************************
-
-\0\b[index\0\b]
-* Menu:
-
-* completion-lazy-hilit: Emacs 30.1. (line 149)
-* completion-lazy-hilit-fn: Emacs 30.1. (line 173)
-* exec-path: Emacs 27.1. (line 228)
-* gensym-counter: Emacs 26.1. (line 77)
-* lisp-directory: Emacs 29.1. (line 23)
-* mounted-file-systems: Emacs 26.1. (line 133)
-* regexp-unmatchable: Emacs 27.1. (line 152)
-* set-transient-map-timeout: Emacs 29.1. (line 742)
-* text-quoting-style: Emacs 25.1. (line 13)
-* trusted-content: Emacs 30.1. (line 14)
-* untrusted-content: Emacs 29.1. (line 17)
-
-
-\1f
-Tag Table:
-Node: Top\7f829
-Node: Introduction\7f2328
-Node: Overview\7f2491
-Node: Usage\7f3017
-Node: Limitations\7f7396
-Node: Support\7f12262
-Node: Emacs 25.1\7f12917
-Node: Emacs 26.1\7f21405
-Node: Emacs 27.1\7f38699
-Node: Emacs 28.1\7f59096
-Node: Emacs 29.1\7f79232
-Node: Emacs 30.1\7f116911
-Node: Development\7f131723
-Node: Function Index\7f133457
-Node: Variable Index\7f150276
-\1f
-End Tag Table
-
-\1f
-Local Variables:
-coding: utf-8
-End:
+++ /dev/null
-This is the file .../info/dir, which contains the
-topmost node of the Info hierarchy, called (dir)Top.
-The first time you invoke Info you start off looking at this node.
-\1f
-File: dir, Node: Top This is the top of the INFO tree
-
- This (the Directory node) gives a menu of major topics.
- Typing "q" exits, "H" lists all Info commands, "d" returns here,
- "h" gives a primer for first-timers,
- "mEmacs<Return>" visits the Emacs manual, etc.
-
- In Emacs, you can click mouse button 2 on a menu item or cross reference
- to select it.
-
-* Menu:
-
-Emacs
-* Compat: (compat). Compatibility Library for Emacs Lisp.