dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

compat-25.el (7516B)


      1 ;;; compat-25.el --- Compatibility Layer for Emacs 25.1  -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
      4 
      5 ;; This program is free software; you can redistribute it and/or modify
      6 ;; it under the terms of the GNU General Public License as published by
      7 ;; the Free Software Foundation, either version 3 of the License, or
      8 ;; (at your option) any later version.
      9 
     10 ;; This program is distributed in the hope that it will be useful,
     11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 ;; GNU General Public License for more details.
     14 
     15 ;; You should have received a copy of the GNU General Public License
     16 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     17 
     18 ;;; Commentary:
     19 
     20 ;; Find here the functionality added in Emacs 25.1, needed by older
     21 ;; versions.
     22 
     23 ;;; Code:
     24 
     25 (eval-when-compile (load "compat-macs.el" nil t t))
     26 (compat-declare-version "25.1")
     27 
     28 ;;;; Defined in alloc.c
     29 
     30 (compat-defun bool-vector (&rest objects) ;; <OK>
     31   "Return a new bool-vector with specified arguments as elements.
     32 Allows any number of arguments, including zero.
     33 usage: (bool-vector &rest OBJECTS)"
     34   (let ((vec (make-bool-vector (length objects) nil))
     35         (i 0))
     36     (while objects
     37       (when (car objects)
     38         (aset vec i t))
     39       (setq objects (cdr objects)
     40             i (1+ i)))
     41     vec))
     42 
     43 ;;;; Defined in fns.c
     44 
     45 (compat-defun sort (seq predicate) ;; <OK>
     46   "Extend `sort' to sort SEQ as a vector."
     47   :explicit t
     48   (cond
     49    ((listp seq)
     50     (sort seq predicate))
     51    ((vectorp seq)
     52     (let* ((list (sort (append seq nil) predicate))
     53            (p list) (i 0))
     54       (while p
     55         (aset seq i (car p))
     56         (setq i (1+ i) p (cdr p)))
     57       (apply #'vector list)))
     58    ((signal 'wrong-type-argument 'list-or-vector-p))))
     59 
     60 ;;;; Defined in editfns.c
     61 
     62 (compat-defalias format-message format) ;; <OK>
     63 
     64 ;;;; Defined in fileio.c
     65 
     66 (compat-defun directory-name-p (name) ;; <OK>
     67   "Return non-nil if NAME ends with a directory separator character."
     68   (eq (eval-when-compile
     69         (if (memq system-type '(cygwin windows-nt ms-dos))
     70             ?\\ ?/))
     71       (aref name (1- (length name)))))
     72 
     73 ;;;; Defined in subr.el
     74 
     75 (compat-defun string-greaterp (string1 string2) ;; <OK>
     76   "Return non-nil if STRING1 is greater than STRING2 in lexicographic order.
     77 Case is significant.
     78 Symbols are also allowed; their print names are used instead."
     79   (string-lessp string2 string1))
     80 
     81 (compat-defmacro with-file-modes (modes &rest body) ;; <OK>
     82   "Execute BODY with default file permissions temporarily set to MODES.
     83 MODES is as for `set-default-file-modes'."
     84   (declare (indent 1) (debug t))
     85   (let ((umask (make-symbol "umask")))
     86     `(let ((,umask (default-file-modes)))
     87        (unwind-protect
     88            (progn
     89              (set-default-file-modes ,modes)
     90              ,@body)
     91          (set-default-file-modes ,umask)))))
     92 
     93 (compat-defun alist-get (key alist &optional default remove) ;; <OK>
     94   "Return the value associated with KEY in ALIST, using `assq'.
     95 If KEY is not found in ALIST, return DEFAULT.
     96 This is a generalized variable suitable for use with `setf'.
     97 When using it to set a value, optional argument REMOVE non-nil
     98 means to remove KEY from ALIST if the new value is `eql' to DEFAULT."
     99   (ignore remove)
    100   (let ((x (assq key alist)))
    101     (if x (cdr x) default)))
    102 
    103 (compat-defmacro if-let (spec then &rest else) ;; <OK>
    104   "Bind variables according to SPEC and evaluate THEN or ELSE.
    105 Evaluate each binding in turn, as in `let*', stopping if a
    106 binding value is nil.  If all are non-nil return the value of
    107 THEN, otherwise the last form in ELSE.
    108 
    109 Each element of SPEC is a list (SYMBOL VALUEFORM) that binds
    110 SYMBOL to the value of VALUEFORM.  An element can additionally be
    111 of the form (VALUEFORM), which is evaluated and checked for nil;
    112 i.e. SYMBOL can be omitted if only the test result is of
    113 interest.  It can also be of the form SYMBOL, then the binding of
    114 SYMBOL is checked for nil.
    115 
    116 As a special case, interprets a SPEC of the form \(SYMBOL SOMETHING)
    117 like \((SYMBOL SOMETHING)).  This exists for backward compatibility
    118 with an old syntax that accepted only one binding."
    119   (declare (indent 2)
    120            (debug ([&or (symbolp form)
    121                         (&rest [&or symbolp (symbolp form) (form)])]
    122                    body)))
    123   (when (and (<= (length spec) 2) (not (listp (car spec))))
    124     ;; Adjust the single binding case
    125     (setq spec (list spec)))
    126   (let ((empty (make-symbol "s"))
    127         (last t) list)
    128     (dolist (var spec)
    129       (push `(,(if (cdr var) (car var) empty)
    130               (and ,last ,(if (cdr var) (cadr var) (car var))))
    131             list)
    132       (when (or (cdr var) (consp (car var)))
    133         (setq last (caar list))))
    134     `(let* ,(nreverse list)
    135        (if ,(caar list) ,then ,@else))))
    136 
    137 (compat-defmacro when-let (spec &rest body) ;; <OK>
    138   "Bind variables according to SPEC and conditionally evaluate BODY.
    139 Evaluate each binding in turn, stopping if a binding value is nil.
    140 If all are non-nil, return the value of the last form in BODY.
    141 
    142 The variable list SPEC is the same as in `if-let'."
    143   (declare (indent 1) (debug if-let))
    144   (list 'if-let spec (macroexp-progn body)))
    145 
    146 ;;;; Defined in subr-x.el
    147 
    148 (compat-defmacro thread-first (&rest forms) ;; <OK>
    149   "Thread FORMS elements as the first argument of their successor.
    150 Example:
    151     (thread-first
    152       5
    153       (+ 20)
    154       (/ 25)
    155       -
    156       (+ 40))
    157 Is equivalent to:
    158     (+ (- (/ (+ 5 20) 25)) 40)
    159 Note how the single `-' got converted into a list before
    160 threading."
    161   (declare (indent 1)
    162            (debug (form &rest [&or symbolp (sexp &rest form)])))
    163   (let ((body (car forms)))
    164     (dolist (form (cdr forms))
    165       (when (symbolp form)
    166         (setq form (list form)))
    167       (setq body (append (list (car form))
    168                          (list body)
    169                          (cdr form))))
    170     body))
    171 
    172 (compat-defmacro thread-last (&rest forms) ;; <OK>
    173   "Thread FORMS elements as the last argument of their successor.
    174 Example:
    175     (thread-last
    176       5
    177       (+ 20)
    178       (/ 25)
    179       -
    180       (+ 40))
    181 Is equivalent to:
    182     (+ 40 (- (/ 25 (+ 20 5))))
    183 Note how the single `-' got converted into a list before
    184 threading."
    185   (declare (indent 1) (debug thread-first))
    186   (let ((body (car forms)))
    187     (dolist (form (cdr forms))
    188       (when (symbolp form)
    189         (setq form (list form)))
    190       (setq body (append form (list body))))
    191     body))
    192 
    193 ;;;; Defined in macroexp.el
    194 
    195 (compat-defun macroexpand-1 (form &optional environment) ;; <OK>
    196   "Perform (at most) one step of macro expansion."
    197   (cond
    198    ((consp form)
    199     (let* ((head (car form))
    200            (env-expander (assq head environment)))
    201       (if env-expander
    202           (if (cdr env-expander)
    203               (apply (cdr env-expander) (cdr form))
    204             form)
    205         (if (not (and (symbolp head) (fboundp head)))
    206             form
    207           (let ((def (autoload-do-load (symbol-function head) head 'macro)))
    208             (cond
    209              ;; Follow alias, but only for macros, otherwise we may end up
    210              ;; skipping an important compiler-macro (e.g. cl--block-wrapper).
    211              ((and (symbolp def) (macrop def)) (cons def (cdr form)))
    212              ((not (consp def)) form)
    213              (t
    214               (if (eq 'macro (car def))
    215                   (apply (cdr def) (cdr form))
    216                 form))))))))
    217    (t form)))
    218 
    219 ;;;; Defined in byte-run.el
    220 
    221 (compat-defalias function-put put) ;; <OK>
    222 
    223 (provide 'compat-25)
    224 ;;; compat-25.el ends here