* Compiled vs. interpreted ERT test
@ 2020-02-27 22:19 Joost Kremers
2020-02-28 1:48 ` Noam Postavsky
2020-02-28 2:18 ` Stefan Monnier
0 siblings, 2 replies; 5+ messages in thread
From: Joost Kremers @ 2020-02-27 22:19 UTC (permalink / raw)
To: help-gnu-emacs
Hi list,
I learned about the package `with-simulated-input`[1] which
provides a macro of the same name that's intended for writing
automated tests for code that takes user input. When trying to
apply this in some ERT test, I found that it works fine if the
tests are interpreted (e.g., loaded with `eval-defun`), but not
when the test is byte-compiled. Byte-compiled tests fail with the
following error:
```
(wrong-type-argument listp
#[nil "\300\207"
[t]
1])
```
I opened an issue on the package's Github page but the maintainer
says he doesn't know how to debug this.[2] So I'm coming here in
the hopes someone has an idea or a suggestion how to debug this.
TIA
Joost
Footnotes:
[1] https://github.com/DarwinAwardWinner/with-simulated-input
[2]
https://github.com/DarwinAwardWinner/with-simulated-input/issues/6
--
Joost Kremers
Life has its moments
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Compiled vs. interpreted ERT test
2020-02-27 22:19 Compiled vs. interpreted ERT test Joost Kremers
@ 2020-02-28 1:48 ` Noam Postavsky
2020-02-28 2:18 ` Stefan Monnier
1 sibling, 0 replies; 5+ messages in thread
From: Noam Postavsky @ 2020-02-28 1:48 UTC (permalink / raw)
To: Joost Kremers; +Cc: Help Gnu Emacs mailing list
On Thu, 27 Feb 2020 at 17:19, Joost Kremers <joostkremers@fastmail.fm> wrote:
> I opened an issue on the package's Github page but the maintainer
> says he doesn't know how to debug this.[2] So I'm coming here in
> the hopes someone has an idea or a suggestion how to debug this.
I'm not really sure, but it could help to reduce the example a bit.
Neither ert nor ebib are necessary to trigger this:
(defun foo ()
(with-simulated-input "RET"
"xxx"))
(byte-compile 'foo)
(foo)
I guess the problem lies in some of the tricks with-simulated-input is
playing with closures and environments and such.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Compiled vs. interpreted ERT test
2020-02-27 22:19 Compiled vs. interpreted ERT test Joost Kremers
2020-02-28 1:48 ` Noam Postavsky
@ 2020-02-28 2:18 ` Stefan Monnier
2020-02-28 3:16 ` Stefan Monnier
1 sibling, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2020-02-28 2:18 UTC (permalink / raw)
To: help-gnu-emacs
> I opened an issue on the package's Github page but the maintainer says he
> doesn't know how to debug this.[2] So I'm coming here in the hopes someone
> has an idea or a suggestion how to debug this.
I haven't looked at the rest of the code, but the first thing I saw is:
(defmacro wsi-current-lexical-environment ()
"Return the current lexical environment.
If `lexical-binding' is not enabled, return nil.
This macro expands to a Lisp form that evaluates to the current
lexical environment. It works by creating a closure and then
extracting and returning its lexical environment.
This can be used to manually construct closures in that
environment."
`(let ((temp-closure (lambda () t)))
(when (eq (car temp-closure) 'closure)
(cadr temp-closure))))
which clearly assumes the code is interpreted since once compiled,
`temp-closure` is not going to be a list any more (and you won't be
able to extract the lexical env from it).
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Compiled vs. interpreted ERT test
2020-02-28 2:18 ` Stefan Monnier
@ 2020-02-28 3:16 ` Stefan Monnier
2020-02-28 8:07 ` Joost Kremers
0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2020-02-28 3:16 UTC (permalink / raw)
To: help-gnu-emacs
>> I opened an issue on the package's Github page but the maintainer says he
>> doesn't know how to debug this.[2] So I'm coming here in the hopes someone
>> has an idea or a suggestion how to debug this.
> I haven't looked at the rest of the code, but the first thing I saw is:
Maybe the 100% untested patch below is a good starting point.
Stefan
diff --git a/README.md b/README.md
index f3f95e7..e85ef05 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ enter "world" after entering "hello" via key sequence:
```elisp
(with-simulated-input
- '("hello SPC" (insert "world") "RET")
+ ("hello SPC" (insert "world") "RET")
(read-string "Say hello: "))
```
@@ -47,7 +47,7 @@ will return `"hello world"`.
(run-with-idle-timer 500 nil 'insert "world")
(with-simulated-input
;; Type "hello ", then "wait" 501 seconds, then type "RET"
- '("hello SPC" (wsi-simulate-idle-time 501) "RET")
+ ("hello SPC" (wsi-simulate-idle-time 501) "RET")
(read-string "Enter a string: "))
```
diff --git a/with-simulated-input.el b/with-simulated-input.el
index 0f344f1..c44f2a3 100644
--- a/with-simulated-input.el
+++ b/with-simulated-input.el
@@ -12,17 +12,6 @@
;; This file is NOT part of GNU Emacs.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-
-;; This package provides a single macro, `with-simulated-input', which
-;; evaluates one or more forms while simulating a sequence of input
-;; events for those forms to read. The result is the same as if you
-;; had evaluated the forms and then manually typed in the same input.
-;; This macro is useful for non-interactive testing of normally
-;; interactive commands and functions, such as `completing-read'.
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This program is free software: you can redistribute it and/or modify
@@ -40,88 +29,18 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;;; Code:
-
-(require 'cl-lib)
-
-(cl-defun wsi-key-bound-p (key)
- "Return non-nil if KEY is bound in any keymap.
-
-This function checks every keymap in `obarray' for a binding for
-KEY, and returns t if it finds and and nil otherwise. Note that
-this checks ALL keymaps, not just currently active ones."
- (catch 'bound
- (mapatoms
- (lambda (sym)
- (let ((keymap
- (when (boundp sym)
- (symbol-value sym))))
- (when (keymapp keymap)
- (let ((binding (lookup-key keymap (kbd key))))
- (when binding
- (throw 'bound t)))))))
- (throw 'bound nil)))
-
-(cl-defun wsi-get-unbound-key
- (&optional (modifiers '("C-M-A-s-H-" "C-M-A-s-" "C-M-A-H-"))
- (keys "abcdefghijklmnopqrstuvwxyz0123456789"))
- "Return a key binding that is not bound in any known keymap.
-
-This function will check every letter from a to z and every
-number from 0 through 9 with several combinations of multiple
-modifiers (i.e. control, meta, alt, super, hyper). For each such
-key combination, it will check for bindings in all known keymaps,
-and return the first combination for which no such bindings
-exist. Thus, it should be safe to bind this key in a new keymap
-without interfering with any existing keymap.
-
-Optional arguments MODIFIERS and KEYS can be used the change the
-search space. MODIFIERS is a list of strings representing
-modifier combinations, e.g.:
-
- '(\"C-\" \"M-\" \"C-M-\")
-
-for control, meta, or both. KEYS is a string containing all keys
-to check.
-"
- (declare (advertised-calling-convention (&optional modifiers keys) nil))
- (when (stringp modifiers)
- (setq modifiers (list modifiers)))
- (when (listp keys)
- (setq keys (apply #'concat keys)))
- (cl-loop
- named findkey
- for modifier in modifiers
- do (cl-loop
- for char across keys
- for bind = (concat modifier (string char))
- when (not (wsi-key-bound-p bind))
- do (cl-return-from findkey bind))
- finally do (error "Could not find an unbound key with the specified modifiers")))
-
-(defmacro wsi-current-lexical-environment ()
- "Return the current lexical environment.
-
-If `lexical-binding' is not enabled, return nil.
-
-This macro expands to a Lisp form that evaluates to the current
-lexical environment. It works by creating a closure and then
-extracting and returning its lexical environment.
+;;; Commentary:
-This can be used to manually construct closures in that
-environment."
- `(let ((temp-closure (lambda () t)))
- (when (eq (car temp-closure) 'closure)
- (cadr temp-closure))))
+;; This package provides a single macro, `with-simulated-input', which
+;; evaluates one or more forms while simulating a sequence of input
+;; events for those forms to read. The result is the same as if you
+;; had evaluated the forms and then manually typed in the same input.
+;; This macro is useful for non-interactive testing of normally
+;; interactive commands and functions, such as `completing-read'.
-(defun wsi-make-closure (expr env)
- "Construct a closure from EXPR and ENV.
+;;; Code:
-Returns a zero-argument function that, when called, evaluates
-EXPR in lexical environment ENV and returns the result."
- (if env
- `(closure ,env () ,expr)
- `(lambda () ,expr)))
+(require 'cl-lib)
(defconst wsi--canary-sym (cl-gensym "wsi-canary-")
"A unique symbol.")
@@ -139,7 +58,7 @@ keys after initiating evaluation of BODY.
KEYS should be a string representing a sequence of key presses,
in the format understood by `kbd'. In the most common case of
typing in some text and pressing RET, KEYS would be something
-like `\"hello RET\"'. Note that spaced must be indicated
+like `\"hello RET\"'. Note that spaces must be indicated
explicitly using `SPC', e.g. `\"hello SPC world RET\"'.
KEYS can also be a list. In this case, each element should either
@@ -161,86 +80,74 @@ are propagated normally.
The return value is the last form in BODY, as if it was wrapped
in `progn'."
- (declare (indent 1))
- `(cl-letf*
- ((lexenv (wsi-current-lexical-environment))
- (correct-current-buffer (current-buffer))
- (next-action-key (wsi-get-unbound-key))
- (result wsi--canary-sym)
- (thrown-error nil)
- (body-form
- '(throw 'wsi-body-finished (progn ,@body)))
- (end-of-actions-form
- (list 'throw
- '(quote wsi-body-finished)
- (list 'quote wsi--canary-sym)))
- ;; Ensure KEYS is a list, and put the body form as the first
- ;; item and `C-g' as the last item
- (keylist ,keys)
- (keylist (if (listp keylist)
- keylist
- (list keylist)))
- ;; Build the full action list, which includes everything in
- ;; KEYS, as well as some additional setup beforehand and
- ;; cleanup afterward.
- (action-list
- (nconc
- (list
- ;; First we switch back to the correct buffer (since
- ;; `execute-kbd-macro' switches to the wrong one).
- (list 'switch-to-buffer correct-current-buffer)
- ;; Then we run the body form
- body-form)
- ;; Then we run each of the actions specified in KEYS
+ (declare (indent 1)) ;; Add `debug' spec?
+ ;; Old usage convention where KEYS was evaluated at run time.
+ (when (eq 'quote (car-safe keys)) (setq keys (cadr keys)))
+ ;; Ensure KEYS is a list.
+ (unless (listp keys) (setq keys (list keys)))
+ `(with--simulated-input
+ ;; Wrap each action in a lexical closure so it can refer to
+ ;; variables from the caller.
+ (list ,@(mapcar (lambda (x) (if (stringp x) x `(lambda () ,x))) keys))
+ (lambda () ,@body)))
+
+(defun with--simulated-input (keys body-fun)
+ (let* ((current-buffer (current-buffer))
+ (next-action-key 'wsi--next-action-key)
+ (result wsi--canary-sym)
+ (thrown-error nil)
+ (real-body-fun
+ (lambda ()
+ (with-current-buffer current-buffer
+ (throw 'wsi-body-finished (funcall body-fun)))))
+ (end-of-actions-fun
+ (lambda () (throw 'wsi-body-finished wsi--canary-sym)))
+ ;; Build the full action list, which includes everything in
+ ;; KEYS, as well as some additional setup beforehand and
+ ;; cleanup afterward.
+ (action-list
+ `(,real-body-fun
+ ;; Then we run each of the actions specified in KEYS
+ ,@(cl-loop
+ for action in keys
+ if (not (stringp action))
+ collect action)
+ ;; Finally we throw the canary if we read past the end of
+ ;; the input.
+ ,end-of-actions-fun))
+ ;; Replace non-strings with `next-action-key' and concat
+ ;; everything together
+ (full-key-sequence
(cl-loop
- for action in keylist
- if (not (stringp action))
- collect action)
- ;; Finally we throw the canary if we read past the end of
- ;; the input.
- (list end-of-actions-form)))
- ;; Wrap each action in a lexical closure so it can refer to
- ;; variables from the caller.
- (action-closures
- (cl-loop
- for action in action-list
- collect (wsi-make-closure action lexenv)))
- ;; Replace non-strings with `next-action-key' and concat
- ;; everything together
- (full-key-sequence
- (cl-loop
- for action in keylist
- if (stringp action)
- collect action into key-sequence-list
- else
- collect next-action-key into key-sequence-list
- finally return
- ;; Prepend and append `next-action-key' as appropriate to
- ;; switch buffer, run body, and throw canary.
- (concat
- ;; Switch to correct buffer
- next-action-key " "
- ;; Start executing body
- next-action-key " "
- ;; Execute the actual key sequence
- (mapconcat #'identity key-sequence-list " ")
- ;; Throw the canary if BODY reads past the provided input
- " " next-action-key)))
- ;; Define the next action command with lexical scope so it can
- ;; access `action-closures'.
- ((symbol-function 'wsi-run-next-action)
- (lambda ()
- (interactive)
- (condition-case err
- (if action-closures
- (let ((next-action (pop action-closures)))
- (funcall next-action))
- (error "`with-simulated-input' reached end of action list without returning"))
- (error (throw 'wsi-threw-error err)))))
- ;; Set up the temporary keymap
- (action-map (make-sparse-keymap)))
+ for action in keys
+
+ collect (if (stringp action) action next-action-key)
+ into key-sequence-list
+ finally return
+ ;; Prepend and append `next-action-key' as appropriate to
+ ;; switch buffer, run body, and throw canary.
+ (concat
+ ;; Start executing body
+ next-action-key " "
+ ;; Execute the actual key sequence
+ (mapconcat #'identity key-sequence-list " ")
+ ;; Throw the canary if BODY reads past the provided input
+ " " next-action-key)))
+ ;; Define the next action command with lexical scope so it can
+ ;; access `action-closures'.
+ (wsi-run-next-action
+ (lambda ()
+ (interactive)
+ (condition-case err
+ (if action-list
+ (let ((next-action (pop action-list)))
+ (funcall next-action))
+ (error "`with-simulated-input' reached end of action list without returning"))
+ (error (throw 'wsi-threw-error err)))))
+ ;; Set up the temporary keymap
+ (action-map (make-sparse-keymap)))
;; Finish setting up the keymap for the temp command
- (define-key action-map (kbd next-action-key) 'wsi-run-next-action)
+ (define-key action-map (kbd next-action-key) wsi-run-next-action)
(setq
thrown-error
(catch 'wsi-threw-error
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: Compiled vs. interpreted ERT test
2020-02-28 3:16 ` Stefan Monnier
@ 2020-02-28 8:07 ` Joost Kremers
0 siblings, 0 replies; 5+ messages in thread
From: Joost Kremers @ 2020-02-28 8:07 UTC (permalink / raw)
To: help-gnu-emacs
Hi Stefan and Noam,
Thank you both for your replies. I've passed them on to the
maintainer of `with-simulated-input`.
Joost
On Fri, Feb 28 2020, Stefan Monnier wrote:
>>> I opened an issue on the package's Github page but the
>>> maintainer says he
>>> doesn't know how to debug this.[2] So I'm coming here in the
>>> hopes someone
>>> has an idea or a suggestion how to debug this.
>> I haven't looked at the rest of the code, but the first thing I
>> saw is:
>
> Maybe the 100% untested patch below is a good starting point.
>
>
> Stefan
>
>
> diff --git a/README.md b/README.md
> index f3f95e7..e85ef05 100644
> --- a/README.md
> +++ b/README.md
> @@ -31,7 +31,7 @@ enter "world" after entering "hello" via key
> sequence:
>
> ```elisp
> (with-simulated-input
> - '("hello SPC" (insert "world") "RET")
> + ("hello SPC" (insert "world") "RET")
> (read-string "Say hello: "))
> ```
>
> @@ -47,7 +47,7 @@ will return `"hello world"`.
> (run-with-idle-timer 500 nil 'insert "world")
> (with-simulated-input
> ;; Type "hello ", then "wait" 501 seconds, then type "RET"
> - '("hello SPC" (wsi-simulate-idle-time 501) "RET")
> + ("hello SPC" (wsi-simulate-idle-time 501) "RET")
> (read-string "Enter a string: "))
> ```
>
> diff --git a/with-simulated-input.el b/with-simulated-input.el
> index 0f344f1..c44f2a3 100644
> --- a/with-simulated-input.el
> +++ b/with-simulated-input.el
> @@ -12,17 +12,6 @@
>
> ;; This file is NOT part of GNU Emacs.
>
> -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> -;;
> -;;; Commentary:
> -
> -;; This package provides a single macro,
> `with-simulated-input', which
> -;; evaluates one or more forms while simulating a sequence of
> input
> -;; events for those forms to read. The result is the same as if
> you
> -;; had evaluated the forms and then manually typed in the same
> input.
> -;; This macro is useful for non-interactive testing of normally
> -;; interactive commands and functions, such as
> `completing-read'.
> -
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;;
> ;; This program is free software: you can redistribute it
> and/or modify
> @@ -40,88 +29,18 @@
> ;;
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> ;;
> -;;; Code:
> -
> -(require 'cl-lib)
> -
> -(cl-defun wsi-key-bound-p (key)
> - "Return non-nil if KEY is bound in any keymap.
> -
> -This function checks every keymap in `obarray' for a binding
> for
> -KEY, and returns t if it finds and and nil otherwise. Note that
> -this checks ALL keymaps, not just currently active ones."
> - (catch 'bound
> - (mapatoms
> - (lambda (sym)
> - (let ((keymap
> - (when (boundp sym)
> - (symbol-value sym))))
> - (when (keymapp keymap)
> - (let ((binding (lookup-key keymap (kbd key))))
> - (when binding
> - (throw 'bound t)))))))
> - (throw 'bound nil)))
> -
> -(cl-defun wsi-get-unbound-key
> - (&optional (modifiers '("C-M-A-s-H-" "C-M-A-s-"
> "C-M-A-H-"))
> - (keys "abcdefghijklmnopqrstuvwxyz0123456789"))
> - "Return a key binding that is not bound in any known keymap.
> -
> -This function will check every letter from a to z and every
> -number from 0 through 9 with several combinations of multiple
> -modifiers (i.e. control, meta, alt, super, hyper). For each
> such
> -key combination, it will check for bindings in all known
> keymaps,
> -and return the first combination for which no such bindings
> -exist. Thus, it should be safe to bind this key in a new keymap
> -without interfering with any existing keymap.
> -
> -Optional arguments MODIFIERS and KEYS can be used the change
> the
> -search space. MODIFIERS is a list of strings representing
> -modifier combinations, e.g.:
> -
> - '(\"C-\" \"M-\" \"C-M-\")
> -
> -for control, meta, or both. KEYS is a string containing all
> keys
> -to check.
> -"
> - (declare (advertised-calling-convention (&optional modifiers
> keys) nil))
> - (when (stringp modifiers)
> - (setq modifiers (list modifiers)))
> - (when (listp keys)
> - (setq keys (apply #'concat keys)))
> - (cl-loop
> - named findkey
> - for modifier in modifiers
> - do (cl-loop
> - for char across keys
> - for bind = (concat modifier (string char))
> - when (not (wsi-key-bound-p bind))
> - do (cl-return-from findkey bind))
> - finally do (error "Could not find an unbound key with the
> specified modifiers")))
> -
> -(defmacro wsi-current-lexical-environment ()
> - "Return the current lexical environment.
> -
> -If `lexical-binding' is not enabled, return nil.
> -
> -This macro expands to a Lisp form that evaluates to the current
> -lexical environment. It works by creating a closure and then
> -extracting and returning its lexical environment.
> +;;; Commentary:
>
> -This can be used to manually construct closures in that
> -environment."
> - `(let ((temp-closure (lambda () t)))
> - (when (eq (car temp-closure) 'closure)
> - (cadr temp-closure))))
> +;; This package provides a single macro,
> `with-simulated-input', which
> +;; evaluates one or more forms while simulating a sequence of
> input
> +;; events for those forms to read. The result is the same as if
> you
> +;; had evaluated the forms and then manually typed in the same
> input.
> +;; This macro is useful for non-interactive testing of normally
> +;; interactive commands and functions, such as
> `completing-read'.
>
> -(defun wsi-make-closure (expr env)
> - "Construct a closure from EXPR and ENV.
> +;;; Code:
>
> -Returns a zero-argument function that, when called, evaluates
> -EXPR in lexical environment ENV and returns the result."
> - (if env
> - `(closure ,env () ,expr)
> - `(lambda () ,expr)))
> +(require 'cl-lib)
>
> (defconst wsi--canary-sym (cl-gensym "wsi-canary-")
> "A unique symbol.")
> @@ -139,7 +58,7 @@ keys after initiating evaluation of BODY.
> KEYS should be a string representing a sequence of key presses,
> in the format understood by `kbd'. In the most common case of
> typing in some text and pressing RET, KEYS would be something
> -like `\"hello RET\"'. Note that spaced must be indicated
> +like `\"hello RET\"'. Note that spaces must be indicated
> explicitly using `SPC', e.g. `\"hello SPC world RET\"'.
>
> KEYS can also be a list. In this case, each element should
> either
> @@ -161,86 +80,74 @@ are propagated normally.
>
> The return value is the last form in BODY, as if it was wrapped
> in `progn'."
> - (declare (indent 1))
> - `(cl-letf*
> - ((lexenv (wsi-current-lexical-environment))
> - (correct-current-buffer (current-buffer))
> - (next-action-key (wsi-get-unbound-key))
> - (result wsi--canary-sym)
> - (thrown-error nil)
> - (body-form
> - '(throw 'wsi-body-finished (progn ,@body)))
> - (end-of-actions-form
> - (list 'throw
> - '(quote wsi-body-finished)
> - (list 'quote wsi--canary-sym)))
> - ;; Ensure KEYS is a list, and put the body form as the
> first
> - ;; item and `C-g' as the last item
> - (keylist ,keys)
> - (keylist (if (listp keylist)
> - keylist
> - (list keylist)))
> - ;; Build the full action list, which includes
> everything in
> - ;; KEYS, as well as some additional setup beforehand
> and
> - ;; cleanup afterward.
> - (action-list
> - (nconc
> - (list
> - ;; First we switch back to the correct buffer (since
> - ;; `execute-kbd-macro' switches to the wrong one).
> - (list 'switch-to-buffer correct-current-buffer)
> - ;; Then we run the body form
> - body-form)
> - ;; Then we run each of the actions specified in KEYS
> + (declare (indent 1)) ;; Add `debug' spec?
> + ;; Old usage convention where KEYS was evaluated at run time.
> + (when (eq 'quote (car-safe keys)) (setq keys (cadr keys)))
> + ;; Ensure KEYS is a list.
> + (unless (listp keys) (setq keys (list keys)))
> + `(with--simulated-input
> + ;; Wrap each action in a lexical closure so it can refer
> to
> + ;; variables from the caller.
> + (list ,@(mapcar (lambda (x) (if (stringp x) x `(lambda
> () ,x))) keys))
> + (lambda () ,@body)))
> +
> +(defun with--simulated-input (keys body-fun)
> + (let* ((current-buffer (current-buffer))
> + (next-action-key 'wsi--next-action-key)
> + (result wsi--canary-sym)
> + (thrown-error nil)
> + (real-body-fun
> + (lambda ()
> + (with-current-buffer current-buffer
> + (throw 'wsi-body-finished (funcall body-fun)))))
> + (end-of-actions-fun
> + (lambda () (throw 'wsi-body-finished
> wsi--canary-sym)))
> + ;; Build the full action list, which includes
> everything in
> + ;; KEYS, as well as some additional setup beforehand
> and
> + ;; cleanup afterward.
> + (action-list
> + `(,real-body-fun
> + ;; Then we run each of the actions specified in
> KEYS
> + ,@(cl-loop
> + for action in keys
> + if (not (stringp action))
> + collect action)
> + ;; Finally we throw the canary if we read past the
> end of
> + ;; the input.
> + ,end-of-actions-fun))
> + ;; Replace non-strings with `next-action-key' and
> concat
> + ;; everything together
> + (full-key-sequence
> (cl-loop
> - for action in keylist
> - if (not (stringp action))
> - collect action)
> - ;; Finally we throw the canary if we read past the
> end of
> - ;; the input.
> - (list end-of-actions-form)))
> - ;; Wrap each action in a lexical closure so it can
> refer to
> - ;; variables from the caller.
> - (action-closures
> - (cl-loop
> - for action in action-list
> - collect (wsi-make-closure action lexenv)))
> - ;; Replace non-strings with `next-action-key' and
> concat
> - ;; everything together
> - (full-key-sequence
> - (cl-loop
> - for action in keylist
> - if (stringp action)
> - collect action into key-sequence-list
> - else
> - collect next-action-key into key-sequence-list
> - finally return
> - ;; Prepend and append `next-action-key' as
> appropriate to
> - ;; switch buffer, run body, and throw canary.
> - (concat
> - ;; Switch to correct buffer
> - next-action-key " "
> - ;; Start executing body
> - next-action-key " "
> - ;; Execute the actual key sequence
> - (mapconcat #'identity key-sequence-list " ")
> - ;; Throw the canary if BODY reads past the provided
> input
> - " " next-action-key)))
> - ;; Define the next action command with lexical scope so
> it can
> - ;; access `action-closures'.
> - ((symbol-function 'wsi-run-next-action)
> - (lambda ()
> - (interactive)
> - (condition-case err
> - (if action-closures
> - (let ((next-action (pop action-closures)))
> - (funcall next-action))
> - (error "`with-simulated-input' reached end of
> action list without returning"))
> - (error (throw 'wsi-threw-error err)))))
> - ;; Set up the temporary keymap
> - (action-map (make-sparse-keymap)))
> + for action in keys
> +
> + collect (if (stringp action) action next-action-key)
> + into key-sequence-list
> + finally return
> + ;; Prepend and append `next-action-key' as
> appropriate to
> + ;; switch buffer, run body, and throw canary.
> + (concat
> + ;; Start executing body
> + next-action-key " "
> + ;; Execute the actual key sequence
> + (mapconcat #'identity key-sequence-list " ")
> + ;; Throw the canary if BODY reads past the provided
> input
> + " " next-action-key)))
> + ;; Define the next action command with lexical scope
> so it can
> + ;; access `action-closures'.
> + (wsi-run-next-action
> + (lambda ()
> + (interactive)
> + (condition-case err
> + (if action-list
> + (let ((next-action (pop action-list)))
> + (funcall next-action))
> + (error "`with-simulated-input' reached end of
> action list without returning"))
> + (error (throw 'wsi-threw-error err)))))
> + ;; Set up the temporary keymap
> + (action-map (make-sparse-keymap)))
> ;; Finish setting up the keymap for the temp command
> - (define-key action-map (kbd next-action-key)
> 'wsi-run-next-action)
> + (define-key action-map (kbd next-action-key)
> wsi-run-next-action)
> (setq
> thrown-error
> (catch 'wsi-threw-error
--
Joost Kremers
Life has its moments
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-02-28 8:07 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-02-27 22:19 Compiled vs. interpreted ERT test Joost Kremers
2020-02-28 1:48 ` Noam Postavsky
2020-02-28 2:18 ` Stefan Monnier
2020-02-28 3:16 ` Stefan Monnier
2020-02-28 8:07 ` Joost Kremers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).