diff options
Diffstat (limited to '.config/emacs/lisp/libs/llama.el')
| -rw-r--r-- | .config/emacs/lisp/libs/llama.el | 572 |
1 files changed, 0 insertions, 572 deletions
diff --git a/.config/emacs/lisp/libs/llama.el b/.config/emacs/lisp/libs/llama.el deleted file mode 100644 index 4bddfe6..0000000 --- a/.config/emacs/lisp/libs/llama.el +++ /dev/null @@ -1,572 +0,0 @@ -;;; llama.el --- Compact syntax for short lambda -*- lexical-binding:t -*- - -;; Copyright (C) 2020-2026 Jonas Bernoulli - -;; Author: Jonas Bernoulli <emacs.llama@jonas.bernoulli.dev> -;; Homepage: https://github.com/tarsius/llama -;; Keywords: extensions - -;; Package-Version: 1.0.5 -;; Package-Requires: ( -;; (emacs "26.1") -;; (compat "31.0")) - -;; 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 package implements a macro named `##', which provides a compact way -;; to write short `lambda' expressions. - -;; The signature of the macro is (## FN &rest BODY) and it expands to a -;; `lambda' expression, which calls the function FN with the arguments BODY -;; and returns the value of that. The arguments of the `lambda' expression -;; are derived from symbols found in BODY. - -;; Each symbol from `%1' through `%9', which appears in an unquoted part -;; of BODY, specifies a mandatory argument. Each symbol from `&1' through -;; `&9', which appears in an unquoted part of BODY, specifies an optional -;; argument. The symbol `&*' specifies extra (`&rest') arguments. - -;; The shorter symbol `%' can be used instead of `%1', but using both in -;; the same expression is not allowed. Likewise `&' can be used instead -;; of `&1'. These shorthands are not recognized in function position. - -;; To support binding forms that use a vector as VARLIST (such as `-let' -;; from the `dash' package), argument symbols are also detected inside of -;; vectors. - -;; The space between `##' and FN can be omitted because `##' is read-syntax -;; for the symbol whose name is the empty string. If you prefer you can -;; place a space there anyway, and if you prefer to not use this somewhat -;; magical symbol at all, you can instead use the alternative name `llama'. - -;; Instead of: -;; -;; (lambda (a &optional _ c &rest d) -;; (foo a (bar c) d)) -;; -;; you can use this macro and write: -;; -;; (##foo %1 (bar &3) &*) -;; -;; which expands to: -;; -;; (lambda (%1 &optional _&2 &3 &rest &*) -;; (foo %1 (bar &3) &*)) - -;; Unused trailing arguments and mandatory unused arguments at the border -;; between mandatory and optional arguments are also supported: -;; -;; (##list %1 _%3 &5 _&6) -;; -;; becomes: -;; -;; (lambda (%1 _%2 _%3 &optional _&4 &5 _&6) -;; (list %1 &5)) -;; -;; Note how `_%3' and `_&6' are removed from the body, because their names -;; begin with an underscore. Also note that `_&4' is optional, unlike the -;; explicitly specified `_%3'. - -;; Consider enabling `llama-fontify-mode' to highlight `##' and its -;; special arguments. - -;;; Code: - -(require 'compat) - -;;;###autoload -(defmacro llama (fn &rest body) - "Expand to a `lambda' expression that wraps around FN and BODY. - -This macro provides a compact way to write short `lambda' expressions. -It expands to a `lambda' expression, which calls the function FN with -arguments BODY and returns its value. The arguments of the `lambda' -expression are derived from symbols found in BODY. - -Each symbol from `%1' through `%9', which appears in an unquoted part -of BODY, specifies a mandatory argument. Each symbol from `&1' through -`&9', which appears in an unquoted part of BODY, specifies an optional -argument. The symbol `&*' specifies extra (`&rest') arguments. - -The shorter symbol `%' can be used instead of `%1', but using both in -the same expression is not allowed. Likewise `&' can be used instead -of `&1'. These shorthands are not recognized in function position. - -To support binding forms that use a vector as VARLIST (such as `-let' -from the `dash' package), argument symbols are also detected inside of -vectors. - -The space between `##' and FN can be omitted because `##' is read-syntax -for the symbol whose name is the empty string. If you prefer you can -place a space there anyway, and if you prefer to not use this somewhat -magical symbol at all, you can instead use the alternative name `llama'. - -Instead of: - - (lambda (a &optional _ c &rest d) - (foo a (bar c) d)) - -you can use this macro and write: - - (##foo %1 (bar &3) &*) - -which expands to: - - (lambda (%1 &optional _&2 &3 &rest &*) - (foo %1 (bar &3) &*)) - -Unused trailing arguments and mandatory unused arguments at the border -between mandatory and optional arguments are also supported: - - (##list %1 _%3 &5 _&6) - -becomes: - - (lambda (%1 _%2 _%3 &optional _&4 &5 _&6) - (list %1 &5)) - -Note how `_%3' and `_&6' are removed from the body, because their names -begin with an underscore. Also note that `_&4' is optional, unlike the -explicitly specified `_%3'. - -Consider enabling `llama-fontify-mode' to highlight `##' and its -special arguments." - (cond ((symbolp fn)) - ((and (eq (car-safe fn) backquote-backquote-symbol) - (not body)) - (setq body (cdr fn)) - (setq fn backquote-backquote-symbol)) - ((signal 'wrong-type-argument - (list 'symbolp backquote-backquote-symbol fn)))) - (let* ((args (make-vector 10 nil)) - (body (cdr (llama--collect (cons fn body) args))) - (rest (aref args 0)) - (args (nreverse (cdr (append args nil)))) - (args (progn (while (and args (null (car args))) - (setq args (cdr args))) - args)) - (pos (length args)) - (opt nil) - (args (mapcar - (lambda (arg) - (if arg - (setq opt (string-match-p "\\`_?&" (symbol-name arg))) - (setq arg (intern (format "_%c%s" (if opt ?& ?%) pos)))) - (setq pos (1- pos)) - arg) - args)) - (opt nil) - (args (mapcar - (lambda (symbol) - (cond - ((string-match-p "\\`_?%" (symbol-name symbol)) - (when opt - (error "`%s' cannot follow optional arguments" symbol)) - (list symbol)) - (opt - (list symbol)) - ((setq opt t) - (list '&optional symbol)))) - (nreverse args)))) - `(lambda - (,@(apply #'nconc args) - ,@(and rest (list '&rest rest))) - (,fn ,@body)))) - -(defalias (intern "") 'llama) -(defalias '\#\# 'llama) - -(defconst llama--unused-argument (make-symbol "llama--unused-argument")) - -(defun llama--collect (expr args &optional fnpos backquoted unquote) - (cond - ((memq (car-safe expr) (list (intern "") 'llama 'quote)) expr) - ((and backquoted (symbolp expr)) expr) - ((and backquoted - (memq (car-safe expr) - (list backquote-unquote-symbol - backquote-splice-symbol))) - (list (car expr) - (llama--collect (cadr expr) args nil nil t))) - ((memq (car-safe expr) - (list backquote-backquote-symbol - backquote-splice-symbol)) - (list (car expr) - (llama--collect (cadr expr) args nil t))) - ((symbolp expr) - (let ((name (symbol-name expr))) - (save-match-data - (cond - ((string-match "\\`\\(_\\)?[%&]\\([1-9*]\\)?\\'" name) - (let* ((pos (match-string 2 name)) - (pos (cond ((equal pos "*") 0) - ((not pos) 1) - ((string-to-number pos)))) - (sym (aref args pos))) - (unless (and fnpos (not unquote) (memq expr '(% &))) - (when (and sym (not (equal expr sym))) - (error "`%s' and `%s' are mutually exclusive" sym expr)) - (aset args pos expr))) - (if (match-string 1 name) - llama--unused-argument - expr)) - (expr))))) - ((or (listp expr) - (vectorp expr)) - (let* ((vectorp (vectorp expr)) - (expr (if vectorp (append expr ()) expr)) - (fnpos (and (not vectorp) - (not backquoted) - (ignore-errors (length expr)))) ;proper-list-p - (ret ())) - (catch t - (while t - (let ((elt (llama--collect (car expr) args fnpos backquoted))) - (unless (eq elt llama--unused-argument) - (push elt ret))) - (setq fnpos nil) - (setq expr (cdr expr)) - (unless (and expr - (listp expr) - (not (eq (car expr) backquote-unquote-symbol))) - (throw t nil)))) - (setq ret (nreverse ret)) - (when expr - (setcdr (last ret) (llama--collect expr args nil backquoted))) - (if vectorp (vconcat ret) ret))) - (expr))) - -;;; Completion - -(define-advice elisp--expect-function-p (:around (fn pos) llama) - "Support function completion directly following `##'." - (or (and (eq (char-before pos) ?#) - (eq (char-before (- pos 1)) ?#)) - (and (eq (char-before pos) ?\s) - (eq (char-before (- pos 1)) ?#) - (eq (char-before (- pos 2)) ?#)) - (funcall fn pos))) - -(define-advice all-completions (:around (fn str table &rest rest) llama) - "Remove empty symbol from completion results if originating from `llama'. - -`##' is the notation for the symbol whose name is the empty string. - (intern \"\") => ## - (symbol-name \\='##) => \"\" - -The `llama' package uses `##' as the name of a macro, which allows -it to be used akin to syntax, without actually being new syntax. -\(`describe-function' won't let you select `##', but because that is an -alias for `llama', you can access the documentation under that name.) - -This advice prevents the empty string from being offered as a completion -candidate when `obarray' or a completion table that internally uses -that is used as TABLE." - (let ((result (apply fn str table rest))) - (if (and (eq obarray table) (equal str "")) - (delete "" result) - result))) - -;;; Fontification - -(defgroup llama () - "Compact syntax for short lambda." - :group 'extensions - :group 'faces - :group 'lisp) - -(defface llama-\#\#-macro '((t :inherit font-lock-function-call-face)) - "Face used for the name of the `##' macro.") - -(defface llama-llama-macro '((t :inherit font-lock-keyword-face)) - "Face used for the name of the `llama' macro.") - -(defface llama-mandatory-argument '((t :inherit font-lock-variable-use-face)) - "Face used for mandatory arguments `%1' through `%9' and `%'.") - -(defface llama-optional-argument '((t :inherit font-lock-type-face)) - "Face used for optional arguments `&1' through `&9', `&' and `&*'.") - -(defface llama-deleted-argument - `((((supports :box t)) - :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1) - :color "red" - :style nil)) - (((supports :underline t)) - :underline "red") - (t - :inherit font-lock-warning-face)) - "Face used for deleted arguments `_%1'...`_%9', `_&1'...`_&9' and `_&*'. -This face is used in addition to one of llama's other argument faces. -Unlike implicit unused arguments (which do not appear in the function -body), these arguments are deleted from the function body during macro -expansion, and the looks of this face should hint at that.") - -(defconst llama-font-lock-keywords-28 - '(("(\\(##\\)" 1 'llama-\#\#-macro) - ("(\\(llama\\)\\_>" 1 'llama-llama-macro) - ("\\_<\\(?:_?%[1-9]?\\)\\_>" - 0 (llama--maybe-face 'llama-mandatory-argument)) - ("\\_<\\(?:_?&[1-9*]?\\)\\_>" - 0 (llama--maybe-face 'llama-optional-argument)) - ("\\_<\\(?:_\\(?:%[1-9]?\\|&[1-9*]?\\)\\)\\_>" - 0 'llama-deleted-argument prepend))) - -(defconst llama-font-lock-keywords-29 - `(("\\_<\\(&[1-9*]?\\)\\_>" 1 'default) - (,(apply-partially #'llama--match-and-fontify "(\\(##\\)") - 1 'llama-\#\#-macro) - (,(apply-partially #'llama--match-and-fontify "(\\(llama\\_>\\)") - 1 'llama-llama-macro))) - -(defvar llama-font-lock-keywords - (if (fboundp 'read-positioning-symbols) - llama-font-lock-keywords-29 - llama-font-lock-keywords-28)) - -(defun llama--maybe-face (face) - (and (not (and (member (match-string 0) '("%" "&")) - (and-let* ((beg (ignore-errors - (scan-lists (match-beginning 0) -1 1)))) - (string-match-p "\\`\\(##\\|llama\\_>\\)?[\s\t\n\r]*\\'" - (buffer-substring-no-properties - (1+ beg) (match-beginning 0)))))) - face)) - -(defun llama--match-and-fontify (re end) - (static-if (fboundp 'bare-symbol) - (and (re-search-forward re end t) - (prog1 t - (save-excursion - (goto-char (match-beginning 0)) - (when-let* - ((_(save-match-data (not (nth 8 (syntax-ppss))))) - (expr (ignore-errors - (read-positioning-symbols (current-buffer))))) - (put-text-property (match-beginning 0) (point) - 'font-lock-multiline t) - (llama--fontify (cdr expr) nil nil t))))) - (progn re end nil))) ; Silence compiler. - -(defun llama--fontify (expr &optional fnpos backquoted top) - (static-if (fboundp 'bare-symbol) - (cond - ((null expr) expr) - ((eq (car-safe expr) 'quote)) - ((eq (ignore-errors (bare-symbol (car-safe expr))) 'quote)) - ((and (memq (ignore-errors (bare-symbol (car-safe expr))) - (list (intern "") 'llama)) - (not top))) - ((and backquoted (symbol-with-pos-p expr))) - ((and backquoted - (memq (car-safe expr) - (list backquote-unquote-symbol - backquote-splice-symbol))) - (llama--fontify expr)) - ((symbol-with-pos-p expr) - (save-match-data - (when-let* - ((name (symbol-name (bare-symbol expr))) - (face (cond - ((and (string-match - "\\_<\\(?:\\(_\\)?%\\([1-9]\\)?\\)\\_>" name) - (or (not fnpos) (match-end 2))) - 'llama-mandatory-argument) - ((and (string-match - "\\_<\\(?:\\(_\\)?&\\([1-9*]\\)?\\)\\_>" name) - (or (not fnpos) (match-end 2))) - 'llama-optional-argument)))) - (when (match-end 1) - (setq face (list 'llama-deleted-argument face))) - (let ((beg (symbol-with-pos-pos expr))) - (put-text-property - beg (save-excursion (goto-char beg) (forward-symbol 1)) - 'face face))))) - ((or (listp expr) - (vectorp expr)) - (let* ((vectorp (vectorp expr)) - (expr (if vectorp (append expr ()) expr)) - (fnpos (and (not vectorp) - (not backquoted) - (ignore-errors (length expr))))) - (catch t - (while t - (cond ((eq (car expr) backquote-backquote-symbol) - (setq expr (cdr expr)) - (llama--fontify (car expr) t t)) - ((llama--fontify (car expr) fnpos backquoted))) - (setq fnpos nil) - (setq expr (cdr expr)) - (unless (and expr - (listp expr) - (not (eq (car expr) backquote-unquote-symbol))) - (throw t nil)))) - (when expr - (llama--fontify expr fnpos)))))) - (and expr fnpos backquoted top nil)) ; Silence compiler. - -(defvar llama-fontify-mode-lighter nil) - -;;;###autoload -(define-minor-mode llama-fontify-mode - "In Emacs Lisp mode, highlight the `##' macro and its special arguments." - :lighter llama-fontify-mode-lighter - :global t - (cond - (llama-fontify-mode - (advice-add 'lisp--el-match-keyword :override - #'lisp--el-match-keyword@llama '((depth . -80))) - (advice-add 'elisp-mode-syntax-propertize :override - #'elisp-mode-syntax-propertize@llama) - (add-hook 'emacs-lisp-mode-hook #'llama--add-font-lock-keywords)) - (t - (advice-remove 'lisp--el-match-keyword - #'lisp--el-match-keyword@llama) - (advice-remove 'elisp-mode-syntax-propertize - #'elisp-mode-syntax-propertize@llama) - (remove-hook 'emacs-lisp-mode-hook #'llama--add-font-lock-keywords))) - (dolist (buffer (buffer-list)) - (with-current-buffer buffer - (when (derived-mode-p 'emacs-lisp-mode) - (if llama-fontify-mode - (font-lock-add-keywords nil llama-font-lock-keywords) - (font-lock-remove-keywords nil llama-font-lock-keywords)) - (font-lock-flush))))) - -(defun llama--add-font-lock-keywords () - (font-lock-add-keywords nil llama-font-lock-keywords)) - -(defun lisp--el-match-keyword@llama (limit) - "Highlight symbols following \"(##\" the same as if they followed \"(\"." - (catch 'found - (while (re-search-forward - (concat "(\\(?:## ?\\)?\\(" - (static-if (get 'lisp-mode-symbol 'rx-definition) ;>= 29.1 - (rx lisp-mode-symbol) - lisp-mode-symbol-regexp) - "\\)\\_>") - limit t) - (let ((sym (intern-soft (match-string 1)))) - (when (and (or (special-form-p sym) - (macrop sym) - (and (bound-and-true-p morlock-mode) - ;; Same as in advice of `morlock' package. - (get sym 'morlock-font-lock-keyword))) - (not (get sym 'no-font-lock-keyword)) - (static-if (fboundp 'lisp--el-funcall-position-p) ;>= 28.1 - (lisp--el-funcall-position-p (match-beginning 0)) - (not (lisp--el-non-funcall-position-p - (match-beginning 0))))) - (throw 'found t)))))) - -(defun elisp-mode-syntax-propertize@llama (start end) - ;; Synced with Emacs up to 6b9510d94f814cacf43793dce76250b5f7e6f64a. - "Highlight `##' as the symbol which it is." - (goto-char start) - (let ((case-fold-search nil)) - (funcall - (syntax-propertize-rules - ;; Empty symbol. - ;; {{ Comment out to prevent the `##' from becoming part of - ;; the following symbol when there is no space in between. - ;; ("##" (0 (unless (nth 8 (syntax-ppss)) - ;; (string-to-syntax "_")))) - ;; }} - ;; {{ As for other symbols, use `font-lock-constant-face' in - ;; docstrings and comments. - ("##" (0 (when (nth 8 (syntax-ppss)) - (string-to-syntax "_")))) - ;; }} - ;; {{ Preserve this part, even though it is absent from - ;; this function in 29.1; backporting it by association. - ;; Prevent the @ from becoming part of a following symbol. - (",@" (0 (unless (nth 8 (syntax-ppss)) - (string-to-syntax "'")))) - ;; }} - ;; Unicode character names. (The longest name is 88 characters - ;; long.) - ("\\?\\\\N{[-A-Za-z0-9 ]\\{,100\\}}" - (0 (unless (nth 8 (syntax-ppss)) - (string-to-syntax "_")))) - ((rx "#" (or (seq (group-n 1 "&" (+ digit)) ?\") ; Bool-vector. - (seq (group-n 1 "s") "(") ; Record. - (seq (group-n 1 (+ "^")) "["))) ; Char-table. - (1 (unless (save-excursion (nth 8 (syntax-ppss (match-beginning 0)))) - (string-to-syntax "'"))))) - start end))) - -;;; Partial applications - -(defun llama--left-apply-partially (fn &rest args) - "Return a function that is a partial application of FN to ARGS. - -ARGS is a list of the first N arguments to pass to FN. The result -is a new function which does the same as FN, except that the first N -arguments are fixed at the values with which this function was called. - -See also `llama--right-apply-partially', which instead fixes the last -N arguments. - -These functions are intended to be used using the names `partial' and -`rpartial'. To be able to use these shorthands in a file, you must set -the file-local value of `read-symbols-shorthands', which was added in -Emacs 28.1. For an example see the end of file \"llama.el\". - -This is an alternative to `apply-partially', whose name is too long." - (declare (pure t) (side-effect-free error-free)) - (lambda (&rest args2) - (apply fn (append args args2)))) - -(defun llama--right-apply-partially (fn &rest args) - "Return a function that is a right partial application of FN to ARGS. - -ARGS is a list of the last N arguments to pass to FN. The result -is a new function which does the same as FN, except that the last N -arguments are fixed at the values with which this function was called. - -See also `llama--left-apply-partially', which instead fixes the first -N arguments. - -These functions are intended to be used using the names `rpartial' and -`partial'. To be able to use these shorthands in a file, you must set -the file-local value of `read-symbols-shorthands', which was added in -Emacs 28.1. For an example see the end of file \"llama.el\"." - (declare (pure t) (side-effect-free error-free)) - (lambda (&rest args2) - (apply fn (append args2 args)))) - -;; An example of how one would use these functions: -;; -;; (list (funcall (partial (lambda (a b) (list a b)) 'fixed) 'after) -;; (funcall (rpartial (lambda (a b) (list a b)) 'fixed) 'before)) - -;; An example of the configuration that is necessary to enable this: -;; -;; Local Variables: -;; indent-tabs-mode: nil -;; read-symbol-shorthands: ( -;; ("partial" . "llama--left-apply-partially") -;; ("rpartial" . "llama--right-apply-partially")) -;; End: -;; -;; Do not set `read-symbol-shorthands' in the ".dir-locals.el" -;; file, because that does not work for uncompiled libraries. - -(provide 'llama) - -;;; llama.el ends here |
