unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* A way for interactive to modify a let-bound variable?
@ 2016-02-12 16:41 Kaushal Modi
  2016-02-12 16:57 ` Drew Adams
  0 siblings, 1 reply; 9+ messages in thread
From: Kaushal Modi @ 2016-02-12 16:41 UTC (permalink / raw)
  To: Help Gnu Emacs mailing list

Hi,

The below snippet will of course not work but I would like to achive
something like that:

(defun my-dummy-fn ()
  (let (msg)
    (interactive (progn
                   (if (use-region-p)
                       (setq msg "Region")
                     (setq msg "No region"))
                   nil))
    (message msg)))


This is a very simplified example. But I need to change a let-bound
variable in the interactive form based on some condition and then use that
variable in the defun body.

Is that possible?

--
Kaushal Modi


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

* RE: A way for interactive to modify a let-bound variable?
  2016-02-12 16:41 A way for interactive to modify a let-bound variable? Kaushal Modi
@ 2016-02-12 16:57 ` Drew Adams
  2016-02-12 17:17   ` Michael Heerdegen
  0 siblings, 1 reply; 9+ messages in thread
From: Drew Adams @ 2016-02-12 16:57 UTC (permalink / raw)
  To: Kaushal Modi, Help Gnu Emacs mailing list

> (defun my-dummy-fn ()
>   (let (msg)
>     (interactive (progn
>                    (if (use-region-p)
>                        (setq msg "Region")
>                      (setq msg "No region"))
>                    nil))
>     (message msg)))
> 
> This is a very simplified example. But I need to change a let-bound
> variable in the interactive form based on some condition and then use that
> variable in the defun body.  Is that possible?

No. The only thing available in the defun body that comes from
the `interactive' form is its return value, which is the list of
arguments passed to the function.

Show or explain what you are really trying to do. IOW, this sounds
like an X-Y problem: you are asking about your try at a solution
instead of asking about your actual problem.

(You can of course use `let' _inside_ `interactive', but it is not
clear what you are trying to do, so I hesitate to guess what
code might help.)



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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 16:57 ` Drew Adams
@ 2016-02-12 17:17   ` Michael Heerdegen
  2016-02-12 18:18     ` Kaushal Modi
  2016-02-12 19:30     ` Marcin Borkowski
  0 siblings, 2 replies; 9+ messages in thread
From: Michael Heerdegen @ 2016-02-12 17:17 UTC (permalink / raw)
  To: help-gnu-emacs

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

> (You can of course use `let' _inside_ `interactive', but it is not
> clear what you are trying to do, so I hesitate to guess what
> code might help.)

Yes, moving it inside is what he wants, I think.

Kaushal, don't hesitate to use whatever elisp you like in `interactive',
nothing special here.  Just be sure your expression returns the list of
arguments.

But the interactive form must look like (interactive ...), else it is
not recognized as such.


Michael.




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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 17:17   ` Michael Heerdegen
@ 2016-02-12 18:18     ` Kaushal Modi
  2016-02-12 18:38       ` Michael Heerdegen
  2016-02-12 19:30     ` Marcin Borkowski
  1 sibling, 1 reply; 9+ messages in thread
From: Kaushal Modi @ 2016-02-12 18:18 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Help Gnu Emacs mailing list

This is the actual function I want to optimize (Reference:
http://thread.gmane.org/gmane.emacs.help/109025/focus=109137 ).

(defun modi/advice-region-or-whole (orig-fun &rest args)
  (interactive (if (use-region-p)
                   (list (region-beginning) (region-end))
                 (list (point-min) (point-max))))
  (prog1
      (apply orig-fun args) ; this defun NEEDS to return this form's value
    (when (and (called-interactively-p 'interactive) ; duplication of
condition
               (not (use-region-p)))                           ;
      (message "Executed %s on the whole buffer."
               (propertize (symbol-name this-command)
                           'face 'font-lock-function-name-face)))))

This is an :around advice function and it needs to return the (apply
orig-fun args) value.

> You can of course use `let' _inside_ `interactive'

If I move the let form inside interactive, the let form needs to return the
list required for interactive. Then how would I return the (apply ..) value?

Eventually I want something like below that actually works:

(defun modi/advice-region-or-whole (orig-fun &rest args)
  (let (msg)
    (interactive (if (use-region-p)
                     (list (region-beginning) (region-end))
                   (setq msg (format "Executed %s on the whole buffer."
                                     (propertize (symbol-name this-command)
                                                 'face
'font-lock-function-name-face)))
                   (list (point-min) (point-max))))
    (prog1
        (apply orig-fun args)
      (when msg
        (message msg)))))


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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 18:18     ` Kaushal Modi
@ 2016-02-12 18:38       ` Michael Heerdegen
  2016-02-12 18:49         ` Kaushal Modi
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Heerdegen @ 2016-02-12 18:38 UTC (permalink / raw)
  To: help-gnu-emacs

Kaushal Modi <kaushal.modi@gmail.com> writes:

> This is an :around advice function and it needs to return the (apply
> orig-fun args) value.

FWIW, for the side effect you want, a :before advice is still
sufficient.

>
> > You can of course use `let' _inside_ `interactive'
>
> If I move the let form inside interactive, the let form needs to
> return the list required for interactive. Then how would I return the
> (apply ..)  value?

Well, `let' returns the result of the evaluation of the last form, so
you have to arrange that this last form is your (apply ...), or evals to
the result of it.

> Eventually I want something like below that actually works:
>
> (defun modi/advice-region-or-whole (orig-fun &rest args)
>   (let (msg)
>     (interactive (if (use-region-p)
>                      (list (region-beginning) (region-end))
>                    (setq msg (format "Executed %s on the whole buffer."
>                                      (propertize (symbol-name this-command)
>                                                  'face
> 'font-lock-function-name-face)))
>                    (list (point-min) (point-max))))
>     (prog1
>         (apply orig-fun args)
>       (when msg
>         (message msg)))))

It may work, but that doesn't define an interactive spec for your
function, so again you change the function you want to advice, which you
wanted to avoid.


Michael.




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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 18:38       ` Michael Heerdegen
@ 2016-02-12 18:49         ` Kaushal Modi
  2016-02-12 19:12           ` Michael Heerdegen
  0 siblings, 1 reply; 9+ messages in thread
From: Kaushal Modi @ 2016-02-12 18:49 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Help Gnu Emacs mailing list

> FWIW, for the side effect you want, a :before advice is still
> sufficient.

I ended up using :around, because I need to call (message ..) *after*
(apply orig-fun args). I need my message to be displayed last in the echo
area after whatever orig-fun could be displaying.

> Well, `let' returns the result of the evaluation of the last form, so
> you have to arrange that this last form is your (apply ...), or evals to
> the result of it.

It's a bit tricky if I put let inside interactive. If I do that, the let
form has to return the list that interactive needs. But I also need the
let-bound msg variable after calling (apply orig-fun args). So that implies
that I would need something like (interactive (let (msg) .. (apply orig-fun
args) (message msg))), which does not look right (and also does not work).

> It may work, but that doesn't define an interactive spec for your
> function, so again you change the function you want to advice, which you
> wanted to avoid.

Exactly, that does not work at all. The (interactive ..) form in there is
as good as it not being there, because it doesn't do anything if it is
wrapped in (let ..).


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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 18:49         ` Kaushal Modi
@ 2016-02-12 19:12           ` Michael Heerdegen
  2016-02-12 19:20             ` Kaushal Modi
  0 siblings, 1 reply; 9+ messages in thread
From: Michael Heerdegen @ 2016-02-12 19:12 UTC (permalink / raw)
  To: help-gnu-emacs

Kaushal Modi <kaushal.modi@gmail.com> writes:

> It's a bit tricky if I put let inside interactive. If I do that, the let
> form has to return the list that interactive needs. But I also need the
> let-bound msg variable after calling (apply orig-fun args). So that
> implies
> that I would need something like (interactive (let (msg) .. (apply
> orig-fun
> args) (message msg))), which does not look right (and also does not work).

Eh, no, that's nonsense.  I didn't fully understand what you wanted.  It
is not possible to bind a variable in the interactive spec and refer to
it in the body.

But your last version with `prog1' is ok.  Are you happy with that one?

Michael.




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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 19:12           ` Michael Heerdegen
@ 2016-02-12 19:20             ` Kaushal Modi
  0 siblings, 0 replies; 9+ messages in thread
From: Kaushal Modi @ 2016-02-12 19:20 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Help Gnu Emacs mailing list

> But your last version with `prog1' is ok.  Are you happy with that one?

I am happy that it works and much much better than my first version (
https://github.com/kaushalmodi/.emacs.d/blob/0b427ce554b1cade7f5fabb8ee4bfb704f6e497f/setup-files/setup-editing.el#L686-L730
).

I just wanted to go an extra mile and prevent the duplication of the
conditions.. first time in the interactive form for settings the fn args
and second time when deciding when to display the message. I just wanted to
check if the "extra optimization" I thought of was possible. So the gist
is.. what happens in interactive stays in interactive. :)

Thanks.


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

* Re: A way for interactive to modify a let-bound variable?
  2016-02-12 17:17   ` Michael Heerdegen
  2016-02-12 18:18     ` Kaushal Modi
@ 2016-02-12 19:30     ` Marcin Borkowski
  1 sibling, 0 replies; 9+ messages in thread
From: Marcin Borkowski @ 2016-02-12 19:30 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: help-gnu-emacs


On 2016-02-12, at 18:17, Michael Heerdegen <michael_heerdegen@web.de> wrote:

> Drew Adams <drew.adams@oracle.com> writes:
>
>> (You can of course use `let' _inside_ `interactive', but it is not
>> clear what you are trying to do, so I hesitate to guess what
>> code might help.)
>
> Yes, moving it inside is what he wants, I think.
>
> Kaushal, don't hesitate to use whatever elisp you like in `interactive',
> nothing special here.  Just be sure your expression returns the list of
> arguments.

My little 2cents & a plug: perhaps this could help?
http://mbork.pl/2015-09-12_A_trick_with_argument_for_interactive_call

> But the interactive form must look like (interactive ...), else it is
> not recognized as such.
>
> Michael.

Best,

-- 
Marcin Borkowski
http://octd.wmi.amu.edu.pl/en/Marcin_Borkowski
Faculty of Mathematics and Computer Science
Adam Mickiewicz University



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

end of thread, other threads:[~2016-02-12 19:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-12 16:41 A way for interactive to modify a let-bound variable? Kaushal Modi
2016-02-12 16:57 ` Drew Adams
2016-02-12 17:17   ` Michael Heerdegen
2016-02-12 18:18     ` Kaushal Modi
2016-02-12 18:38       ` Michael Heerdegen
2016-02-12 18:49         ` Kaushal Modi
2016-02-12 19:12           ` Michael Heerdegen
2016-02-12 19:20             ` Kaushal Modi
2016-02-12 19:30     ` Marcin Borkowski

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).