positron-solutions / transient-showcase

Example forms for transient UI's in Emacs
GNU General Public License v3.0
213 stars 22 forks source link

`:setup-children` error: "transient-setup: Assertion failed: (and prefix (symbolp prefix))" #30

Closed mooseyboots closed 1 month ago

mooseyboots commented 2 months ago

in "Dynamically generating layouts", there's an example for dynamically inserting group children using :setup-children.

i'm unable to get it to run. it errors with (cl-assertion-failed ((and prefix (symbolp prefix)) nil)), which suggests to me that when the function is run transient--prefix is nil somehow. using the prefix name (e.g. tsc-generated-child likewise errors with (void-variable tsc-generated-child).

do you have any ideas on how to fix it? i'm hoping work out :setup-children to dynamically generate infix options.

mooseyboots commented 2 months ago

the linked docs report that the :setup-children function takes a single argument, children, not suffix. but that shouldn't matter as we are ignoring it either way.

i also tried using transient-current-prefix to no avail.

i'm trying to construct children from scratch, based on a list of names, so also ignoring the argument of the :setup-children function.

mooseyboots commented 2 months ago

looks like the variable needs to be quoted

as per https://github.com/magit/transient/blob/main/docs/transient.org#group-specifications (scroll down for a code example).

i tried making a PR but i don't know how to regenerate anything, so i figure i best to just point to it:

https://github.com/mooseyboots/transient-showcase/commit/64f48a218f9365ef1d84872338eeb54229f0e19a

psionic-k commented 1 month ago

What is the command name? I didn't see any issues with two dynamic layout examples.

The generation is just done with M-x org-babel-tangle in the org file. The markdown was generated from the org. The org is the truth.

The markdown seems out of date. I'm super busy though.

mooseyboots commented 1 month ago

if you view the commit i linked to you can expand the diff to see where it is. i'm not 100% sure what i did was right, but as it was it was not working for me, and the quoting fixed it. actually, i think i also had to change

(list (transient-parse-suffix
          transient--prefix

to

(list (transient-parse-suffixes
              'transient--prefix

in the first example.

it's the first two code blocs in the section "Dynamically generating layouts".

i can do the babel tangle to .el but not sure how to update the md.

if they both work for you, perhaps there's something else breaking for me? i'm on latest transient and emacs 30.0.50.

psionic-k commented 1 month ago

org-md-export-to-markdown

I'll take a look. I don't think that quoting make sense. It strikes me as something that accidentally works and hides something else.

mooseyboots commented 1 month ago

that would not be surprising. i'm still learning transient, and often still struggling with the commands to wrangle values.

psionic-k commented 1 month ago

In practice, you would name the function instead of using a lambda. The quoting can feel rather ambiguous within vectors. Can you just debug it with a stack trace?

I ran both commands with no issues. I would bet maybe the latest transient changes something about the macro that is making it look like there's a quoting issue.

I won't get to this more deeply for a few days.

mooseyboots commented 1 month ago

here's a stacktrace:

Debugger entered--Lisp error: (cl-assertion-failed ((and prefix (symbolp prefix)) nil))
apply(debug (error (cl-assertion-failed ((and prefix (symbolp prefix)) nil))))
transient--exit-and-debug(error (cl-assertion-failed ((and prefix (symbolp prefix)) nil)))
cl--assertion-failed((and prefix (symbolp prefix)))
(or (and prefix (symbolp prefix)) (cl--assertion-failed '(and prefix (symbolp prefix))))
(progn (or (and prefix (symbolp prefix)) (cl--assertion-failed '(and prefix (symbolp prefix)))) nil)
transient-parse-suffix(#<transient-prefix transient-prefix-15835039bc20> (("r" "replacement" (lambda nil (interactive) (message "okay!")))))
(list (transient-parse-suffix transient--prefix '(("r" "replacement" (lambda nil (interactive) (message "okay!"))))))
(lambda (_) (list (transient-parse-suffix transient--prefix '(("r" "replacement" (lambda nil ... ...))))))(((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683))))
funcall((lambda (_) (list (transient-parse-suffix transient--prefix '(("r" "replacement" (lambda nil ... ...)))))) ((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683))))
(if (slot-boundp group 'setup-children) (funcall (eieio-oref group 'setup-children) children) children)
(progn (if (slot-boundp group 'setup-children) (funcall (eieio-oref group 'setup-children) children) children))
transient-setup-children(#<transient-column transient-column-15835039bd6e> ((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683))))
(cl-mapcan #'(lambda (c) (transient--init-child levels c obj)) (transient-setup-children obj children))
(and s (cl-mapcan #'(lambda (c) (transient--init-child levels c obj)) (transient-setup-children obj children)))
(let* ((s (and t (transient--use-level-p level))) (obj (and s (apply class :level level args))) (s (and obj (transient--use-suffix-p obj))) (s (and s (prog1 t (if (or (and parent ...) (transient--inapt-suffix-p obj)) (progn (eieio-oset obj ... t)))))) (suffixes (and s (cl-mapcan #'(lambda (c) (transient--init-child levels c obj)) (transient-setup-children obj children))))) (if suffixes (progn (progn (eieio-oset obj 'suffixes suffixes) (list obj)))))
(let ((level x14659) (class x14661) (args x14663) (children x14665)) (let* ((s (and t (transient--use-level-p level))) (obj (and s (apply class :level level args))) (s (and obj (transient--use-suffix-p obj))) (s (and s (prog1 t (if (or ... ...) (progn ...))))) (suffixes (and s (cl-mapcan #'(lambda ... ...) (transient-setup-children obj children))))) (if suffixes (progn (progn (eieio-oset obj 'suffixes suffixes) (list obj))))))
(progn (ignore (null x14666)) (let ((level x14659) (class x14661) (args x14663) (children x14665)) (let* ((s (and t (transient--use-level-p level))) (obj (and s (apply class :level level args))) (s (and obj (transient--use-suffix-p obj))) (s (and s (prog1 t (if ... ...)))) (suffixes (and s (cl-mapcan #'... (transient-setup-children obj children))))) (if suffixes (progn (progn (eieio-oset obj 'suffixes suffixes) (list obj)))))))
(let* ((x14665 (car-safe x14664)) (x14666 (cdr-safe x14664))) (progn (ignore (null x14666)) (let ((level x14659) (class x14661) (args x14663) (children x14665)) (let* ((s (and t (transient--use-level-p level))) (obj (and s (apply class :level level args))) (s (and obj (transient--use-suffix-p obj))) (s (and s (prog1 t ...))) (suffixes (and s (cl-mapcan ... ...)))) (if suffixes (progn (progn (eieio-oset obj ... suffixes) (list obj))))))))
(progn (ignore (consp x14664)) (let* ((x14665 (car-safe x14664)) (x14666 (cdr-safe x14664))) (progn (ignore (null x14666)) (let ((level x14659) (class x14661) (args x14663) (children x14665)) (let* ((s (and t ...)) (obj (and s ...)) (s (and obj ...)) (s (and s ...)) (suffixes (and s ...))) (if suffixes (progn (progn ... ...))))))))
(let* ((x14663 (car-safe x14662)) (x14664 (cdr-safe x14662))) (progn (ignore (consp x14664)) (let* ((x14665 (car-safe x14664)) (x14666 (cdr-safe x14664))) (progn (ignore (null x14666)) (let ((level x14659) (class x14661) (args x14663) (children x14665)) (let* ((s ...) (obj ...) (s ...) (s ...) (suffixes ...)) (if suffixes (progn ...))))))))
(progn (ignore (consp x14662)) (let* ((x14663 (car-safe x14662)) (x14664 (cdr-safe x14662))) (progn (ignore (consp x14664)) (let* ((x14665 (car-safe x14664)) (x14666 (cdr-safe x14664))) (progn (ignore (null x14666)) (let ((level x14659) (class x14661) (args x14663) (children x14665)) (let* (... ... ... ... ...) (if suffixes ...))))))))
(let* ((x14661 (car-safe x14660)) (x14662 (cdr-safe x14660))) (progn (ignore (consp x14662)) (let* ((x14663 (car-safe x14662)) (x14664 (cdr-safe x14662))) (progn (ignore (consp x14664)) (let* ((x14665 (car-safe x14664)) (x14666 (cdr-safe x14664))) (progn (ignore (null x14666)) (let (... ... ... ...) (let* ... ...))))))))
(progn (ignore (consp x14660)) (let* ((x14661 (car-safe x14660)) (x14662 (cdr-safe x14660))) (progn (ignore (consp x14662)) (let* ((x14663 (car-safe x14662)) (x14664 (cdr-safe x14662))) (progn (ignore (consp x14664)) (let* ((x14665 ...) (x14666 ...)) (progn (ignore ...) (let ... ...))))))))
(let* ((x14659 (car-safe val)) (x14660 (cdr-safe val))) (progn (ignore (consp x14660)) (let* ((x14661 (car-safe x14660)) (x14662 (cdr-safe x14660))) (progn (ignore (consp x14662)) (let* ((x14663 (car-safe x14662)) (x14664 (cdr-safe x14662))) (progn (ignore (consp x14664)) (let* (... ...) (progn ... ...))))))))
(progn (ignore (consp val)) (let* ((x14659 (car-safe val)) (x14660 (cdr-safe val))) (progn (ignore (consp x14660)) (let* ((x14661 (car-safe x14660)) (x14662 (cdr-safe x14660))) (progn (ignore (consp x14662)) (let* ((x14663 ...) (x14664 ...)) (progn (ignore ...) (let* ... ...))))))))
(let* ((val (append spec nil))) (progn (ignore (consp val)) (let* ((x14659 (car-safe val)) (x14660 (cdr-safe val))) (progn (ignore (consp x14660)) (let* ((x14661 (car-safe x14660)) (x14662 (cdr-safe x14660))) (progn (ignore (consp x14662)) (let* (... ...) (progn ... ...))))))))
transient--init-group(nil [1 transient-column (:description "Replace this child" :setup-children (lambda (_) (list (transient-parse-suffix transient--prefix '(...))))) ((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683)))] nil)
(cond ((vectorp spec) (transient--init-group levels spec parent)) ((listp spec) (transient--init-suffix levels spec parent)) ((stringp spec) (list spec)) ((error "cl-etypecase failed: %s, %s" spec '(vector list string)) nil))
transient--init-child(nil [1 transient-column (:description "Replace this child" :setup-children (lambda (_) (list (transient-parse-suffix transient--prefix '(...))))) ((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683)))] nil)
(closure ((levels)) (c) (transient--init-child levels c nil))([1 transient-column (:description "Replace this child" :setup-children (lambda (_) (list (transient-parse-suffix transient--prefix '(...))))) ((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683)))])
cl-mapcan((closure ((levels)) (c) (transient--init-child levels c nil)) ([1 transient-column (:description "Replace this child" :setup-children (lambda (_) (list (transient-parse-suffix transient--prefix '...)))) ((1 transient-suffix (:key "s" :description "haha stupid suffix" :command transient:tsc-generated-child::14683)))] [1 transient-columns (:hide (closure (Man-notify-method t) nil (and (not (memq ... transient--common-command-prefixes)) (not transient-show-common-commands)))) ([1 transient-column (:description "Value commands") ((1 transient-suffix (:key "C-x s  " :description "Set" :command transient-set)) (1 transient-suffix (:key "C-x C-s" :description "Save" :command transient-save)) (1 transient-suffix (:key "C-x C-k" :description "Reset" :command transient-reset)) (1 transient-suffix (:key "C-x p  " :description "Previous value" :command transient-history-prev)) (1 transient-suffix (:key "C-x n  " :description "Next value" :command transient-history-next)))] [1 transient-column (:description "Sticky commands") ((1 transient-suffix (:key "C-g" :description "Quit prefix or transient" :command transient-quit-one)) (1 transient-suffix (:key "C-q" :description "Quit transient stack" :command transient-quit-all)) (1 transient-suffix (:key "C-z" :description "Suspend transient stack" :command transient-suspend)))] [1 transient-column (:description "Customize") ((1 transient-suffix (:key "C-x t" :command transient-toggle-common :description ...)) (1 transient-suffix (:key "C-x l" :description "Show/hide suffixes" :command transient-set-level)) (1 transient-suffix (:key "C-x a" :command transient-toggle-level-limit)))])]))
(let ((levels (alist-get name transient-levels))) (cl-mapcan #'(lambda (c) (transient--init-child levels c nil)) (append (get name 'transient--layout) (and (not transient--editp) (get 'transient-common-commands 'transient--layout)))))
transient--init-suffixes(tsc-generated-child)
(or layout (transient--init-suffixes name))
(setq transient--layout (or layout (transient--init-suffixes name)))
transient--init-objects(tsc-generated-child nil nil)
(progn (cond ((not name) (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map) (setq name (eieio-oref transient--prefix 'command)) (setq params (list :scope (eieio-oref transient--prefix 'scope)))) (transient--prefix (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map)) ((not (or layout transient-current-command)) (transient--stack-zap)) (edit (setq transient--editp t))) (transient--init-objects name layout params) (transient--init-keymaps) (transient--history-init transient--prefix) (setq transient--original-window (selected-window)) (setq transient--original-buffer (current-buffer)) (setq transient--minibuffer-depth (minibuffer-depth)) (transient--redisplay) (transient--init-transient) (transient--suspend-which-key-mode))
(let ((debugger #'transient--exit-and-debug)) (progn (cond ((not name) (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map) (setq name (eieio-oref transient--prefix 'command)) (setq params (list :scope (eieio-oref transient--prefix 'scope)))) (transient--prefix (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map)) ((not (or layout transient-current-command)) (transient--stack-zap)) (edit (setq transient--editp t))) (transient--init-objects name layout params) (transient--init-keymaps) (transient--history-init transient--prefix) (setq transient--original-window (selected-window)) (setq transient--original-buffer (current-buffer)) (setq transient--minibuffer-depth (minibuffer-depth)) (transient--redisplay) (transient--init-transient) (transient--suspend-which-key-mode)))
(condition-case err (let ((debugger #'transient--exit-and-debug)) (progn (cond ((not name) (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map) (setq name (eieio-oref transient--prefix 'command)) (setq params (list :scope (eieio-oref transient--prefix ...)))) (transient--prefix (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map)) ((not (or layout transient-current-command)) (transient--stack-zap)) (edit (setq transient--editp t))) (transient--init-objects name layout params) (transient--init-keymaps) (transient--history-init transient--prefix) (setq transient--original-window (selected-window)) (setq transient--original-buffer (current-buffer)) (setq transient--minibuffer-depth (minibuffer-depth)) (transient--redisplay) (transient--init-transient) (transient--suspend-which-key-mode))) ((debug error) (transient--emergency-exit :setup) (signal (car err) (cdr err))))
transient-setup(tsc-generated-child)
tsc-generated-child()
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
eros-eval-last-sexp(nil)
funcall-interactively(eros-eval-last-sexp nil)
command-execute(eros-eval-last-sexp)
psionic-k commented 1 month ago

Reproduced in latest version of transient. Fixed in 2d7b1d9. Thanks :+1: