From: Andreas Gerler Date: Thu, 23 Nov 2023 18:47:04 +0000 (+0100) Subject: update compat X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=5fc1137a0288061d32df9f684742ea177504e8cd;p=emacsconfig.git update compat Signed-off-by: Andreas Gerler --- diff --git a/elpa/compat-29.1.3.4.signed b/elpa/compat-29.1.3.4.signed deleted file mode 100644 index 6475f6a4..00000000 --- a/elpa/compat-29.1.3.4.signed +++ /dev/null @@ -1 +0,0 @@ -Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) (trust undefined) created at 2023-02-11T23:05:03+0100 using RSA \ No newline at end of file diff --git a/elpa/compat-29.1.3.4/NEWS.org b/elpa/compat-29.1.3.4/NEWS.org deleted file mode 100644 index 0a54477a..00000000 --- a/elpa/compat-29.1.3.4/NEWS.org +++ /dev/null @@ -1,268 +0,0 @@ -#+title: compat.el - Changelog - -* 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. -- 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. -- 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: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: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: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: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 warrent 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>) diff --git a/elpa/compat-29.1.3.4/compat-25.el b/elpa/compat-29.1.3.4/compat-25.el deleted file mode 100644 index f6ad2ad4..00000000 --- a/elpa/compat-29.1.3.4/compat-25.el +++ /dev/null @@ -1,271 +0,0 @@ -;;; compat-25.el --- Functionality added in Emacs 25.1 -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2023 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 . - -;;; Commentary: - -;; Functionality added in Emacs 25.1, needed by older Emacs versions. - -;;; Code: - -(eval-when-compile (require 'compat-macs)) - -(compat-version "25.1") - -;;;; Defined in alloc.c - -(compat-defun bool-vector (&rest objects) ;; - "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 fns.c - -(compat-defun sort (seq predicate) ;; - "Handle vector SEQ." - :extended t - (cond - ((listp seq) - (sort seq predicate)) - ((vectorp seq) - (let* ((list (sort (append seq nil) predicate)) - (p list) (i 0)) - (while p - (aset seq i (car p)) - (setq i (1+ i) p (cdr p))) - (apply #'vector list))) - ((signal 'wrong-type-argument 'list-or-vector-p)))) - -;;;; Defined in editfns.c - -(compat-defalias format-message format) ;; - -;;;; Defined in fileio.c - -(compat-defun directory-name-p (name) ;; - "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 ;; - "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) ;; - -(declare-function region-bounds nil) ;; Defined in compat-26.el -(compat-defun region-noncontiguous-p () ;; - "Return non-nil if the region contains several pieces. -An example is a rectangular region handled as a list of -separate contiguous regions for each line." - (let ((bounds (region-bounds))) (and (cdr bounds) bounds))) - -;;;; Defined in subr.el - -(compat-defun string-greaterp (string1 string2) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "Check whether HASH-TABLE is empty (has 0 elements)." - (zerop (hash-table-count hash-table))) - -(compat-defmacro thread-first (&rest forms) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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))) - -(provide 'compat-25) -;;; compat-25.el ends here diff --git a/elpa/compat-29.1.3.4/compat-26.el b/elpa/compat-29.1.3.4/compat-26.el deleted file mode 100644 index 956c4a75..00000000 --- a/elpa/compat-29.1.3.4/compat-26.el +++ /dev/null @@ -1,554 +0,0 @@ -;;; compat-26.el --- Functionality added in Emacs 26.1 -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2023 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 . - -;;; Commentary: - -;; Functionality added in Emacs 26.1, needed by older Emacs versions. - -;;; Code: - -(eval-when-compile (require 'compat-macs)) -(compat-require compat-25 "25.1") - -(compat-version "26.1") - -;;;; Defined in fns.c - -(compat-defun buffer-hash (&optional buffer-or-name) ;; - "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) ;; - "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) ;; - "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 () ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - (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) ;; - "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) ;; - "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) ;; - "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) ;; - "Return the `car' of the `car' of the `car' of X." - (declare (pure t)) - (car (car (car x)))) - -(compat-defun caadr (x) ;; - "Return the `car' of the `car' of the `cdr' of X." - (declare (pure t)) - (car (car (cdr x)))) - -(compat-defun cadar (x) ;; - "Return the `car' of the `cdr' of the `car' of X." - (declare (pure t)) - (car (cdr (car x)))) - -(compat-defun caddr (x) ;; - "Return the `car' of the `cdr' of the `cdr' of X." - (declare (pure t)) - (car (cdr (cdr x)))) - -(compat-defun cdaar (x) ;; - "Return the `cdr' of the `car' of the `car' of X." - (declare (pure t)) - (cdr (car (car x)))) - -(compat-defun cdadr (x) ;; - "Return the `cdr' of the `car' of the `cdr' of X." - (declare (pure t)) - (cdr (car (cdr x)))) - -(compat-defun cddar (x) ;; - "Return the `cdr' of the `cdr' of the `car' of X." - (declare (pure t)) - (cdr (cdr (car x)))) - -(compat-defun cdddr (x) ;; - "Return the `cdr' of the `cdr' of the `cdr' of X." - (declare (pure t)) - (cdr (cdr (cdr x)))) - -(compat-defun caaaar (x) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - "Number used to construct the name of the next symbol created by `gensym'.") - -(compat-defun gensym (&optional prefix) ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - (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) ;; - "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 () ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "Return the number of links in ATTRIBUTES returned by `file-attributes'." - (nth 1 attributes)) - -(compat-defun file-attribute-user-id (attributes) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "The integer size (in bytes) in ATTRIBUTES returned by `file-attributes'." - (nth 7 attributes)) - -(compat-defun file-attribute-modes (attributes) ;; - "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) ;; - "The inode number in ATTRIBUTES returned by `file-attributes'. -It is a nonnegative integer." - (nth 10 attributes)) - -(compat-defun file-attribute-device-number (attributes) ;; - "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) ;; - "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 ;; - "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) ;; - "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) ;; - "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 diff --git a/elpa/compat-29.1.3.4/compat-27.el b/elpa/compat-29.1.3.4/compat-27.el deleted file mode 100644 index a2e47ca2..00000000 --- a/elpa/compat-29.1.3.4/compat-27.el +++ /dev/null @@ -1,898 +0,0 @@ -;;; compat-27.el --- Functionality added in Emacs 27.1 -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2023 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 . - -;;; Commentary: - -;; Functionality added in Emacs 27.1, needed by older Emacs versions. - -;;; Code: - -(eval-when-compile (require 'compat-macs)) -(compat-require compat-26 "26.1") - -(compat-version "27.1") - -;;;; Defined in fns.c - -(compat-defun proper-list-p (object) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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-defalias bignump ignore) ;; - -(compat-defmacro setq-local (&rest pairs) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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\\`" ;; - "Standard regexp guaranteed not to match any string at all." - :constant t) - -(compat-defun assoc-delete-all (key alist &optional test) ;; - "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 ;; - "Suspended major mode." - :local permanent) - -(compat-defun 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) ;; - "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 () ;; - "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 () ;; - "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 ;; - "The default history for the `read-char-from-minibuffer' function.") - -(compat-defvar read-char-from-minibuffer-map ;; - (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 ;; - (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) ;; - "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)) ;; - (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 () ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - (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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "Human-readable string for SIZE bytes, using IEC prefixes." - (compat--file-size-human-readable size 'iec " ")) - -(compat-defun 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) ;; - "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) ;; - "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) ;; - "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 () ;; - "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 "-", - ;; 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 - ;; "-" 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 dired.el - -(compat-defun dired-get-marked-files - (&optional localp arg filter distinguish-one-marked error) - "Obsolete function." - :obsolete "The compatibility function has been made obsolete." - :feature dired - :extended t - (let ((result (dired-get-marked-files localp arg filter distinguish-one-marked))) - (if (and (null result) error) - (user-error (if (stringp error) error "No files specified")) - result))) - -;;;; Defined in time-date.el - -(compat-defun 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) ;; - "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) ;; - "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)) ;; - (cl-defstruct (prop-match) beginning end value)) - -(compat-defun 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 ;; - (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) ;; - "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 ;; - "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) ;; - "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 diff --git a/elpa/compat-29.1.3.4/compat-28.el b/elpa/compat-29.1.3.4/compat-28.el deleted file mode 100644 index 57a40f71..00000000 --- a/elpa/compat-29.1.3.4/compat-28.el +++ /dev/null @@ -1,837 +0,0 @@ -;;; compat-28.el --- Functionality added in Emacs 28.1 -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2023 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 . - -;;; Commentary: - -;; Functionality added in Emacs 28.1, needed by older Emacs versions. - -;;; Code: - -(eval-when-compile (require 'compat-macs)) -(compat-require compat-27 "27.1") - -(compat-version "28.1") - -;;;; Defined in fns.c - -;; FIXME Should handle multibyte regular expressions -(compat-defun string-search (needle haystack &optional start-pos) ;; - "Search for the string NEEDLE in the strign 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))) - (save-match-data - (let ((case-fold-search nil)) - (string-match (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)) - ((signal 'wrong-type-argument 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)) - ((signal 'wrong-type-argument 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)) - ((signal 'wrong-type-argument sequence)))) - -;;;; Defined in fileio.c - -(compat-defun file-name-concat (directory &rest components) ;; - "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) ;; - -;;;; Defined in characters.c - -(compat-defun string-width (string &optional from to) ;; - "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) ;; - "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) ;; - "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) ;; - "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] http://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) ;; - "Make a string appropriate for usage as a visual separator line. -If LENGTH is nil, use the window width." - (concat (propertize (make-string (or length (1- (window-width))) ?-) - 'face 'separator-line) - "\n")) - -;;;; Defined in subr.el - -(compat-defun 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." - (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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "Return non-nil if SYMBOL is bound in BUFFER. -Also see `local-variable-p'." - (catch 'fail - (condition-case nil - (buffer-local-value symbol buffer) - (void-variable nil (throw 'fail nil))) - t)) - -(compat-defmacro with-existing-directory (&rest body) ;; - "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) ;; - "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) ;; - "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) ;; - -;;;; Defined in data.c - -(compat-defalias subr-native-elisp-p ignore) ;; - -;;;; Defined in subr-x.el - -(compat-defun string-clean-whitespace (string) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 () ;; - "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) ;; - "Set VARIABLES in the environent 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) ;; - "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 () ;; - "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) ;; - -(provide 'compat-28) -;;; compat-28.el ends here diff --git a/elpa/compat-29.1.3.4/compat-29.el b/elpa/compat-29.1.3.4/compat-29.el deleted file mode 100644 index 9cf4a769..00000000 --- a/elpa/compat-29.1.3.4/compat-29.el +++ /dev/null @@ -1,1503 +0,0 @@ -;;; compat-29.el --- Functionality added in Emacs 29.1 -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2023 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 . - -;;; Commentary: - -;; Functionality added in Emacs 29.1, needed by older Emacs versions. - -;;; Code: - -(eval-when-compile (require 'compat-macs)) -(compat-require compat-28 "28.1") - -;; Preloaded in loadup.el -;; TODO Update to 29.1 as soon as the Emacs emacs-29 branch version bumped -(compat-require seq "29.0") ;; - -;; TODO Update to 29.1 as soon as the Emacs emacs-29 branch version bumped -(compat-version "29.0") - -;;;; Defined in xdisp.c - -(compat-defun get-display-property (position prop &optional object properties) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "Handle optional argument PREDICATE." - :extended t - (if (or (null predicate) (eq predicate 'eq)) - (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) ;; - "Handle optional argument PREDICATE." - :extended t - (if (or (null predicate) (eq predicate 'eq)) - (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) ;; - "Handle optional argument PREDICATE." - :extended t - (if (or (null predicate) (eq predicate '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 ;; - (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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 () ;; - "Delete the current line." - (delete-region (pos-bol) (pos-bol 2))) - -(compat-defmacro with-narrowing (start end &rest rest) ;; - "Execute BODY with restrictions set to START and END. - -The current restrictions, if any, are restored upon return. - -With the optional :locked TAG argument, inside BODY, -`narrow-to-region' and `widen' can be used only within the START -and END limits, unless the restrictions are unlocked by calling -`narrowing-unlock' with TAG. See `narrowing-lock' for a more -detailed description. - -\(fn START END [:locked TAG] BODY)" - `(save-restriction - (narrow-to-region ,start ,end) - ;; Locking is ignored - ,@(if (eq (car rest) :locked) (cddr rest) rest))) - -(compat-defmacro with-memoization (place &rest code) ;; - "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-defun compiled-function-p (object) ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - "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 ;; - "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) ;; - "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 use-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 () ;; - "Return the start of the region if `use-region-p'." - (and (use-region-p) (region-beginning))) - -(compat-defun use-region-end () ;; - "Return the end of the region if `use-region-p'." - (and (use-region-p) (region-end))) - -(compat-defun 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) ;; - "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 ;; - &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) ;; - "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 file-name-split (filename) ;; - "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) ;; - "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) ;; - "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 ;; - (make-hash-table :test #'equal) - "Internal variable used by `file-has-changed-p'.") - -(compat-defun file-has-changed-p (file &optional tag) ;; - "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) ;; - "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-\" (the key named \"left\" with the hyper modifier) - \"M-RET\" (the \"return\" key with a meta modifier) - \"C-M-\" (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 . - (= (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) ;; - "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) ;; - "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 "". - (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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - (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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 by default all -commands in the map enter `repeat-mode'. This is useful when -there is a command that has the `repeat-map' symbol property, but -doesn'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'. This is useful when a -command exists in this specific map, but it doesn't have the -`repeat-map' symbol property on its symbol. - -\(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) ;; - "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) ;; - "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) ;; - "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) ;; - "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) ;; - "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 ;; - (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) ;; - "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-macs.el - -(compat-defmacro cl-with-gensyms (names &rest body) ;; - "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) ;; - "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) ;; - "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) ;; - "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)) - -(provide 'compat-29) -;;; compat-29.el ends here diff --git a/elpa/compat-29.1.3.4/compat-autoloads.el b/elpa/compat-29.1.3.4/compat-autoloads.el deleted file mode 100644 index 2044a1b7..00000000 --- a/elpa/compat-29.1.3.4/compat-autoloads.el +++ /dev/null @@ -1,34 +0,0 @@ -;;; compat-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "compat" "compat.el" (0 0 0 0)) -;;; Generated autoloads from compat.el - -(register-definition-prefixes "compat" '("compat-")) - -;;;*** - -;;;### (autoloads nil "compat-macs" "compat-macs.el" (0 0 0 0)) -;;; Generated autoloads from compat-macs.el - -(register-definition-prefixes "compat-macs" '("compat-")) - -;;;*** - -;;;### (autoloads nil nil ("compat-25.el" "compat-26.el" "compat-27.el" -;;;;;; "compat-28.el" "compat-29.el" "compat-pkg.el") (0 0 0 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; compat-autoloads.el ends here diff --git a/elpa/compat-29.1.3.4/compat-macs.el b/elpa/compat-29.1.3.4/compat-macs.el deleted file mode 100644 index f34cb0d4..00000000 --- a/elpa/compat-29.1.3.4/compat-macs.el +++ /dev/null @@ -1,266 +0,0 @@ -;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: t; -*- - -;; Copyright (C) 2021-2023 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 . - -;;; Commentary: - -;; This file provides *internal* macros, which are used by Compat to -;; facilitate the definition of compatibility functions, macros and -;; 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 should be considered -;; internal and may change any time between Compat releases. - -;;; 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)) - (when (<= emacs-major-version 25) - (delq (assq 'side-effect-free (car body)) (car body)) - (delq (assq 'pure (car body)) (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 -overriden. 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. - -- :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 - :local (lambda (x) (memq x '(nil t permanent))) - :obsolete (lambda (x) (or (booleanp x) (stringp x)))) - (lambda (constant local obsolete) - (compat-macs--strict (not (boundp name)) "%s already defined" name) - (compat-macs--assert (not (and constant local)) "Both :constant 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. - `((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 (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 diff --git a/elpa/compat-29.1.3.4/compat-pkg.el b/elpa/compat-29.1.3.4/compat-pkg.el deleted file mode 100644 index fc1c8acd..00000000 --- a/elpa/compat-29.1.3.4/compat-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;; Generated package description from compat.el -*- no-byte-compile: t -*- -(define-package "compat" "29.1.3.4" "Emacs Lisp Compatibility Library" '((emacs "24.4") (seq "2.3")) :commit "42cf6f29bcab1d390046299c09285db7be03932c" :authors '(("Philip Kaludercic , Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '("Daniel Mendler , Compat Development" . "~pkal/compat-devel@lists.sr.ht") :keywords '("lisp") :url "https://github.com/emacs-compat/compat") diff --git a/elpa/compat-29.1.3.4/compat.el b/elpa/compat-29.1.3.4/compat.el deleted file mode 100644 index 48d30c54..00000000 --- a/elpa/compat-29.1.3.4/compat.el +++ /dev/null @@ -1,93 +0,0 @@ -;;; compat.el --- Emacs Lisp Compatibility Library -*- lexical-binding: t; -*- - -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. - -;; Author: Philip Kaludercic , Daniel Mendler -;; Maintainer: Daniel Mendler , Compat Development <~pkal/compat-devel@lists.sr.ht> -;; Version: 29.1.3.4 -;; URL: https://github.com/emacs-compat/compat -;; Package-Requires: ((emacs "24.4") (seq "2.3")) -;; Keywords: lisp - -;; 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 . - -;;; 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-29 () - (when (< emacs-major-version 29) - (require 'compat-29) - '(require 'compat-29)))) -(compat--maybe-require-29) - -;;;; 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 diff --git a/elpa/compat-29.1.3.4/compat.info b/elpa/compat-29.1.3.4/compat.info deleted file mode 100644 index 8dc4614f..00000000 --- a/elpa/compat-29.1.3.4/compat.info +++ /dev/null @@ -1,2888 +0,0 @@ -This is doc5ZeelO.info, produced by makeinfo version 6.7 from -compat.texi. - -Copyright © 2022-2023 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 - - -File: doc5ZeelO.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 -29.1.3.4. - - Copyright © 2022-2023 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 - - - -File: doc5ZeelO.info, Node: Introduction, Next: Support, Prev: Top, Up: Top - -1 Introduction -************** - -* Menu: - -* Overview:: -* Usage:: -* Limitations:: - - -File: doc5ZeelO.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. - - -File: doc5ZeelO.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: - - ;; Package-Requires: ((emacs "24.4") (compat "29.1.3.4")) - - There is no need to depend on ‘emacs’ 24.4 specifically. One can -choose to 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. In packages which are part of Emacs itself -and which want to take advantage of Compat, the ‘noerror’ flag should be -specified: ‘(require 'compat nil 'noerror)’. In the future a minimal -version of Compat may be added to the Emacs core, such that the -‘noerror’ flag will not be necessary anymore. - - This will load all necessary Compat definitions. Compat also 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. - - Note that Compat provides replacement functions with extended -functionality for functions that are already defined (‘sort’, ‘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. - - (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 core packages, where Compat must be required -currently with the ‘noerror’ flag, the macros ‘compat-call’ and -‘compat-function’ ar not available. In the future the macros could be -added to subr. Alternatively a minimal version of compat.el could be -added to the core. For now it is necessary to replicate the definition -of the macros within core packages. For example the package ERC defines -its own macro ‘erc-compat-call’, which replicates the Compat definition -precisely. - - This design has been chosen 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-devel@lists.sr.ht -<~pkal/compat-devel@lists.sr.ht>). - - -File: doc5ZeelO.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. 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 -maintainance significantly 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. - - • 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 maintainance 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 - cannot be emulated. - - • The semantics of Elisp changed on a deep level. For example the - addition of Bigint support in Emacs 27.1 cannot be replicated on - the level of Compat. - - -File: doc5ZeelO.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 - - -File: doc5ZeelO.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 Extended Definitions --------------------------- - -These functions must be called explicitly via ‘compat-call’, since their -calling convention or behavior was extended in Emacs 25.1: - - -- Function: compat-call sort sequence predicate - This function sorts SEQUENCE stably. Note that this function - doesn’t work for all sequences; it may be used only for lists and - vectors. If SEQUENCE is a list, it is modified destructively. - This functions returns the sorted SEQUENCE and compares elements - using PREDICATE. A stable sort is one in which elements with equal - sort keys maintain their relative order before and after the sort. - Stability is important when successive sorts are used to order - elements according to different criteria. - - *Note (elisp)Sequence Functions::. - - The compatibility version adds support for vectors to be sorted, - not just lists. - -2.1.3 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. - - -File: doc5ZeelO.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 . 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 - ). - - -- 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 ‘svg’ library. - • The ‘xdg’ library. - - -File: doc5ZeelO.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. - - -File: doc5ZeelO.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. - - -- 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 regexp replacement &optional - start end - This function replaces all the occurrences of REGEXP with - REPLACEMENT in the region of buffer text between START and END; - START defaults to position of point, and END defaults to the last - accessible position of the buffer. The search for REGEXP is - case-sensitive, and REPLACEMENT is inserted without changing its - letter-case. The REPLACEMENT string can use the same special - elements starting with ‘\’ as ‘replace-match’ does. The function - returns the number of replaced occurrences, or ‘nil’ if REGEXP is - not found. The function preserves the position of point. - - (replace-regexp-in-region "foo[ \t]+bar" "foobar") - *Note (elisp)Search and Replace::. - - -- Function: replace-regexp-in-string 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. - - *Note (elisp)Search and Replace::. - - -- 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: subr-native-elisp-p object - Return ‘t’ if OBJECT if the object is native compiled lisp. If - native compilation is not available, this function always returns - ‘nil’. - - -- 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’. - • Support for the ‘natnum’ defcustom type. - • 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. - - -File: doc5ZeelO.info, Node: Emacs 29.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. - - -- 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. - - -- Macro: with-narrowing start end [:locked tag] &rest body - Execute BODY with restrictions set to START and END. The current - restrictions, if any, are restored upon return. With the optional - :locked TAG argument, inside TAG, ‘narrow-to-region’ and ‘widen’ - can be used only within the START and END limits, unless the - restrictions are unlocked by calling ‘narrowing-unlock’ with TAG. - See ‘narrowing-lock’ for a more detailed description. - - -- 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). - - -- 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 suvh 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: 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-’ - The key named "left" with the hyper modifier. - ‘M-RET’ - The "return" key with a meta modifier. - ‘C-M-’ - 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-’, ‘M-RET’ or ‘C-M-’. - - -- 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 ‘’, 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*’. - - -- 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’. - - -- 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 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. - - -File: doc5ZeelO.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-devel@lists.sr.ht -<~pkal/compat-devel@lists.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. - - -File: doc5ZeelO.info, Node: Function Index, Next: Variable Index, Prev: Development, Up: Top - -Appendix A Function Index -************************* - -[index] -* Menu: - -* add-display-text-property: Emacs 29.1. (line 137) -* alist-get: Emacs 25.1. (line 82) -* always: Emacs 28.1. (line 80) -* 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 178) -* bounds-of-thing-at-mouse: Emacs 28.1. (line 289) -* buffer-hash: Emacs 26.1. (line 80) -* buffer-local-boundp: Emacs 28.1. (line 122) -* buffer-local-restore-state: Emacs 29.1. (line 39) -* buffer-local-set-state: Emacs 29.1. (line 39) -* buffer-match-p: Emacs 29.1. (line 205) -* buttonize: Emacs 29.1. (line 103) -* buttonize-region: Emacs 29.1. (line 112) -* cl-once-only: Emacs 29.1. (line 588) -* cl-with-gensyms: Emacs 29.1. (line 569) -* color-dark-p: Emacs 28.1. (line 320) -* color-values-from-color-spec: Emacs 28.1. (line 326) -* compat-call: Usage. (line 43) -* compat-call <1>: Emacs 26.1. (line 278) -* 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 count-windows: Emacs 28.1. (line 402) -* compat-call define-key: Emacs 29.1. (line 685) -* 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 plist-get: Emacs 29.1. (line 701) -* compat-call plist-member: Emacs 29.1. (line 725) -* compat-call plist-put: Emacs 29.1. (line 713) -* 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 640) -* compat-call setq-local: Emacs 27.1. (line 370) -* compat-call sort: Emacs 25.1. (line 190) -* compat-call string-lines: Emacs 29.1. (line 676) -* 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 385) -* compat-function: Usage. (line 51) -* compiled-function-p: Emacs 29.1. (line 173) -* count-sentences: Emacs 29.1. (line 14) -* 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 357) -* 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 457) -* defvar-keymap: Emacs 29.1. (line 525) -* delete-line: Emacs 29.1. (line 48) -* directory-empty-p: Emacs 28.1. (line 240) -* directory-name-p: Emacs 25.1. (line 56) -* dlet: Emacs 28.1. (line 140) -* dolist-with-progress-reporter: Emacs 27.1. (line 119) -* ensure-list: Emacs 28.1. (line 155) -* ert-with-temp-directory: Emacs 29.1. (line 557) -* ert-with-temp-file: Emacs 29.1. (line 551) -* 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 286) -* 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 345) -* file-has-changed-p: Emacs 29.1. (line 311) -* file-local-name: Emacs 26.1. (line 167) -* file-modes-number-to-symbolic: Emacs 28.1. (line 339) -* file-name-concat: Emacs 28.1. (line 50) -* file-name-parent-directory: Emacs 29.1. (line 302) -* file-name-quote: Emacs 26.1. (line 102) -* file-name-quoted-p: Emacs 26.1. (line 95) -* file-name-split: Emacs 29.1. (line 292) -* file-name-unquote: Emacs 26.1. (line 90) -* file-name-with-extension: Emacs 28.1. (line 222) -* file-size-human-readable-iec: Emacs 27.1. (line 251) -* 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 251) -* funcall-with-delayed-message: Emacs 29.1. (line 95) -* function-alias-p: Emacs 29.1. (line 180) -* garbage-collect-maybe: Emacs 28.1. (line 65) -* gensym: Emacs 26.1. (line 70) -* get-display-property: Emacs 29.1. (line 120) -* get-scratch-buffer-create: Emacs 29.1. (line 27) -* hash-table-empty: Emacs 25.1. (line 120) -* if-let: Emacs 25.1. (line 97) -* 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 89) -* key-parse: Emacs 29.1. (line 358) -* key-valid-p: Emacs 29.1. (line 326) -* keymap-global-lookup: Emacs 29.1. (line 453) -* keymap-global-set: Emacs 29.1. (line 387) -* keymap-global-unset: Emacs 29.1. (line 407) -* keymap-local-lookup: Emacs 29.1. (line 449) -* keymap-local-set: Emacs 29.1. (line 397) -* keymap-local-unset: Emacs 29.1. (line 422) -* keymap-lookup: Emacs 29.1. (line 436) -* keymap-set: Emacs 29.1. (line 363) -* keymap-substitute: Emacs 29.1. (line 428) -* length<: Emacs 28.1. (line 42) -* length=: Emacs 28.1. (line 39) -* length>: Emacs 28.1. (line 47) -* list-of-strings-p: Emacs 29.1. (line 51) -* macroexp-file-name: Emacs 28.1. (line 298) -* macroexp-parse: Emacs 25.1. (line 175) -* macroexp-quote: Emacs 25.1. (line 172) -* macroexp-warn-and-return: Emacs 28.1. (line 302) -* macroexpand-1: Emacs 25.1. (line 165) -* 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 353) -* make-nearby-temp-file: Emacs 26.1. (line 120) -* make-separator-line: Emacs 28.1. (line 85) -* mapcan: Emacs 26.1. (line 53) -* mark-thing-at-mouse: Emacs 28.1. (line 295) -* match-buffers: Emacs 29.1. (line 239) -* minibuffer-history-value: Emacs 27.1. (line 32) -* named-let: Emacs 28.1. (line 204) -* ntake: Emacs 29.1. (line 160) -* package-get-version: Emacs 27.1. (line 205) -* plistp: Emacs 29.1. (line 54) -* pos-bol: Emacs 29.1. (line 70) -* pos-eol: Emacs 29.1. (line 74) -* process-lines-handling-status: Emacs 28.1. (line 17) -* process-lines-ignore-status: Emacs 28.1. (line 13) -* 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 17) -* region-bounds: Emacs 25.1. (line 28) -* region-noncontiguous-p: Emacs 25.1. (line 34) -* replace-regexp-in-string: Emacs 28.1. (line 114) -* replace-string-in-region: Emacs 28.1. (line 99) -* ring-resize: Emacs 27.1. (line 28) -* save-mark-and-excursion: Emacs 25.1. (line 39) -* string-chop-newline: Emacs 28.1. (line 199) -* string-clean-whitespace: Emacs 28.1. (line 168) -* string-distance: Emacs 27.1. (line 86) -* string-equal-ignore-case: Emacs 29.1. (line 193) -* string-fill: Emacs 28.1. (line 175) -* string-glyph-split: Emacs 29.1. (line 248) -* string-greaterp: Emacs 25.1. (line 64) -* string-lines: Emacs 28.1. (line 183) -* string-pad: Emacs 28.1. (line 190) -* string-replace: Emacs 28.1. (line 74) -* string-search: Emacs 28.1. (line 31) -* string-split: Emacs 29.1. (line 199) -* subr-native-elisp-p: Emacs 28.1. (line 369) -* subr-primitive-p: Emacs 28.1. (line 362) -* substitute-quotes: Emacs 29.1. (line 23) -* take: Emacs 29.1. (line 146) -* 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 25) -* thing-at-mouse: Emacs 28.1. (line 282) -* thread-first: Emacs 25.1. (line 123) -* thread-last: Emacs 25.1. (line 144) -* time-equal-p: Emacs 27.1. (line 208) -* use-region-beginning: Emacs 29.1. (line 36) -* use-region-end: Emacs 29.1. (line 33) -* use-region-noncontiguous-p: Emacs 29.1. (line 30) -* when-let: Emacs 25.1. (line 115) -* when-let*: Emacs 26.1. (line 153) -* while-let: Emacs 29.1. (line 545) -* with-buffer-unmodified-if-unchanged: Emacs 29.1. (line 271) -* with-delayed-message: Emacs 29.1. (line 78) -* with-environment-variables: Emacs 28.1. (line 306) -* with-existing-directory: Emacs 28.1. (line 129) -* with-file-modes: Emacs 25.1. (line 71) -* with-memoization: Emacs 29.1. (line 57) -* with-minibuffer-selected-window: Emacs 27.1. (line 38) -* with-narrowing: Emacs 29.1. (line 62) -* with-suppressed-warnings: Emacs 27.1. (line 65) -* with-window-non-dedicated: Emacs 28.1. (line 374) -* xor: Emacs 27.1. (line 142) - - -File: doc5ZeelO.info, Node: Variable Index, Prev: Function Index, Up: Top - -Appendix B Variable Index -************************* - -[index] -* Menu: - -* exec-path: Emacs 27.1. (line 228) -* gensym-counter: Emacs 26.1. (line 77) -* mounted-file-systems: Emacs 26.1. (line 133) -* regexp-unmatchable: Emacs 27.1. (line 152) -* set-transient-map-timeout: Emacs 29.1. (line 666) -* text-quoting-style: Emacs 25.1. (line 13) - - - -Tag Table: -Node: Top829 -Node: Introduction2258 -Node: Overview2421 -Node: Usage2947 -Node: Limitations7161 -Node: Support11786 -Node: Emacs 25.112371 -Node: Emacs 26.121773 -Node: Emacs 27.139025 -Node: Emacs 28.159422 -Node: Emacs 29.179048 -Node: Development113288 -Node: Function Index114308 -Node: Variable Index129229 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/compat-29.1.3.4/dir b/elpa/compat-29.1.3.4/dir deleted file mode 100644 index de02c6ea..00000000 --- a/elpa/compat-29.1.3.4/dir +++ /dev/null @@ -1,18 +0,0 @@ -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. - -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" 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. diff --git a/elpa/compat-29.1.4.1.signed b/elpa/compat-29.1.4.1.signed new file mode 100644 index 00000000..2e67f96e --- /dev/null +++ b/elpa/compat-29.1.4.1.signed @@ -0,0 +1 @@ +Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) (trust undefined) created at 2023-03-26T23:05:02+0200 using RSA \ No newline at end of file diff --git a/elpa/compat-29.1.4.1/NEWS.org b/elpa/compat-29.1.4.1/NEWS.org new file mode 100644 index 00000000..f7f1a1a3 --- /dev/null +++ b/elpa/compat-29.1.4.1/NEWS.org @@ -0,0 +1,289 @@ +#+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 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 warrent 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>) diff --git a/elpa/compat-29.1.4.1/compat-25.el b/elpa/compat-29.1.4.1/compat-25.el new file mode 100644 index 00000000..b393dc8e --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-25.el @@ -0,0 +1,271 @@ +;;; compat-25.el --- Functionality added in Emacs 25.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2023 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 . + +;;; 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) ;; + "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 fns.c + +(compat-defun sort (seq predicate) ;; + "Handle vector SEQ." + :extended t + (cond + ((listp seq) + (sort seq predicate)) + ((vectorp seq) + (let* ((list (sort (append seq nil) predicate)) + (p list) (i 0)) + (while p + (aset seq i (car p)) + (setq i (1+ i) p (cdr p))) + (apply #'vector list))) + ((signal 'wrong-type-argument 'list-or-vector-p)))) + +;;;; Defined in editfns.c + +(compat-defalias format-message format) ;; + +;;;; Defined in fileio.c + +(compat-defun directory-name-p (name) ;; + "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 ;; + "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) ;; + +(declare-function region-bounds nil) ;; Defined in compat-26.el +(compat-defun region-noncontiguous-p () ;; + "Return non-nil if the region contains several pieces. +An example is a rectangular region handled as a list of +separate contiguous regions for each line." + (let ((bounds (region-bounds))) (and (cdr bounds) bounds))) + +;;;; Defined in subr.el + +(compat-defun string-greaterp (string1 string2) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "Check whether HASH-TABLE is empty (has 0 elements)." + (zerop (hash-table-count hash-table))) + +(compat-defmacro thread-first (&rest forms) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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))) + +(provide 'compat-25) +;;; compat-25.el ends here diff --git a/elpa/compat-29.1.4.1/compat-26.el b/elpa/compat-29.1.4.1/compat-26.el new file mode 100644 index 00000000..0c22fbf0 --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-26.el @@ -0,0 +1,554 @@ +;;; compat-26.el --- Functionality added in Emacs 26.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2023 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 . + +;;; 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) ;; + "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) ;; + "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) ;; + "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 () ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "Return the `car' of the `car' of the `car' of X." + (declare (pure t)) + (car (car (car x)))) + +(compat-defun caadr (x) ;; + "Return the `car' of the `car' of the `cdr' of X." + (declare (pure t)) + (car (car (cdr x)))) + +(compat-defun cadar (x) ;; + "Return the `car' of the `cdr' of the `car' of X." + (declare (pure t)) + (car (cdr (car x)))) + +(compat-defun caddr (x) ;; + "Return the `car' of the `cdr' of the `cdr' of X." + (declare (pure t)) + (car (cdr (cdr x)))) + +(compat-defun cdaar (x) ;; + "Return the `cdr' of the `car' of the `car' of X." + (declare (pure t)) + (cdr (car (car x)))) + +(compat-defun cdadr (x) ;; + "Return the `cdr' of the `car' of the `cdr' of X." + (declare (pure t)) + (cdr (car (cdr x)))) + +(compat-defun cddar (x) ;; + "Return the `cdr' of the `cdr' of the `car' of X." + (declare (pure t)) + (cdr (cdr (car x)))) + +(compat-defun cdddr (x) ;; + "Return the `cdr' of the `cdr' of the `cdr' of X." + (declare (pure t)) + (cdr (cdr (cdr x)))) + +(compat-defun caaaar (x) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + "Number used to construct the name of the next symbol created by `gensym'.") + +(compat-defun gensym (&optional prefix) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + (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) ;; + "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 () ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "Return the number of links in ATTRIBUTES returned by `file-attributes'." + (nth 1 attributes)) + +(compat-defun file-attribute-user-id (attributes) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "The integer size (in bytes) in ATTRIBUTES returned by `file-attributes'." + (nth 7 attributes)) + +(compat-defun file-attribute-modes (attributes) ;; + "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) ;; + "The inode number in ATTRIBUTES returned by `file-attributes'. +It is a nonnegative integer." + (nth 10 attributes)) + +(compat-defun file-attribute-device-number (attributes) ;; + "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) ;; + "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 ;; + "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) ;; + "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) ;; + "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 diff --git a/elpa/compat-29.1.4.1/compat-27.el b/elpa/compat-29.1.4.1/compat-27.el new file mode 100644 index 00000000..3ff075dd --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-27.el @@ -0,0 +1,885 @@ +;;; compat-27.el --- Functionality added in Emacs 27.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2023 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 . + +;;; 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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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-defalias bignump ignore) ;; + +(compat-defmacro setq-local (&rest pairs) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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\\`" ;; + "Standard regexp guaranteed not to match any string at all." + :constant t) + +(compat-defun assoc-delete-all (key alist &optional test) ;; + "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 ;; + "Suspended major mode." + :local permanent) + +(compat-defun 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) ;; + "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 () ;; + "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 () ;; + "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 ;; + "The default history for the `read-char-from-minibuffer' function.") + +(compat-defvar read-char-from-minibuffer-map ;; + (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 ;; + (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) ;; + "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)) ;; + (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 () ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "Human-readable string for SIZE bytes, using IEC prefixes." + (compat--file-size-human-readable size 'iec " ")) + +(compat-defun 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) ;; + "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) ;; + "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) ;; + "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 () ;; + "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 "-", + ;; 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 + ;; "-" 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 ;; + (&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) ;; + "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) ;; + "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)) ;; + (cl-defstruct (prop-match) beginning end value)) + +(compat-defun 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 ;; + (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) ;; + "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 ;; + "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) ;; + "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 diff --git a/elpa/compat-29.1.4.1/compat-28.el b/elpa/compat-29.1.4.1/compat-28.el new file mode 100644 index 00000000..4cca3c20 --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-28.el @@ -0,0 +1,848 @@ +;;; compat-28.el --- Functionality added in Emacs 28.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2023 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 . + +;;; 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 fns.c + +;; FIXME Should handle multibyte regular expressions +(compat-defun string-search (needle haystack &optional start-pos) ;; + "Search for the string NEEDLE in the strign 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))) + (save-match-data + (let ((case-fold-search nil)) + (string-match (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)) + ((signal 'wrong-type-argument 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)) + ((signal 'wrong-type-argument 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)) + ((signal 'wrong-type-argument sequence)))) + +;;;; Defined in fileio.c + +(compat-defun file-name-concat (directory &rest components) ;; + "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) ;; + +;;;; Defined in characters.c + +(compat-defun string-width (string &optional from to) ;; + "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) ;; + "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) ;; + "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) ;; + "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] http://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) ;; + "Make a string appropriate for usage as a visual separator line. +If LENGTH is nil, use the window width." + (concat (propertize (make-string (or length (1- (window-width))) ?-) + 'face 'separator-line) + "\n")) + +;;;; Defined in subr.el + +(compat-defun 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." + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "Return non-nil if SYMBOL is bound in BUFFER. +Also see `local-variable-p'." + (catch 'fail + (condition-case nil + (buffer-local-value symbol buffer) + (void-variable nil (throw 'fail nil))) + t)) + +(compat-defmacro with-existing-directory (&rest body) ;; + "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) ;; + "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) ;; + "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) ;; + +;;;; Defined in data.c + +(compat-defalias subr-native-elisp-p ignore) ;; + +;;;; Defined in subr-x.el + +(compat-defun string-clean-whitespace (string) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 () ;; + "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) ;; + "Set VARIABLES in the environent 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) ;; + "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 () ;; + "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) ;; + +;;;; Defined in wid-edit.el + +(compat-guard t ;; + :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 diff --git a/elpa/compat-29.1.4.1/compat-29.el b/elpa/compat-29.1.4.1/compat-29.el new file mode 100644 index 00000000..8a22639b --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-29.el @@ -0,0 +1,1579 @@ +;;; compat-29.el --- Functionality added in Emacs 29.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2023 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 . + +;;; 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 +;; TODO Update to 29.1 as soon as the Emacs emacs-29 branch version bumped +(compat-require seq "29.0") ;; + +;; TODO Update to 29.1 as soon as the Emacs emacs-29 branch version bumped +(compat-version "29.0") + +;;;; Defined in xdisp.c + +(compat-defun get-display-property (position prop &optional object properties) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "Handle optional argument PREDICATE." + :extended t + (if (or (null predicate) (eq predicate 'eq)) + (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) ;; + "Handle optional argument PREDICATE." + :extended t + (if (or (null predicate) (eq predicate 'eq)) + (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) ;; + "Handle optional argument PREDICATE." + :extended t + (if (or (null predicate) (eq predicate '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 ;; + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 () ;; + "Delete the current line." + (delete-region (pos-bol) (pos-bol 2))) + +(compat-defmacro with-restriction (start end &rest rest) ;; + "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) ;; + "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) ;; + "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-defun compiled-function-p (object) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + "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 ;; + "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) ;; + "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 use-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 () ;; + "Return the start of the region if `use-region-p'." + (and (use-region-p) (region-beginning))) + +(compat-defun use-region-end () ;; + "Return the end of the region if `use-region-p'." + (and (use-region-p) (region-end))) + +(compat-defun 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) ;; + "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 ;; + &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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + (make-hash-table :test #'equal) + "Internal variable used by `file-has-changed-p'.") + +(compat-defun file-has-changed-p (file &optional tag) ;; + "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) ;; + "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-\" (the key named \"left\" with the hyper modifier) + \"M-RET\" (the \"return\" key with a meta modifier) + \"C-M-\" (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 . + (= (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) ;; + "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) ;; + "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 "". + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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 ;; + (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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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) ;; + "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)) ;; + :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 diff --git a/elpa/compat-29.1.4.1/compat-autoloads.el b/elpa/compat-29.1.4.1/compat-autoloads.el new file mode 100644 index 00000000..2044a1b7 --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-autoloads.el @@ -0,0 +1,34 @@ +;;; compat-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "compat" "compat.el" (0 0 0 0)) +;;; Generated autoloads from compat.el + +(register-definition-prefixes "compat" '("compat-")) + +;;;*** + +;;;### (autoloads nil "compat-macs" "compat-macs.el" (0 0 0 0)) +;;; Generated autoloads from compat-macs.el + +(register-definition-prefixes "compat-macs" '("compat-")) + +;;;*** + +;;;### (autoloads nil nil ("compat-25.el" "compat-26.el" "compat-27.el" +;;;;;; "compat-28.el" "compat-29.el" "compat-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; compat-autoloads.el ends here diff --git a/elpa/compat-29.1.4.1/compat-macs.el b/elpa/compat-29.1.4.1/compat-macs.el new file mode 100644 index 00000000..f34cb0d4 --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-macs.el @@ -0,0 +1,266 @@ +;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: t; -*- + +;; Copyright (C) 2021-2023 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 . + +;;; Commentary: + +;; This file provides *internal* macros, which are used by Compat to +;; facilitate the definition of compatibility functions, macros and +;; 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 should be considered +;; internal and may change any time between Compat releases. + +;;; 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)) + (when (<= emacs-major-version 25) + (delq (assq 'side-effect-free (car body)) (car body)) + (delq (assq 'pure (car body)) (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 +overriden. 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. + +- :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 + :local (lambda (x) (memq x '(nil t permanent))) + :obsolete (lambda (x) (or (booleanp x) (stringp x)))) + (lambda (constant local obsolete) + (compat-macs--strict (not (boundp name)) "%s already defined" name) + (compat-macs--assert (not (and constant local)) "Both :constant 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. + `((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 (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 diff --git a/elpa/compat-29.1.4.1/compat-pkg.el b/elpa/compat-29.1.4.1/compat-pkg.el new file mode 100644 index 00000000..ce297f22 --- /dev/null +++ b/elpa/compat-29.1.4.1/compat-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from compat.el -*- no-byte-compile: t -*- +(define-package "compat" "29.1.4.1" "Emacs Lisp Compatibility Library" '((emacs "24.4") (seq "2.3")) :commit "cb09942868d50e654f159f9614fe3f22af96e547" :authors '(("Philip Kaludercic , Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '("Daniel Mendler , Compat Development" . "~pkal/compat-devel@lists.sr.ht") :keywords '("lisp") :url "https://github.com/emacs-compat/compat") diff --git a/elpa/compat-29.1.4.1/compat.el b/elpa/compat-29.1.4.1/compat.el new file mode 100644 index 00000000..d318489d --- /dev/null +++ b/elpa/compat-29.1.4.1/compat.el @@ -0,0 +1,93 @@ +;;; compat.el --- Emacs Lisp Compatibility Library -*- lexical-binding: t; -*- + +;; Copyright (C) 2021-2023 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic , Daniel Mendler +;; Maintainer: Daniel Mendler , Compat Development <~pkal/compat-devel@lists.sr.ht> +;; Version: 29.1.4.1 +;; URL: https://github.com/emacs-compat/compat +;; Package-Requires: ((emacs "24.4") (seq "2.3")) +;; Keywords: lisp + +;; 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 . + +;;; 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-29 () + (when (< emacs-major-version 29) + (require 'compat-29) + '(require 'compat-29)))) +(compat--maybe-require-29) + +;;;; 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 diff --git a/elpa/compat-29.1.4.1/compat.info b/elpa/compat-29.1.4.1/compat.info new file mode 100644 index 00000000..fcd83e1c --- /dev/null +++ b/elpa/compat-29.1.4.1/compat.info @@ -0,0 +1,2951 @@ +This is doc0jZUSv.info, produced by makeinfo version 6.7 from +compat.texi. + +Copyright © 2022-2023 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 + + +File: doc0jZUSv.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 +29.1.4.1. + + Copyright © 2022-2023 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 + + + +File: doc0jZUSv.info, Node: Introduction, Next: Support, Prev: Top, Up: Top + +1 Introduction +************** + +* Menu: + +* Overview:: +* Usage:: +* Limitations:: + + +File: doc0jZUSv.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. + + +File: doc0jZUSv.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: + + ;; Package-Requires: ((emacs "24.4") (compat "29.1.4.1")) + + There is no need to depend on ‘emacs’ 24.4 specifically. One can +choose to 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. In packages which are part of Emacs itself +and which want to take advantage of Compat, the ‘noerror’ flag should be +specified: ‘(require 'compat nil 'noerror)’. In the future a minimal +version of Compat may be added to the Emacs core, such that the +‘noerror’ flag will not be necessary anymore. + + This will load all necessary Compat definitions. Compat also 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. + + Note that Compat provides replacement functions with extended +functionality for functions that are already defined (‘sort’, ‘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. + + (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 core packages, where Compat must be required +currently with the ‘noerror’ flag, the macros ‘compat-call’ and +‘compat-function’ ar not available. In the future the macros could be +added to subr. Alternatively a minimal version of compat.el could be +added to the core. For now it is necessary to replicate the definition +of the macros within core packages. For example the package ERC defines +its own macro ‘erc-compat-call’, which replicates the Compat definition +precisely. + + This design has been chosen 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-devel@lists.sr.ht +<~pkal/compat-devel@lists.sr.ht>). + + +File: doc0jZUSv.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. 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 +maintainance significantly 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 maintainance 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 + cannot be emulated. + + • The semantics of Elisp changed on a deep level. For example the + addition of Bigint support in Emacs 27.1 cannot be replicated on + the level of Compat. + + +File: doc0jZUSv.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 + + +File: doc0jZUSv.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 Extended Definitions +-------------------------- + +These functions must be called explicitly via ‘compat-call’, since their +calling convention or behavior was extended in Emacs 25.1: + + -- Function: compat-call sort sequence predicate + This function sorts SEQUENCE stably. Note that this function + doesn’t work for all sequences; it may be used only for lists and + vectors. If SEQUENCE is a list, it is modified destructively. + This functions returns the sorted SEQUENCE and compares elements + using PREDICATE. A stable sort is one in which elements with equal + sort keys maintain their relative order before and after the sort. + Stability is important when successive sorts are used to order + elements according to different criteria. + + *Note (elisp)Sequence Functions::. + + The compatibility version adds support for vectors to be sorted, + not just lists. + +2.1.3 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. + + +File: doc0jZUSv.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 . 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 + ). + + -- 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 ‘svg’ library. + • The ‘xdg’ library. + + +File: doc0jZUSv.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. + + +File: doc0jZUSv.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 regexp replacement &optional + start end + This function replaces all the occurrences of REGEXP with + REPLACEMENT in the region of buffer text between START and END; + START defaults to position of point, and END defaults to the last + accessible position of the buffer. The search for REGEXP is + case-sensitive, and REPLACEMENT is inserted without changing its + letter-case. The REPLACEMENT string can use the same special + elements starting with ‘\’ as ‘replace-match’ does. The function + returns the number of replaced occurrences, or ‘nil’ if REGEXP is + not found. The function preserves the position of point. + + (replace-regexp-in-region "foo[ \t]+bar" "foobar") + *Note (elisp)Search and Replace::. + + -- Function: replace-regexp-in-string 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. + + *Note (elisp)Search and Replace::. + + -- 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: subr-native-elisp-p object + Return ‘t’ if OBJECT if the object is native compiled lisp. If + native compilation is not available, this function always returns + ‘nil’. + + -- 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. + + +File: doc0jZUSv.info, Node: Emacs 29.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 28.1 is made available +by Compat. + + -- 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). + + -- 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 suvh 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-’ + The key named "left" with the hyper modifier. + ‘M-RET’ + The "return" key with a meta modifier. + ‘C-M-’ + 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-’, ‘M-RET’ or ‘C-M-’. + + -- 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 ‘’, 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*’. + + -- 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 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. + + +File: doc0jZUSv.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-devel@lists.sr.ht +<~pkal/compat-devel@lists.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. + + +File: doc0jZUSv.info, Node: Function Index, Next: Variable Index, Prev: Development, Up: Top + +Appendix A Function Index +************************* + +[index] +* Menu: + +* add-display-text-property: Emacs 29.1. (line 178) +* 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 178) +* bounds-of-thing-at-mouse: Emacs 28.1. (line 292) +* buffer-hash: Emacs 26.1. (line 80) +* buffer-local-boundp: Emacs 28.1. (line 125) +* buffer-local-restore-state: Emacs 29.1. (line 42) +* buffer-local-set-state: Emacs 29.1. (line 42) +* buffer-match-p: Emacs 29.1. (line 246) +* buttonize: Emacs 29.1. (line 144) +* buttonize-region: Emacs 29.1. (line 153) +* cl-constantly: Emacs 29.1. (line 618) +* cl-once-only: Emacs 29.1. (line 641) +* cl-with-gensyms: Emacs 29.1. (line 622) +* color-dark-p: Emacs 28.1. (line 323) +* color-values-from-color-spec: Emacs 28.1. (line 329) +* compat-call: Usage. (line 43) +* compat-call <1>: Emacs 26.1. (line 278) +* 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 count-windows: Emacs 28.1. (line 405) +* compat-call define-key: Emacs 29.1. (line 738) +* 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 plist-get: Emacs 29.1. (line 754) +* compat-call plist-member: Emacs 29.1. (line 778) +* compat-call plist-put: Emacs 29.1. (line 766) +* 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 693) +* compat-call setq-local: Emacs 27.1. (line 370) +* compat-call sort: Emacs 25.1. (line 190) +* compat-call string-lines: Emacs 29.1. (line 729) +* 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 388) +* compat-function: Usage. (line 51) +* compiled-function-p: Emacs 29.1. (line 214) +* count-sentences: Emacs 29.1. (line 17) +* 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 360) +* 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 506) +* defvar-keymap: Emacs 29.1. (line 574) +* delete-line: Emacs 29.1. (line 51) +* directory-abbrev-apply: Emacs 29.1. (line 370) +* directory-abbrev-make-regexp: Emacs 29.1. (line 367) +* directory-empty-p: Emacs 28.1. (line 243) +* directory-name-p: Emacs 25.1. (line 56) +* dlet: Emacs 28.1. (line 143) +* dolist-with-progress-reporter: Emacs 27.1. (line 119) +* ensure-list: Emacs 28.1. (line 158) +* ert-with-temp-directory: Emacs 29.1. (line 606) +* ert-with-temp-file: Emacs 29.1. (line 600) +* 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 327) +* 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 348) +* file-has-changed-p: Emacs 29.1. (line 352) +* file-local-name: Emacs 26.1. (line 167) +* file-modes-number-to-symbolic: Emacs 28.1. (line 342) +* file-name-concat: Emacs 28.1. (line 53) +* file-name-parent-directory: Emacs 29.1. (line 343) +* file-name-quote: Emacs 26.1. (line 102) +* file-name-quoted-p: Emacs 26.1. (line 95) +* file-name-split: Emacs 29.1. (line 333) +* file-name-unquote: Emacs 26.1. (line 90) +* file-name-with-extension: Emacs 28.1. (line 225) +* file-size-human-readable-iec: Emacs 27.1. (line 251) +* 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 254) +* funcall-with-delayed-message: Emacs 29.1. (line 136) +* function-alias-p: Emacs 29.1. (line 221) +* garbage-collect-maybe: Emacs 28.1. (line 68) +* gensym: Emacs 26.1. (line 70) +* get-display-property: Emacs 29.1. (line 161) +* get-scratch-buffer-create: Emacs 29.1. (line 30) +* hash-table-empty: Emacs 25.1. (line 120) +* if-let: Emacs 25.1. (line 97) +* 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) +* key-parse: Emacs 29.1. (line 407) +* key-valid-p: Emacs 29.1. (line 375) +* keymap-global-lookup: Emacs 29.1. (line 502) +* keymap-global-set: Emacs 29.1. (line 436) +* keymap-global-unset: Emacs 29.1. (line 456) +* keymap-local-lookup: Emacs 29.1. (line 498) +* keymap-local-set: Emacs 29.1. (line 446) +* keymap-local-unset: Emacs 29.1. (line 471) +* keymap-lookup: Emacs 29.1. (line 485) +* keymap-set: Emacs 29.1. (line 412) +* keymap-substitute: Emacs 29.1. (line 477) +* 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 54) +* macroexp-file-name: Emacs 28.1. (line 301) +* macroexp-parse: Emacs 25.1. (line 175) +* macroexp-quote: Emacs 25.1. (line 172) +* macroexp-warn-and-return: Emacs 28.1. (line 305) +* macroexpand-1: Emacs 25.1. (line 165) +* 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 356) +* 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 298) +* match-buffers: Emacs 29.1. (line 280) +* minibuffer-history-value: Emacs 27.1. (line 32) +* named-let: Emacs 28.1. (line 207) +* ntake: Emacs 29.1. (line 201) +* package-get-version: Emacs 27.1. (line 205) +* plistp: Emacs 29.1. (line 57) +* pos-bol: Emacs 29.1. (line 111) +* pos-eol: Emacs 29.1. (line 115) +* 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 20) +* region-bounds: Emacs 25.1. (line 28) +* region-noncontiguous-p: Emacs 25.1. (line 34) +* replace-regexp-in-string: Emacs 28.1. (line 117) +* replace-string-in-region: Emacs 28.1. (line 102) +* ring-resize: Emacs 27.1. (line 28) +* save-mark-and-excursion: Emacs 25.1. (line 39) +* string-chop-newline: Emacs 28.1. (line 202) +* string-clean-whitespace: Emacs 28.1. (line 171) +* string-distance: Emacs 27.1. (line 86) +* string-equal-ignore-case: Emacs 29.1. (line 234) +* string-fill: Emacs 28.1. (line 178) +* string-glyph-split: Emacs 29.1. (line 289) +* string-greaterp: Emacs 25.1. (line 64) +* string-lines: Emacs 28.1. (line 186) +* string-pad: Emacs 28.1. (line 193) +* string-replace: Emacs 28.1. (line 77) +* string-search: Emacs 28.1. (line 34) +* string-split: Emacs 29.1. (line 240) +* subr-native-elisp-p: Emacs 28.1. (line 372) +* subr-primitive-p: Emacs 28.1. (line 365) +* substitute-quotes: Emacs 29.1. (line 26) +* take: Emacs 29.1. (line 187) +* 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 285) +* thread-first: Emacs 25.1. (line 123) +* thread-last: Emacs 25.1. (line 144) +* time-equal-p: Emacs 27.1. (line 208) +* use-region-beginning: Emacs 29.1. (line 39) +* use-region-end: Emacs 29.1. (line 36) +* use-region-noncontiguous-p: Emacs 29.1. (line 33) +* when-let: Emacs 25.1. (line 115) +* when-let*: Emacs 26.1. (line 153) +* while-let: Emacs 29.1. (line 594) +* with-buffer-unmodified-if-unchanged: Emacs 29.1. (line 312) +* with-delayed-message: Emacs 29.1. (line 119) +* with-environment-variables: Emacs 28.1. (line 309) +* with-existing-directory: Emacs 28.1. (line 132) +* with-file-modes: Emacs 25.1. (line 71) +* with-memoization: Emacs 29.1. (line 60) +* with-minibuffer-selected-window: Emacs 27.1. (line 38) +* with-restriction: Emacs 29.1. (line 65) +* with-suppressed-warnings: Emacs 27.1. (line 65) +* with-window-non-dedicated: Emacs 28.1. (line 377) +* without-restriction: Emacs 29.1. (line 99) +* xor: Emacs 27.1. (line 142) + + +File: doc0jZUSv.info, Node: Variable Index, Prev: Function Index, Up: Top + +Appendix B Variable Index +************************* + +[index] +* Menu: + +* exec-path: Emacs 27.1. (line 228) +* gensym-counter: Emacs 26.1. (line 77) +* mounted-file-systems: Emacs 26.1. (line 133) +* regexp-unmatchable: Emacs 27.1. (line 152) +* set-transient-map-timeout: Emacs 29.1. (line 719) +* text-quoting-style: Emacs 25.1. (line 13) + + + +Tag Table: +Node: Top829 +Node: Introduction2258 +Node: Overview2421 +Node: Usage2947 +Node: Limitations7161 +Node: Support11945 +Node: Emacs 25.112530 +Node: Emacs 26.121932 +Node: Emacs 27.139184 +Node: Emacs 28.159581 +Node: Emacs 29.179251 +Node: Development115649 +Node: Function Index116669 +Node: Variable Index131882 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/compat-29.1.4.1/dir b/elpa/compat-29.1.4.1/dir new file mode 100644 index 00000000..de02c6ea --- /dev/null +++ b/elpa/compat-29.1.4.1/dir @@ -0,0 +1,18 @@ +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. + +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" 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.