Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reusing infixes as readers in interactive forms, normalizing M-x and transient code paths #261

Open
psionic-k opened this issue Nov 17, 2023 · 6 comments
Labels
enhancement New feature or request

Comments

@psionic-k
Copy link
Contributor

The vision is to make (interactive) forms in transient commands easier to write for both directly calling by M-x and via transient.

  • If I call an interactive command by lisp, I pass arguments.
  • When invoked as a command, the interactive form uses readers to obtain the values.
  • When a transient suffix is called, it must extract the arguments it needs from the current prefix
  • Transient infixes describe readers, but we can't easily re-use these readers to complete the interactive form
  • To support both transient and M-x paths, the user must do everything explicitly using transient style code on one branch and traditional code on the M-x branch

It ends up looking like:

(transient-define-suffix pmx-frame-resolution (resolution)
  (interactive
   (if transient-current-command
       (list
        (transient-arg-value
         "resolution="
         (transient-args transient-current-command)))
     (pmx-non-infix-resolution-reader)))

Instead, I propose enabling a form like this:

(defun dual-use-suffix (arg1 arg2 arg3)
    (interactive (list (infix) (infix) (infix))
    ( ... ))

If the infix commands are made just a little smarter, they can call their reader and return the read value without using transient-infix-value. This has many advantages for reducing code size.

  • Positional arguments using infix command symbols avoid transient-arg-value.
  • There is no unnecessary stringly typed re-read.
  • Moving the prefix versus M-x check to the infix class avoids requiring each suffix to check if transient-current-command is non-nil entirely.

To implement, when the infix is called and the transient is active, it should behave normally. When called without a prefix, the infix should be initialized, call its reader, and return its value.

Calling customized infixes without an active prefix may require smarter init-value and init-scope functions, but the user is opting into this by writing the (interactive (list (infix) (infix) (infix)) style. I will avoid discussing providing more kinds of history for infixes to usually produce smart reader defaults, but this proposal would enhance potential value in that discussion.

This usage pattern would also yield values without stringly typing values, eliminating the need to re-read them in the suffix. When providing alists for choices, we can use assoc instead of assoc-string and the even more brittle "my-value=" in calls to transient-args.

transient-args itself relies on stringly typed information to locate the arg, and IMO should be mostly relied upon for CLI interfaces.

However, CLI interfaces for new programs are not a good solution. When writing a new program, a JSON rpc style interface such as used by LSP or even an elisp extension with automatic serialization will lead to a less fragile Emacs <-> program interface. In this case, the stringly typing should be avoided and returning the infix value directly in interactive accomplishes this.

@tarsius
Copy link
Member

tarsius commented Nov 17, 2023

There's some good suggestions here.

But please note that after the recent increase in activity here, I plan to work on Forge for the next few weeks, enjoy the holiday season, and then create releases in early January. Only after that do I intend to return to Transient. I do however plan to make Transient a primary focus at that time, and I do appreciate these suggestions.

@tarsius tarsius added the enhancement New feature or request label Nov 17, 2023
@psionic-k
Copy link
Contributor Author

What's Forge?

@tarsius
Copy link
Member

tarsius commented Nov 19, 2023

../../forge

@tarsius
Copy link
Member

tarsius commented Nov 29, 2023

Transient infixes describe readers, but we can't easily re-use these readers to complete the interactive form

You can use (transient-infix-read 'some-infix-command) for that.

@psionic-k
Copy link
Contributor Author

The anonymous ones seem to recurse infinitely in 0.5.2. I can't try master until I update seq.

Was beginning to look at how to implement this. We have an interactive-p. What's our best way to infer transient-p?

@tarsius
Copy link
Member

tarsius commented Jan 13, 2024

The anonymous ones seem to recurse infinitely

Yes, COMMAND has to be a symbol that identifies a infix command. I have improved the error you get when that is not the case, in 3ebb6ac.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants