* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
@ 2023-03-31 7:27 Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-31 7:38 ` Eli Zaretskii
0 siblings, 1 reply; 7+ messages in thread
From: Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-03-31 7:27 UTC (permalink / raw)
To: 62563
Hello,
I find myself sometimes needing to manually write code that do the same
job as the string-form `interactive' would do, like "read for an
existing file name" (the "f" form), etc. This happens because I want to
do the following conversion.
--8<---------------cut here---------------start------------->8---
(defun foo (fname)
(interactive "f")
(ignore fname))
(defun foo (fname bar)
(interactive
(list (simulate-interactive-f)
(get-bar)))
(ignore fname bar))
--8<---------------cut here---------------end--------------->8---
In short, this is useful when I need to add an interactive argument that
is not already covered by interactive codes, so I have to use the more
verbose interactive list form.
Currently, the code that handles interactive codes is written as part of
`call-interactively'. This is in src/callint.c,
DEFUN("call-interactively").
In fact, there is already _a way_ to do it (I consider it more like a
workaround). However, I think my proposal might be more concise than
the workaround for readers. And also more performant, since the
workaround unnecessarily creates a lambda and then extracts its
interactive form, only to make use of the result of its interactive
code.
--8<---------------cut here---------------start------------->8---
(call-interactively (lambda (f) (interactive "f") f))
--8<---------------cut here---------------end--------------->8---
If people are in favor of exposing the interactive codes, I imagine it
can be defined as `interactive-handle-code (code &optional prompt)', and
I would be able to do this:
--8<---------------cut here---------------start------------->8---
(interactive-handle-code ?f)
(interactive-handle-code ?M "Insert some random text: ")
;; etc
--8<---------------cut here---------------end--------------->8---
Alternatively, if we believe that my c-i + λ workaround is sufficiently
small, we could advise people in the same boat to follow suit? That
implies modifying the `interactive' docstring and (info "(elisp)
Interactive Codes").
--
Best,
RY
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
2023-03-31 7:27 bug#62563: [FR] Expose `interactive' arg handling as an Elisp function Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-03-31 7:38 ` Eli Zaretskii
2023-09-11 23:54 ` Stefan Kangas
0 siblings, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2023-03-31 7:38 UTC (permalink / raw)
To: Ruijie Yu; +Cc: 62563
> Date: Fri, 31 Mar 2023 15:27:47 +0800
> From: Ruijie Yu via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
>
> I find myself sometimes needing to manually write code that do the same
> job as the string-form `interactive' would do, like "read for an
> existing file name" (the "f" form), etc. This happens because I want to
> do the following conversion.
>
> --8<---------------cut here---------------start------------->8---
> (defun foo (fname)
> (interactive "f")
> (ignore fname))
>
> (defun foo (fname bar)
> (interactive
> (list (simulate-interactive-f)
> (get-bar)))
> (ignore fname bar))
> --8<---------------cut here---------------end--------------->8---
>
> In short, this is useful when I need to add an interactive argument that
> is not already covered by interactive codes, so I have to use the more
> verbose interactive list form.
I don't think I understand the rationale, so please tell more. The
interactive spec can be used like this:
(interactive "bBuffer to rename: \nsRename buffer %s to: ")
So basically, you can prompt for anything using the 's' descriptor and
the following prompt string with %-constructs. In what use cases is
this not enough, so much so that it would require exposing the guts of
this to Lisp?
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
2023-03-31 7:38 ` Eli Zaretskii
@ 2023-09-11 23:54 ` Stefan Kangas
2023-09-17 0:50 ` Michael Heerdegen
0 siblings, 1 reply; 7+ messages in thread
From: Stefan Kangas @ 2023-09-11 23:54 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Ruijie Yu, 62563-done
Eli Zaretskii <eliz@gnu.org> writes:
>> Date: Fri, 31 Mar 2023 15:27:47 +0800
>> From: Ruijie Yu via "Bug reports for GNU Emacs,
>> the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
>>
>> I find myself sometimes needing to manually write code that do the same
>> job as the string-form `interactive' would do, like "read for an
>> existing file name" (the "f" form), etc. This happens because I want to
>> do the following conversion.
>>
>> --8<---------------cut here---------------start------------->8---
>> (defun foo (fname)
>> (interactive "f")
>> (ignore fname))
>>
>> (defun foo (fname bar)
>> (interactive
>> (list (simulate-interactive-f)
>> (get-bar)))
>> (ignore fname bar))
>> --8<---------------cut here---------------end--------------->8---
>>
>> In short, this is useful when I need to add an interactive argument that
>> is not already covered by interactive codes, so I have to use the more
>> verbose interactive list form.
>
> I don't think I understand the rationale, so please tell more. The
> interactive spec can be used like this:
>
> (interactive "bBuffer to rename: \nsRename buffer %s to: ")
>
> So basically, you can prompt for anything using the 's' descriptor and
> the following prompt string with %-constructs. In what use cases is
> this not enough, so much so that it would require exposing the guts of
> this to Lisp?
More information was requested, but none was given within 6 months, so
I'm closing this bug. If this is still an issue, please reply to this
email (use "Reply to all" in your email client) and we can reopen the
bug report.
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
2023-09-11 23:54 ` Stefan Kangas
@ 2023-09-17 0:50 ` Michael Heerdegen
2023-09-17 11:31 ` Stefan Kangas
0 siblings, 1 reply; 7+ messages in thread
From: Michael Heerdegen @ 2023-09-17 0:50 UTC (permalink / raw)
To: 62563; +Cc: ruijie, stefankangas
Stefan Kangas <stefankangas@gmail.com> writes:
> >> --8<---------------cut here---------------start------------->8---
> >> (defun foo (fname)
> >> (interactive "f")
> >> (ignore fname))
> >>
> >> (defun foo (fname bar)
> >> (interactive
> >> (list (simulate-interactive-f)
> >> (get-bar)))
> >> (ignore fname bar))
> >> --8<---------------cut here---------------end--------------->8---
Something like this can be useful if you need to read an additional
argument in a way that involves the need to run some Lisp, where using a
normal code letter is not enough. Then you need to substitute the other
code letters you still want to have been read also with Lisp code. Is
that understandable?
We have `advice-eval-interactive-spec' which can be used like
(advice-eval-interactive-spec "f") - that comes very close to what is
requested here. Combined with `interactive-form' one can use this to
simulate the argument reading from a given command from Lisp.
`advice-eval-interactive-spec' has a FIXME:
| ;; FIXME: How about renaming this to just `eval-interactive-spec'?
| ;; It's not specific to the advice system.
Any opinions whether we want to do that? If the implementation is not
something ugly (it probably is, a bit, though), I would vote for it.
Michael.
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
2023-09-17 0:50 ` Michael Heerdegen
@ 2023-09-17 11:31 ` Stefan Kangas
2023-09-18 4:28 ` Michael Heerdegen
2023-09-19 10:21 ` Richard Stallman
0 siblings, 2 replies; 7+ messages in thread
From: Stefan Kangas @ 2023-09-17 11:31 UTC (permalink / raw)
To: Michael Heerdegen, 62563
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Stefan Kangas <stefankangas@gmail.com> writes:
>
>> >> --8<---------------cut here---------------start------------->8---
>> >> (defun foo (fname)
>> >> (interactive "f")
>> >> (ignore fname))
>> >>
>> >> (defun foo (fname bar)
>> >> (interactive
>> >> (list (simulate-interactive-f)
>> >> (get-bar)))
>> >> (ignore fname bar))
>> >> --8<---------------cut here---------------end--------------->8---
>
> Something like this can be useful if you need to read an additional
> argument in a way that involves the need to run some Lisp, where using a
> normal code letter is not enough. Then you need to substitute the other
> code letters you still want to have been read also with Lisp code. Is
> that understandable?
Yes, I think that explanation is clear.
> We have `advice-eval-interactive-spec' which can be used like
> (advice-eval-interactive-spec "f") - that comes very close to what is
> requested here. Combined with `interactive-form' one can use this to
> simulate the argument reading from a given command from Lisp.
>
> `advice-eval-interactive-spec' has a FIXME:
>
> | ;; FIXME: How about renaming this to just `eval-interactive-spec'?
> | ;; It's not specific to the advice system.
>
> Any opinions whether we want to do that? If the implementation is not
> something ugly (it probably is, a bit, though), I would vote for it.
Could you point to one (or more) examples of real code that would have
been made significantly simpler by this? The idea sounds good in
theory, but it is important to understand if it will also be useful in
practice. That will give us a better basis for deciding if this is
something we would want to add or not.
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
2023-09-17 11:31 ` Stefan Kangas
@ 2023-09-18 4:28 ` Michael Heerdegen
2023-09-19 10:21 ` Richard Stallman
1 sibling, 0 replies; 7+ messages in thread
From: Michael Heerdegen @ 2023-09-18 4:28 UTC (permalink / raw)
To: Stefan Kangas; +Cc: 62563
Stefan Kangas <stefankangas@gmail.com> writes:
> Could you point to one (or more) examples of real code that would have
> been made significantly simpler by this? The idea sounds good in
> theory, but it is important to understand if it will also be useful in
> practice. That will give us a better basis for deciding if this is
> something we would want to add or not.
[ Note I only asked about renaming `advice-eval-interactive-spec' to
`eval-interactive-spec', not about adding something new. Because the
function is not only useful in nadvice.el. Dunno if I made that clear. ]
People can of course already use the name `advice-eval-interactive-spec'
- but it is probably not well known.
Ehm - examples, ok. Whenever a package or config file wants to define a
variant of an existing command that needs to read in the same arguments
in the same order (i.e. the user wants to have multiple commands instead
of one, an additional definition, not an advice), one has to copy the
interactive spec of the original definition. Or one can use
`advice-eval-interactive-spec'. The body of the variant also may or may
not reuse the other function. This is all very similar to defining
advices - only that it doesn't involve an advice, as I described.
When the variant of an existing command wants to skip reading one
argument, `advice-eval-interactive-spec' is not of much use. But the
same is true of advices of interactive functions that want to skip
reading an argument.
In the Emacs sources it's possible to factor the interactive spec out
into its own defun and reuse it in several places. So this kind of use
case is mostly relevant for external packages and user configurations.
Ok, you wanted a real life example. In my init file I have a command
like this:
#+begin_src emacs-lisp
(defun my-dired-restrict-marks ()
"Restrict marks using the following command.
Only files that are currently marked and are marked again with
the subsequent command will be marked afterwards. Thereby only
`dired-marker-char' marked files are considered - other marks are
not touched.
The next key sequence can optionally be prefixed with key ! to
mean \"not\" - then only marked files that would _not_ be marked
again with the next command keep their mark [...]
...
)
#+end_src
That way I can combine several marking commands to have files marked
fulfill more than one condition. If I bind the above command to `&', I
can use * / & * % to mark directories whose name is matched by a certain
regexp, for example.
The implementation saves the current file marks, reads a key sequence,
determines the bound command, then evals the interactive spec to get the
arguments (it is better to do this using the original buffer state, this
is the important part here).
Then all marks are removed, the command is called with the read in
arguments (simply using `apply'), then the marks are merged with the
remembered marks.
A similar case is my command `my-profiler-profile-next-command': It
similarly reads in a key sequence and the according arguments using the
interactive spec, but only after that starts the profiler and calls the
body of the command. This is nice if you want to avoid that the
argument reading messes the profiler results of the command's code.
Yes, such things, but admittedly, the large majority of calls of
`advice-eval-interactive-spec' is still for defining advices.
I also want to add that what I describe here is related, but not the
same as the request in the original report which, AFAIU, more asked
about a convenient way to simulate (interactive "f") conveniently from
Lisp. If we would have access to the code reading in the individual
arguments that would be even nicer, but it's not possible in the general
case because the interactive spec returns a list that is the result of
any arbitrary code that returns a list (i.e. there is no separate code
for each single argument in every case).
I let you decide whether my examples are enough to justify this
renaming. There are probably not that many use cases, still, there are
a few.
Michael.
^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#62563: [FR] Expose `interactive' arg handling as an Elisp function
2023-09-17 11:31 ` Stefan Kangas
2023-09-18 4:28 ` Michael Heerdegen
@ 2023-09-19 10:21 ` Richard Stallman
1 sibling, 0 replies; 7+ messages in thread
From: Richard Stallman @ 2023-09-19 10:21 UTC (permalink / raw)
To: Stefan Kangas; +Cc: michael_heerdegen, 62563
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
In general, each interactive spec can be programmed with Lisp code
inside `interactive'. But maybe there are some exceptions, Which ones
are exceptions? If we post the list of those, maybe we can provide a
simple specific solutions for them.
Also, maybe people will point out existing ways to handle some of the
codes that were first thought to be "missing".
--
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-09-19 10:21 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-31 7:27 bug#62563: [FR] Expose `interactive' arg handling as an Elisp function Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-31 7:38 ` Eli Zaretskii
2023-09-11 23:54 ` Stefan Kangas
2023-09-17 0:50 ` Michael Heerdegen
2023-09-17 11:31 ` Stefan Kangas
2023-09-18 4:28 ` Michael Heerdegen
2023-09-19 10:21 ` Richard Stallman
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.