emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* access a let* value whe ndefining a function?
@ 2018-10-23 17:40 Matt Price
  2018-10-23 18:31 ` John Kitchin
  0 siblings, 1 reply; 6+ messages in thread
From: Matt Price @ 2018-10-23 17:40 UTC (permalink / raw)
  To: Org Mode

[-- Attachment #1: Type: text/plain, Size: 596 bytes --]

Hey, I guess this is OT.

I'm trying to advice org-mime-org-buffer-htmlize so that it returns to the
org buffer when its done. I want to do something like this:

(let ((thisbuffer (current-buffer))
 (advice-add
     'mu4e-sent-handler
     :after (lambda (docid props)
              (switch-to-buffer thisbuffer)
              (advice-remove 'mu4e-sent-handler 'om-sent-advice)
              ) '((name . 'om-sent-advice)))

but by the time the hook is run, the (let) has long since lapsed, and
thisbuffer is no longer defined. Can I force evaluation of the variable
during definition?

Thanks,
m

[-- Attachment #2: Type: text/html, Size: 868 bytes --]

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

* Re: access a let* value whe ndefining a function?
  2018-10-23 17:40 access a let* value whe ndefining a function? Matt Price
@ 2018-10-23 18:31 ` John Kitchin
  2018-10-23 19:38   ` Matt Price
  0 siblings, 1 reply; 6+ messages in thread
From: John Kitchin @ 2018-10-23 18:31 UTC (permalink / raw)
  To: Matt Price; +Cc: org-mode-email

[-- Attachment #1: Type: text/plain, Size: 1936 bytes --]

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.

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.

John

-----------------------------------
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu



On Tue, Oct 23, 2018 at 1:40 PM Matt Price <moptop99@gmail.com> wrote:

> Hey, I guess this is OT.
>
> I'm trying to advice org-mime-org-buffer-htmlize so that it returns to the
> org buffer when its done. I want to do something like this:
>
> (let ((thisbuffer (current-buffer))
>  (advice-add
>      'mu4e-sent-handler
>      :after (lambda (docid props)
>               (switch-to-buffer thisbuffer)
>               (advice-remove 'mu4e-sent-handler 'om-sent-advice)
>               ) '((name . 'om-sent-advice)))
>
> but by the time the hook is run, the (let) has long since lapsed, and
> thisbuffer is no longer defined. Can I force evaluation of the variable
> during definition?
>
> Thanks,
> m
>

[-- Attachment #2: Type: text/html, Size: 2859 bytes --]

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

* Re: access a let* value whe ndefining a function?
  2018-10-23 18:31 ` John Kitchin
@ 2018-10-23 19:38   ` Matt Price
  2018-10-23 20:05     ` Matt Price
  2018-10-23 20:34     ` John Kitchin
  0 siblings, 2 replies; 6+ messages in thread
From: Matt Price @ 2018-10-23 19:38 UTC (permalink / raw)
  To: John Kitchin; +Cc: Org Mode

[-- Attachment #1: Type: text/plain, Size: 3283 bytes --]

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 :-(.


> 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?

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\")))"))))

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




> John
>
> -----------------------------------
> Professor John Kitchin
> Doherty Hall A207F
> Department of Chemical Engineering
> Carnegie Mellon University
> Pittsburgh, PA 15213
> 412-268-7803
> @johnkitchin
> http://kitchingroup.cheme.cmu.edu
>
>
>
> On Tue, Oct 23, 2018 at 1:40 PM Matt Price <moptop99@gmail.com> wrote:
>
>> Hey, I guess this is OT.
>>
>> I'm trying to advice org-mime-org-buffer-htmlize so that it returns to
>> the org buffer when its done. I want to do something like this:
>>
>> (let ((thisbuffer (current-buffer))
>>  (advice-add
>>      'mu4e-sent-handler
>>      :after (lambda (docid props)
>>               (switch-to-buffer thisbuffer)
>>               (advice-remove 'mu4e-sent-handler 'om-sent-advice)
>>               ) '((name . 'om-sent-advice)))
>>
>> but by the time the hook is run, the (let) has long since lapsed, and
>> thisbuffer is no longer defined. Can I force evaluation of the variable
>> during definition?
>>
>> Thanks,
>> m
>>
>

[-- Attachment #2: Type: text/html, Size: 5363 bytes --]

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

* Re: access a let* value whe ndefining a function?
  2018-10-23 19:38   ` Matt Price
@ 2018-10-23 20:05     ` Matt Price
  2018-10-23 20:34     ` John Kitchin
  1 sibling, 0 replies; 6+ messages in thread
From: Matt Price @ 2018-10-23 20:05 UTC (permalink / raw)
  To: John Kitchin; +Cc: Org Mode

[-- Attachment #1: Type: text/plain, Size: 3994 bytes --]

On Tue, Oct 23, 2018 at 3:38 PM Matt Price <moptop99@gmail.com> wrote:

>
>
> 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 :-(.
>
>
>> 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?
>
> 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\")))"))))
>
> seems a little baroque. Maybe what you have there is way better.  I don't
> really undertand backquotes and leading ocmmas even now.
>
>
> I'd think this owuld be equivalent but the advice removal isn't working:
(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")  ))))

the naming isn't being carried out succesfully.  I guess the regular
quoting works differnely inside a backquote or osmething?



>
>
>> John
>>
>> -----------------------------------
>> Professor John Kitchin
>> Doherty Hall A207F
>> Department of Chemical Engineering
>> Carnegie Mellon University
>> Pittsburgh, PA 15213
>> 412-268-7803
>> @johnkitchin
>> http://kitchingroup.cheme.cmu.edu
>>
>>
>>
>> On Tue, Oct 23, 2018 at 1:40 PM Matt Price <moptop99@gmail.com> wrote:
>>
>>> Hey, I guess this is OT.
>>>
>>> I'm trying to advice org-mime-org-buffer-htmlize so that it returns to
>>> the org buffer when its done. I want to do something like this:
>>>
>>> (let ((thisbuffer (current-buffer))
>>>  (advice-add
>>>      'mu4e-sent-handler
>>>      :after (lambda (docid props)
>>>               (switch-to-buffer thisbuffer)
>>>               (advice-remove 'mu4e-sent-handler 'om-sent-advice)
>>>               ) '((name . 'om-sent-advice)))
>>>
>>> but by the time the hook is run, the (let) has long since lapsed, and
>>> thisbuffer is no longer defined. Can I force evaluation of the variable
>>> during definition?
>>>
>>> Thanks,
>>> m
>>>
>>

[-- Attachment #2: Type: text/html, Size: 6722 bytes --]

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

* Re: access a let* value whe ndefining a function?
  2018-10-23 19:38   ` Matt Price
  2018-10-23 20:05     ` Matt Price
@ 2018-10-23 20:34     ` John Kitchin
  2018-10-24 11:58       ` Matt Price
  1 sibling, 1 reply; 6+ messages in thread
From: John Kitchin @ 2018-10-23 20:34 UTC (permalink / raw)
  To: Matt Price; +Cc: Org Mode


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.

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.

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

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

>
>
>
>
>> John
>>
>> -----------------------------------
>> Professor John Kitchin
>> Doherty Hall A207F
>> Department of Chemical Engineering
>> Carnegie Mellon University
>> Pittsburgh, PA 15213
>> 412-268-7803
>> @johnkitchin
>> http://kitchingroup.cheme.cmu.edu
>>
>>
>>
>> On Tue, Oct 23, 2018 at 1:40 PM Matt Price <moptop99@gmail.com> wrote:
>>
>>> Hey, I guess this is OT.
>>>
>>> I'm trying to advice org-mime-org-buffer-htmlize so that it returns to
>>> the org buffer when its done. I want to do something like this:
>>>
>>> (let ((thisbuffer (current-buffer))
>>>  (advice-add
>>>      'mu4e-sent-handler
>>>      :after (lambda (docid props)
>>>               (switch-to-buffer thisbuffer)
>>>               (advice-remove 'mu4e-sent-handler 'om-sent-advice)
>>>               ) '((name . 'om-sent-advice)))
>>>
>>> but by the time the hook is run, the (let) has long since lapsed, and
>>> thisbuffer is no longer defined. Can I force evaluation of the variable
>>> during definition?
>>>
>>> Thanks,
>>> m
>>>
>>


--
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu

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

* Re: access a let* value whe ndefining a function?
  2018-10-23 20:34     ` John Kitchin
@ 2018-10-24 11:58       ` Matt Price
  0 siblings, 0 replies; 6+ messages in thread
From: Matt Price @ 2018-10-24 11:58 UTC (permalink / raw)
  To: John Kitchin; +Cc: Org Mode

[-- Attachment #1: Type: text/plain, Size: 6061 bytes --]

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

[-- Attachment #2: Type: text/html, Size: 8457 bytes --]

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

end of thread, other threads:[~2018-10-24 12:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-10-23 17:40 access a let* value whe ndefining a function? Matt Price
2018-10-23 18:31 ` John Kitchin
2018-10-23 19:38   ` Matt Price
2018-10-23 20:05     ` Matt Price
2018-10-23 20:34     ` John Kitchin
2018-10-24 11:58       ` Matt Price

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

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