branch: elpa/llama
commit b890bfb76aea8df253c5baf3a95df008b67dd1dc
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>
Revive and give up on display magic
No longer suggest using `l' instead but also give up
on using `display' property to display it as ##(...).
---
README.md | 106 +++++++++++++++++-------------------------
llama.el | 155 +++++++++++++++++---------------------------------------------
2 files changed, 83 insertions(+), 178 deletions(-)
diff --git a/README.md b/README.md
index 7cc580ef7b..30189c2e12 100644
--- a/README.md
+++ b/README.md
@@ -1,65 +1,41 @@
-Compact syntax for short lambdas.
-
-Unfortunately compact syntax for short `lambda`s won't be added to
-Emacs anytime soon. IMO the arguments as to why we would like to have
-that has been layed out convincingly but the proposal has been
-rejected anyway.
-
-Several packages exist that implement anonymous function literals,
-but until now they all either are waiting for a patch to the C part
-be merged into Emacs, or they depart too far from the ideal syntax.
-
-This package is another attempt.
-
-> **Update:** I have come up with a second syntax, which does not put
-> anything *before* the opening parenthesis and looks like `(l'foo %)`.
-> Unlike with my original `llama` idea I am no longer suggesting making
-> it look like some character(s) appear before the paren using font-lock
-> or similar trickery (see below). If you so desire, then you could
-> however use `prettify-symbols-mode` to display it as e.g. `(ƒ'foo
-> %)`. This approach is implemented in [`l`](https://git.sr.ht/~tarsius/l).
-
-In a stroke of luck I discovered a loophole that allows us to have
-almost the syntax that we want without having to convince anyone.
-
- $(foo %) is what I would have used if it were up to me.
- #(foo %) works just as well for me.
- ##(foo %) is similar enough to that.
- (##foo %) is the loophole that I discovered.
-
-Even though there is no space between the second `#` and `foo`, this
-last form is read as a list with three arguments `(## foo %)` and it
-is also indented the way we want!
-
- (##foo %
- bar)
-
-This is good enough for me, but with a bit of font-lock trickery,
-we can even get it to be display like this:
-
- ##(foo %
- bar)
-
-This is completely optional and you have to opt-in by enabling
-`llama-mode` (or the global variant `global-llama-mode`).
-
-An unfortunate edge-case exists that you have to be aware off; if
-no argument is placed on the same line as the function, then Emacs
-does not indent as we would want it too:
-
- (##foo ##(foo
- bar) which llama-mode displays as bar)
-
-I recommend that in this case you simply write this instead:
-
- (## foo ##( foo
- bar) which llama-mode displays as bar)
-
-It is my hope that this package helps to eventually get similar
-syntax into Emacs itself, by demonstrating that this is useful and
-that people want to use it.
-
-*Also see the [announcement](https://emacsair.me/2021/01/28/llama-0.1).*
-
-*Also see [`l`](https://git.sr.ht/~tarsius/l), my second attempt at
-faking such syntax.*
+This package implements the macro `##`, which provides compact
+syntax for short `lambda`, without actually being new syntax,
+which would be difficult to get merged into Emacs. Past attempts
+to add syntax were met with determined pushback and the use of a
+macro was suggested as an alternative.
+
+The `##` macro, whose signature is `(## FN &rest args)`, expands
+to a `lambda` expressions, which wraps around its arguments.
+
+This `lambda` expression calls the function FN with arguments
+ARGS and returns its value. Its own arguments are derived from
+symbols found in ARGS. Each symbol from `%1` through `%9`, which
+appears in ARGS, is treated as a positional argument. Missing
+arguments are named `_%N`, which keeps the byte-compiler quiet.
+In place of `%1` the shorthand `%` can be used, but only one of
+these two can appear in ARGS. `%*` represents extra `&rest`
+arguments.
+
+Instead of:
+
+```elisp
+(lambda (a _ c &rest d)
+ (foo a (bar c) d))
+```
+
+you can use this macro and write:
+
+```elisp
+(##foo % (bar %3) %*)
+```
+
+which expands to:
+
+```elisp
+(lambda (% _%2 %3 &rest %*)
+ (foo % (bar %3) %*))
+```
+
+The name `##` was choosen because that allows (optionally)
+omitting the whitespace between it and the following symbol.
+It also looks similar to `#'function`.
diff --git a/llama.el b/llama.el
index 4baae2201e..250684b263 100644
--- a/llama.el
+++ b/llama.el
@@ -1,4 +1,4 @@
-;;; llama.el --- Anonymous function literals -*- lexical-binding:t -*-
+;;; llama.el --- Compact syntax for short lambda -*- lexical-binding:t -*-
;; Copyright (C) 2020-2022 Jonas Bernoulli
@@ -25,61 +25,41 @@
;;; Commentary:
-;; This package implements compact syntax for short `lambda's, without
-;; relying on a C patch to Emacs or adding an additional pair of
-;; parentheses.
-
-;; [!] I have come up with another approach that does not put anything
-;; [!] before the opening parenthesis: https://git.sr.ht/~tarsius/l.
-
-;; Unfortunately anonymous function literals won't be added to Emacs
-;; anytime soon. The arguments as to why we would like to have that
-;; has been layed out convincingly but the proposal has been rejected
-;; anyway.
-
-;; Several packages exist that implement anonymous function literals,
-;; but until now they all either are waiting for a patch to the C part
-;; be merged into Emacs, or they depart too far from the ideal syntax.
-
-;; In a stroke of luck I discovered a loophole that allows us to have
-;; almost the syntax that we want without having to convince anyone.
+;; This package implements the macro `##', which provides compact
+;; syntax for short `lambda', without actually being new syntax,
+;; which would be difficult to get merged into Emacs. Past attempts
+;; to add syntax were met with determined pushback and the use of a
+;; macro was suggested as an alternative.
+
+;; The `##' macro, whose signature is (## FN &rest args), expands
+;; to a `lambda' expressions, which wraps around its arguments.
+
+;; This `lambda' expression calls the function FN with arguments
+;; ARGS and returns its value. Its own arguments are derived from
+;; symbols found in ARGS. Each symbol from `%1' through `%9', which
+;; appears in ARGS, is treated as a positional argument. Missing
+;; arguments are named `_%N', which keeps the byte-compiler quiet.
+;; In place of `%1' the shorthand `%' can be used, but only one of
+;; these two can appear in ARGS. `%*' represents extra `&rest'
+;; arguments.
+
+;; Instead of:
;;
-;; $(foo %) is what I would have used if it were up to me.
-;; #(foo %) works just as well for me.
-;; ##(foo %) is similar enough to that.
-;; (##foo %) is the loophole that I discovered.
-
-;; Even though there is no space between the second # and `foo', this
-;; last form is read as a list with three arguments (## foo %) and it
-;; is also indented the way we want!
+;; (lambda (a _ c &rest d)
+;; (foo a (bar c) d))
;;
-;; (##foo %
-;; bar)
-
-;; This is good enough for me, but with a bit of font-lock trickery,
-;; we can even get it to be display like this:
+;; you can use this macro and write:
;;
-;; ##(foo %
-;; bar)
+;; (##foo % (bar %3) %*)
;;
-;; This is completely optional and you have to opt-in by enabling
-;; `llama-mode' (or the global variant `global-llama-mode').
-
-;; An unfortunate edge-case exists that you have to be aware off; if
-;; no argument is placed on the same line as the function, then Emacs
-;; does not indent as we would want it too:
+;; which expands to:
;;
-;; (##foo ##(foo
-;; bar) which llama-mode displays as bar)
+;; (lambda (% _%2 %3 &rest %*)
+;; (foo % (bar %3) %*))
-;; I recommend that in this case you simply write this instead:
-;;
-;; (## foo ##( foo
-;; bar) which llama-mode displays as bar)
-
-;; It is my hope that this package helps to eventually get similar
-;; syntax into Emacs itself, by demonstrating that this is useful and
-;; that people want to use it.
+;; The name `##' was choosen because that allows (optionally)
+;; omitting the whitespace between it and the following symbol.
+;; It also looks similar to #'function.
;;; Code:
@@ -87,17 +67,16 @@
;;;###autoload
(defmacro ## (fn &rest args)
- "Return an anonymous function.
-
-The returned function calls the function FN with arguments ARGS
-and returns its value.
+ "Expand to a `lambda' expression that wraps around FN and ARGS.
-The arguments of the outer function are determined recursively
-from ARGS. Each symbol from `%1' through `%9' that appears in
-ARGS is treated as a positional argument. Missing arguments
-are named `_%N', which keeps the byte-compiler quiet. `%' is
-a shorthand for `%1'; only one of these can appear in ARGS.
-`%*' represents extra `&rest' arguments.
+This `lambda' expression calls the function FN with arguments
+ARGS and returns its value. Its own arguments are derived from
+symbols found in ARGS. Each symbol from `%1' through `%9', which
+appears in ARGS, is treated as a positional argument. Missing
+arguments are named `_%N', which keeps the byte-compiler quiet.
+In place of `%1' the shorthand `%' can be used, but only one of
+these two can appear in ARGS. `%*' represents extra `&rest'
+arguments.
Instead of:
@@ -113,13 +92,9 @@ which expands to:
(lambda (% _%2 %3 &rest %*)
(foo % (bar %3) %*))
-Note that there really does not have to be any whitespace
-between \"##\" and \"foo\"!
-
-If you enable `llama-mode' or `global-llama-mode', then the
-above is *displayed* as:
-
- ##(foo % (bar %3) %*)"
+The name `##' was choosen because that allows (optionally)
+omitting the whitespace between it and the following symbol.
+It also looks a bit like #\\='function."
(unless (symbolp fn)
(signal 'wrong-type-argument (list 'symbolp fn)))
`(lambda ,(llama--arguments args)
@@ -158,52 +133,6 @@ above is *displayed* as:
(seq-doseq (elt data)
(llama--collect elt args)))))
-(defvar llama--keywords
- '(("(##" (0 (llama--transpose)))))
-
-(defun llama--transpose ()
- (and (not (nth 8 (syntax-ppss)))
- `(face nil display "##(")))
-
-(defvar-local llama--display-already-managed nil)
-
-;;;###autoload
-(define-minor-mode llama-mode
- "Toggle Llama mode.
-
-When Llama mode is enabled then forms like (##foo %) are
-displayed as ##(foo %) instead.
-
-You can enable this mode locally in desired buffers, or use
-`global-llama-mode' to enable it in all `emacs-lisp-mode'
-buffers."
- :init-value nil
- (cond
- (llama-mode
- (font-lock-add-keywords nil llama--keywords)
- (add-to-list 'font-lock-extra-managed-props 'display)
- (when (memq 'display font-lock-extra-managed-props)
- (setq llama--display-already-managed t)))
- (t
- (font-lock-remove-keywords nil llama--keywords)
- (if llama--display-already-managed
- (setq llama--display-already-managed nil)
- (setq font-lock-extra-managed-props
- (delq 'display font-lock-extra-managed-props)))
- (with-silent-modifications
- (remove-text-properties (point-min) (point-max) '(display nil)))))
- (font-lock-flush))
-
-;;;###autoload
-(define-globalized-minor-mode global-llama-mode
- llama-mode llama--turn-on-mode
- :group 'lisp)
-
-(defun llama--turn-on-mode ()
- (when (and (not llama-mode)
- (derived-mode-p 'emacs-lisp-mode))
- (llama-mode 1)))
-
;;; _
(provide 'llama)
;; Local Variables: