Function: cond-let--prepare-clauses

cond-let--prepare-clauses is a byte-compiled function defined in cond-let.el.

Signature

(cond-let--prepare-clauses TAG SEQUENTIAL CLAUSES)

Documentation

Used by macros cond-let* and cond-let.

Source Code

;; Defined in ~/.emacs.d/elpa/cond-let-20260201.1500/cond-let.el
;;; cond-let.el --- Additional and improved binding conditionals  -*- lexical-binding:t -*-

;; Copyright (C) 2025-2026 Jonas Bernoulli

;; May contain traces of Emacs, which is
;; Copyright (C) 1985-2025 Free Software Foundation, Inc.

;; Authors: Jonas Bernoulli <emacs.cond-let@jonas.bernoulli.dev>
;; Homepage: https://github.com/tarsius/cond-let
;; Keywords: extensions

;; Package-Version: 20260201.1500
;; Package-Revision: 8bf87d45e169
;; Package-Requires: ((emacs "28.1"))

;; SPDX-License-Identifier: GPL-3.0-or-later

;; This file 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 file 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 file.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; This is a BETA release!
;; Breaking changes are unlikely but still possible!
;; See https://github.com/tarsius/cond-let/wiki.

;; Emacs provides the binding conditionals `if-let', `if-let*',
;; `when-let', `when-let*', `and-let*' and `while-let'.

;; This package implements the missing `and-let' and `while-let*',
;; and the original `cond-let', `cond-let*', `when$', `and$' and
;; `and>'.

;; This package additionally provides more consistent and improved
;; implementations of the binding conditionals already provided by
;; Emacs.  Merely loading this library does not shadow the built-in
;; implementations; this can optionally be done in the context of
;; an individual library, as described below.

;; `cond-let' and `cond-let*' are provided exactly under these names.
;; The names of all other macros implemented by this package begin
;; with `cond-let--', the package's prefix for private symbol.

;; Users of this package are not expected to use these unwieldy
;; names.  Instead one should use Emacs' shorthand feature to use
;; all or some of these macros by their conceptual names.  E.g., if
;; you want to use all of the available macros, add this at the end
;; of a library.

;; Local Variables:
;; read-symbol-shorthands: (
;;   ("and$"      . "cond-let--and$")
;;   ("and>"      . "cond-let--and>")
;;   ("and-let"   . "cond-let--and-let")
;;   ("if-let"    . "cond-let--if-let")
;;   ("when$"     . "cond-let--when$")
;;   ("when-let"  . "cond-let--when-let")
;;   ("while-let" . "cond-let--while-let"))
;; End:

;; You can think of these file-local settings as import statements of
;; sorts.  If you do this, then this package's implementations shadow
;; the built-in implementations.  Doing so does not affect any other
;; libraries, which continue to use the built-in implementations.

;; Due to limitations of the shorthand implementation this has to be
;; done for each individual library.  "dir-locals.el" cannot be used.

;; If you use `when$', `and$' and `and>', you might want to add this
;; to your configuration:

;;   (with-eval-after-load 'cond-let
;;     (font-lock-add-keywords 'emacs-lisp-mode
;;                             cond-let-font-lock-keywords t))

;; For information about the individual macros, please refer to their
;; docstrings.

;; See also https://github.com/tarsius/cond-let/wiki.

;;; Code:
;;; Cond

(defun cond-let--prepare-clauses (tag sequential clauses)
  "Used by macros `cond-let*' and `cond-let'."
  (let (body)
    (dolist (clause (nreverse clauses))
      (cond
        ((vectorp clause)
         (setq body
               `((,(if (and sequential (length> clause 1)) 'let* 'let)
                  ,(mapcar (lambda (vec) (append vec nil)) clause)
                  ,@body))))
        ((let (varlist)
           (while (vectorp (car clause))
             (push (append (pop clause) nil) varlist))
           (push (cond
                   (varlist
                    `(,(pcase (list (and body t)
                                    (and sequential (length> varlist 1)))
                         ('(t   t ) 'cond-let--when-let*)
                         (`(t   ,_) 'cond-let--when-let)
                         ('(nil t ) 'cond-let--and-let*)
                         (`(nil ,_) 'cond-let--and-let))
                      ,(nreverse varlist)
                      ,(if body
                           `(throw ',tag ,(macroexp-progn clause))
                         (macroexp-progn clause))))
                   ((length= clause 1)
                    (if body
                        (let ((a (gensym "anon")))
                          `(let ((,a ,(car clause)))
                             (when ,a (throw ',tag ,a))))
                      (car clause)))
                   ((and (eq (car clause) t) (not body))
                    (macroexp-progn (cdr clause)))
                   (t
                    `(when ,(pop clause)
                       (throw ',tag ,(macroexp-progn clause)))))
                 body)))))
    body))