From: Andreas Gerler Date: Sun, 11 Dec 2022 16:18:21 +0000 (+0100) Subject: add compat X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=79af9fa7b054e5407aa92cc436ba80ba26765514;p=emacsconfig.git add compat Signed-off-by: Andreas Gerler --- diff --git a/custom.el b/custom.el index 5410c282..f7a8b3e7 100644 --- a/custom.el +++ b/custom.el @@ -6,17 +6,13 @@ '(ansi-color-names-vector ["black" "red3" "green3" "yellow3" "LightSkyBlue1" "magenta3" "cyan3" "gray90"]) '(aws-snippets-ec2-list-instances-query - (quote - ("Reservations[].Instances[].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Schedule`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime]" "Reservations[].Instances[].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Schedule`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime, IamInstanceProfile.Arn]" "Reservations[].Instances[].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Schedule`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime, KeyName]" "Reservations[].Instances[?IamInstanceProfile.Arn==null].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Type`].Value[] | [0],Tags[?Key==`Project`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime, IamInstanceProfile.Arn]"))) - '(aws-snippets-profiles (quote ("test" "prod" "cn"))) - '(aws-snippets-regions - (quote - ("us-east-1" "eu-west-1" "ap-southeast-1" "cn-north-1"))) + '("Reservations[].Instances[].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Schedule`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime]" "Reservations[].Instances[].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Schedule`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime, IamInstanceProfile.Arn]" "Reservations[].Instances[].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Schedule`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime, KeyName]" "Reservations[].Instances[?IamInstanceProfile.Arn==null].[Tags[?Key==`Name`].Value[] | [0],Tags[?Key==`Type`].Value[] | [0],Tags[?Key==`Project`].Value[] | [0],InstanceId, State.Name, PublicDnsName, InstanceType,Placement.AvailabilityZone,LaunchTime, IamInstanceProfile.Arn]")) + '(aws-snippets-profiles '("test" "prod" "cn")) + '(aws-snippets-regions '("us-east-1" "eu-west-1" "ap-southeast-1" "cn-north-1")) '(blink-cursor-mode t) '(cfengine-parameters-indent '(promise pname 2)) '(custom-safe-themes - (quote - ("8db4b03b9ae654d4a57804286eb3e332725c84d7cdab38463cb6b97d5762ad26" default))) + '("8db4b03b9ae654d4a57804286eb3e332725c84d7cdab38463cb6b97d5762ad26" default)) '(gnuserv-program (concat exec-directory "/gnuserv")) '(grep-template "grep -i -nH -e ") '(helm-comint-mode-list '(comint-mode slime-repl-mode sql-interactive-mode)) @@ -32,10 +28,13 @@ '(german-holidays jenkinsfile-mode cider company seq flymake log4e annotate a magit-section bicycle beacon alert graphviz-dot-mode helm-core apache-mode groovy-mode kubel solarized-theme lsp-ui docker-tramp dockerfile-mode yasnippet with-editor treepy transient simple-httpd request markdown-mode magit-popup hydra htmlize hl-todo helm git-commit f elfeed dash-functional dash clomacs clojure-mode async magit org lsp-mode git-link eglot helm-org biblio parsebib parseedn lv yaml-mode xah-lookup x-path-walker visual-regexp visual-ascii-mode vertica-snippets undo-tree twittering-mode tt-mode tldr terraform-mode tabulated-list sx string-inflection string-edit sqlup-mode sokoban smartparens sicp s3ed rhtml-mode restclient-helm rainbow-mode rainbow-delimiters puppet-mode paradox pacmacs package-lint ox-reveal ox-jira ox-clip org-tree-slide org-sticky-header org-ref org-plus-contrib org-mime org-jira org-chef org-ac ob-tmux ob-restclient ob-cfengine3 ob-async neotree mwe-log-commands mustache multiple-cursors mew magit-todos magit-gitflow langtool keyfreq json-mode impatient-mode highlight-symbol helm-swoop helm-safari helm-projectile helm-gtags helm-git helm-descbinds helm-c-yasnippet helm-aws guide-key graphql go-snippets go-mode gnuplot git-timemachine ghub ggtags fullscreen-mode fullframe flymake-yaml flymake-puppet flymake-perlcritic flymake-json flycheck fast-scroll expand-region ess epoch-view engine-mode elfeed-org ejc-sql editorconfig edit-indirect dired-narrow dired+ demo-it debian-changelog-mode csv-nav csv-mode command-log-mode color-identifiers-mode centered-cursor-mode bug-hunter aws-snippets avy ascii artbollocks-mode apples-mode ac-helm)) '(package-user-dir "~/.emacs.d/elpa") '(paradox-github-token t) - '(safe-local-variable-values (quote ((bba-keep-whitespaces . 1)))) - '(template-default-directories (quote ("~/.emacs.d/templates/"))) + '(safe-local-variable-values + '((user-mail-address . "baron@bundesbrandschatzamt.de") + (user-mail-address . baron@bundesbrandschatzamt\.de) + (bba-keep-whitespaces . 1))) + '(template-default-directories '("~/.emacs.d/templates/")) '(toolbar-visible-p nil) - '(vc-handled-backends (quote (RCS CVS SVN SCCS Bzr Hg Arch)))) + '(vc-handled-backends '(RCS CVS SVN SCCS Bzr Hg Arch))) (defcustom sql-mysql-program "~/bin/mysql" "*Command to start mysql by mysqlDB." :type 'file diff --git a/elpa/compat-28.1.2.2.signed b/elpa/compat-28.1.2.2.signed new file mode 100644 index 00000000..0973a8f4 --- /dev/null +++ b/elpa/compat-28.1.2.2.signed @@ -0,0 +1 @@ +Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) (trust undefined) created at 2022-08-25T23:05:04+0200 using RSA \ No newline at end of file diff --git a/elpa/compat-28.1.2.2/.dir-locals.el b/elpa/compat-28.1.2.2/.dir-locals.el new file mode 100644 index 00000000..900dee5f --- /dev/null +++ b/elpa/compat-28.1.2.2/.dir-locals.el @@ -0,0 +1,7 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((emacs-lisp-mode + (byte-compile-docstring-max-column . 100) + (show-trailing-whitespace . t) + (indent-tabs-mode . nil))) diff --git a/elpa/compat-28.1.2.2/NEWS.org b/elpa/compat-28.1.2.2/NEWS.org new file mode 100644 index 00000000..abb3448d --- /dev/null +++ b/elpa/compat-28.1.2.2/NEWS.org @@ -0,0 +1,108 @@ +#+options: toc:nil num:nil +#+link: compat https://todo.sr.ht/~pkal/compat/ + +* 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*=. + +Furthermore a bug tracker was added: https://todo.sr.ht/~pkal/compat, +which is the preferred way to report issues or feature requests. +General problems, questions, etc. are still better discussed on the +development mailing list: https://lists.sr.ht/~pkal/compat-devel. + +(Released <2022-04-22 Fri>) + + diff --git a/elpa/compat-28.1.2.2/compat-24.el b/elpa/compat-28.1.2.2/compat-24.el new file mode 100644 index 00000000..d38f0511 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-24.el @@ -0,0 +1,495 @@ +;;; compat-24.el --- Compatibility Layer for Emacs 24.4 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; URL: https://git.sr.ht/~pkal/compat/ +;; 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: + +;; Find here the functionality added in Emacs 24.4, needed by older +;; versions. +;; +;; Only load this library if you need to use one of the following +;; functions: +;; +;; - `compat-=' +;; - `compat-<' +;; - `compat->' +;; - `compat-<=' +;; - `compat->=' +;; - `split-string'. + +;;; Code: + +(require 'compat-macs "compat-macs.el") + +(compat-declare-version "24.4") + +;;;; Defined in data.c + +(compat-defun = (number-or-marker &rest numbers-or-markers) + "Handle multiple arguments." + :prefix t + (catch 'fail + (while numbers-or-markers + (unless (= number-or-marker (car numbers-or-markers)) + (throw 'fail nil)) + (setq number-or-marker (pop numbers-or-markers))) + t)) + +(compat-defun < (number-or-marker &rest numbers-or-markers) + "Handle multiple arguments." + :prefix t + (catch 'fail + (while numbers-or-markers + (unless (< number-or-marker (car numbers-or-markers)) + (throw 'fail nil)) + (setq number-or-marker (pop numbers-or-markers))) + t)) + +(compat-defun > (number-or-marker &rest numbers-or-markers) + "Handle multiple arguments." + :prefix t + (catch 'fail + (while numbers-or-markers + (unless (> number-or-marker (car numbers-or-markers)) + (throw 'fail nil)) + (setq number-or-marker (pop numbers-or-markers))) + t)) + +(compat-defun <= (number-or-marker &rest numbers-or-markers) + "Handle multiple arguments." + :prefix t + (catch 'fail + (while numbers-or-markers + (unless (<= number-or-marker (car numbers-or-markers)) + (throw 'fail nil)) + (setq number-or-marker (pop numbers-or-markers))) + t)) + +(compat-defun >= (number-or-marker &rest numbers-or-markers) + "Handle multiple arguments." + :prefix t + (catch 'fail + (while numbers-or-markers + (unless (>= number-or-marker (pop numbers-or-markers)) + (throw 'fail nil))) + t)) + +(compat-defun bool-vector-exclusive-or (a b &optional c) + "Return A ^ B, bitwise exclusive or. +If optional third argument C is given, store result into C. +A, B, and C must be bool vectors of the same length. +Return the destination vector if it changed or nil otherwise." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (unless (bool-vector-p b) + (signal 'wrong-type-argument (list 'bool-vector-p b))) + (unless (or (null c) (bool-vector-p c)) + (signal 'wrong-type-argument (list 'bool-vector-p c))) + (when (/= (length a) (length b)) + (signal 'wrong-length-argument (list (length a) (length b)))) + (let ((dest (or c (make-bool-vector (length a) nil))) changed) + (when (/= (length a) (length dest)) + (signal 'wrong-length-argument (list (length a) (length dest)))) + (dotimes (i (length dest)) + (let ((val (not (eq (aref a i) (aref b i))))) + (unless (eq val (aref dest i)) + (setq changed t)) + (aset dest i val))) + (if c (and changed c) dest))) + +(compat-defun bool-vector-union (a b &optional c) + "Return A | B, bitwise or. +If optional third argument C is given, store result into C. +A, B, and C must be bool vectors of the same length. +Return the destination vector if it changed or nil otherwise." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (unless (bool-vector-p b) + (signal 'wrong-type-argument (list 'bool-vector-p b))) + (unless (or (null c) (bool-vector-p c)) + (signal 'wrong-type-argument (list 'bool-vector-p c))) + (when (/= (length a) (length b)) + (signal 'wrong-length-argument (list (length a) (length b)))) + (let ((dest (or c (make-bool-vector (length a) nil))) changed) + (when (/= (length a) (length dest)) + (signal 'wrong-length-argument (list (length a) (length dest)))) + (dotimes (i (length dest)) + (let ((val (or (aref a i) (aref b i)))) + (unless (eq val (aref dest i)) + (setq changed t)) + (aset dest i val))) + (if c (and changed c) dest))) + +(compat-defun bool-vector-intersection (a b &optional c) + "Return A & B, bitwise and. +If optional third argument C is given, store result into C. +A, B, and C must be bool vectors of the same length. +Return the destination vector if it changed or nil otherwise." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (unless (bool-vector-p b) + (signal 'wrong-type-argument (list 'bool-vector-p b))) + (unless (or (null c) (bool-vector-p c)) + (signal 'wrong-type-argument (list 'bool-vector-p c))) + (when (/= (length a) (length b)) + (signal 'wrong-length-argument (list (length a) (length b)))) + (let ((dest (or c (make-bool-vector (length a) nil))) changed) + (when (/= (length a) (length dest)) + (signal 'wrong-length-argument (list (length a) (length dest)))) + (dotimes (i (length dest)) + (let ((val (and (aref a i) (aref b i)))) + (unless (eq val (aref dest i)) + (setq changed t)) + (aset dest i val))) + (if c (and changed c) dest))) + +(compat-defun bool-vector-set-difference (a b &optional c) + "Return A &~ B, set difference. +If optional third argument C is given, store result into C. +A, B, and C must be bool vectors of the same length. +Return the destination vector if it changed or nil otherwise." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (unless (bool-vector-p b) + (signal 'wrong-type-argument (list 'bool-vector-p b))) + (unless (or (null c) (bool-vector-p c)) + (signal 'wrong-type-argument (list 'bool-vector-p c))) + (when (/= (length a) (length b)) + (signal 'wrong-length-argument (list (length a) (length b)))) + (let ((dest (or c (make-bool-vector (length a) nil))) changed) + (when (/= (length a) (length dest)) + (signal 'wrong-length-argument (list (length a) (length dest)))) + (dotimes (i (length dest)) + (let ((val (and (aref a i) (not (aref b i))))) + (unless (eq val (aref dest i)) + (setq changed t)) + (aset dest i val))) + (if c (and changed c) dest))) + +(compat-defun bool-vector-not (a &optional b) + "Compute ~A, set complement. +If optional second argument B is given, store result into B. +A and B must be bool vectors of the same length. +Return the destination vector." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (unless (or (null b) (bool-vector-p b)) + (signal 'wrong-type-argument (list 'bool-vector-p b))) + (let ((dest (or b (make-bool-vector (length a) nil)))) + (when (/= (length a) (length dest)) + (signal 'wrong-length-argument (list (length a) (length dest)))) + (dotimes (i (length dest)) + (aset dest i (not (aref a i)))) + dest)) + +(compat-defun bool-vector-subsetp (a b) + "Return t if every t value in A is also t in B, nil otherwise. +A and B must be bool vectors of the same length." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (unless (bool-vector-p b) + (signal 'wrong-type-argument (list 'bool-vector-p b))) + (when (/= (length a) (length b)) + (signal 'wrong-length-argument (list (length a) (length b)))) + (catch 'not-subset + (dotimes (i (length a)) + (when (if (aref a i) (not (aref b i)) nil) + (throw 'not-subset nil))) + t)) + +(compat-defun bool-vector-count-consecutive (a b i) + "Count how many consecutive elements in A equal B starting at I. +A is a bool vector, B is t or nil, and I is an index into A." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (setq b (and b t)) ;normalise to nil or t + (unless (< i (length a)) + (signal 'args-out-of-range (list a i))) + (let ((len (length a)) (n i)) + (while (and (< i len) (eq (aref a i) b)) + (setq i (1+ i))) + (- i n))) + +(compat-defun bool-vector-count-population (a) + "Count how many elements in A are t. +A is a bool vector. To count A's nil elements, subtract the +return value from A's length." + (unless (bool-vector-p a) + (signal 'wrong-type-argument (list 'bool-vector-p a))) + (let ((n 0)) + (dotimes (i (length a)) + (when (aref a i) + (setq n (1+ n)))) + n)) + +;;;; Defined in subr.el + +;;* UNTESTED +(compat-defmacro with-eval-after-load (file &rest body) + "Execute BODY after FILE is loaded. +FILE is normally a feature name, but it can also be a file name, +in case that file does not provide any feature. See `eval-after-load' +for more details about the different forms of FILE and their semantics." + (declare (indent 1) (debug (form def-body))) + ;; See https://nullprogram.com/blog/2018/02/22/ on how + ;; `eval-after-load' is used to preserve compatibility with 24.3. + `(eval-after-load ,file `(funcall ',,`(lambda () ,@body)))) + +(compat-defun special-form-p (object) + "Non-nil if and only if OBJECT is a special form." + (if (and (symbolp object) (fboundp object)) + (setq object (condition-case nil + (indirect-function object) + (void-function nil)))) + (and (subrp object) (eq (cdr (subr-arity object)) 'unevalled))) + +(compat-defun macrop (object) + "Non-nil if and only if OBJECT is a macro." + (let ((def (condition-case nil + (indirect-function object) + (void-function nil)))) + (when (consp def) + (or (eq 'macro (car def)) + (and (autoloadp def) (memq (nth 4 def) '(macro t))))))) + +(compat-defun string-suffix-p (suffix string &optional ignore-case) + "Return non-nil if SUFFIX is a suffix of STRING. +If IGNORE-CASE is non-nil, the comparison is done without paying +attention to case differences." + (let ((start-pos (- (length string) (length suffix)))) + (and (>= start-pos 0) + (eq t (compare-strings suffix nil nil + string start-pos nil ignore-case))))) + +(compat-defun split-string (string &optional separators omit-nulls trim) + "Extend `split-string' by a TRIM argument. +The remaining arguments STRING, SEPARATORS and OMIT-NULLS are +handled just as with `split-string'." + :prefix t + (let* ((token (split-string string separators omit-nulls)) + (trimmed (if trim + (mapcar + (lambda (token) + (when (string-match (concat "\\`" trim) token) + (setq token (substring token (match-end 0)))) + (when (string-match (concat trim "\\'") token) + (setq token (substring token 0 (match-beginning 0)))) + token) + token) + token))) + (if omit-nulls (delete "" trimmed) trimmed))) + +(compat-defun delete-consecutive-dups (list &optional circular) + "Destructively remove `equal' consecutive duplicates from LIST. +First and last elements are considered consecutive if CIRCULAR is +non-nil." + (let ((tail list) last) + (while (cdr tail) + (if (equal (car tail) (cadr tail)) + (setcdr tail (cddr tail)) + (setq last tail + tail (cdr tail)))) + (if (and circular + last + (equal (car tail) (car list))) + (setcdr last nil))) + list) + +;;* UNTESTED +(compat-defun define-error (name message &optional parent) + "Define NAME as a new error signal. +MESSAGE is a string that will be output to the echo area if such an error +is signaled without being caught by a `condition-case'. +PARENT is either a signal or a list of signals from which it inherits. +Defaults to `error'." + (unless parent (setq parent 'error)) + (let ((conditions + (if (consp parent) + (apply #'append + (mapcar (lambda (parent) + (cons parent + (or (get parent 'error-conditions) + (error "Unknown signal `%s'" parent)))) + parent)) + (cons parent (get parent 'error-conditions))))) + (put name 'error-conditions + (delete-dups (copy-sequence (cons name conditions)))) + (when message (put name 'error-message message)))) + +;;;; Defined in minibuffer.el + +;;* UNTESTED +(compat-defun completion-table-with-cache (fun &optional ignore-case) + "Create dynamic completion table from function FUN, with cache. +This is a wrapper for `completion-table-dynamic' that saves the last +argument-result pair from FUN, so that several lookups with the +same argument (or with an argument that starts with the first one) +only need to call FUN once. This can be useful when FUN performs a +relatively slow operation, such as calling an external process. + +When IGNORE-CASE is non-nil, FUN is expected to be case-insensitive." + (let* (last-arg last-result + (new-fun + (lambda (arg) + (if (and last-arg (string-prefix-p last-arg arg ignore-case)) + last-result + (prog1 + (setq last-result (funcall fun arg)) + (setq last-arg arg)))))) + (completion-table-dynamic new-fun))) + +;;* UNTESTED +(compat-defun completion-table-merge (&rest tables) + "Create a completion table that collects completions from all TABLES." + (lambda (string pred action) + (cond + ((null action) + (let ((retvals (mapcar (lambda (table) + (try-completion string table pred)) + tables))) + (if (member string retvals) + string + (try-completion string + (mapcar (lambda (value) + (if (eq value t) string value)) + (delq nil retvals)) + pred)))) + ((eq action t) + (apply #'append (mapcar (lambda (table) + (all-completions string table pred)) + tables))) + (t + (completion--some (lambda (table) + (complete-with-action action table string pred)) + tables))))) + +;;;; Defined in subr-x.el + +;;* UNTESTED +(compat-advise require (feature &rest args) + "Allow for Emacs 24.x to require the inexistent FEATURE subr-x." + ;; As the compatibility advise around `require` is more a hack than + ;; of of actual value, the highlighting is suppressed. + :no-highlight t + (if (eq feature 'subr-x) + (let ((entry (assq feature after-load-alist))) + (let ((load-file-name nil)) + (dolist (form (cdr entry)) + (funcall (eval form t))))) + (apply oldfun feature args))) + +(compat-defun hash-table-keys (hash-table) + "Return a list of keys in HASH-TABLE." + (let (values) + (maphash + (lambda (k _v) (push k values)) + hash-table) + values)) + +(compat-defun hash-table-values (hash-table) + "Return a list of values in HASH-TABLE." + (let (values) + (maphash + (lambda (_k v) (push v values)) + hash-table) + values)) + +(compat-defun string-empty-p (string) + "Check whether STRING is empty." + (string= string "")) + +(compat-defun string-join (strings &optional separator) + "Join all STRINGS using SEPARATOR. +Optional argument SEPARATOR must be a string, a vector, or a list of +characters; nil stands for the empty string." + (mapconcat #'identity strings separator)) + +(compat-defun string-blank-p (string) + "Check whether STRING is either empty or only whitespace. +The following characters count as whitespace here: space, tab, newline and +carriage return." + (string-match-p "\\`[ \t\n\r]*\\'" string)) + +(compat-defun string-remove-prefix (prefix string) + "Remove PREFIX from STRING if present." + (if (string-prefix-p prefix string) + (substring string (length prefix)) + string)) + +(compat-defun string-remove-suffix (suffix string) + "Remove SUFFIX from STRING if present." + (if (string-suffix-p suffix string) + (substring string 0 (- (length string) (length suffix))) + string)) + +;;;; Defined in faces.el + +;;* UNTESTED +(compat-defun face-spec-set (face spec &optional spec-type) + "Set the FACE's spec SPEC, define FACE, and recalculate its attributes. +See `defface' for the format of SPEC. + +The appearance of each face is controlled by its specs (set via +this function), and by the internal frame-specific face +attributes (set via `set-face-attribute'). + +This function also defines FACE as a valid face name if it is not +already one, and (re)calculates its attributes on existing +frames. + +The optional argument SPEC-TYPE determines which spec to set: + nil, omitted or `face-override-spec' means the override spec, + which overrides all the other types of spec mentioned below + (this is usually what you want if calling this function + outside of Custom code); + `customized-face' or `saved-face' means the customized spec or + the saved custom spec; + `face-defface-spec' means the default spec + (usually set only via `defface'); + `reset' means to ignore SPEC, but clear the `customized-face' + and `face-override-spec' specs; +Any other value means not to set any spec, but to run the +function for defining FACE and recalculating its attributes." + (if (get face 'face-alias) + (setq face (get face 'face-alias))) + ;; Save SPEC to the relevant symbol property. + (unless spec-type + (setq spec-type 'face-override-spec)) + (if (memq spec-type '(face-defface-spec face-override-spec + customized-face saved-face)) + (put face spec-type spec)) + (if (memq spec-type '(reset saved-face)) + (put face 'customized-face nil)) + ;; Setting the face spec via Custom empties out any override spec, + ;; similar to how setting a variable via Custom changes its values. + (if (memq spec-type '(customized-face saved-face reset)) + (put face 'face-override-spec nil)) + ;; If we reset the face based on its custom spec, it is unmodified + ;; as far as Custom is concerned. + (unless (eq face 'face-override-spec) + (put face 'face-modified nil)) + ;; Initialize the face if it does not exist, then recalculate. + (make-empty-face face) + (dolist (frame (frame-list)) + (face-spec-recalc face frame))) + +(compat--inhibit-prefixed (provide 'compat-24)) +;;; compat-24.el ends here diff --git a/elpa/compat-28.1.2.2/compat-25.el b/elpa/compat-28.1.2.2/compat-25.el new file mode 100644 index 00000000..471fbee8 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-25.el @@ -0,0 +1,322 @@ +;;; compat-25.el --- Compatibility Layer for Emacs 25.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; URL: https://git.sr.ht/~pkal/compat/ +;; 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: + +;; Find here the functionality added in Emacs 25.1, needed by older +;; versions. +;; +;; Only load this library if you need to use one of the following +;; functions: +;; +;; - `compat-sort' + +;;; Code: + +(require 'compat-macs "compat-macs.el") + +(compat-declare-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) + "Extend `sort' to sort SEQ as a vector." + :prefix t + (cond + ((listp seq) + (sort seq predicate)) + ((vectorp seq) + (let ((cseq (sort (append seq nil) predicate))) + (dotimes (i (length cseq)) + (setf (aref seq i) (nth i cseq))) + (apply #'vector cseq))) + ((signal 'wrong-type-argument 'list-or-vector-p)))) + +;;;; Defined in editfns.c + +(compat-defun format-message (string &rest objects) + "Format a string out of a format-string and arguments. +The first argument is a format control string. +The other arguments are substituted into it to make the result, a string. + +This implementation is equivalent to `format'." + (apply #'format string objects)) + +;;;; Defined in minibuf.c + +;; TODO advise read-buffer to handle 4th argument + +;;;; Defined in fileio.c + +(compat-defun directory-name-p (name) + "Return non-nil if NAME ends with a directory separator character." + :realname compat--directory-name-p + (eq (eval-when-compile + (if (memq system-type '(cygwin windows-nt ms-dos)) + ?\\ ?/)) + (aref name (1- (length name))))) + +;;;; 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)) + +;;* UNTESTED +(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-defun alist-get (key alist &optional default remove testfn) + "Find the first element of ALIST whose `car' equals KEY and return its `cdr'. +If KEY is not found in ALIST, return DEFAULT. +Equality with KEY is tested by TESTFN, defaulting to `eq'." + :realname compat--alist-get-full-elisp + (ignore remove) + (let (entry) + (cond + ((or (null testfn) (eq testfn 'eq)) + (setq entry (assq key alist))) + ((eq testfn 'equal) + (setq entry (assoc key alist))) + ((catch 'found + (dolist (ent alist) + (when (and (consp ent) (funcall testfn (car ent) key)) + (throw 'found (setq entry ent)))) + default))) + (if entry (cdr entry) default))) + +;;;; Defined in subr-x.el + +(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." + :realname compat--if-let + :feature 'subr-x + (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))) + `(compat--if-let* ,spec ,then ,(macroexp-progn 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'." + :feature 'subr-x + (declare (indent 1) (debug if-let)) + `(compat--if-let ,spec ,(macroexp-progn body))) + +(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." + :feature 'subr-x + (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." + :feature 'subr-x + (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 + +(declare-function macrop nil (object)) +(compat-defun macroexpand-1 (form &optional environment) + "Perform (at most) one step of macro expansion." + :feature 'macroexp + (cond + ((consp form) + (let* ((head (car form)) + (env-expander (assq head environment))) + (if env-expander + (if (cdr env-expander) + (apply (cdr env-expander) (cdr form)) + form) + (if (not (and (symbolp head) (fboundp head))) + form + (let ((def (autoload-do-load (symbol-function head) head 'macro))) + (cond + ;; Follow alias, but only for macros, otherwise we may end up + ;; skipping an important compiler-macro (e.g. cl--block-wrapper). + ((and (symbolp def) (macrop def)) (cons def (cdr form))) + ((not (consp def)) form) + (t + (if (eq 'macro (car def)) + (apply (cdr def) (cdr form)) + form)))))))) + (t form))) + +;;;; Defined in byte-run.el + +;;* UNTESTED +(compat-defun function-put (func prop value) + "Set FUNCTION's property PROP to VALUE. +The namespace for PROP is shared with symbols. +So far, FUNCTION can only be a symbol, not a lambda expression." + :version "24.4" + (put func prop value)) + +;;;; Defined in files.el + +;;* UNTESTED +(compat-defun directory-files-recursively + (dir regexp &optional include-directories predicate follow-symlinks) + "Return list of all files under directory DIR whose names match REGEXP. +This function works recursively. Files are returned in \"depth +first\" order, and files from each directory are sorted in +alphabetical order. Each file name appears in the returned list +in its absolute form. + +By default, the returned list excludes directories, but if +optional argument INCLUDE-DIRECTORIES is non-nil, they are +included. + +PREDICATE can be either nil (which means that all subdirectories +of DIR are descended into), t (which means that subdirectories that +can't be read are ignored), or a function (which is called with +the name of each subdirectory, and should return non-nil if the +subdirectory is to be descended into). + +If FOLLOW-SYMLINKS is non-nil, symbolic links that point to +directories are followed. Note that this can lead to infinite +recursion." + :realname compat--directory-files-recursively + (let* ((result nil) + (files nil) + (dir (directory-file-name dir)) + ;; When DIR is "/", remote file names like "/method:" could + ;; also be offered. We shall suppress them. + (tramp-mode (and tramp-mode (file-remote-p (expand-file-name dir))))) + (dolist (file (sort (file-name-all-completions "" dir) + 'string<)) + (unless (member file '("./" "../")) + (if (directory-name-p file) + (let* ((leaf (substring file 0 (1- (length file)))) + (full-file (concat dir "/" leaf))) + ;; Don't follow symlinks to other directories. + (when (and (or (not (file-symlink-p full-file)) + (and (file-symlink-p full-file) + follow-symlinks)) + ;; Allow filtering subdirectories. + (or (eq predicate nil) + (eq predicate t) + (funcall predicate full-file))) + (let ((sub-files + (if (eq predicate t) + (condition-case nil + (compat--directory-files-recursively + full-file regexp include-directories + predicate follow-symlinks) + (file-error nil)) + (compat--directory-files-recursively + full-file regexp include-directories + predicate follow-symlinks)))) + (setq result (nconc result sub-files)))) + (when (and include-directories + (string-match regexp leaf)) + (setq result (nconc result (list full-file))))) + (when (string-match regexp file) + (push (concat dir "/" file) files))))) + (nconc result (nreverse files)))) + +(compat--inhibit-prefixed (provide 'compat-25)) +;;; compat-25.el ends here diff --git a/elpa/compat-28.1.2.2/compat-26.el b/elpa/compat-28.1.2.2/compat-26.el new file mode 100644 index 00000000..98f7b2fb --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-26.el @@ -0,0 +1,675 @@ +;;; compat-26.el --- Compatibility Layer for Emacs 26.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; URL: https://git.sr.ht/~pkal/compat/ +;; 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: + +;; Find here the functionality added in Emacs 26.1, needed by older +;; versions. +;; +;; Only load this library if you need to use one of the following +;; functions: +;; +;; - `compat-sort' +;; - `line-number-at-pos' +;; - `compat-alist-get' +;; - `string-trim-left' +;; - `string-trim-right' +;; - `string-trim' + +;;; Code: + +(require 'compat-macs "compat-macs.el") + +(compat-declare-version "26.1") + +;;;; Defined in eval.c + +(compat-defun func-arity (func) + "Return minimum and maximum number of args allowed for FUNC. +FUNC must be a function of some kind. +The returned value is a cons cell (MIN . MAX). MIN is the minimum number +of args. MAX is the maximum number, or the symbol `many', for a +function with `&rest' args, or `unevalled' for a special form." + :realname compat--func-arity + (cond + ((or (null func) (and (symbolp func) (not (fboundp func)))) + (signal 'void-function func)) + ((and (symbolp func) (not (null func))) + (compat--func-arity (symbol-function func))) + ((eq (car-safe func) 'macro) + (compat--func-arity (cdr func))) + ((subrp func) + (subr-arity func)) + ((memq (car-safe func) '(closure lambda)) + ;; See lambda_arity from eval.c + (when (eq (car func) 'closure) + (setq func (cdr func))) + (let ((syms-left (if (consp func) + (car func) + (signal 'invalid-function func))) + (min-args 0) (max-args 0) optional) + (catch 'many + (dolist (next syms-left) + (cond + ((not (symbolp next)) + (signal 'invalid-function func)) + ((eq next '&rest) + (throw 'many (cons min-args 'many))) + ((eq next '&optional) + (setq optional t)) + (t (unless optional + (setq min-args (1+ min-args))) + (setq max-args (1+ max-args))))) + (cons min-args max-args)))) + ((and (byte-code-function-p func) (numberp (aref func 0))) + ;; See get_byte_code_arity from bytecode.c + (let ((at (aref func 0))) + (cons (logand at 127) + (if (= (logand at 128) 0) + (ash at -8) + 'many)))) + ((and (byte-code-function-p func) (numberp (aref func 0))) + ;; See get_byte_code_arity from bytecode.c + (let ((at (aref func 0))) + (cons (logand at 127) + (if (= (logand at 128) 0) + (ash at -8) + 'many)))) + ((and (byte-code-function-p func) (listp (aref func 0))) + ;; Based on `byte-compile-make-args-desc', this is required for + ;; old versions of Emacs that don't use a integer for the argument + ;; list description, per e2abe5a13dffb08d6371b6a611bc39c3a9ac2bc6. + (let ((arglist (aref func 0)) (mandatory 0) nonrest) + (while (and arglist (not (memq (car arglist) '(&optional &rest)))) + (setq mandatory (1+ mandatory)) + (setq arglist (cdr arglist))) + (setq nonrest mandatory) + (when (eq (car arglist) '&optional) + (setq arglist (cdr arglist)) + (while (and arglist (not (eq (car arglist) '&rest))) + (setq nonrest (1+ nonrest)) + (setq arglist (cdr arglist)))) + (cons mandatory (if arglist 'many nonrest)))) + ((autoloadp func) + (autoload-do-load func) + (compat--func-arity func)) + ((signal 'invalid-function func)))) + +;;;; Defined in fns.c + +(compat-defun assoc (key alist &optional testfn) + "Handle the optional argument TESTFN. +Equality is defined by the function TESTFN, defaulting to +`equal'. TESTFN is called with 2 arguments: a car of an alist +element and KEY. With no optional argument, the function behaves +just like `assoc'." + :prefix t + (if testfn + (catch 'found + (dolist (ent alist) + (when (funcall testfn (car ent) key) + (throw 'found ent)))) + (assoc key alist))) + +(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))) + +;;* UNTESTED +(compat-defun line-number-at-pos (&optional position absolute) + "Handle optional argument ABSOLUTE: + +If the buffer is narrowed, the return value by default counts the lines +from the beginning of the accessible portion of the buffer. But if the +second optional argument ABSOLUTE is non-nil, the value counts the lines +from the absolute start of the buffer, disregarding the narrowing." + :prefix t + (if absolute + (save-restriction + (widen) + (line-number-at-pos position)) + (line-number-at-pos position))) + +;;;; Defined in subr.el + +(declare-function compat--alist-get-full-elisp "compat-25" + (key alist &optional default remove testfn)) +(compat-defun alist-get (key alist &optional default remove testfn) + "Handle TESTFN manually." + :realname compat--alist-get-handle-testfn + :prefix t + (if testfn + (compat--alist-get-full-elisp key alist default remove testfn) + (alist-get key alist default remove))) + +(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 `(if (and ,testfn (not (eq ,testfn 'eq))) + (compat-assoc ,k ,getter ,testfn) + (assq ,k ,getter)) + (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)))))))))) + +(compat-defun string-trim-left (string &optional regexp) + "Trim STRING of leading string matching REGEXP. + +REGEXP defaults to \"[ \\t\\n\\r]+\"." + :realname compat--string-trim-left + :prefix 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) + "Trim STRING of trailing string matching REGEXP. + +REGEXP defaults to \"[ \\t\\n\\r]+\"." + :realname compat--string-trim-right + :prefix 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) + "Trim STRING of leading with and trailing matching TRIM-LEFT and TRIM-RIGHT. + +TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"." + :prefix t + ;; `string-trim-left' and `string-trim-right' were moved from subr-x + ;; to subr in Emacs 27, so to avoid loading subr-x we use the + ;; compatibility function here: + (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)))) + +;;;; Defined in files.el + +(declare-function temporary-file-directory nil) + +;;* UNTESTED +(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'." + (let ((handler (find-file-name-handler + default-directory 'make-nearby-temp-file))) + (if (and handler (not (file-name-absolute-p default-directory))) + (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-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'." + :realname compat--file-local-name + (or (file-remote-p file 'localname) file)) + +(compat-defun file-name-quoted-p (name &optional top) + "Whether NAME is quoted with prefix \"/:\". +If NAME is a remote file name and TOP is nil, check the local part of NAME." + :realname compat--file-name-quoted-p + (let ((file-name-handler-alist (unless top file-name-handler-alist))) + (string-prefix-p "/:" (compat--file-local-name name)))) + +(compat-defun file-name-quote (name &optional top) + "Add the quotation prefix \"/:\" to file NAME. +If NAME is a remote file name and TOP is nil, the local part of +NAME is quoted. If NAME is already a quoted file name, NAME is +returned unchanged." + (let ((file-name-handler-alist (unless top file-name-handler-alist))) + (if (compat--file-name-quoted-p name top) + name + (concat (file-remote-p name) "/:" (compat--file-local-name name))))) + +;;* UNTESTED +(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." + (let ((handler (find-file-name-handler + default-directory 'temporary-file-directory))) + (if handler + (funcall handler 'temporary-file-directory) + (if (string-match mounted-file-systems default-directory) + default-directory + temporary-file-directory)))) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(compat-defun file-attribute-link-number (attributes) + "Return the number of links in ATTRIBUTES returned by `file-attributes'." + (nth 1 attributes)) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(compat-defun file-attribute-size (attributes) + "The integer size (in bytes) in ATTRIBUTES returned by `file-attributes'." + (nth 7 attributes)) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(compat-defun file-attribute-inode-number (attributes) + "The inode number in ATTRIBUTES returned by `file-attributes'. +It is a nonnegative integer." + (nth 10 attributes)) + +;;* UNTESTED +(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 subr-x.el + +(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." + :realname compat--if-let* + :feature 'subr-x + (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 ,(or (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." + ;; :feature 'subr-x + (declare (indent 1) (debug if-let*)) + (let ((empty (make-symbol "s")) + (last t) list) + (dolist (var varlist) + (push `(,(if (cdr var) (car var) empty) + (and ,last ,(or (cadr var) (car var)))) + list) + (when (or (cdr var) (consp (car var))) + (setq last (caar list)))) + `(let* ,(nreverse list) + (when ,(caar list) ,@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." + :feature 'subr-x + (declare (indent 1) (debug if-let*)) + (let ((empty (make-symbol "s")) + (last t) list) + (dolist (var varlist) + (push `(,(if (cdr var) (car var) empty) + (and ,last ,(or (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 image.el + +;;* UNTESTED +(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." + (plist-get (cdr image) property)) + +;;* UNTESTED +(unless (get 'image-property 'gv-expander) + (gv-define-setter image-property (image property value) + (let ((image* (make-symbol "image")) + (property* (make-symbol "property")) + (value* (make-symbol "value"))) + `(let ((,image* ,image) + (,property* ,property) + (,value* ,value)) + (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*))))))) + +;;;; Defined in rmc.el + +;;*UNTESTED +(compat-defun read-multiple-choice + (prompt choices &optional _help-string _show-help long-form) + "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). + +If LONG-FORM, do a `completing-read' over the NAME elements in +CHOICES instead." + :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." + (if long-form + (let ((options (mapconcat #'cadr choices "/")) + choice) + (setq prompt (concat prompt " (" options "): ")) + (setq choice (completing-read prompt (mapcar #'cadr choices) nil t)) + (catch 'found + (dolist (option choices) + (when (string= choice (cadr option)) + (throw 'found option))) + (error "Invalid choice"))) + (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-char prompt) choices))) + (message "Invalid choice") + (sit-for 1)) + choice))) + +(compat--inhibit-prefixed (provide 'compat-26)) +;;; compat-26.el ends here diff --git a/elpa/compat-28.1.2.2/compat-27.el b/elpa/compat-28.1.2.2/compat-27.el new file mode 100644 index 00000000..a96b1e96 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-27.el @@ -0,0 +1,764 @@ +;;; compat-27.el --- Compatibility Layer for Emacs 27.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; URL: https://git.sr.ht/~pkal/compat/ +;; 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: + +;; Find here the functionality added in Emacs 27.1, needed by older +;; versions. +;; +;; Only load this library if you need to use one of the following +;; functions or macros: +;; +;; - `compat-recenter' +;; - `compat-lookup-key' +;; - `compat-setq-local' +;; - `compat-assoc-delete-all' +;; - `compat-file-size-human-readable' +;; - `compat-executable-find' +;; - `compat-regexp-opt' +;; - `compat-dired-get-marked-files' + +;;; Code: + +(require 'compat-macs "compat-macs.el") + +(compat-declare-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)." + :min-version "26.1" + :max-version "26.3" + :realname compat--proper-list-p-length-signal + (condition-case nil + (and (listp object) (length object)) + (wrong-type-argument nil) + (circular-list nil))) + +(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)." + :max-version "25.3" + :realname compat--proper-list-p-tortoise-hare + (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)))))) + +(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." + :prefix 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." + :prefix t + (cond + ((keymapp keymap) + (lookup-key keymap key accept-default)) + ((listp keymap) + (catch 'found + (dolist (map keymap) + (let ((fn (lookup-key map key accept-default))) + (when fn (throw 'found fn)))))) + ((signal 'wrong-type-argument (list 'keymapp keymap))))) + +;;;; Defined in json.c + +(declare-function json-parse-string nil (string &rest args)) +(declare-function json-encode "json" (object)) +(declare-function json-read-from-string "json" (string)) +(declare-function json-read "json" ()) +(defvar json-encoding-pretty-print) +(defvar json-object-type) +(defvar json-array-type) +(defvar json-false) +(defvar json-null) + +;; The function is declared to satisfy the byte compiler while testing +;; if native JSON parsing is available.; +(declare-function json-serialize nil (object &rest args)) +(compat-defun json-serialize (object &rest args) + "Return the JSON representation of OBJECT as a string. + +OBJECT must be t, a number, string, vector, hashtable, alist, plist, +or the Lisp equivalents to the JSON null and false values, and its +elements must recursively consist of the same kinds of values. t will +be converted to the JSON true value. Vectors will be converted to +JSON arrays, whereas hashtables, alists and plists are converted to +JSON objects. Hashtable keys must be strings without embedded null +characters and must be unique within each object. Alist and plist +keys must be symbols; if a key is duplicate, the first instance is +used. + +The Lisp equivalents to the JSON null and false values are +configurable in the arguments ARGS, a list of keyword/argument pairs: + +The keyword argument `:null-object' specifies which object to use +to represent a JSON null value. It defaults to `:null'. + +The keyword argument `:false-object' specifies which object to use to +represent a JSON false value. It defaults to `:false'. + +In you specify the same value for `:null-object' and `:false-object', +a potentially ambiguous situation, the JSON output will not contain +any JSON false values." + :cond (not (condition-case nil + (equal (json-serialize '()) "{}") + (:success t) + (void-function nil) + (json-unavailable nil))) + :realname compat--json-serialize + (require 'json) + (letrec ((fix (lambda (obj) + (cond + ((hash-table-p obj) + (let ((ht (copy-hash-table obj))) + (maphash + (lambda (key val) + (unless (stringp key) + (signal + 'wrong-type-argument + (list 'stringp key))) + (puthash key (funcall fix val) ht)) + obj) + ht)) + ((and (listp obj) (consp (car obj))) ;alist + (mapcar + (lambda (ent) + (cons (symbol-name (car ent)) + (funcall fix (cdr ent)))) + obj)) + ((listp obj) ;plist + (let (alist) + (while obj + (push (cons (cond + ((keywordp (car obj)) + (substring + (symbol-name (car obj)) + 1)) + ((symbolp (car obj)) + (symbol-name (car obj))) + ((signal + 'wrong-type-argument + (list 'symbolp (car obj))))) + (funcall fix (cadr obj))) + alist) + (unless (consp (cdr obj)) + (signal 'wrong-type-argument '(consp nil))) + (setq obj (cddr obj))) + (nreverse alist))) + ((vectorp obj) + (let ((vec (make-vector (length obj) nil))) + (dotimes (i (length obj)) + (aset vec i (funcall fix (aref obj i)))) + vec)) + (obj)))) + (json-encoding-pretty-print nil) + (json-false (or (plist-get args :false-object) :false)) + (json-null (or (plist-get args :null-object) :null))) + (json-encode (funcall fix object)))) + +(compat-defun json-insert (object &rest args) + "Insert the JSON representation of OBJECT before point. +This is the same as (insert (json-serialize OBJECT)), but potentially +faster. See the function `json-serialize' for allowed values of +OBJECT." + :cond (not (condition-case nil + (equal (json-serialize '()) "{}") + (:success t) + (void-function nil) + (json-unavailable nil))) + (insert (apply #'compat--json-serialize object args))) + +(compat-defun json-parse-string (string &rest args) + "Parse the JSON STRING into a Lisp object. +This is essentially the reverse operation of `json-serialize', which +see. The returned object will be the JSON null value, the JSON false +value, t, a number, a string, a vector, a list, a hashtable, an alist, +or a plist. Its elements will be further objects of these types. If +there are duplicate keys in an object, all but the last one are +ignored. If STRING doesn't contain a valid JSON object, this function +signals an error of type `json-parse-error'. + +The arguments ARGS are a list of keyword/argument pairs: + +The keyword argument `:object-type' specifies which Lisp type is used +to represent objects; it can be `hash-table', `alist' or `plist'. It +defaults to `hash-table'. + +The keyword argument `:array-type' specifies which Lisp type is used +to represent arrays; it can be `array' (the default) or `list'. + +The keyword argument `:null-object' specifies which object to use +to represent a JSON null value. It defaults to `:null'. + +The keyword argument `:false-object' specifies which object to use to +represent a JSON false value. It defaults to `:false'." + :cond (not (condition-case nil + (equal (json-serialize '()) "{}") + (:success t) + (void-function nil) + (json-unavailable nil))) + (require 'json) + (condition-case err + (let ((json-object-type (or (plist-get args :object-type) 'hash-table)) + (json-array-type (or (plist-get args :array-type) 'vector)) + (json-false (or (plist-get args :false-object) :false)) + (json-null (or (plist-get args :null-object) :null))) + (when (eq json-array-type 'array) + (setq json-array-type 'vector)) + (json-read-from-string string)) + (json-error (signal 'json-parse-error err)))) + +(compat-defun json-parse-buffer (&rest args) + "Read JSON object from current buffer starting at point. +Move point after the end of the object if parsing was successful. +On error, don't move point. + +The returned object will be a vector, list, hashtable, alist, or +plist. Its elements will be the JSON null value, the JSON false +value, t, numbers, strings, or further vectors, lists, hashtables, +alists, or plists. If there are duplicate keys in an object, all +but the last one are ignored. + +If the current buffer doesn't contain a valid JSON object, the +function signals an error of type `json-parse-error'. + +The arguments ARGS are a list of keyword/argument pairs: + +The keyword argument `:object-type' specifies which Lisp type is used +to represent objects; it can be `hash-table', `alist' or `plist'. It +defaults to `hash-table'. + +The keyword argument `:array-type' specifies which Lisp type is used +to represent arrays; it can be `array' (the default) or `list'. + +The keyword argument `:null-object' specifies which object to use +to represent a JSON null value. It defaults to `:null'. + +The keyword argument `:false-object' specifies which object to use to +represent a JSON false value. It defaults to `:false'." + :cond (not (condition-case nil + (equal (json-serialize '()) "{}") + (:success t) + (void-function nil) + (json-unavailable nil))) + (require 'json) + (condition-case err + (let ((json-object-type (or (plist-get args :object-type) 'hash-table)) + (json-array-type (or (plist-get args :array-type) 'vector)) + (json-false (or (plist-get args :false-object) :false)) + (json-null (or (plist-get args :null-object) :null))) + (when (eq json-array-type 'array) + (setq json-array-type 'vector)) + (json-read)) + (json-error (signal 'json-parse-buffer err)))) + +;;;; 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)) + ((let ((now (current-time))) + ;; 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 (or t1 now)) + (float-time (or t2 now)))) + 1e-5))))) + +;;;; Defined in fileio.c + +(compat-defun file-name-absolute-p (filename) + "Return t if FILENAME is an absolute file name. +On Unix, absolute file names start with `/'. In Emacs, an absolute +file name can also start with an initial `~' or `~USER' component, +where USER is a valid login name." + ;; See definitions in filename.h + (let ((seperator + (eval-when-compile + (if (memq system-type '(cygwin windows-nt ms-dos)) + "[\\/]" "/"))) + (drive + (eval-when-compile + (cond + ((memq system-type '(windows-nt ms-dos)) + "\\`[A-Za-z]:[\\/]") + ((eq system-type 'cygwin) + "\\`\\([\\/]\\|[A-Za-z]:\\)") + ("\\`/")))) + (home + (eval-when-compile + (if (memq system-type '(cygwin windows-nt ms-dos)) + "\\`~[\\/]" "\\`~/"))) + (user-home + (eval-when-compile + (format "\\`\\(~.*?\\)\\(%s.*\\)?$" + (if (memq system-type '(cygwin windows-nt ms-dos)) + "[\\/]" "/"))))) + (or (and (string-match-p drive filename) t) + (and (string-match-p home filename) t) + (save-excursion + (when (string-match user-home filename) + (let ((init (match-string 1 filename))) + (not (string= + (file-name-base (expand-file-name init)) + init)))))))) + +;;;; Defined in subr.el + +(compat-defmacro setq-local (&rest pairs) + "Handle multiple assignments." + :prefix 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-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'." + :realname compat--provided-mode-derived-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) + +;;* UNTESTED +(defun derived-mode-p (&rest modes) + "Non-nil if the current major mode is derived from one of MODES. +Uses the `derived-mode-parent' property of the symbol to trace backwards." + (apply #'compat--provided-mode-derived-p major-mode modes)) + +;;* UNTESTED +(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))) + +;;* UNTESTED +(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 (1- (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) + "Delete from ALIST all elements whose car is KEY. +Compare keys with TEST. Defaults to `equal'. +Return the modified alist. +Elements of ALIST that are not conses are ignored." + :prefix t + (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) + +;;;; Defined in simple.el + +;;* UNTESTED +(compat-defun decoded-time-second (time) + "The seconds in TIME, which is a value returned by `decode-time'. +This is an integer between 0 and 60 (inclusive). (60 is a leap +second, which only some operating systems support.)" + (nth 0 time)) + +;;* UNTESTED +(compat-defun decoded-time-minute (time) + "The minutes in TIME, which is a value returned by `decode-time'. +This is an integer between 0 and 59 (inclusive)." + (nth 1 time)) + +;;* UNTESTED +(compat-defun decoded-time-hour (time) + "The hours in TIME, which is a value returned by `decode-time'. +This is an integer between 0 and 23 (inclusive)." + (nth 2 time)) + +;;* UNTESTED +(compat-defun decoded-time-day (time) + "The day-of-the-month in TIME, which is a value returned by `decode-time'. +This is an integer between 1 and 31 (inclusive)." + (nth 3 time)) + +;;* UNTESTED +(compat-defun decoded-time-month (time) + "The month in TIME, which is a value returned by `decode-time'. +This is an integer between 1 and 12 (inclusive). January is 1." + (nth 4 time)) + +;;* UNTESTED +(compat-defun decoded-time-year (time) + "The year in TIME, which is a value returned by `decode-time'. +This is a four digit integer." + (nth 5 time)) + +;;* UNTESTED +(compat-defun decoded-time-weekday (time) + "The day-of-the-week in TIME, which is a value returned by `decode-time'. +This is a number between 0 and 6, and 0 is Sunday." + (nth 6 time)) + +;;* UNTESTED +(compat-defun decoded-time-dst (time) + "The daylight saving time in TIME, which is a value returned by `decode-time'. +This is t if daylight saving time is in effect, and nil if not." + (nth 7 time)) + +;;* UNTESTED +(compat-defun decoded-time-zone (time) + "The time zone in TIME, which is a value returned by `decode-time'. +This is an integer indicating the UTC offset in seconds, i.e., +the number of seconds east of Greenwich." + (nth 8 time)) + +;; TODO define gv-setters + +;;;; Defined in files.el + +(compat-defun file-size-human-readable (file-size &optional flavor space unit) + "Handle the optional third and forth argument: + +Optional third argument SPACE is a string put between the number and unit. +It defaults to the empty string. We recommend a single space or +non-breaking space, unless other constraints prohibit a space in that +position. + +Optional fourth argument UNIT is the unit to use. It defaults to \"B\" +when FLAVOR is `iec' and the empty string otherwise. We recommend \"B\" +in all cases, since that is the standard symbol for byte." + :prefix 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)))) + +(declare-function compat--file-name-quote "compat-26" + (name &optional top)) + +;;*UNTESTED +(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'." + :realname compat--exec-path + (cond + ((let ((handler (find-file-name-handler default-directory 'exec-path))) + ;; FIXME: The handler was added in 27.1, and this compatibility + ;; function only applies to versions of Emacs before that. + (when handler + (condition-case nil + (funcall handler 'exec-path) + (error nil))))) + ((file-remote-p default-directory) + ;; TODO: This is not completely portable, even if "sh" and + ;; "getconf" should be provided on every POSIX system, the chance + ;; of this not working are greater than zero. + ;; + ;; FIXME: This invokes a shell process every time exec-path is + ;; called. It should instead be cached on a host-local basis. + (with-temp-buffer + (if (condition-case nil + (zerop (process-file "sh" nil t nil "-c" "getconf PATH")) + (file-missing t)) + (list "/bin" "/usr/bin") + (let (path) + (while (re-search-forward "\\([^:]+?\\)[\n:]" nil t) + (push (match-string 1) path)) + (nreverse path))))) + (exec-path))) + +(declare-function compat--file-local-name "compat-26" + (file)) + +;;*UNTESTED +(compat-defun executable-find (command &optional remote) + "Search for COMMAND in `exec-path' and return the absolute file name. +Return nil if COMMAND is not found anywhere in `exec-path'. If +REMOTE is non-nil, search on the remote host indicated by +`default-directory' instead." + :prefix t + (if (and remote (file-remote-p default-directory)) + (let ((res (locate-file + command + (mapcar + (apply-partially + #'concat (file-remote-p default-directory)) + (compat--exec-path)) + exec-suffixes 'file-executable-p))) + (when (stringp res) (compat--file-local-name res))) + (executable-find command))) + +;; TODO provide advice for directory-files-recursively + +;;;; Defined in format-spec.el + +;; TODO provide advice for format-spec + +;;;; Defined in regexp-opt.el + +(compat-defun regexp-opt (strings &optional paren) + "Handle an empty list of strings." + :prefix 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") + +;;* UNTESTED +(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)." + ;; 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 (and (boundp 'byte-compile-current-file) byte-compile-current-file) + load-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 + +(declare-function + dired-get-marked-files "dired.el" + (&optional localp arg filter distinguish-one-marked error)) + +;;* UNTESTED +(compat-defun dired-get-marked-files + (&optional localp arg filter distinguish-one-marked error) + "Return the marked files’ names as list of strings." + :feature 'dired + :prefix 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 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--inhibit-prefixed (provide 'compat-27)) +;;; compat-27.el ends here diff --git a/elpa/compat-28.1.2.2/compat-28.el b/elpa/compat-28.1.2.2/compat-28.el new file mode 100644 index 00000000..a3dc7693 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-28.el @@ -0,0 +1,882 @@ +;;; compat-28.el --- Compatibility Layer for Emacs 28.1 -*- lexical-binding: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; URL: https://git.sr.ht/~pkal/compat/ +;; 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: + +;; Find here the functionality added in Emacs 28.1, needed by older +;; versions. +;; +;; Only load this library if you need to use one of the following +;; functions: +;; +;; - `unlock-buffer' +;; - `string-width' +;; - `directory-files' +;; - `json-serialize' +;; - `json-insert' +;; - `json-parse-string' +;; - `json-parse-buffer' +;; - `count-windows' + +;;; Code: + +(require 'compat-macs "compat-macs.el") + +(compat-declare-version "28.1") + +;;;; Defined in fns.c + +;;* INCOMPLETE FEATURE: 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) + "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) + "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) + "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 ((seperator (eval-when-compile + (if (memq system-type '(ms-dos windows-nt cygwin)) + "\\" "/"))) + (last (if components (car (last components)) directory))) + (mapconcat (lambda (part) + (if (eq part last) ;the last component is not modified + last + (replace-regexp-in-string + (concat seperator "+\\'") "" part))) + (cons directory components) + seperator))) + +;;;; Defined in alloc.c + +;;* UNTESTED (but also not necessary) +(compat-defun garbage-collect-maybe (_factor) + "Call ‘garbage-collect’ if enough allocation happened. +FACTOR determines what \"enough\" means here: If FACTOR is a +positive number N, it means to run GC if more than 1/Nth of the +allocations needed to trigger automatic allocation took place. +Therefore, as N gets higher, this is more likely to perform a GC. +Returns non-nil if GC happened, and nil otherwise." + :note "For releases of Emacs before version 28, this function will do nothing." + ;; Do nothing + nil) + +;;;; Defined in filelock.c + +(compat-defun unlock-buffer () + "Handle `file-error' conditions: + +Handles file system errors by calling ‘display-warning’ and +continuing as if the error did not occur." + :prefix t + (condition-case error + (unlock-buffer) + (file-error + (display-warning + '(unlock-file) + (message "%s, ignored" (error-message-string error)) + :warning)))) + +;;;; Defined in characters.c + +(compat-defun string-width (string &optional from to) + "Handle optional arguments FROM and TO: + +Optional arguments FROM and TO specify the substring of STRING to +consider, and are interpreted as in `substring'." + :prefix 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 + +;;* UNTESTED +(compat-defun directory-files (directory &optional full match nosort count) + "Handle additional optional argument COUNT: + +If COUNT is non-nil and a natural number, the function will + return COUNT number of file names (if so many are present)." + :prefix t + (let ((files (directory-files directory full match nosort))) + (when (natnump count) + (setf (nthcdr count files) nil)) + files)) + +;;;; Defined in json.c + +(declare-function json-insert nil (object &rest args)) +(declare-function json-serialize nil (object &rest args)) +(declare-function json-parse-string nil (string &rest args)) +(declare-function json-parse-buffer nil (&rest args)) + +(compat-defun json-serialize (object &rest args) + "Handle top-level JSON values." + :prefix t + :min-version "27" + (if (or (listp object) (vectorp object)) + (apply #'json-serialize object args) + (substring (json-serialize (list object)) 1 -1))) + +(compat-defun json-insert (object &rest args) + "Handle top-level JSON values." + :prefix t + :min-version "27" + (if (or (listp object) (vectorp object)) + (apply #'json-insert object args) + ;; `compat-json-serialize' is not sharp-quoted as the byte + ;; compiled doesn't always know that the function has been + ;; defined, but it will only be used in this function if the + ;; prefixed definition of `json-serialize' (see above) has also + ;; been defined. + (insert (apply 'compat-json-serialize object args)))) + +(compat-defun json-parse-string (string &rest args) + "Handle top-level JSON values." + :prefix t + :min-version "27" + (if (string-match-p "\\`[[:space:]]*[[{]" string) + (apply #'json-parse-string string args) + ;; Wrap the string in an array, and extract the value back using + ;; `elt', to ensure that no matter what the value of `:array-type' + ;; is we can access the first element. + (elt (apply #'json-parse-string (concat "[" string "]") args) 0))) + +(compat-defun json-parse-buffer (&rest args) + "Handle top-level JSON values." + :prefix t + :min-version "27" + (if (looking-at-p "[[:space:]]*[[{]") + (apply #'json-parse-buffer args) + (catch 'escape + (atomic-change-group + (with-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?\" "\"" st) + (modify-syntax-entry ?. "_" st) + st) + (let ((inhibit-read-only t)) + (save-excursion + (insert "[") + (forward-sexp 1) + (insert "]")))) + (throw 'escape (elt (apply #'json-parse-buffer args) 0)))))) + +;;;; 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 subr.el + +;;* INCOMPLETE FEATURE: 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) + +;;* UNTESTED +(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)))) + +;;* UNTESTED +(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 + (let ((matches 0) + (case-fold-search nil)) + (goto-char start) + (while (search-forward string end t) + (delete-region (match-beginning 0) (match-end 0)) + (insert replacement) + (setq matches (1+ matches))) + (and (not (zerop matches)) + matches)))) + +;;* UNTESTED +(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 + (let ((matches 0) + (case-fold-search nil)) + (goto-char start) + (while (re-search-forward regexp end t) + (replace-match replacement t) + (setq matches (1+ matches))) + (and (not (zerop matches)) + matches)))) + +;;* UNTESTED +(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)) + +;;* UNTESTED +(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 ((quit (make-symbol "with-existing-directory-quit"))) + `(catch ',quit + (dolist (dir (list default-directory + (expand-file-name "~/") + (getenv "TMPDIR") + "/tmp/" + ;; XXX: check if "/" works on non-POSIX + ;; system. + "/")) + (when (and dir (file-exists-p dir)) + (throw ',quit (let ((default-directory dir)) + ,@body))))))) + +;;* UNTESTED +(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-defun subr-primitive-p (object) + "Return t if OBJECT is a built-in primitive function." + (subrp object)) + +;;;; 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." + :feature 'subr-x + (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." + :feature 'subr-x + (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-lines (string &optional omit-nulls) + "Split STRING into a list of lines. +If OMIT-NULLS, empty lines will be removed from the results." + :feature 'subr-x + (split-string string "\n" omit-nulls)) + +(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." + :feature 'subr-x + (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." + :feature 'subr-x + (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." + :feature 'subr-x + (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)))))) + (let ((tco-body (funcall tco (macroexpand-all (macroexp-progn body))))) + (when tco-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 + +(declare-function compat--string-trim-left "compat-26" (string &optional regexp)) +(declare-function compat--directory-name-p "compat-25" (name)) +(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 (compat--string-trim-left extension "[.]"))) + (cond + ((string= filename "") + (error "Empty filename")) + ((string= extn "") + (error "Malformed extension: %s" extension)) + ((compat--directory-name-p filename) + (error "Filename is a directory: %s" filename)) + (t + (concat (file-name-sans-extension filename) "." extn))))) + +;;* UNTESTED +(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 (lsh 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)))) + +;;* UNTESTED +(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 files-x.el + +(declare-function tramp-tramp-file-p "tramp" (name)) + +;;* UNTESTED +(compat-defun null-device () + "Return the best guess for the null device." + (require 'tramp) + (if (tramp-tramp-file-p default-directory) + "/dev/null" + null-device)) + +;;;; 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 windows.el + +;;* UNTESTED +(compat-defun count-windows (&optional minibuf all-frames) + "Handle optional argument ALL-FRAMES: + +If ALL-FRAMES is non-nil, count the windows in all frames instead +just the selected frame." + :prefix 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 + +(declare-function mouse-set-point "mouse" (event &optional promote-to-region)) + +;;* UNTESTED +(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." + :feature 'thingatpt + (save-excursion + (mouse-set-point event) + (thing-at-point thing no-properties))) + +;;;; Defined in macroexp.el + +;;* UNTESTED +(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." + :feature 'macroexp + (let ((file (car (last current-load-list)))) + (or (if (stringp file) file) + (bound-and-true-p byte-compile-current-file)))) + +;;;; Defined in env.el + +;;* UNTESTED +(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 button.el + +;;* UNTESTED +(compat-defun button-buttonize (string callback &optional data) + "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." + :feature 'button + (propertize string + 'face 'button + 'button t + 'follow-link t + 'category t + 'button-data data + 'keymap button-map + 'action callback)) + +;;;; Defined in autoload.el + +(defvar generated-autoload-file) + +;;* UNTESTED +(compat-defun make-directory-autoloads (dir output-file) + "Update autoload definitions for Lisp files in the directories DIRS. +DIR can be either a single directory or a list of +directories. (The latter usage is discouraged.) + +The autoloads will be written to OUTPUT-FILE. If any Lisp file +binds `generated-autoload-file' as a file-local variable, write +its autoloads into the specified file instead. + +The function does NOT recursively descend into subdirectories of the +directory or directories specified." + (let ((generated-autoload-file output-file)) + ;; We intentionally don't sharp-quote + ;; `update-directory-autoloads', because it was deprecated in + ;; Emacs 28 and we don't want to trigger the byte compiler for + ;; newer versions. + (apply 'update-directory-autoloads + (if (listp dir) dir (list dir))))) + +;;;; 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 + :version "28" + ;; Inlining the definitions from compat-27 + (+ (if (consp (nth 0 time)) + ;; Fractional second. + (/ (float (car (nth 0 time))) + (cdr (nth 0 time))) + (or (nth 0 time) 0)) + (* (or (nth 1 time) 0) 60) + (* (or (nth 2 time) 0) 60 60) + (* (or (nth 3 time) 0) 60 60 24) + (* (or (nth 4 time) 0) 60 60 24 30) + (* (or (nth 5 time) 0) 60 60 24 365))) + +(compat--inhibit-prefixed (provide 'compat-28)) +;;; compat-28.el ends here diff --git a/elpa/compat-28.1.2.2/compat-autoloads.el b/elpa/compat-28.1.2.2/compat-autoloads.el new file mode 100644 index 00000000..8df84445 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-autoloads.el @@ -0,0 +1,42 @@ +;;; 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-27" "compat-27.el" (0 0 0 0)) +;;; Generated autoloads from compat-27.el + +(register-definition-prefixes "compat-27" '("derived-mode-p")) + +;;;*** + +;;;### (autoloads nil "compat-help" "compat-help.el" (0 0 0 0)) +;;; Generated autoloads from compat-help.el + +(register-definition-prefixes "compat-help" '("compat---describe")) + +;;;*** + +;;;### (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-24.el" "compat-25.el" "compat-26.el" +;;;;;; "compat-28.el" "compat-font-lock.el" "compat-pkg.el" "compat.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-28.1.2.2/compat-font-lock.el b/elpa/compat-28.1.2.2/compat-font-lock.el new file mode 100644 index 00000000..66a62e55 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-font-lock.el @@ -0,0 +1,48 @@ +;;; compat-font-lock.el --- -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Keywords: + +;; 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: + +;; Optional font-locking for `compat' definitions. Every symbol with +;; an active compatibility definition will be highlighted. +;; +;; Load this file to enable the functionality. + +;;; Code: + +(eval-and-compile + (require 'cl-lib) + (require 'compat-macs)) + +(defvar compat-generate-common-fn) +(let ((compat-generate-common-fn + (lambda (name _def-fn _install-fn check-fn attr _type) + (unless (and (plist-get attr :no-highlight) + (funcall check-fn)) + `(font-lock-add-keywords + 'emacs-lisp-mode + ',`((,(concat "\\_<\\(" + (regexp-quote (symbol-name name)) + "\\)\\_>") + 1 font-lock-preprocessor-face prepend))))))) + (load "compat")) + +(provide 'compat-font-lock) +;;; compat-font-lock.el ends here diff --git a/elpa/compat-28.1.2.2/compat-help.el b/elpa/compat-28.1.2.2/compat-help.el new file mode 100644 index 00000000..440e35f2 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-help.el @@ -0,0 +1,57 @@ +;;; compat-help.el --- Documentation for compat functions -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic + +;; 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: + +;; Load this file to insert `compat'-relevant documentation next to +;; the regular documentation of a symbol. + +;;; Code: + +(defun compat---describe (symbol) + "Insert documentation for SYMBOL if it has compatibility code." + (let ((compat (get symbol 'compat-def))) + (when compat + (let ((doc (get compat 'compat-doc)) + (start (point))) + (when doc + (insert "There is a ") + (insert-button + "compatibility notice" + 'action (let ((type (get compat 'compat-type))) + (cond + ((memq type '(func macro advice)) + #'find-function) + ((memq type '(variable)) + #'find-variable) + ((error "Unknown type")))) + 'button-data compat) + (insert (format " for %s (for versions of Emacs before %s):" + (symbol-name symbol) + (get compat 'compat-version))) + (add-text-properties start (point) '(face bold)) + (newline 2) + (insert (substitute-command-keys doc)) + (fill-region start (point)) + (newline 2)))))) + +(add-hook 'help-fns-describe-function-functions #'compat---describe) + +(provide 'compat-help) +;;; compat-help.el ends here diff --git a/elpa/compat-28.1.2.2/compat-macs.el b/elpa/compat-28.1.2.2/compat-macs.el new file mode 100644 index 00000000..c6417c83 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-macs.el @@ -0,0 +1,316 @@ +;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; 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: + +;; These macros are used to define compatibility functions, macros and +;; advice. + +;;; Code: + +(defmacro compat--ignore (&rest _) + "Ignore all arguments." + nil) + +(defvar compat--inhibit-prefixed nil + "Non-nil means that prefixed definitions are not loaded. +A prefixed function is something like `compat-assoc', that is +only made visible when the respective compatibility version file +is loaded (in this case `compat-26').") + +(defmacro compat--inhibit-prefixed (&rest body) + "Ignore BODY unless `compat--inhibit-prefixed' is true." + `(unless (bound-and-true-p compat--inhibit-prefixed) + ,@body)) + +(defvar compat-current-version nil + "Default version to use when no explicit version was given.") + +(defmacro compat-declare-version (version) + "Set the Emacs version that is currently being handled to VERSION." + ;; FIXME: Avoid setting the version for any definition that might + ;; follow, but try to restrict it to the current file/buffer. + (setq compat-current-version version) + nil) + +(defvar compat--generate-function #'compat--generate-default + "Function used to generate compatibility code. +The function must take six arguments: NAME, DEF-FN, INSTALL-FN, +CHECK-FN, ATTR and TYPE. The resulting body is constructed by +invoking the functions DEF-FN (passed the \"realname\" and the +version number, returning the compatibility definition), the +INSTALL-FN (passed the \"realname\" and returning the +installation code), CHECK-FN (passed the \"realname\" and +returning a check to see if the compatibility definition should +be installed). ATTR is a plist used to modify the generated +code. The following attributes are handled, all others are +ignored: + +- :min-version :: Prevent the compatibility definition from begin + installed in versions older than indicated (string). + +- :max-version :: Prevent the compatibility definition from begin + installed in versions newer than indicated (string). + +- :feature :: The library the code is supposed to be loaded + with (via `eval-after-load'). + +- :cond :: Only install the compatibility code, iff the value + evaluates to non-nil. + + For prefixed functions, this can be interpreted as a test to + `defalias' an existing definition or not. + +- :no-highlight :: Do not highlight this definition as + compatibility function. + +- :version :: Manual specification of the version the compatee + code was defined in (string). + +- :realname :: Manual specification of a \"realname\" to use for + the compatibility definition (symbol). + +- :notes :: Additional notes that a developer using this + compatibility function should keep in mind. + +- :prefix :: Add a `compat-' prefix to the name, and define the + compatibility code unconditionally. + +TYPE is used to set the symbol property `compat-type' for NAME.") + +(defun compat--generate-default (name def-fn install-fn check-fn attr type) + "Generate a leaner compatibility definition. +See `compat-generate-function' for details on the arguments NAME, +DEF-FN, INSTALL-FN, CHECK-FN, ATTR and TYPE." + (let* ((min-version (plist-get attr :min-version)) + (max-version (plist-get attr :max-version)) + (feature (plist-get attr :feature)) + (cond (plist-get attr :cond)) + (version (or (plist-get attr :version) + compat-current-version)) + (realname (or (plist-get attr :realname) + (intern (format "compat--%S" name)))) + (check (cond + ((or (and min-version + (version< emacs-version min-version)) + (and max-version + (version< max-version emacs-version))) + '(compat--ignore)) + ((plist-get attr :prefix) + '(compat--inhibit-prefixed)) + ((and version (version<= version emacs-version) (not cond)) + '(compat--ignore)) + (`(when (and ,(if cond cond t) + ,(funcall check-fn))))))) + (cond + ((and (plist-get attr :prefix) (memq type '(func macro)) + (string-match "\\`compat-\\(.+\\)\\'" (symbol-name name)) + (let* ((actual-name (intern (match-string 1 (symbol-name name)))) + (body (funcall install-fn actual-name version))) + (when (and (version<= version emacs-version) + (fboundp actual-name)) + `(,@check + ,(if feature + ;; See https://nullprogram.com/blog/2018/02/22/: + `(eval-after-load ,feature `(funcall ',(lambda () ,body))) + body)))))) + ((plist-get attr :realname) + `(progn + ,(funcall def-fn realname version) + (,@check + ,(let ((body (funcall install-fn realname version))) + (if feature + ;; See https://nullprogram.com/blog/2018/02/22/: + `(eval-after-load ,feature `(funcall ',(lambda () ,body))) + body))))) + ((let* ((body (if (eq type 'advice) + `(,@check + ,(funcall def-fn realname version) + ,(funcall install-fn realname version)) + `(,@check ,(funcall def-fn name version))))) + (if feature + ;; See https://nullprogram.com/blog/2018/02/22/: + `(eval-after-load ,feature `(funcall ',(lambda () ,body))) + body)))))) + +(defun compat-generate-common (name def-fn install-fn check-fn attr type) + "Common code for generating compatibility definitions. +See `compat-generate-function' for details on the arguments NAME, +DEF-FN, INSTALL-FN, CHECK-FN, ATTR and TYPE." + (when (and (plist-get attr :cond) (plist-get attr :prefix)) + (error "A prefixed function %s cannot have a condition" name)) + (funcall compat--generate-function + name def-fn install-fn check-fn attr type)) + +(defun compat-common-fdefine (type name arglist docstring rest) + "Generate compatibility code for a function NAME. +TYPE is one of `func', for functions and `macro' for macros, and +`advice' ARGLIST is passed on directly to the definition, and +DOCSTRING is prepended with a compatibility note. REST contains +the remaining definition, that may begin with a property list of +attributes (see `compat-generate-common')." + (let ((oldname name) (body rest)) + (while (keywordp (car body)) + (setq body (cddr body))) + ;; 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 (version<= emacs-version "25") + (delq (assq 'side-effect-free (car body)) (car body)) + (delq (assq 'pure (car body)) (car body)))) + ;; Check if we want an explicitly prefixed function + (when (plist-get rest :prefix) + (setq name (intern (format "compat-%s" name)))) + (compat-generate-common + name + (lambda (realname version) + `(,(cond + ((memq type '(func advice)) 'defun) + ((eq type 'macro) 'defmacro) + ((error "Unknown type"))) + ,realname ,arglist + ;; Prepend compatibility notice to the actual + ;; documentation string. + ,(let ((type (cond + ((eq type 'func) "function") + ((eq type 'macro) "macro") + ((eq type 'advice) "advice") + ((error "Unknown type"))))) + (if version + (format + "[Compatibility %s for `%S', defined in Emacs %s]\n\n%s" + type oldname version docstring) + (format + "[Compatibility %s for `%S']\n\n%s" + type oldname docstring))) + ;; Advice may use the implicit variable `oldfun', but + ;; to avoid triggering the byte compiler, we make + ;; sure the argument is used at least once. + ,@(if (eq type 'advice) + (cons '(ignore oldfun) body) + body))) + (lambda (realname _version) + (cond + ((memq type '(func macro)) + ;; Functions and macros are installed by + ;; aliasing the name of the compatible + ;; function to the name of the compatibility + ;; function. + `(defalias ',name #',realname)) + ((eq type 'advice) + `(advice-add ',name :around #',realname)))) + (lambda () + (cond + ((memq type '(func macro)) + `(not (fboundp ',name))) + ((eq type 'advice) t))) + rest type))) + +(defmacro compat-defun (name arglist docstring &rest rest) + "Define NAME with arguments ARGLIST as a compatibility function. +The function must be documented in DOCSTRING. REST may begin +with a plist, that is interpreted by the macro but not passed on +to the actual function. See `compat-generate-common' for a +listing of attributes. + +The definition will only be installed, if the version this +function was defined in, as indicated by the `:version' +attribute, is greater than the current Emacs version." + (declare (debug (&define name (&rest symbolp) + stringp + [&rest keywordp sexp] + def-body)) + (doc-string 3) (indent 2)) + (compat-common-fdefine 'func name arglist docstring rest)) + +(defmacro compat-defmacro (name arglist docstring &rest rest) + "Define NAME with arguments ARGLIST as a compatibility macro. +The macro must be documented in DOCSTRING. REST may begin +with a plist, that is interpreted by this macro but not passed on +to the actual macro. See `compat-generate-common' for a +listing of attributes. + +The definition will only be installed, if the version this +function was defined in, as indicated by the `:version' +attribute, is greater than the current Emacs version." + (declare (debug compat-defun) (doc-string 3) (indent 2)) + (compat-common-fdefine 'macro name arglist docstring rest)) + +(defmacro compat-advise (name arglist docstring &rest rest) + "Define NAME with arguments ARGLIST as a compatibility advice. +The advice function must be documented in DOCSTRING. REST may +begin with a plist, that is interpreted by this macro but not +passed on to the actual advice function. See +`compat-generate-common' for a listing of attributes. The advice +wraps the old definition, that is accessible via using the symbol +`oldfun'. + +The advice will only be installed, if the version this function +was defined in, as indicated by the `:version' attribute, is +greater than the current Emacs version." + (declare (debug compat-defun) (doc-string 3) (indent 2)) + (compat-common-fdefine 'advice name (cons 'oldfun arglist) docstring rest)) + +(defmacro compat-defvar (name initval docstring &rest attr) + "Declare compatibility variable NAME with initial value INITVAL. +The obligatory documentation string DOCSTRING must be given. + +The remaining arguments ATTR form a plist, modifying the +behaviour of this macro. See `compat-generate-common' for a +listing of attributes. Furthermore, `compat-defvar' also handles +the attribute `:local' that either makes the variable permanent +local with a value of `permanent' or just buffer local with any +non-nil value." + (declare (debug (name form stringp [&rest keywordp sexp])) + (doc-string 3) (indent 2)) + ;; Check if we want an explicitly prefixed function + (let ((oldname name)) + (when (plist-get attr :prefix) + (setq name (intern (format "compat-%s" name)))) + (compat-generate-common + name + (lambda (realname version) + (let ((localp (plist-get attr :local))) + `(progn + (,(if (plist-get attr :constant) 'defconst 'defvar) + ,realname ,initval + ;; Prepend compatibility notice to the actual + ;; documentation string. + ,(if version + (format + "[Compatibility variable for `%S', defined in Emacs %s]\n\n%s" + oldname version docstring) + (format + "[Compatibility variable for `%S']\n\n%s" + oldname docstring))) + ;; Make variable as local if necessary + ,(cond + ((eq localp 'permanent) + `(put ',realname 'permanent-local t)) + (localp + `(make-variable-buffer-local ',realname)))))) + (lambda (realname _version) + `(defvaralias ',name ',realname)) + (lambda () + `(not (boundp ',name))) + attr 'variable))) + +(provide 'compat-macs) +;;; compat-macs.el ends here diff --git a/elpa/compat-28.1.2.2/compat-pkg.el b/elpa/compat-28.1.2.2/compat-pkg.el new file mode 100644 index 00000000..c3a4bf48 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from compat.el -*- no-byte-compile: t -*- +(define-package "compat" "28.1.2.2" "Emacs Lisp Compatibility Library" '((emacs "24.3") (nadvice "0.3")) :commit "d533692182c084bad623977b69f9dc298255eaab" :authors '(("Philip Kaludercic" . "philipk@posteo.net")) :maintainer '("Compat Development" . "~pkal/compat-devel@lists.sr.ht") :keywords '("lisp") :url "https://sr.ht/~pkal/compat") diff --git a/elpa/compat-28.1.2.2/compat.el b/elpa/compat-28.1.2.2/compat.el new file mode 100644 index 00000000..921f4f8b --- /dev/null +++ b/elpa/compat-28.1.2.2/compat.el @@ -0,0 +1,58 @@ +;;; compat.el --- Emacs Lisp Compatibility Library -*- lexical-binding: t; -*- + +;; Copyright (C) 2021, 2022 Free Software Foundation, Inc. + +;; Author: Philip Kaludercic +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; Version: 28.1.2.2 +;; URL: https://sr.ht/~pkal/compat +;; Package-Requires: ((emacs "24.3") (nadvice "0.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: + +;; To allow for the usage of Emacs functions and macros that are +;; defined in newer versions of Emacs, compat.el provides definitions +;; that are installed ONLY if necessary. These reimplementations of +;; functions and macros are at least subsets of the actual +;; implementations. Be sure to read the documentation string to make +;; sure. +;; +;; Not every function provided in newer versions of Emacs is provided +;; here. Some depend on new features from the core, others cannot be +;; implemented to a meaningful degree. Please consult the Compat +;; manual for details. The main audience for this library are not +;; regular users, but package maintainers. Therefore commands and +;; user options are usually not implemented here. + +;;; Code: + +(defvar compat--inhibit-prefixed) +(let ((compat--inhibit-prefixed (not (bound-and-true-p compat-testing)))) + ;; Instead of using `require', we manually check `features' and call + ;; `load' to avoid the issue of not using `provide' at the end of + ;; the file (which is disabled by `compat--inhibit-prefixed', so + ;; that the file can be loaded again at some later point when the + ;; prefixed definitions are needed). + (dolist (vers '(24 25 26 27 28)) + (unless (memq (intern (format "compat-%d" vers)) features) + (load (format "compat-%d%s" vers + (if (bound-and-true-p compat-testing) + ".el" "")) + nil t)))) + +(provide 'compat) +;;; compat.el ends here diff --git a/elpa/compat-28.1.2.2/compat.info b/elpa/compat-28.1.2.2/compat.info new file mode 100644 index 00000000..de212352 --- /dev/null +++ b/elpa/compat-28.1.2.2/compat.info @@ -0,0 +1,2070 @@ +This is compat.info, produced by makeinfo version 6.7 from compat.texi. + +Copyright © 2022 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: compat.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 +28.1.2.2. + + Copyright © 2022 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:: +* Intentions:: + +Usage + +* Additional libraries:: + +Support + +* Emacs 24.4:: Compatibility support for Emacs 24.4 +* 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 + + + +File: compat.info, Node: Introduction, Next: Support, Prev: Top, Up: Top + +1 Introduction +************** + +* Menu: + +* Overview:: +* Usage:: +* Intentions:: + + +File: compat.info, Node: Overview, Next: Usage, Up: Introduction + +1.1 Overview +============ + +The objective of Compat is to provide "forwards compatibility" library +for Emacs Lisp. That is to say 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. + + Version 24.3 is chosen as the oldest version, because this is the +newest version on CentOS 7. It is intended to preserve compatibility +for at least as the Centos 7 reaches EOL +(https://wiki.centos.org/About/Product), 2024. + + If you are developing a package with Compat in mind, consider loading +‘compat-help‘ (on your system, not in a package) to get relevant notes +inserted into the help buffers of functions that are implemented or +advised in Compat. + + Note that Compat provides a few prefixed function, ie. functions +with a ‘compat-’ prefix. These are used to provide extended +functionality for commands that are already defined (‘sort’, ‘assoc’, +‘seq’, ...). It might be possible to transform these into advised +functions later on, so that the modified functionality is accessible +without a prefix. Feedback on this point is appreciated. + + +File: compat.info, Node: Usage, Next: Intentions, 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.3") (compat "28.1.2.2")) + + There is no need to depend on ‘emacs’ 24.3 specifically. One can +choose to any newer version, if features not provided by Compat +necessitate it. + + In any file where compatibility forms are used, a + + (require 'compat) + + should be added early on. + + This will load all non-prefixed definitions (functions and macros +with a leading ‘compat-‘). To load these, an additional + + (require 'compat-XY) ; e.g. 26 + + will be necessary, to load compatibility code for Emacs version XY. + + It is recommended 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. + +* Menu: + +* Additional libraries:: + + +File: compat.info, Node: Additional libraries, Up: Usage + +1.2.1 Additional libraries +-------------------------- + +These libraries are packages with Compat, but are disabled by default. +To use them you can use ‘M-x load-library’: + +compat-help + Add notes to ‘*Help*’ buffer, if a compatibility definition has + something to warn you about. +compat-font-lock + Highlight functions that are implemented as compatibility + definitions. + + +File: compat.info, Node: Intentions, Prev: Usage, Up: Introduction + +1.3 Intentions +============== + +The library intends to provide support back until Emacs 24.3. The +intended audience are package developers that are interested in using +newer developments, without having to break compatibility. + + Sadly, total backwards compatibility cannot be provided for technical +reasons. These might include: + + • An existing function or macro was extended by some new + functionality. To support these cases, the function or macro would + have to be advised. As this is usually regarded as invasive and is + shown to be a significant overhead, even when the new feature is + not used, this approach is not used. + + As a compromise, prefixed functions and macros (starting with a + ‘compat-’ prefix) can be provided. + + • New functionality was implemented in the core, and depends on + external libraries that cannot be reasonably duplicated in the + scope of a compatibility library. + + • New functionality depends on an entire new, non-trivial library. + Sometimes these are provided via ELPA (xref, project, ...), but + other times it would be infeasible to duplicate an entire library + within Compat while also providing the necessary backwards + compatibility. + + • It just wasn’t added, and there is no good reason (though good + excuses might exist). If you happen to find such a function, *note + reporting: Development. it would be much appreciated. + + Always begin by assuming that this might be the case, unless proven + otherwise. + + +File: compat.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 24.4:: Compatibility support for Emacs 24.4 +* 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 + + +File: compat.info, Node: Emacs 24.4, Next: Emacs 25.1, Up: Support + +2.1 Emacs 24.4 +============== + +2.1.1 Unprefixed Definitions +---------------------------- + +The following functions and macros implemented in 24.4, and are provided +by Compat by default: + + -- Macro: with-eval-after-load library body... + This macro arranges to evaluate BODY at the end of loading the file + LIBRARY, each time LIBRARY is loaded. If LIBRARY is already + loaded, it evaluates BODY right away. + + You don’t need to give a directory or extension in the file name + LIBRARY. Normally, you just give a bare file name, like this: + + (with-eval-after-load "js" (keymap-set js-mode-map "C-c C-c" 'js-eval)) + + To restrict which files can trigger the evaluation, include a + directory or an extension or both in LIBRARY. Only a file whose + absolute true name (i.e., the name with all symbolic links chased + out) matches all the given name components will match. In the + following example, ‘my_inst.elc’ or ‘my_inst.elc.gz’ in some + directory ‘..../foo/bar’ will trigger the evaluation, but not + ‘my_inst.el’: + + (with-eval-after-load "foo/bar/my_inst.elc" ...) + + LIBRARY can also be a feature (i.e., a symbol), in which case BODY + is evaluated at the end of any file where ‘(provide LIBRARY)’ is + called. + + An error in BODY does not undo the load, but does prevent execution + of the rest of BODY. + + *Note (elisp)Hooks for Loading::. + + -- Function: special-form-p object + This predicate tests whether its argument is a special form, and + returns ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Special Forms::. + + -- Function: macrop object + This predicate tests whether its argument is a macro, and returns + ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Simple Macro::. + + -- Function: string-suffix-p suffix string &optional ignore-case + This function returns non-‘nil’ if SUFFIX is a suffix of STRING; + i.e., if STRING ends with SUFFIX. If the optional argument + IGNORE-CASE is non-‘nil’, the comparison ignores case differences. + + *Note (elisp)Text Comparison::. + + -- Function: delete-consecutive-dups list &optional circular + Destructively remove ‘equal’ consecutive duplicates from LIST. + First and last elements are considered consecutive if CIRCULAR is + non-nil. + + -- Function: define-error name message &optional parent + In order for a symbol to be an error symbol, it must be defined + with ‘define-error’ which takes a parent condition (defaults to + ‘error’). This parent defines the conditions that this kind of + error belongs to. The transitive set of parents always includes + the error symbol itself, and the symbol ‘error’. Because quitting + is not considered an error, the set of parents of ‘quit’ is just + ‘(quit)’. + + *Note (elisp)Error Symbols::. + + -- Function: bool-vector-exclusive-or a b &optional c + Return “bitwise exclusive or” of bool vectors A and B. If optional + argument C is given, the result of this operation is stored into C. + All arguments should be bool vectors of the same length. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-union a b &optional c + Return “bitwise or” of bool vectors A and B. If optional argument + C is given, the result of this operation is stored into C. All + arguments should be bool vectors of the same length. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-intersection a b &optional c + Return “bitwise and” of bool vectors A and B. If optional argument + C is given, the result of this operation is stored into C. All + arguments should be bool vectors of the same length. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-set-difference a b &optional c + Return “set difference” of bool vectors A and B. If optional + argument C is given, the result of this operation is stored into C. + All arguments should be bool vectors of the same length. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-not a &optional b + Return “set complement” of bool vector A. If optional argument B + is given, the result of this operation is stored into B. All + arguments should be bool vectors of the same length. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-subsetp a b + Return ‘t’ if every ‘t’ value in A is also ‘t’ in B, ‘nil’ + otherwise. All arguments should be bool vectors of the same + length. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-count-consecutive a b i + Return the number of consecutive elements in A equal B starting at + I. ‘a’ is a bool vector, B is ‘t’ or ‘nil’, and I is an index into + ‘a’. + + *Note (elisp)Bool-Vectors::. + + -- Function: bool-vector-count-population a + Return the number of elements that are ‘t’ in bool vector A. + + *Note (elisp)Bool-Vectors::. + + -- Function: completion-table-with-cache function &optional ignore-case + This is a wrapper for ‘completion-table-dynamic’ that saves the + last argument-result pair. This means that multiple lookups with + the same argument only need to call FUNCTION once. This can be + useful when a slow operation is involved, such as calling an + external process. + + *Note (elisp)Programmed Completion::. + + -- Function: face-spec-set face spec &optional spec-type + This function applies SPEC as a face spec for ‘face’. SPEC should + be a face spec, as described in the above documentation for + ‘defface’. + + This function also defines FACE as a valid face name if it is not + already one, and (re)calculates its attributes on existing frames. + + The optional argument SPEC-TYPE determines which spec to set. If + it is omitted or ‘nil’ or ‘face-override-spec’, this function sets + the “override spec”, which overrides face specs on FACE of all the + other types mentioned below. This is useful when calling this + function outside of Custom code. If SPEC-TYPE is ‘customized-face’ + or ‘saved-face’, this function sets the customized spec or the + saved custom spec, respectively. If it is ‘face-defface-spec’, + this function sets the default face spec (the same one set by + ‘defface’). If it is ‘reset’, this function clears out all + customization specs and override specs from FACE (in this case, the + value of SPEC is ignored). The effect of any other value of + SPEC-TYPE on the face specs is reserved for internal use, but the + function will still define FACE itself and recalculate its + attributes, as described above. + + *Note (elisp)Defining Faces::. + +2.1.2 Prefixed Definitions +-------------------------- + +These functions are prefixed with ‘compat’ prefix, and are only loaded +when ‘compat-24’ is required: + + -- Function: compat-= number-or-marker &rest number-or-markers + This function tests whether all its arguments are numerically + equal, and returns ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Comparison of Numbers::. + -- Function: compat-< number-or-marker &rest number-or-markers + This function tests whether each argument is strictly less than the + following argument. It returns ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Comparison of Numbers::. + -- Function: compat-> number-or-marker &rest number-or-markers + This function tests whether each argument is strictly greater than + the following argument. It returns ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Comparison of Numbers::. + -- Function: compat-<= number-or-marker &rest number-or-markers + This function tests whether each argument is less than or equal to + the following argument. It returns ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Comparison of Numbers::. + -- Function: compat->= number-or-marker &rest number-or-markers + This function tests whether each argument is greater than or equal + to the following argument. It returns ‘t’ if so, ‘nil’ otherwise. + + *Note (elisp)Comparison of Numbers::. + + These functions differ from the previous implementation in that they +allow for more than two argument to be compared. + + -- Function: compat-split-string string &optional separators omit-nulls + trim + This function splits STRING into substrings based on the regular + expression SEPARATORS (*note (elisp)Regular Expressions::). Each + match for SEPARATORS defines a splitting point; the substrings + between splitting points are made into a list, which is returned. + + *note (elisp)Creating Strings:: for more details. + + This version handles the optional argument TRIM. If it is + non-‘nil’, it should be a regular expression to match text to trim + from the beginning and end of each substring. If trimming makes + the substring empty, it is treated as null. + +2.1.3 Missing Definitions +------------------------- + +Compat does not provide support for the following Lisp features +implemented in 24.4: + + • Allowing the second optional argument to ‘eval’ to specify a + lexical environment. + • The ‘define-alternatives’ macro. + • Support for the ‘defalias-fset-function’ symbol property. + • The ‘group-gid’ and ‘groupd-read-gid’ functions. + • The ‘pre-redisplay-function’ hook. + • Allowing for ‘with-demoted-errors’ to take a additional argument + ‘format’. + • The ‘add-face-text-property’ function. + • No ‘tty-setup-hook’ hook. + • The ‘get-pos-property’ function. + • The ‘define-advice’ macro. + • Support for generators. + • The ‘string-trim’, ‘string-trim-left’ and ‘string-trim-right’ + functions. These are instead provided as prefixed function as part + of *note Emacs 26.1:: support. + + +File: compat.info, Node: Emacs 25.1, Next: Emacs 26.1, Prev: Emacs 24.4, Up: Support + +2.2 Emacs 25.1 +============== + +2.2.1 Unprefixed Definitions +---------------------------- + +The following functions and macros implemented in 25.1, and are provided +by Compat by default: + + -- 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 testfn + 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’. + + 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*’. + + -- 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: directory-files-recursively directory regexp &optional + include-directories predicate follow-symlinks + Return all files under DIRECTORY whose names match REGEXP. This + function searches the specified DIRECTORY and its sub-directories, + recursively, for files whose basenames (i.e., without the leading + directories) match the specified REGEXP, and returns a list of the + absolute file names of the matching files (*note absolute file + names: (elisp)Relative File Names.). The file names are returned + in depth-first order, meaning that files in some sub-directory are + returned before the files in its parent directory. In addition, + matching files found in each subdirectory are sorted alphabetically + by their basenames. By default, directories whose names match + REGEXP are omitted from the list, but if the optional argument + INCLUDE-DIRECTORIES is non-‘nil’, they are included. + + By default, all subdirectories are descended into. If PREDICATE is + ‘t’, errors when trying to descend into a subdirectory (for + instance, if it’s not readable by this user) are ignored. If it’s + neither ‘nil’ nor ‘t’, it should be a function that takes one + parameter (the subdirectory name) and should return non-‘nil’ if + the directory is to be descended into. + + Symbolic links to subdirectories are not followed by default, but + if FOLLOW-SYMLINKS is non-‘nil’, they are followed. + + *Note (elisp)Contents of Directories::. + + -- Function: bool-vector &rest objects + This function creates and returns a bool-vector whose elements are + the arguments, OBJECTS. + + *Note (elisp)Bool-Vectors::. + +2.2.2 Prefixed Definitions +-------------------------- + +These functions are prefixed with ‘compat’ prefix, and are only loaded +when ‘compat-25’ is required: + + -- Function: compat-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.2.3 Missing Definitions +------------------------- + +Compat does not provide support for the following Lisp features +implemented in 25.1: + + • 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-interactivly’. + • 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’. + + +File: compat.info, Node: Emacs 26.1, Next: Emacs 27.1, Prev: Emacs 25.1, Up: Support + +2.3 Emacs 26.1 +============== + +2.3.1 Unprefixed Definitions +---------------------------- + +The following functions and macros implemented in 26.1, and are provided +by Compat by default: + + -- Function: func-arity function + This function provides information about the argument list of the + specified FUNCTION. The returned value is a cons cell of the form + ‘(MIN . MAX)’, where MIN is the minimum number of arguments, and + MAX is either the maximum number of arguments, or the symbol ‘many’ + for functions with ‘&rest’ arguments, or the symbol ‘unevalled’ if + FUNCTION is a special form. + + Note that this function might return inaccurate results in some + situations, such as the following: + + − Functions defined using ‘apply-partially’ (*note + apply-partially: (elisp)Calling Functions.). + + − Functions that are advised using ‘advice-add’ (*note + (elisp)Advising Named Functions::). + + − Functions that determine the argument list dynamically, as + part of their code. + + *Note (elisp)What Is a Function::. + + -- 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: 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::. + + -- Macro: 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::. + + -- Macro: 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 (file-name-quote "bar/~/foo")) ⇒ + "/:bar/~/foo" + + (substitute-in-file-name (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: read-multiple-choice prompt choices &optional help-string + show-help long-form + 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. + + If optional argument LONG-FORM is non-‘nil’, the user will have to + type in long-form answers (using ‘completing-read’) instead of + hitting a single key. The answers must be among the second + elements of the values in the CHOICES list. + + Note: The Compat implementation of this function ignores the + optional arguments HELP-STRING and SHOW-HELP. Therefore the + optional third element in each CHOICES entry will also be + disregarded. + + 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. To use + this you need to explicitly require ‘compat-26’. + + -- 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.3.2 Prefixed Definitions +-------------------------- + +These functions are prefixed with ‘compat’ prefix, and are only loaded +when ‘compat-26’ is required: + + -- Function: compat-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-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-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-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-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-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.3.3 Missing Definitions +------------------------- + +Compat does not provide support for the following Lisp features +implemented in 26.1: + + • The function ‘secure-hash-algorithms’. + • The function ‘gnutls-avalaible-p’. + • Support for records and record functions. + • The function ‘mapbacktrace’. + • The function ‘file-name-case-insensitive-p’. + • The file-attributes constructors. + • 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’. + • Support for side windows and atomic windows. + • All changes related to ‘display-buffer’. + • The function ‘window-swap-states’. + + +File: compat.info, Node: Emacs 27.1, Next: Emacs 28.1, Prev: Emacs 26.1, Up: Support + +2.4 Emacs 27.1 +============== + +2.4.1 Unprefixed Definitions +---------------------------- + +The following functions and macros implemented in 27.1, and are provided +by Compat by default: + + -- 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::. + + -- Function: json-serialize object &rest args + This function returns a new Lisp string which contains the JSON + representation of OBJECT. The argument ARGS is a list of + keyword/argument pairs. The following keywords are accepted: + + ‘:null-object’ + The value decides which Lisp object to use to represent the + JSON keyword ‘null’. It defaults to the symbol ‘:null’. + + ‘:false-object’ + The value decides which Lisp object to use to represent the + JSON keyword ‘false’. It defaults to the symbol ‘:false’. + + *Note (elisp)Parsing JSON::. + + -- Function: json-insert object &rest args + This function inserts the JSON representation of OBJECT into the + current buffer before point. The argument ARGS are interpreted as + in ‘json-parse-string’. + + *Note (elisp)Parsing JSON::. + + -- Function: json-parse-string string &rest args + This function parses the JSON value in STRING, which must be a Lisp + string. If STRING doesn’t contain a valid JSON object, this + function signals the ‘json-parse-error’ error. + + The argument ARGS is a list of keyword/argument pairs. The + following keywords are accepted: + + ‘:object-type’ + The value decides which Lisp object to use for representing + the key-value mappings of a JSON object. It can be either + ‘hash-table’, the default, to make hashtables with strings as + keys; ‘alist’ to use alists with symbols as keys; or ‘plist’ + to use plists with keyword symbols as keys. + + ‘:array-type’ + The value decides which Lisp object to use for representing a + JSON array. It can be either ‘array’, the default, to use + Lisp arrays; or ‘list’ to use lists. + + ‘:null-object’ + The value decides which Lisp object to use to represent the + JSON keyword ‘null’. It defaults to the symbol ‘:null’. + + ‘:false-object’ + The value decides which Lisp object to use to represent the + JSON keyword ‘false’. It defaults to the symbol ‘:false’. + + *Note (elisp)Parsing JSON::. + + -- Function: json-parse-buffer &rest args + This function reads the next JSON value from the current buffer, + starting at point. It moves point to the position immediately + after the value if contains a valid JSON object; otherwise it + signals the ‘json-parse-error’ error and doesn’t move point. The + arguments ARGS are interpreted as in ‘json-parse-string’. + + *Note (elisp)Parsing JSON::. + + -- 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. + + -- Function: decoded-time-minute time + Return the MINUTE field of a ‘decoded-time’ record TIME. + + -- Function: decoded-time-hour time + Return the HOUR field of a ‘decoded-time’ record TIME. + + -- Function: decoded-time-day time + Return the DAY field of a ‘decoded-time’ record TIME. + + -- Function: decoded-time-month time + Return the MONTH field of a ‘decoded-time’ record TIME. + + -- Function: decoded-time-year time + Return the YEAR field of a ‘decoded-time’ record TIME. + + -- Function: decoded-time-weekday time + Return the WEEKDAY field of a ‘decoded-time’ record TIME. + + -- Function: decoded-time-dst time + Return the DST (daylight saving time indicator) field of a + ‘decoded-time’ record TIME. + + -- Function: decoded-time-zone time + Return the ZONE field of a ‘decoded-time’ record TIME. + + -- 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. + + -- 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: derived-mode-p &rest modes + This function returns non-‘nil’ if the current major mode is + derived from any of the major modes given by the symbols MODES. + + *Note (elisp)Derived Modes::. + +2.4.2 Prefixed Definitions +-------------------------- + +These functions are prefixed with ‘compat’ prefix, and are only loaded +when ‘compat-27’ is required: + + -- Function: compat-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-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: 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-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-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-assoc-delete-all + 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-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. + + -- Function: compat-dired-get-marked-files &optional localp arg filter + distinguish-one-marked error + Return a list of file names that are _marked_ in a Dired buffer. + + This compatibility version handles the optional fifth (ERROR) + argument, which signals an error if the list of found files is + empty. ‘error’ can be a string with the error message. + +2.4.3 Missing Definitions +------------------------- + +Compat does not provide support for the following Lisp features +implemented in 27.1: + + • Bigint support. + • The function ‘time-convert’. + • All ‘iso8601-*’ functions. + • The macro ‘benchmark-progn’. + • The function ‘read-char-from-minibuffer’. + • The minor mode ‘reveal-mode’. + • The macro ‘with-suppressed-warnings’. + • Support for ‘condition-case’ to handle t. + • The functions ‘major-mode-suspend’ and ‘major-mode-restore’. + • The function ‘provided-mode-derived-p’. + • The function ‘file-system-info’. + • The more consistent treatment of NaN values. + • The function ‘ring-resize’. + • The function ‘group-name’. + • Additional ‘format-spec’ modifiers. + • Support for additional body forms for + ‘define-globalized-minor-mode’. + • The macro ‘with-connection-local-variables’ and related + functionality. + + +File: compat.info, Node: Emacs 28.1, Prev: Emacs 27.1, Up: Support + +2.5 Emacs 28.1 +============== + +2.5.1 Unprefixed Definitions +---------------------------- + +The following functions and macros implemented in 28.1, and are provided +by Compat by default: + + -- 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: 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 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: 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: macroexp-file-name + Return the name of the file in which the code is currently being + evaluated, or ‘nil’ if it cannot be determined. + + -- 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: button-buttonize string callback &optional data help-echo + Return a button with STRING as its label. When interacted on, the + one-argument function in CALLBACK is called and DATA (or ‘nil’ is + not present) will be passed as the argument. + + If non-‘nil’, the argument HELP-ECHO will be used to set the + ‘help-echo’ text property. + + -- Function: make-directory-autoloads dir output-file + Parse and search the directory DIR for autoload definitions, and + write the processed results to the file OUTPUT-FILE. + + -- 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: null-device + Return the path to the null device (usually something like + ‘/dev/null’) on the current system. + + -- 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 avaliable, this function behaves + identically to ‘subrp’. + + -- Function: file-name-absolute-p filename + This function returns ‘t’ if file FILENAME is an absolute file + name, ‘nil’ otherwise. A file name is considered to be absolute if + its first component is ‘~’, or is ‘~USER’ where USER is a valid + login name. In the following examples, assume that there is a user + named ‘rms’ but no user named ‘nosuchuser’. + + (file-name-absolute-p "~rms/foo") + ⇒ t + (file-name-absolute-p "~nosuchuser/foo") + ⇒ nil + (file-name-absolute-p "rms/foo") + ⇒ nil + (file-name-absolute-p "/user/rms/foo") + ⇒ t + + *Note (elisp)Absolute and Relative File Names::. + +2.5.2 Prefixed Definitions +-------------------------- + +These functions are prefixed with ‘compat’ prefix, and are only loaded +when ‘compat-28’ is required: + + -- Function: compat-unlock-buffer + This function unlocks the file being visited in the current buffer, + if the buffer is modified. If the buffer is not modified, then the + file should not be locked, so this function does nothing. It also + does nothing if the current buffer is not visiting a file, or is + not locked. This function handles file system errors by calling + ‘display-warning’ and otherwise ignores the error. + + *Note (elisp)File Locks::. + + This compatibility versions catches the ‘file-error’ condition, + issuing a warning instead of propagating on the error. + + -- Function: compat-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-json-serialize + *Note Emacs 27.1::. + + This compatibility version handles primitive, top-level JSON values + (numbers, strings, booleans). + + -- Function: compat-json-insert + *Note Emacs 27.1::. + + This compatibility version handles primitive, top-level JSON values + (numbers, strings, booleans). + + -- Function: compat-json-parse-string + *Note Emacs 27.1::. + + This compatibility version handles primitive, top-level JSON values + (numbers, strings, booleans). + + -- Function: compat-json-parse-buffer + *Note Emacs 27.1::. + + This compatibility version handles primitive, top-level JSON values + (numbers, strings, booleans). + + -- Function: compat-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.5.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’. + • "Success handler" for ‘condition-case’. + • The function ‘benchmark-call’. + • Support for the ‘natnum’ defcustom type. + • The function ‘macroexp-compiling-p’. + • The function ‘macroexp-warn-and-return’. + • Additional Edebug keywords. + • Shorthand support. + • The function ‘custom-add-choice’. + • The function ‘decoded-time-period’. + • The function ‘dom-print’. + • The function ‘dom-remove-attribute’. + • The function ‘dns-query-asynchronous’. + • The function ‘get-locale-names’. + • The function ‘json-avaliable-p’. + • The function ‘mail-header-parse-addresses-lax’. + • The function ‘mail-header-parse-address-lax’. + • The function ‘make-separator-line’. + • The function ‘num-processors’. + • The function ‘object-intervals’. + • The function ‘process-lines-ignore-status’. + • The function ‘require-theme’. + • The function ‘syntax-class-to-char’. + • The function ‘path-separator’. + + +File: compat.info, Node: Development, Next: Function Index, Prev: Support, Up: Top + +3 Development +************* + +Compat is developed on SourceHut (https://sr.ht/~pkal/compat). A +restricted GitHub mirror (https://github.com/phikal/compat.el) is also +maintained. + + Patches and comments can be sent to the development mailing list +(https://lists.sr.ht/~pkal/compat-devel) (~pkal/compat-devel@lists.sr.ht +<~pkal/compat-devel@lists.sr.ht>). Bug reports are best sent to the +issue tracker (https://todo.sr.ht/~pkal/compat) (~pkal/compat@todo.sr.ht +<~pkal/compat@todo.sr.ht>). The GitHub mirror can also be used to +submit patches. These may include issues in the compatibility code, +missing definitions or performance issues. + + 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. + + +File: compat.info, Node: Function Index, Next: Variable Index, Prev: Development, Up: Top + +Appendix A Function Index +************************* + +[index] +* Menu: + +* alist-get: Emacs 25.1. (line 50) +* always: Emacs 28.1. (line 61) +* and-let*: Emacs 26.1. (line 99) +* bool-vector: Emacs 25.1. (line 166) +* bool-vector-count-consecutive: Emacs 24.4. (line 118) +* bool-vector-count-population: Emacs 24.4. (line 125) +* bool-vector-exclusive-or: Emacs 24.4. (line 76) +* bool-vector-intersection: Emacs 24.4. (line 90) +* bool-vector-not: Emacs 24.4. (line 104) +* bool-vector-set-difference: Emacs 24.4. (line 97) +* bool-vector-subsetp: Emacs 24.4. (line 111) +* bool-vector-union: Emacs 24.4. (line 83) +* buffer-local-boundp: Emacs 28.1. (line 99) +* button-buttonize: Emacs 28.1. (line 285) +* color-values-from-color-spec: Emacs 28.1. (line 297) +* compat-<: Emacs 24.4. (line 175) +* compat-<=: Emacs 24.4. (line 185) +* compat-=: Emacs 24.4. (line 170) +* compat->: Emacs 24.4. (line 180) +* compat->=: Emacs 24.4. (line 190) +* compat-alist-get: Emacs 26.1. (line 284) +* compat-assoc: Emacs 26.1. (line 256) +* compat-assoc-delete-all: Emacs 27.1. (line 305) +* compat-count-windows: Emacs 28.1. (line 422) +* compat-dired-get-marked-files: Emacs 27.1. (line 333) +* compat-executable-find: Emacs 27.1. (line 317) +* compat-file-size-human-readable: Emacs 27.1. (line 285) +* compat-json-insert: Emacs 28.1. (line 404) +* compat-json-parse-buffer: Emacs 28.1. (line 416) +* compat-json-parse-string: Emacs 28.1. (line 410) +* compat-json-serialize: Emacs 28.1. (line 398) +* compat-line-number-at-pos: Emacs 26.1. (line 270) +* compat-lookup-key: Emacs 27.1. (line 245) +* compat-recenter: Emacs 27.1. (line 235) +* compat-regexp-opt: Emacs 27.1. (line 273) +* compat-sort: Emacs 25.1. (line 178) +* compat-split-string: Emacs 24.4. (line 199) +* compat-string-trim: Emacs 26.1. (line 314) +* compat-string-trim-left: Emacs 26.1. (line 298) +* compat-string-trim-right: Emacs 26.1. (line 306) +* compat-string-width: Emacs 28.1. (line 381) +* compat-unlock-buffer: Emacs 28.1. (line 368) +* completion-table-with-cache: Emacs 24.4. (line 130) +* cXXXr: Emacs 26.1. (line 47) +* cXXXXr: Emacs 26.1. (line 48) +* date-days-in-month: Emacs 27.1. (line 193) +* decoded-time-day: Emacs 27.1. (line 166) +* decoded-time-dst: Emacs 27.1. (line 178) +* decoded-time-hour: Emacs 27.1. (line 163) +* decoded-time-minute: Emacs 27.1. (line 160) +* decoded-time-month: Emacs 27.1. (line 169) +* decoded-time-period: Emacs 28.1. (line 332) +* decoded-time-second: Emacs 27.1. (line 157) +* decoded-time-weekday: Emacs 27.1. (line 175) +* decoded-time-year: Emacs 27.1. (line 172) +* decoded-time-zone: Emacs 27.1. (line 182) +* define-error: Emacs 24.4. (line 65) +* delete-consecutive-dups: Emacs 24.4. (line 60) +* derived-mode-p: Emacs 27.1. (line 223) +* directory-empty-p: Emacs 28.1. (line 218) +* directory-files-recursively: Emacs 25.1. (line 139) +* directory-name-p: Emacs 25.1. (line 24) +* dlet: Emacs 28.1. (line 117) +* dolist-with-progress-reporter: Emacs 27.1. (line 116) +* ensure-list: Emacs 28.1. (line 132) +* face-spec-set: Emacs 24.4. (line 139) +* file-attribute-access-time: Emacs 26.1. (line 201) +* file-attribute-collect: Emacs 26.1. (line 238) +* file-attribute-device-number: Emacs 26.1. (line 233) +* file-attribute-group-id: Emacs 26.1. (line 196) +* file-attribute-inode-number: Emacs 26.1. (line 228) +* file-attribute-link-number: Emacs 26.1. (line 186) +* file-attribute-modes: Emacs 26.1. (line 223) +* file-attribute-modification-time: Emacs 26.1. (line 206) +* file-attribute-size: Emacs 26.1. (line 218) +* file-attribute-status-change-time: Emacs 26.1. (line 212) +* file-attribute-type: Emacs 26.1. (line 181) +* file-attribute-user-id: Emacs 26.1. (line 191) +* file-backup-file-names: Emacs 28.1. (line 316) +* file-local-name: Emacs 26.1. (line 108) +* file-modes-number-to-symbolic: Emacs 28.1. (line 310) +* file-name-absolute-p: Emacs 28.1. (line 344) +* file-name-concat: Emacs 28.1. (line 31) +* file-name-quote: Emacs 26.1. (line 133) +* file-name-quoted-p: Emacs 26.1. (line 126) +* file-name-with-extension: Emacs 28.1. (line 200) +* flatten-tree: Emacs 27.1. (line 129) +* format-message: Emacs 25.1. (line 12) +* format-prompt: Emacs 28.1. (line 229) +* func-arity: Emacs 26.1. (line 12) +* garbage-collect-maybe: Emacs 28.1. (line 46) +* gensym: Emacs 26.1. (line 51) +* if-let: Emacs 25.1. (line 67) +* if-let*: Emacs 26.1. (line 90) +* ignore-errors: Emacs 27.1. (line 103) +* image-property: Emacs 26.1. (line 175) +* insert-into-buffer: Emacs 28.1. (line 66) +* json-insert: Emacs 27.1. (line 57) +* json-parse-buffer: Emacs 27.1. (line 94) +* json-parse-string: Emacs 27.1. (line 64) +* json-serialize: Emacs 27.1. (line 42) +* length<: Emacs 28.1. (line 23) +* length=: Emacs 28.1. (line 20) +* length>: Emacs 28.1. (line 28) +* macroexp-file-name: Emacs 28.1. (line 267) +* macroexpand-1: Emacs 25.1. (line 132) +* macrop: Emacs 24.4. (line 47) +* make-directory-autoloads: Emacs 28.1. (line 293) +* make-lock-file-name: Emacs 28.1. (line 324) +* make-nearby-temp-file: Emacs 26.1. (line 61) +* mapcan: Emacs 26.1. (line 34) +* named-let: Emacs 28.1. (line 182) +* null-device: Emacs 28.1. (line 328) +* package-get-version: Emacs 27.1. (line 185) +* proper-list-p: Emacs 27.1. (line 12) +* provided-mode-derived-p: Emacs 27.1. (line 219) +* read-multiple-choice: Emacs 26.1. (line 151) +* replace-regexp-in-string: Emacs 28.1. (line 91) +* replace-string-in-region: Emacs 28.1. (line 76) +* setq-local: Emacs 27.1. (line 258) +* special-form-p: Emacs 24.4. (line 41) +* string-chop-newline: Emacs 28.1. (line 177) +* string-clean-whitespace: Emacs 28.1. (line 145) +* string-distance: Emacs 27.1. (line 22) +* string-fill: Emacs 28.1. (line 152) +* string-greaterp: Emacs 25.1. (line 32) +* string-lines: Emacs 28.1. (line 160) +* string-pad: Emacs 28.1. (line 168) +* string-replace: Emacs 28.1. (line 55) +* string-search: Emacs 28.1. (line 12) +* string-suffix-p: Emacs 24.4. (line 53) +* subr-primitive-p: Emacs 28.1. (line 337) +* temporary-file-directory: Emacs 26.1. (line 78) +* thing-at-mouse: Emacs 28.1. (line 260) +* thread-first: Emacs 25.1. (line 90) +* thread-last: Emacs 25.1. (line 111) +* time-equal-p: Emacs 27.1. (line 188) +* when-let: Emacs 25.1. (line 85) +* when-let*: Emacs 26.1. (line 94) +* with-environment-variables: Emacs 28.1. (line 271) +* with-eval-after-load: Emacs 24.4. (line 12) +* with-existing-directory: Emacs 28.1. (line 106) +* with-file-modes: Emacs 25.1. (line 39) +* xor: Emacs 27.1. (line 139) + + +File: compat.info, Node: Variable Index, Prev: Function Index, Up: Top + +Appendix B Variable Index +************************* + +[index] +* Menu: + +* exec-path: Emacs 27.1. (line 200) +* gensym-counter: Emacs 26.1. (line 58) +* mounted-file-systems: Emacs 26.1. (line 74) +* regexp-unmatchable: Emacs 27.1. (line 149) + + + +Tag Table: +Node: Top821 +Node: Introduction2274 +Node: Overview2433 +Node: Usage3656 +Node: Additional libraries4663 +Node: Intentions5118 +Node: Support6728 +Node: Emacs 24.47310 +Node: Emacs 25.117364 +Node: Emacs 26.126321 +Node: Emacs 27.140419 +Node: Emacs 28.155775 +Node: Development75469 +Node: Function Index76484 +Node: Variable Index87168 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/compat-28.1.2.2/dir b/elpa/compat-28.1.2.2/dir new file mode 100644 index 00000000..de02c6ea --- /dev/null +++ b/elpa/compat-28.1.2.2/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.