all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Suppress user-prompting when calling commands in programs
@ 2014-06-13 13:51 Thorsten Jolitz
  2014-06-13 14:03 ` Eli Zaretskii
  2014-06-13 14:20 ` Nicolas Richard
  0 siblings, 2 replies; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-13 13:51 UTC (permalink / raw
  To: help-gnu-emacs


Hi List, 

I often encounter user commands that do exactly what I want, and would
like to reuse them in a program, but they are not really written for
programmatical use, i.e. they prompt the user for information to be
stored in (local) variables, but don't expose these variables as
function arguments:

#+begin_src emacs-lisp
(defun foo (&optional arg)
  (interactive "P")
  (let ((bar (org-icompleting-read ...)))))
#+end_src

I guess thats because writing the interactive spec and binding keys
becomes so much simpler that way. 

Assuming `foo' can't be changed - is there another way to bind `bar'
before calling `foo' in a program rather than advising `foo' (with the
aim to suppress any user-prompting at all during the execution of
`foo')?

I seem to remember that a solution for this exists, but I can't find
it anymore. Thanks for any hint. 

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 13:51 Suppress user-prompting when calling commands in programs Thorsten Jolitz
@ 2014-06-13 14:03 ` Eli Zaretskii
  2014-06-13 14:25   ` Stefan Monnier
  2014-06-13 14:20 ` Nicolas Richard
  1 sibling, 1 reply; 19+ messages in thread
From: Eli Zaretskii @ 2014-06-13 14:03 UTC (permalink / raw
  To: help-gnu-emacs

> From: Thorsten Jolitz <tjolitz@gmail.com>
> Date: Fri, 13 Jun 2014 15:51:47 +0200
> 
> (defun foo (&optional arg)
>   (interactive "P")
>   (let ((bar (org-icompleting-read ...)))))

Yuck!

> Assuming `foo' can't be changed - is there another way to bind `bar'
> before calling `foo' in a program rather than advising `foo' (with the
> aim to suppress any user-prompting at all during the execution of
> `foo')?

cl-flet org-icompleting-read to 'ignore?



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 13:51 Suppress user-prompting when calling commands in programs Thorsten Jolitz
  2014-06-13 14:03 ` Eli Zaretskii
@ 2014-06-13 14:20 ` Nicolas Richard
  2014-06-13 15:18   ` Thorsten Jolitz
       [not found]   ` <mailman.3579.1402672740.1147.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 19+ messages in thread
From: Nicolas Richard @ 2014-06-13 14:20 UTC (permalink / raw
  To: Thorsten Jolitz; +Cc: help-gnu-emacs

Thorsten Jolitz <tjolitz@gmail.com> writes:
> I seem to remember that a solution for this exists, but I can't find
> it anymore. Thanks for any hint.

flet would work but is obsolete. See Stefan's
http://lists.gnu.org/archive/html/help-gnu-emacs/2013-04/msg00429.html
for possible replacements (namely cl-letf and advising).

OTOH, is it really not possible to change the function upstream ? "bar"
could be made an optional argument upstream (possibly with proper
interactive spec), or the body of the let form could be factored out as
a function for you to use.

-- 
Nico.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 14:03 ` Eli Zaretskii
@ 2014-06-13 14:25   ` Stefan Monnier
  2014-06-13 15:09     ` Thorsten Jolitz
  2014-06-13 15:29     ` Drew Adams
  0 siblings, 2 replies; 19+ messages in thread
From: Stefan Monnier @ 2014-06-13 14:25 UTC (permalink / raw
  To: help-gnu-emacs

>> (defun foo (&optional arg)
>>   (interactive "P")
>>   (let ((bar (org-icompleting-read ...)))))
> Yuck!

Indeed, the prompting should normally take place in the `interactive'
spec, but the above is sadly pretty common.

>> Assuming `foo' can't be changed - is there another way to bind `bar'
>> before calling `foo' in a program rather than advising `foo' (with the
>> aim to suppress any user-prompting at all during the execution of
>> `foo')?

Not really, no.  And advising `foo' only won't help: you also need to
advise org-icompleting-read.

> cl-flet org-icompleting-read to 'ignore?

Nope.  That worked with `flet', but `cl-flet' is actually providing
Common-Lisp's `flet' which defines a lexically-scoped function.
Better use an advice here.


        Stefan




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 14:25   ` Stefan Monnier
@ 2014-06-13 15:09     ` Thorsten Jolitz
  2014-06-13 15:29     ` Drew Adams
  1 sibling, 0 replies; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-13 15:09 UTC (permalink / raw
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>> (defun foo (&optional arg)
>>>   (interactive "P")
>>>   (let ((bar (org-icompleting-read ...)))))
>> Yuck!
>
> Indeed, the prompting should normally take place in the `interactive'
> spec, but the above is sadly pretty common.
>
>>> Assuming `foo' can't be changed - is there another way to bind `bar'
>>> before calling `foo' in a program rather than advising `foo' (with the
>>> aim to suppress any user-prompting at all during the execution of
>>> `foo')?
>
> Not really, no.  And advising `foo' only won't help: you also need to
> advise org-icompleting-read.
>
>> cl-flet org-icompleting-read to 'ignore?
>
> Nope.  That worked with `flet', but `cl-flet' is actually providing
> Common-Lisp's `flet' which defines a lexically-scoped function.
> Better use an advice here.

Thanks (Eli and) Stefan, so an advice is ok here.

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 14:20 ` Nicolas Richard
@ 2014-06-13 15:18   ` Thorsten Jolitz
  2014-06-13 16:04     ` Drew Adams
       [not found]   ` <mailman.3579.1402672740.1147.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-13 15:18 UTC (permalink / raw
  To: help-gnu-emacs

Nicolas Richard <theonewiththeevillook@yahoo.fr> writes:

> Thorsten Jolitz <tjolitz@gmail.com> writes:
>> I seem to remember that a solution for this exists, but I can't find
>> it anymore. Thanks for any hint.
>
> flet would work but is obsolete. See Stefan's
> http://lists.gnu.org/archive/html/help-gnu-emacs/2013-04/msg00429.html
> for possible replacements (namely cl-letf and advising).
>
> OTOH, is it really not possible to change the function upstream ? "bar"
> could be made an optional argument upstream (possibly with proper
> interactive spec), or the body of the let form could be factored out as
> a function for you to use.

I tried convincing upstream before and never made it! And I actually
understand the authors of code like that and even copied that technique
sometimes, because it might be harder to write the interactive spec for
both interactive and programmatical use than to write the function
itself, and then there is no need for a wrapper command or interactive
(lambda ...) expression when it comes to define a key for that command.

But OTOH its a shame that many commands are hard/impossible to reuse in
programs because of this 'trick'. 

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: Suppress user-prompting when calling commands in programs
  2014-06-13 14:25   ` Stefan Monnier
  2014-06-13 15:09     ` Thorsten Jolitz
@ 2014-06-13 15:29     ` Drew Adams
  2014-06-13 15:49       ` Thorsten Jolitz
  1 sibling, 1 reply; 19+ messages in thread
From: Drew Adams @ 2014-06-13 15:29 UTC (permalink / raw
  To: help-gnu-emacs

> >> (defun foo (&optional arg)
> >>   (interactive "P")
> >>   (let ((bar (org-icompleting-read ...)))))
> > Yuck!
> 
> Indeed, the prompting should normally take place in the `interactive'
> spec, but the above is sadly pretty common.

File a code bug / enhancement request for `foo'...

> >> Assuming `foo' can't be changed - is there another way to bind `bar'
> >> before calling `foo' in a program rather than advising `foo' (with the
> >> aim to suppress any user-prompting at all during the execution of
> >> `foo')?
> 
> Not really, no.

Sure there is.  If `bar' is a dynamic variable, at least.

> And advising `foo' only won't help: you also need to
> advise org-icompleting-read.
>
> > cl-flet org-icompleting-read to 'ignore?
> 
> Nope.  That worked with `flet', but `cl-flet' is actually providing
> Common-Lisp's `flet' which defines a lexically-scoped function.
> Better use an advice here.

It's pretty simple if `bar' is dynamic, not lexical - e.g., top-level
(defvar bar 51 "Step up to the bar")

;; Unchangeable `foo' - just instantiating your "...", for a test:
(defun foo (&optional arg)
  (interactive "P")
  (let ((bar  (org-icompleting-read "Prompt: " '("a" "b" "c"))))
    (message "`foo' arg is %S.  BAR is %S" arg bar)))

Write a function that binds `bar' to whatever you want and
provides whatever arg you want to `foo'.  Temporarily redefine
`org-icompleting-read' to just return your value of `bar'.
Then restore `org-icompleting-read'.

(defun toto (my-bar my-foo-arg)
  (let ((bar    my-bar)
        (o-i-r  (symbol-function 'org-icompleting-read)))
    (unwind-protect
         (progn (fset 'org-icompleting-read
                      (lambda (&rest _) (symbol-value 'bar)))
                (foo my-foo-arg))
      (fset 'org-icompleting-read o-i-r))))
    
(toto 42 36)
==> `foo' arg is 36.  BAR is 42

The original definition of `org-icompleting-read' is ignored (no
prompting etc.), and `foo's binding of `bar' is overruled by
`toto's binding of `bar'.

None of this is pretty.  But it's not complicated either.  And yes,
the `foo' code should be rewritten in one of the ways already
suggested (file a bug).



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 15:29     ` Drew Adams
@ 2014-06-13 15:49       ` Thorsten Jolitz
  0 siblings, 0 replies; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-13 15:49 UTC (permalink / raw
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> Indeed, the prompting should normally take place in the `interactive'
>> spec, but the above is sadly pretty common.
>
> File a code bug / enhancement request for `foo'...

Well, I don't want to be PITA, and there are quite some examples for
this e.g. in Org-mode (thats why most Org commands are directly bound to
keys without having to deal with function args)...

To me this looks more like a 'political decision' from upstream (don't
do this, its not acceptable, and fix it when you have done it) than like
a bug report.

> Sure there is.  If `bar' is a dynamic variable, at least.

[...]

> None of this is pretty.  But it's not complicated either.  And yes,
> the `foo' code should be rewritten in one of the ways already
> suggested (file a bug).

Pretty or not, thanks for the working and easy-to-digest recipe, very
helpful!

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: Suppress user-prompting when calling commands in programs
  2014-06-13 15:18   ` Thorsten Jolitz
@ 2014-06-13 16:04     ` Drew Adams
  2014-06-13 18:14       ` Thorsten Jolitz
  2014-06-14  3:33       ` Eric Abrahamsen
  0 siblings, 2 replies; 19+ messages in thread
From: Drew Adams @ 2014-06-13 16:04 UTC (permalink / raw
  To: Thorsten Jolitz, help-gnu-emacs

> > OTOH, is it really not possible to change the function upstream ? "bar"
> > could be made an optional argument upstream (possibly with proper
> > interactive spec), or the body of the let form could be factored out as
> > a function for you to use.
> 
> I tried convincing upstream before and never made it!

Try again.

> And I actually understand the authors of code like that and even copied
> that technique sometimes, because it might be harder to write the
> interactive spec for both interactive and programmatical use than to
> write the function itself, and then there is no need for a wrapper
> command or interactive (lambda ...) expression when it comes to define
> a key for that command.

Huh?  Instead of:

(defun foo (&optional arg)
  (interactive "P")
  (let ((bar  (org-icompleting-read ...)))
    ...))

What's wrong with them pushing the read into the interactive spec?

(defun foo (&optional arg bar)
  (interactive (list current-prefix-arg
                     (org-icompleting-read ...))))
  ...)

That's the recommended approach, in general.

Or if the (org-icompleting-read ...) code itself uses the prefix
arg as the variable ARG, then rename such occurrences of ARG to,
say, PREF), and bind PREF before invoking `org-icompleting-read':

(defun foo (&optional arg bar)
  (interactive
    (let ((pref  current-prefix-arg))
      (list pref (org-icompleting-read ...))))
  ...)

Or if they really want to leave the beginning of the code the
same for some reason, they could at least factor out the body
(the second "..."), so you can invoke that code directly:

(defun foo (&optional arg)
  (interactive "P")
  (let ((bar (org-icompleting-read ...)))
    (foo-guts arg bar))) ; <== Just a wrapper for the body.
                         ;     No other code changes needed.

Then your code would just call `foo-guts'.

> But OTOH its a shame that many commands are hard/impossible to reuse in
> programs because of this 'trick'.

A shame and unnecessary.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 16:04     ` Drew Adams
@ 2014-06-13 18:14       ` Thorsten Jolitz
  2014-06-14  3:33       ` Eric Abrahamsen
  1 sibling, 0 replies; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-13 18:14 UTC (permalink / raw
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> I tried convincing upstream before and never made it!
>
> Try again.

hmmm ...

>> And I actually understand the authors of code like that and even copied
>> that technique sometimes, because it might be harder to write the
>> interactive spec for both interactive and programmatical use than to
>> write the function itself, and then there is no need for a wrapper
>> command or interactive (lambda ...) expression when it comes to define
>> a key for that command.
>
> Huh?  Instead of:
>
> (defun foo (&optional arg)
>   (interactive "P")
>   (let ((bar  (org-icompleting-read ...)))
>     ...))
>
> What's wrong with them pushing the read into the interactive spec?
>
> (defun foo (&optional arg bar)
>   (interactive (list current-prefix-arg
>                      (org-icompleting-read ...))))
>   ...)

probably nothing ...

> That's the recommended approach, in general.
>
> Or if the (org-icompleting-read ...) code itself uses the prefix
> arg as the variable ARG, then rename such occurrences of ARG to,
> say, PREF), and bind PREF before invoking `org-icompleting-read':
>
> (defun foo (&optional arg bar)
>   (interactive
>     (let ((pref  current-prefix-arg))
>       (list pref (org-icompleting-read ...))))
>   ...)
>
> Or if they really want to leave the beginning of the code the
> same for some reason, they could at least factor out the body
> (the second "..."), so you can invoke that code directly:
>
> (defun foo (&optional arg)
>   (interactive "P")
>   (let ((bar (org-icompleting-read ...)))
>     (foo-guts arg bar))) ; <== Just a wrapper for the body.
>                          ;     No other code changes needed.
>
> Then your code would just call `foo-guts'.

yes, does not look too complicated ...

>> But OTOH its a shame that many commands are hard/impossible to reuse in
>> programs because of this 'trick'.
>
> A shame and unnecessary.

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
       [not found]   ` <mailman.3579.1402672740.1147.help-gnu-emacs@gnu.org>
@ 2014-06-13 18:55     ` Stefan Monnier
  2014-06-14  8:07       ` Thorsten Jolitz
  0 siblings, 1 reply; 19+ messages in thread
From: Stefan Monnier @ 2014-06-13 18:55 UTC (permalink / raw
  To: help-gnu-emacs

> I tried convincing upstream before and never made it! And I actually
> understand the authors of code like that and even copied that technique
> sometimes, because it might be harder to write the interactive spec for
> both interactive and programmatical use than to write the function
> itself, and then there is no need for a wrapper command or interactive
> (lambda ...) expression when it comes to define a key for that command.

I don't know what complications you're referring to.

In 99% of the cases you can just turn

    (defun foo (&optional arg)
      (interactive "P")
      (let ((bar (org-icompleting-read ...)))))

into

    (defun foo (bar &optional arg)
      (interactive
       (list (org-icompleting-read ...) current-prefix-arg))

I'm not saying it's always perfect, but there's clearly some difference
between my experience and yours, so if you give some examples, it would help.


        Stefan


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 16:04     ` Drew Adams
  2014-06-13 18:14       ` Thorsten Jolitz
@ 2014-06-14  3:33       ` Eric Abrahamsen
  2014-06-14  3:36         ` Drew Adams
  1 sibling, 1 reply; 19+ messages in thread
From: Eric Abrahamsen @ 2014-06-14  3:33 UTC (permalink / raw
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:


[...]


> What's wrong with them pushing the read into the interactive spec?
>
> (defun foo (&optional arg bar)
>   (interactive (list current-prefix-arg
>                      (org-icompleting-read ...))))
>   ...)

A quick side-question: Everyone here is using &optional for the prefix
arg name. I have several functions lying around that use the "P"
interactive spec but don't specify arg as &optional, and seem to work
fine. My understanding is that, if there is no prefix arg, arg will
simply be nil, as it should be.

Apart from style/code clarity, are there other reasons for specifying
&optional?

Thanks,
E




^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: Suppress user-prompting when calling commands in programs
  2014-06-14  3:33       ` Eric Abrahamsen
@ 2014-06-14  3:36         ` Drew Adams
  2014-06-14  3:47           ` Eric Abrahamsen
  0 siblings, 1 reply; 19+ messages in thread
From: Drew Adams @ 2014-06-14  3:36 UTC (permalink / raw
  To: Eric Abrahamsen, help-gnu-emacs

> > What's wrong with them pushing the read into the interactive spec?
> >
> > (defun foo (&optional arg bar)
> >   (interactive (list current-prefix-arg
> >                      (org-icompleting-read ...))))
> >   ...)
> 
> A quick side-question: Everyone here is using &optional for the prefix
> arg name.

I used &optional because that is what was used in the original `foo'.
Presumably there is existing code that uses `foo' and expects that
signature, e.g., tries to evaluate `(foo)'.

> I have several functions lying around that use the "P"
> interactive spec but don't specify arg as &optional, and seem to work
> fine. My understanding is that, if there is no prefix arg, arg will
> simply be nil, as it should be.

Correct.

> Apart from style/code clarity, are there other reasons for specifying
> &optional?

See above.  Use &optional if you want to be able to call the function
without passing that argument.



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-14  3:36         ` Drew Adams
@ 2014-06-14  3:47           ` Eric Abrahamsen
  0 siblings, 0 replies; 19+ messages in thread
From: Eric Abrahamsen @ 2014-06-14  3:47 UTC (permalink / raw
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> > What's wrong with them pushing the read into the interactive spec?
>> >
>> > (defun foo (&optional arg bar)
>> >   (interactive (list current-prefix-arg
>> >                      (org-icompleting-read ...))))
>> >   ...)
>> 
>> A quick side-question: Everyone here is using &optional for the prefix
>> arg name.
>
> I used &optional because that is what was used in the original `foo'.
> Presumably there is existing code that uses `foo' and expects that
> signature, e.g., tries to evaluate `(foo)'.
>
>> I have several functions lying around that use the "P"
>> interactive spec but don't specify arg as &optional, and seem to work
>> fine. My understanding is that, if there is no prefix arg, arg will
>> simply be nil, as it should be.
>
> Correct.
>
>> Apart from style/code clarity, are there other reasons for specifying
>> &optional?
>
> See above.  Use &optional if you want to be able to call the function
> without passing that argument.

Ah, of course -- sort of the inverse of the OP's question. Thanks!




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-13 18:55     ` Stefan Monnier
@ 2014-06-14  8:07       ` Thorsten Jolitz
  2014-06-14  8:22         ` Thorsten Jolitz
  2014-06-14 15:52         ` Drew Adams
  0 siblings, 2 replies; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-14  8:07 UTC (permalink / raw
  To: help-gnu-emacs

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> I tried convincing upstream before and never made it! And I actually
>> understand the authors of code like that and even copied that technique
>> sometimes, because it might be harder to write the interactive spec for
>> both interactive and programmatical use than to write the function
>> itself, and then there is no need for a wrapper command or interactive
>> (lambda ...) expression when it comes to define a key for that command.
>
> I don't know what complications you're referring to.
>
> In 99% of the cases you can just turn
>
>     (defun foo (&optional arg)
>       (interactive "P")
>       (let ((bar (org-icompleting-read ...)))))
>
> into
>
>     (defun foo (bar &optional arg)
>       (interactive
>        (list (org-icompleting-read ...) current-prefix-arg))
>
> I'm not saying it's always perfect, but there's clearly some difference
> between my experience and yours, so if you give some examples, it would help.

Maybe I just find the Emacs Lisp Manual too dense and lacking examples
and templates for using lists in the interactive spec?

  * It may be a Lisp expression that is not a string; then it should
    be a form that is evaluated to get a list of arguments to pass
    to the command. Usually this form will call various functions to
    read input from the user, most often through the minibuffer (see
    Minibuffers) or directly from the keyboard (see Reading Input).
   
    Providing point or the mark as an argument value is also common,
    but if you do this and read input (whether using the minibuffer
    or not), be sure to get the integer values of point or the mark
    after reading. The current buffer may be receiving subprocess
    output; if subprocess output arrives while the command is
    waiting for input, it could relocate point and the mark.
   
    Here's an example of what not to do:
   
              (interactive
               (list (region-beginning) (region-end)
                     (read-string "Foo: " nil 'my-history)))
    
    Here's how to avoid the problem, by examining point and the mark
    after reading the keyboard input:
   
              (interactive
               (let ((string (read-string "Foo: " nil 'my-history)))
                 (list (region-beginning) (region-end) string)))



#+begin_src emacs-lisp 
;; Start a REPL
(defun iorg-scrape-repl (&optional port host how local)
  "Run inferior Picolisp and setup process for GUI-scripting."
  (interactive
   (cond
    ((equal current-prefix-arg nil) nil)
    ((equal current-prefix-arg '(4))
     (list
      (read-number "Port: ")))
    ((equal current-prefix-arg '(16))
     (list
      (read-number "Port: ")
      (read-string "Host: ")))
    ((equal current-prefix-arg '(32))
     (list
      (read-number "Port: ")
      (read-string "Host: ")
      (read-string "How: ")))
    (t
     (list
      (read-number "Port: ")
      (read-string "Host: ")
      (read-string "How: ")
      (read-string "Local: ")))))
  (let* ((hst (or host "localhost"))
         (prt (or port 5000)) [...]
#+end_src
-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-14  8:07       ` Thorsten Jolitz
@ 2014-06-14  8:22         ` Thorsten Jolitz
  2014-06-15  1:58           ` Stefan Monnier
  2014-06-14 15:52         ` Drew Adams
  1 sibling, 1 reply; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-14  8:22 UTC (permalink / raw
  To: help-gnu-emacs

Thorsten Jolitz <tjolitz@gmail.com> writes:

> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> I tried convincing upstream before and never made it! And I actually
>>> understand the authors of code like that and even copied that technique
>>> sometimes, because it might be harder to write the interactive spec for
>>> both interactive and programmatical use than to write the function
>>> itself, and then there is no need for a wrapper command or interactive
>>> (lambda ...) expression when it comes to define a key for that command.
>>
>> I don't know what complications you're referring to.
>>
>> In 99% of the cases you can just turn
>>
>>     (defun foo (&optional arg)
>>       (interactive "P")
>>       (let ((bar (org-icompleting-read ...)))))
>>
>> into
>>
>>     (defun foo (bar &optional arg)
>>       (interactive
>>        (list (org-icompleting-read ...) current-prefix-arg))
>>
>> I'm not saying it's always perfect, but there's clearly some difference
>> between my experience and yours, so if you give some examples, it would help.

[Ups, that one was send to early accidentally ...]

Maybe I just find the Emacs Lisp Manual too dense and lacking examples
and templates for using lists in the interactive spec?

This is more or less or there is:

 ,-------------------------------------------------------------------
 | * It may be a Lisp expression that is not a string; then it should
 |   be a form that is evaluated to get a list of arguments to pass
 |   to the command. Usually this form will call various functions to
 |   read input from the user, most often through the minibuffer (see
 |   Minibuffers) or directly from the keyboard (see Reading Input).
 |  
 |   Providing point or the mark as an argument value is also common,
 |   but if you do this and read input (whether using the minibuffer
 |   or not), be sure to get the integer values of point or the mark
 |   after reading. The current buffer may be receiving subprocess
 |   output; if subprocess output arrives while the command is
 |   waiting for input, it could relocate point and the mark.
 |  
 |   Here's an example of what not to do:
 |  
 |             (interactive
 |              (list (region-beginning) (region-end)
 |                    (read-string "Foo: " nil 'my-history)))
 |   
 |   Here's how to avoid the problem, by examining point and the mark
 |   after reading the keyboard input:
 |  
 |             (interactive
 |              (let ((string (read-string "Foo: " nil 'my-history)))
 |                (list (region-beginning) (region-end) string)))
 `-------------------------------------------------------------------

But what about a case like this, a command with several optional args,
that are not always necessary. How to give the user the option to decide
for which args he wants to give input (and use the defaults for the
others)? Where to put the (prefix) 'arg argument in this case? How does
Emacs know which of the optional arguments should be the
prefix-argument? Do I need a "P" or "p" then somewhere in the spec when
I add 'arg' to the arguments list? 

I came up with something like this, but most likely inspired by other
elisp libraries, not by the manual. Is it a good solution? Hard to tell,
since there are no templates or best practice examples given for more
complex interactive specs in the manual. 

 #+begin_src emacs-lisp 
 ;; Start a REPL
 (defun iorg-scrape-repl (&optional port host how local)
   "Run inferior Picolisp and setup process for GUI-scripting."
   (interactive
    (cond
     ((equal current-prefix-arg nil) nil)
     ((equal current-prefix-arg '(4))
      (list
       (read-number "Port: ")))
     ((equal current-prefix-arg '(16))
      (list
       (read-number "Port: ")
       (read-string "Host: ")))
     ((equal current-prefix-arg '(32))
      (list
       (read-number "Port: ")
       (read-string "Host: ")
       (read-string "How: ")))
     (t
      (list
       (read-number "Port: ")
       (read-string "Host: ")
       (read-string "How: ")
       (read-string "Local: ")))))
   (let* ((hst (or host "localhost"))
          (prt (or port 5000)) [...]
 #+end_src

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* RE: Suppress user-prompting when calling commands in programs
  2014-06-14  8:07       ` Thorsten Jolitz
  2014-06-14  8:22         ` Thorsten Jolitz
@ 2014-06-14 15:52         ` Drew Adams
  2014-06-14 16:27           ` Thorsten Jolitz
  1 sibling, 1 reply; 19+ messages in thread
From: Drew Adams @ 2014-06-14 15:52 UTC (permalink / raw
  To: Thorsten Jolitz, help-gnu-emacs

> (equal current-prefix-arg '(32))

Perhaps you mean (equal current-prefix-arg '(64))?

N `C-u' occurrences (for N>0) result in (expt 4 N) as the list car.

[Why this is not documented in the Elisp manual, I don't know.
Certainly (IMHO), user code should be able to depend on it.]



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-14 15:52         ` Drew Adams
@ 2014-06-14 16:27           ` Thorsten Jolitz
  0 siblings, 0 replies; 19+ messages in thread
From: Thorsten Jolitz @ 2014-06-14 16:27 UTC (permalink / raw
  To: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

>> (equal current-prefix-arg '(32))
>
> Perhaps you mean (equal current-prefix-arg '(64))?
>
> N `C-u' occurrences (for N>0) result in (expt 4 N) as the list car.

definitely, thanks 

> [Why this is not documented in the Elisp manual, I don't know.
> Certainly (IMHO), user code should be able to depend on it.]

this (expt 4 N) is well-know, by me too, just forgot about it apparently
...

-- 
cheers,
Thorsten




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Suppress user-prompting when calling commands in programs
  2014-06-14  8:22         ` Thorsten Jolitz
@ 2014-06-15  1:58           ` Stefan Monnier
  0 siblings, 0 replies; 19+ messages in thread
From: Stefan Monnier @ 2014-06-15  1:58 UTC (permalink / raw
  To: help-gnu-emacs

> But what about a case like this, a command with several optional args,
> that are not always necessary. How to give the user the option to decide
> for which args he wants to give input (and use the defaults for the
> others)?

That's a UI issue more than a programming issue.  The general design we
try to follow in Emacs in this respect is to only have 2 options:
either minimal prompting (the default) or full prompting (which the user
can request with C-u).
But that's completely up to the package's author.

> Where to put the (prefix) 'arg argument in this case? How does Emacs
> know which of the optional arguments should be the prefix-argument?

These questions can't be answered directly because they only indicate
a misunderstanding of what is the prefix argument.

> Do I need a "P" or "p" then somewhere in the spec when
> I add 'arg' to the arguments list? 

"P" only means that the argument at that position will receive the value
of `current-prefix-arg'.  And "p" does the same for
(prefix-numeric-value current-prefix-arg).  You can call that argument
`arg', or `best-friends-for-ever', or any other name you like.

>  (defun iorg-scrape-repl (&optional port host how local)
>    "Run inferior Picolisp and setup process for GUI-scripting."
>    (interactive
>     (cond
>      ((equal current-prefix-arg nil) nil)
>      ((equal current-prefix-arg '(4))
>       (list
>        (read-number "Port: ")))
>      ((equal current-prefix-arg '(16))
>       (list
>        (read-number "Port: ")
>        (read-string "Host: ")))
>      ((equal current-prefix-arg '(32))
>       (list
>        (read-number "Port: ")
>        (read-string "Host: ")
>        (read-string "How: ")))
>      (t
>       (list
>        (read-number "Port: ")
>        (read-string "Host: ")
>        (read-string "How: ")
>        (read-string "Local: ")))))

That would work.

As mentioned above, we usually prefer not to distinguish (4) from (16)
or any other value, other than nil, so it would be just:

   (defun iorg-scrape-repl (&optional port host how local)
     "Run inferior Picolisp and setup process for GUI-scripting."
     (interactive
      (when current-prefix-arg
        (list
         (read-number "Port: ")
         (read-string "Host: ")
         (read-string "How: ")
         (read-string "Local: "))))

And then we'd try to reduce the worst-case prompting either by avoiding
some of the prompts depending on previous prompt's return value, or by
merging prompts.  E.g.:

   (defun iorg-scrape-repl (&optional port host how local)
     "Run inferior Picolisp and setup process for GUI-scripting."
     (interactive
      (when current-prefix-arg
        (let ((host+port (split-string (read-string "Host (and port): ")
                                       ":")))
          `(,(nth 1 host+port)
            ,(nth 0 host+port)
            ,@(unless (equal (nth 0 host+port) "localhost")
                (list (read-string "How: ")
                      (read-string "Local: "))))))))

-- Stefan




^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2014-06-15  1:58 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-13 13:51 Suppress user-prompting when calling commands in programs Thorsten Jolitz
2014-06-13 14:03 ` Eli Zaretskii
2014-06-13 14:25   ` Stefan Monnier
2014-06-13 15:09     ` Thorsten Jolitz
2014-06-13 15:29     ` Drew Adams
2014-06-13 15:49       ` Thorsten Jolitz
2014-06-13 14:20 ` Nicolas Richard
2014-06-13 15:18   ` Thorsten Jolitz
2014-06-13 16:04     ` Drew Adams
2014-06-13 18:14       ` Thorsten Jolitz
2014-06-14  3:33       ` Eric Abrahamsen
2014-06-14  3:36         ` Drew Adams
2014-06-14  3:47           ` Eric Abrahamsen
     [not found]   ` <mailman.3579.1402672740.1147.help-gnu-emacs@gnu.org>
2014-06-13 18:55     ` Stefan Monnier
2014-06-14  8:07       ` Thorsten Jolitz
2014-06-14  8:22         ` Thorsten Jolitz
2014-06-15  1:58           ` Stefan Monnier
2014-06-14 15:52         ` Drew Adams
2014-06-14 16:27           ` Thorsten Jolitz

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.