From mboxrd@z Thu Jan 1 00:00:00 1970 From: Matt Price Subject: Re: access a let* value whe ndefining a function? Date: Wed, 24 Oct 2018 07:58:09 -0400 Message-ID: References: Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="0000000000001bceb20578f831f0" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:57527) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFI6V-0006a1-IA for emacs-orgmode@gnu.org; Wed, 24 Oct 2018 08:17:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gFHn5-0004g9-RJ for emacs-orgmode@gnu.org; Wed, 24 Oct 2018 07:57:38 -0400 Received: from mail-io1-xd36.google.com ([2607:f8b0:4864:20::d36]:33596) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gFHn5-0004fh-GW for emacs-orgmode@gnu.org; Wed, 24 Oct 2018 07:57:35 -0400 Received: by mail-io1-xd36.google.com with SMTP id l25-v6so2967164ioj.0 for ; Wed, 24 Oct 2018 04:57:35 -0700 (PDT) In-Reply-To: List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: John Kitchin Cc: Org Mode --0000000000001bceb20578f831f0 Content-Type: text/plain; charset="UTF-8" On Tue, Oct 23, 2018 at 4:34 PM John Kitchin wrote: > > Matt Price writes: > > > On Tue, Oct 23, 2018 at 2:32 PM John Kitchin > > wrote: > > > >> I think that what you really want to do here is modify org-mime-compose > so > >> that you can use the send-actions argument to message-mail. In > >> scimax-email.el I use that to be able to turn an org-heading into an > email, > >> send it, and then jump back to the heading to insert some information > about > >> the email into the heading properties after it is sent. A lot of the > >> information gets passed via global variables. Maybe there is a better > way > >> to do that, I wrote that code a long time ago. > >> > >> > > I'm trying to use mu4e~compose-mail instead of message-compose, I guess > > mostly because I want to be able to use the mu4e email address completion > > features in the `To:` header. And it wouldalso be nice to save the email > > to the appropriate mu folder. But I didn't seem to be able to make mu4e > > bounce back to my buffer no matter what I do, and though > mu4e~compose-mail > > accepts a return-action argument it doesn't actually use it :-(. > > This is kind of tricky. Here is an approach that seems to work: > > (defun my-compose () > (interactive) > (mu4e~compose-mail) > (advice-add 'mu4e~switch-back-to-mu4e-buffer :after > `(lambda () > (switch-to-buffer (get-buffer ,(buffer-name) )) > (advice-remove 'mu4e~switch-back-to-mu4e-buffer > "om-temp-advice")) > '((name . "om-temp-advice")))) > > You just call M-x my-compose to get this behavior. I guess you could > advise mu4e~compose too to add the advice. > > Right now I am adding my advice from inside of ~org-mime-org-*-htmlize~ in the org-mime code (which I guess you no longer use, since you have written your own email handler). It seems to be a good place for it & is minimally invasive to other packages. Here's the code ` code I attempted but which didn't work for me: (advice-add 'mu4e~switch-back-to-mu4e-buffer :after (eval `(lambda () (switch-to-buffer (get-buffer ,(buffer-name) )) (advice-remove 'mu4e~switch-back-to-mu4e-buffer "om-temp-advice") '((name . "om-temp-advice") )))) Seems like maybe the problem fore me is the extra "eval". What maybe I don't understand is why the backquote works when the ordinary way to add an advice is the unquoted (advice-add 'sym (lambda () (message "I am an advice")) while IIUC yours should evaluate to (advice-add 'sym '(lambda () (message "I am an advice")) There should be a difference, shouldn't there? But clearly I don't understand. > It seems necessary to use a temporary advice here. I wasn't aware of the > name way of removing advice, that is pretty nice here, since we use a > changing anonymous function. > > yes it's nice right? > >> Otherwise, you need to figure out how to use something like a macro that > >> captures the current-buffer and creates a lambda function with that > >> information in it, and attaches it to the message-buffer hook somehow. > For > >> example this will display a message-box for me after the message is > sent. > >> > >> (let ((f `(lambda () > >> (message-box "Came from %s" ,(current-buffer))))) > >> (message-mail) > >> (add-hook 'kill-buffer-hook f nil t)) > >> > >> Some important notes is this hook is added in local mode, so it only > >> affects that email buffer. > >> > >> > > Can you explain to me what yo umean by "added in local mode" -- how is > that > > achieved? > > This is what the final t argument in the add-hood function does. I think > it makes the hook local to the buffer it runs in, as opposed to in every > buffer. > > OK thanks that's very helpful. I guess my problem was that there was no built-in hook that executed *after* mu4e~switch-back-to-buffer. Which is why I have had to learn about advice. > > > > Meanwhile, htis is what I've done and it seems to work: > > > > (eval (car (read-from-string > > (concat > > "(advice-add 'mu4e~switch-back-to-mu4e-buffer :after > > (lambda () > > (switch-to-buffer > > (get-buffer \"" > > (buffer-name) > > "\" )) > > (advice-remove > > 'mu4e~switch-back-to-mu4e-buffer \"om-temp-advice\")) > > '((name . \"om-temp-advice\")))")))) > > This is practically the same as my `, solution above, you just use > strings to protect some parts of code from evaluation, regular function > calls in places, and then you concat it all together and read it. The `, > syntax is optional, but without it you have to use list and quotes to > build up the code in a similar way: > > (let ((f (list > 'lambda () > (list 'message-box "Came from %s" (current-buffer))))) > (message-mail) > (add-hook 'kill-buffer-hook f nil t)) > > here the ' means treat something like a symbol, and don't evaluate it. > We build up the lambda expression using runtime information, e.g. what > is the current-buffer when the code is run. > cool to see the unquoted code here. thank you. > > > seems a little baroque. Maybe what you have there is way better. I don't > > really undertand backquotes and leading ocmmas even now. > > It takes some practice. Suppose you have some variables defined, e.g. > a=3, then here are two ways to make a list where you put the value of a > into the first place, and a symbol b in the second place. > > (list a 'b) => '(3 'b) > > `(,a b) => '(3 'b) > > This lets you build up expressions, including functions that are defined > at runtime. Lots of macros use this syntax to build up expressions that > are later evaluated. > > THanks for the tutorial, John, htis is veyr helpful. Now also maybe I will finally learn the difference between functions and macros. :-) --0000000000001bceb20578f831f0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


On Tue, Oct 23, 2018 at 4:34 PM John Kitchin <jkitchin@andrew.cmu.edu> wrote:

Matt Price <mopt= op99@gmail.com> writes:

> On Tue, Oct 23, 2018 at 2:32 PM John Kitchin <jkitchin@andrew.cmu.edu>
> wrote:
>
>> I think that what you really want to do here is modify org-mime-co= mpose so
>> that you can use the send-actions argument to message-mail. In
>> scimax-email.el I use that to be able to turn an org-heading into = an email,
>> send it, and then jump back to the heading to insert some informat= ion about
>> the email into the heading properties after it is sent. A lot of t= he
>> information gets passed via global variables. Maybe there is a bet= ter way
>> to do that, I wrote that code a long time ago.
>>
>>
> I'm trying to use mu4e~compose-mail instead of message-compose, I = guess
> mostly because I want to be able to use the mu4e email address complet= ion
> features in the `To:` header.=C2=A0 And it wouldalso be nice to save t= he email
> to the appropriate mu folder.=C2=A0 =C2=A0But I didn't seem to be = able to make mu4e
> bounce back to my buffer no matter what I do, and though mu4e~compose-= mail
> accepts a return-action argument it doesn't actually use it :-(.
This is kind of tricky. Here is an approach that seems to work:

(defun my-compose ()
=C2=A0(interactive)
=C2=A0(mu4e~compose-mail)
=C2=A0(advice-add 'mu4e~switch-back-to-mu4e-buffer :after
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0`(lambda ()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (switch-to-buffer (= get-buffer ,(buffer-name) ))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (advice-remove '= ;mu4e~switch-back-to-mu4e-buffer "om-temp-advice"))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'((name . "om-temp= -advice"))))

You just call M-x my-compose to get this behavior. I guess you could
advise mu4e~compose too to add the advice.

Right now I am adding my advice from inside of ~org-m= ime-org-*-htmlize~ in the org-mime code (which I guess you no longer use, s= ince you have written your own email handler). It seems to be a good place = for it & is minimally invasive to other packages.=C2=A0 Here's the = code ` code I attempted but which didn't work for me:

(advice-add 'mu4e~switch-back-to-mu4e-buffer :after
=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 (eval
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 `(lambda ()
=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 (switch-to-buffer (get-buffer ,(buffer-name) ))=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (advice-remove 'mu4e~switch-= back-to-mu4e-buffer "om-temp-advice")
=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 '((name . "om-temp-advice")=C2=A0 ))))
<= div>
Seems like maybe the problem fore me is the extra "= eval".=C2=A0 What maybe I don't understand is why the backquote wo= rks when the ordinary way to add an advice is the unquoted
<= br>
(advice-add 'sym (lambda () (message "I am an advice= "))

while IIUC yours should evaluate to
<= /div>

(advice-add 'sym '(lambda () (message &quo= t;I am an advice"))

There should be a differe= nce, shouldn't there?=C2=A0 But clearly I don't understand.=C2=A0 <= br>
=C2=A0
It seems necessary to use a temporary advice here. I wasn't aware of th= e
name way of removing advice, that is pretty nice here, since we use a
changing anonymous function.

yes it's nice right?=C2=A0
=C2=A0<= /div>
>> Otherwise, = you need to figure out how to use something like a macro that
>> captures the current-buffer and creates a lambda function with tha= t
>> information in it, and attaches it to the message-buffer hook some= how. For
>> example this will display a message-box for me after the message i= s sent.
>>
>> (let ((f `(lambda ()
>>=C2=A0 =C2=A0 =C2=A0(message-box "Came from %s" ,(current= -buffer)))))
>>=C2=A0 =C2=A0(message-mail)
>>=C2=A0 =C2=A0(add-hook 'kill-buffer-hook f nil t))
>>
>> Some important notes is this hook is added in local mode, so it on= ly
>> affects that email buffer.
>>
>>
> Can you explain to me what yo umean by "added in local mode"= -- how is that
> achieved?

This is what the final t argument in the add-hood function does. I think it makes the hook local to the buffer it runs in, as opposed to in every bu= ffer.


OK thanks that's very helpful. I g= uess my problem was that there was no built-in hook that executed *after* m= u4e~switch-back-to-buffer.
Which is why I have had to learn = about advice.
>
> Meanwhile, htis is what I've done and it seems to work:
>
> (eval (car (read-from-string
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(concat
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "(advice-add '= ;mu4e~switch-back-to-mu4e-buffer=C2=A0 :after
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(lambda ()
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(switch-to-buffer
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (get-buffer \""
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (buffer-name)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "\" ))
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(advice-remove
> 'mu4e~switch-back-to-mu4e-buffer \"om-temp-advice\")) >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'((name . \"om-temp-advice\"= ;)))"))))

This is practically the same as my `, solution above, you just use
strings to protect some parts of code from evaluation, regular function
calls in places, and then you concat it all together and read it. The `, syntax is optional, but without it you have to use list and quotes to
build up the code in a similar way:

(let ((f (list
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 'lambda ()
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (list 'message-box "Came from %= s" (current-buffer)))))
=C2=A0 (message-mail)
=C2=A0 (add-hook 'kill-buffer-hook f nil t))

here the ' means treat something like a symbol, and don't evaluate = it.
We build up the lambda expression using runtime information, e.g. what
is the current-buffer when the code is run.

=
cool to see the unquoted code here. thank you.

>
> seems a little baroque. Maybe what you have there is way better.=C2=A0= I don't
> really undertand backquotes and leading ocmmas even now.

It takes some practice. Suppose you have some variables defined, e.g.
a=3D3, then here are two ways to make a list where you put the value of a into the first place, and a symbol b in the second place.

(list a 'b)=C2=A0 =3D> '(3 'b)

`(,a b) =3D> '(3 'b)

This lets you build up expressions, including functions that are defined at runtime. Lots of macros use this syntax to build up expressions that
are later evaluated.
=C2=A0

THanks for the tutorial, John, htis is= veyr helpful. Now also maybe I will finally learn the difference between f= unctions and macros.=C2=A0 :-)

--0000000000001bceb20578f831f0--