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

Matt Price <moptop99@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-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.  :-)