RE: Problem with let/cl-letf binding stuff with org-capture

2023-02-15 Thread arthur miller
Hemma thanks, for some reason, my Emacs does not display the link but it 
does for other functions. Strange.

Thanks for the help!


 Originalmeddelande 
Från: Bruno Barbier 
Datum: 2023-02-15 14:18 (GMT+01:00)
Till: Arthur Miller 
Kopia: Ihor Radchenko , emacs-orgmode@gnu.org
Ämne: Re: Problem with let/cl-letf binding stuff with org-capture

Arthur Miller  writes:

>
> Anyway, a follow question: Where is the source code?!

lisp/textmodes/string-edit.el

> Normally the help window says "... is a Lisp function in ."
>

My Emacs tells me it's an autoloaded function with the usual link.

Bruno



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-15 Thread Bruno Barbier
Arthur Miller  writes:

>
> Anyway, a follow question: Where is the source code?!

lisp/textmodes/string-edit.el

> Normally the help window says "... is a Lisp function in ."
>

My Emacs tells me it's an autoloaded function with the usual link.

Bruno




Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-15 Thread Arthur Miller
Ihor Radchenko  writes:

> Arthur Miller  writes:
>
>> Based on a Reddit thread:
>>
>> https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3
>>
>> I did a small experiment to see if I can re-use org-capture, to just capture 
>> a
>> string from a buffer, without actually writing to any file.
>
> You can use a template target set to function pointing to temporary
> buffer. + org-capture-before-finalize-hook

I did try something this:

#+begin_src emacs-lisp
(defun my-func ()
  (with-current-buffer (get-buffer-create "my-capture-buffer")))

(defun my-hook ()
  (with-current-buffer 
  (try-completion "CAPTURE" (mapcar #'buffer-name (buffer-list)))
(let ((content (buffer-string)))
  (kill-buffer)
  content)))

(defun my-read-string ()
  (let ((org-capture-templates
 `(("s" "string" plain (function my-func
(org-capture-before-finalize-hook #'my-hook))
(org-capture nil "s")))
#+end_src

But that does not work well, because capture will put buffer it is called from
as original buffer and write to that one. To prevent that I can call capture
from a temporary buffer:

#+begin_src emacs-lisp
(defun my-read-string ()
  (with-current-buffer (get-buffer-create "my-capture-buffer")
(let ((org-capture-templates
   `(("s" "string" plain (function ignore
  (org-capture-before-finalize-hook #'my-hook))
  (org-capture nil "s"
#+end_src

but than capture complains about the buffer not being a file buffer, despite the
before finalize hook. I could point it to some temp file like /tmp/my-capture, 
by
manipulating capture plist myself, but it seems to be too expensive to create a
temp file just for a hack to read a string form a buffer. There is probably some
other way, but I give up here, especially since you point our
read-string-from-buffer :)

Anyway, thanks for the input and help.

/a



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-13 Thread Bruno Barbier


Ihor Radchenko  writes:

> Note that Emacs 29 has `read-string-from-buffer'.

I completely missed the fact that it was already in Emacs.

I'll definitely use the string-edit version (the version
with callbacks).

Thanks Ihor.

Bruno



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-13 Thread Bruno Barbier
Arthur Miller  writes:

> Bruno Barbier  writes:
>
>>
>
> That looks very nice indeed. I am not aware of that package, I will definitely
> use it somewhere, sometime. But with that we are getting now into 1K extra 
> sloc
> solution. With this experiment, I was mostly interesting to see how I can 
> re-use
> what already is in Emacs. Lisps are great for prototyping and writing new
> software. Legend says that Steele was cranking out 10 intepreters a week at 
> his
> time :). I don't know how true it is, just read it in some blog, but the
> point is that we are rather typing fast new pieces instead of learning how
> to re-use stuff, which in the long run I believe is a bad habit, since we are
> debugging bits that does the same what someone else already debugged. Don't 
> get
> me wrong, I have nothing against using someones package, certainly not
> with-editor, seems like a good package; I am just talking about programming in
> general.

... And the piece of code, that I just wrote and sent, was already
available in Emacs (see Ihor's email). I've definitely failed to do my
research before coding ... I definitely get your point! :-)

> This was also me trying to get better in Emacs Lisp, but I have to admit I am 
> a
> bit dissapointed we can't just override function bindings with cl-flet. 
> Function
> slot is just another slot :).
>
> I am using cl-labels and cl-flet myself to introduce "local" functions, to not
> pollute global namespace (symbol table), which they are good for, and to keep
> code local where it is used, and I think they are also slightly more clear 
> then
> lambdas. They are good for that, unfortunately it is a bit of dissapoitment 
> that
> we can't locally bind functions slots other then actually overriding them 
> globally.

Since I've learned that cl-flet and cl-labels are local lexically, I'm
using them more and more: that removes lot of noisy funcalls, compare to
lambdas.


> And for the last time: I am not using this version of read-string, I don't 
> need
> it myself; it was just me thinking how to implement something after reading a
> blog post. Anyway, thanks for the input, it was valuable to me.

Got it. Thanks for your patience and your valuable inputs too.

And I'm definitely going to use the version that is in Emacs. Thanks for
this too.

best,

Bruno



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-12 Thread Ihor Radchenko
Arthur Miller  writes:

> And for the last time: I am not using this version of read-string, I don't 
> need
> it myself; it was just me thinking how to implement something after reading a
> blog post. Anyway, thanks for the input, it was valuable to me.

Note that Emacs 29 has `read-string-from-buffer'.
 
-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at .
Support Org development at ,
or support my work at 



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-12 Thread Arthur Miller
Bruno Barbier  writes:

> Hi Arthur,
>
> Arthur Miller  writes:
>
>> Bruno Barbier  writes:
>>
>> ...  but I feel a
>> bit of passive aggressivity here, for no good reason tbh.
>
> I'm just trying to help, giving some valid or invalid advices.  I'm
> sorry that what I wrote, and how I wrote it, made you feel that way.

It is ok, I just don't want us to go into social media discussion style where
there is more important to assert own ego then to come into some insight.

>>>
>>> Yes, let binding is fundamental. But I think it's the first time I see
>>> 'cl-letf' with the 'symbol-function' place.
>>
>> https://nullprogram.com/blog/2017/10/27/
>> https://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html
>> https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf
>>
>
> Thanks for these links. I like cl-flet and cl-labels :-)

They are good for introducing *new* bindings, not so for overriding locally.

 but I am not sure if I can do anything here without introducing at-least an
 extra keymap, to not install into the org-capture-mode-map, so I can as 
 well
 create a minor mode, but at this point it is not much different than
 re-invinting the read-string, so I'll terminate my experiment here :).
>>>
>>> You can replace the buffer keymap with a keymap that only contain your 
>>> custom
>>> keys, and inherits everything else from org-capture-mode-map.
>>
>> Isn't that what I wrote: introducing an extra keymap?
>> Of course I can solve the problem differently, but that was not what question
>> was about :).
>
> Right. Even when inheriting from the old keymap, it's still building a
> new keymap.  Sorry :-)
>
>
>> Well, I definitely understand you, and agree that overwriting function for
>> everyone and everything is not the best idea, but unfortunately bindings 
>> work as
>> they do in Emacs. I would prefer to have a local binding, with cl-flet, but 
>> this
>> does not work in Emacs:
>>
>> (defun my-read-string (prompt)
>>   (let ((delta 20 )
>> (minibuffer-mode-map org-mode-map))
>> (window-resize (minibuffer-window) delta)
>> (cl-flet ((org-ctrl-c-ctrl-c ()
>> (interactive)
>> (let ((s (buffer-string)))
>>   (exit-minibuffer) s))
>>   (minibuffer-mode () #'org-mode)
>>   (minibuffer-complete-and-exit () #'org-return)
>>   (org-kill-note-or-show-branches () #'keyboard-escape-quit))
>>   (read-string (concat "# Press C-c C-c to continue, C-c C-k to 
>> cancel\n# "
>>   prompt "\n\n")
>
> Yes. cl-flet looks safe to me :-)
>
>>
>> Hooks serve a different purpose. Advice can serve same purpose with exactly
>> same side effect, and some other limitations. With some care, let-binding is
>> still more "local" then advice. With other words, I agree with you about the
>> problems, but not with dogmatic approach that it should never be done, and
>> that hooks and advices are the replacement.
>
> Sorry if my words sounding dogmatic.
> Else, I agree too :-)
>
>
>>>
 I am very interested to hear more on the topic, since I would definitely 
 like to
 learn more about different techniques.
>>>
>>> Variables are designed to be overriden (let bounds). Functions are not
>>
>> I have never heard before that functions are not designed to be overriden. I
>> think of them as two slots in a symbol structure; let creates bindings for 
>> value
>> slot, and flet for function slot. Functions are just objects or data as any
>> other value in lisp.
>>
>>> (as there is only one binding at any given time).
>>
>> Yes, unfortunately, in Emacs it is so;
>
> ok. We do really agree then :-)
>
>
>> but I don't think it should be > :).
>
> ... oh no ! ;-)
>
>
>>
>> There is an interesting package by Nick Ferrier
>>
>> https://github.com/nicferrier/emacs-noflet
>
>> but it does not seem to work, at least not for me.
>
> It's almost like a temporary advice ;-)
>
>
> About your use case, if what you need is asynchronous editing, maybe the
> with-editor package will be of interest to you:
> https://github.com/magit/with-editor/blob/main/lisp/with-editor.el
> 
> It allows sub-processes to call Emacs for editing tasks. It's used by
> magit. It's easy enough to reuse. I've attached my attempt at it if
> you're interested.
>
> best,
>
> Bruno
>
> (cl-defun my-edit-async (finish  mode buffer-name setup cancel)
>   "Open a buffer, let the user edit its content.
> Return the editing buffer.  Call FINISH in the editing buffer if
> the user validates his edit (C-c C-c).  When CANCEL is non-nil,
> call CANCEL in the editing buffer if the user cancels his
> edit (C-c C-k). When done, delete the buffer and its content.
>
> When MODE is non-nil, use it as the major-mode.  When BUFFER-NAME
> is non-nil, use it to generate a new unique name of the editing buffer.
> When SETUP is non-nil, call it in the edit buffer to setup the
> buffer before starting 

Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-12 Thread Bruno Barbier

Hi Arthur,

Arthur Miller  writes:

> Bruno Barbier  writes:
>
> ...  but I feel a
> bit of passive aggressivity here, for no good reason tbh.

I'm just trying to help, giving some valid or invalid advices.  I'm
sorry that what I wrote, and how I wrote it, made you feel that way.

>>
>> Yes, let binding is fundamental. But I think it's the first time I see
>> 'cl-letf' with the 'symbol-function' place.
>
> https://nullprogram.com/blog/2017/10/27/
> https://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html
> https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf
>

Thanks for these links. I like cl-flet and cl-labels :-)


>>> but I am not sure if I can do anything here without introducing at-least an
>>> extra keymap, to not install into the org-capture-mode-map, so I can as well
>>> create a minor mode, but at this point it is not much different than
>>> re-invinting the read-string, so I'll terminate my experiment here :).
>>
>> You can replace the buffer keymap with a keymap that only contain your custom
>> keys, and inherits everything else from org-capture-mode-map.
>
> Isn't that what I wrote: introducing an extra keymap?
> Of course I can solve the problem differently, but that was not what question
> was about :).

Right. Even when inheriting from the old keymap, it's still building a
new keymap.  Sorry :-)


> Well, I definitely understand you, and agree that overwriting function for
> everyone and everything is not the best idea, but unfortunately bindings work 
> as
> they do in Emacs. I would prefer to have a local binding, with cl-flet, but 
> this
> does not work in Emacs:
>
> (defun my-read-string (prompt)
>   (let ((delta 20 )
> (minibuffer-mode-map org-mode-map))
> (window-resize (minibuffer-window) delta)
> (cl-flet ((org-ctrl-c-ctrl-c ()
> (interactive)
> (let ((s (buffer-string)))
>   (exit-minibuffer) s))
>   (minibuffer-mode () #'org-mode)
>   (minibuffer-complete-and-exit () #'org-return)
>   (org-kill-note-or-show-branches () #'keyboard-escape-quit))
>   (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# 
> "
>   prompt "\n\n")

Yes. cl-flet looks safe to me :-)

>
> Hooks serve a different purpose. Advice can serve same purpose with exactly
> same side effect, and some other limitations. With some care, let-binding is
> still more "local" then advice. With other words, I agree with you about the
> problems, but not with dogmatic approach that it should never be done, and
> that hooks and advices are the replacement.

Sorry if my words sounding dogmatic.
Else, I agree too :-)


>>
>>> I am very interested to hear more on the topic, since I would definitely 
>>> like to
>>> learn more about different techniques.
>>
>> Variables are designed to be overriden (let bounds). Functions are not
>
> I have never heard before that functions are not designed to be overriden. I
> think of them as two slots in a symbol structure; let creates bindings for 
> value
> slot, and flet for function slot. Functions are just objects or data as any
> other value in lisp.
>
>> (as there is only one binding at any given time).
>
> Yes, unfortunately, in Emacs it is so;

ok. We do really agree then :-)


> but I don't think it should be > :).

... oh no ! ;-)


>
> There is an interesting package by Nick Ferrier
>
> https://github.com/nicferrier/emacs-noflet

> but it does not seem to work, at least not for me.

It's almost like a temporary advice ;-)


About your use case, if what you need is asynchronous editing, maybe the
with-editor package will be of interest to you:
https://github.com/magit/with-editor/blob/main/lisp/with-editor.el

It allows sub-processes to call Emacs for editing tasks. It's used by
magit. It's easy enough to reuse. I've attached my attempt at it if
you're interested.

best,

Bruno

(cl-defun my-edit-async (finish  mode buffer-name setup cancel)
  "Open a buffer, let the user edit its content.
Return the editing buffer.  Call FINISH in the editing buffer if
the user validates his edit (C-c C-c).  When CANCEL is non-nil,
call CANCEL in the editing buffer if the user cancels his
edit (C-c C-k). When done, delete the buffer and its content.

When MODE is non-nil, use it as the major-mode.  When BUFFER-NAME
is non-nil, use it to generate a new unique name of the editing buffer.
When SETUP is non-nil, call it in the edit buffer to setup the
buffer before starting the edit."
  (unless buffer-name (setq buffer-name "@Async edit"))
  (let ((buf (generate-new-buffer buffer-name)))
(with-current-buffer buf
  (when mode (funcall mode))
  (when setup
(funcall setup))
  (with-editor-mode 1)
  (setq with-editor-previous-winconf
(current-window-configuration))
  (add-hook 'with-editor-pre-finish-hook
(lambda () 
  

Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-11 Thread Arthur Miller
Bruno Barbier  writes:

> Arthur Miller  writes:
>
>> Bruno Barbier  writes:
>>
>>> Arthur Miller  writes:
>>>
>>> The hook `org-capture-mode-hook' will be run in your special
>>> capture buffer. You can override the "C-c C-c" binding only there.
>>
>> Yes and in every other capture buffer
>
> No. If you modify the hook only during your call to 'org-capture', it
> will be called only once in your buffer.
>
>>> Even if I could let bind the function at the right time, I would avoid
>>> that solution, as I can't garantuee that this global hack will not break
>>> other parts of Emacs (other captures, output filters, threads, timers,
>>> etc.).
>>
>> Why do you think it will break other parts? This is not a global hack, on 
>> contrary it
>> exactly tries to prevent to be "global" in entire Emacs, by let-binding a 
>> name
>> to a local lambda, which becomes "global" only in that buffer. If that
>> explains.
>
> You are assigning a local value to the global binding. Everything in
> Emacs will use your functions until you exit the cl-letf. It's like if
> you were using 'fset'.

Yes, you are totally correct; unfortunately binding with cl-flet or cl-labels,
does not work, so binding the global is the only one that works.

> Here is an example that uses cl-letf. Note that the call to
> async-shell-command is outside the "local" binding, yet, the cl-letf
> breaks it. You should try this in an other Emacs, just in case.
>
> (defun oops ()
>   (let ((v (async-shell-command "date" "!sh async")))
> (cl-letf
> (((symbol-function 'comint-output-filter)
>   (lambda (proc string)
> (message "async-shell-command is using my binding: %s" string)
> (read-string "What's the password?"
>   (read-string "what: ")
>   )))
> (oops)

Yes, I definitely agree with you about the concerns, which are certainly
valid, but you would get same effect with advice, it is not different at
all. The difference is that let-binding is automatically removed and installed,
and only active during the cl-letf, while advice is manually installed and
active until manually removed. It is not about the tool, but what you do with
the tool.

>> Here is another version on the same theme, where I don't think you could 
>> modify the local
>> environment without let-binding at all:
>>
>> #+begin_src emacs-lisp
>> (defun my-read-string (prompt)
>>   (let ((delta 20 )
>> (minibuffer-mode-map org-mode-map))
>> (window-resize (minibuffer-window) delta)
>> (cl-letf (((symbol-function 'org-ctrl-c-ctrl-c)
>>(lambda ()
>>  (interactive)
>>  (let ((s (buffer-string)))
>>(exit-minibuffer) s)))
>>   ((symbol-function 'minibuffer-mode) #'org-mode)
>>   ((symbol-function 'minibuffer-complete-and-exit) #'org-return)
>>   ((symbol-function 'org-kill-note-or-show-branches) 
>> #'keyboard-escape-quit))
>>   (read-string (concat "# Press C-c C-c to continue, C-c C-k to 
>> cancel\n# " prompt "\n\n")
>> #+end_src
>
> I hope I've convinced you to not do that. I definitely will not try it,
> as Emacs needs a working minibuffer for plenty of things: debugging,
> saving, quitting, etc.

Your minibuffer will continue to work during and after that function. If you
don't use recursive minibuffer, that will only affect the internal buffer
created by read-string.

If recursive minibuffer is enabled, yes they will also be affected. Of course,
there is no reason for you to try that, that was just an example, but I feel a
bit of passive aggressivity here, for no good reason tbh.

>> read-string is written in C and creates its own minibuffer, which is deleted 
>> by
>> the time read-string exits. I don't know of any other way to cutomize exactly
>> *that* minibuffer, without installing a hook or advising some functions, 
>> which I
>> think is way less clean and much more "global" than just running the 
>> function in
>> a local environment. As I understand, let binding for this purpose is a 
>> normal
>> technique in lisps, but I am not an expert as said; I am actually 
>> experimenting
>> with this for the purpose of learning and seeing what is possible.
>
> Yes, let binding is fundamental. But I think it's the first time I see
> 'cl-letf' with the 'symbol-function' place.

https://nullprogram.com/blog/2017/10/27/
https://endlessparentheses.com/understanding-letf-and-how-it-replaces-flet.html
https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf

>> but I am not sure if I can do anything here without introducing at-least an
>> extra keymap, to not install into the org-capture-mode-map, so I can as well
>> create a minor mode, but at this point it is not much different than
>> re-invinting the read-string, so I'll terminate my experiment here :).
>
> You can replace the buffer keymap with a keymap that only contain your custom
> keys, and inherits everything 

Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-11 Thread Bruno Barbier
Arthur Miller  writes:

> Bruno Barbier  writes:
>
>> Arthur Miller  writes:
>>
>> The hook `org-capture-mode-hook' will be run in your special
>> capture buffer. You can override the "C-c C-c" binding only there.
>
> Yes and in every other capture buffer

No. If you modify the hook only during your call to 'org-capture', it
will be called only once in your buffer.

>> Even if I could let bind the function at the right time, I would avoid
>> that solution, as I can't garantuee that this global hack will not break
>> other parts of Emacs (other captures, output filters, threads, timers,
>> etc.).
>
> Why do you think it will break other parts? This is not a global hack, on 
> contrary it
> exactly tries to prevent to be "global" in entire Emacs, by let-binding a name
> to a local lambda, which becomes "global" only in that buffer. If that
> explains.

You are assigning a local value to the global binding. Everything in
Emacs will use your functions until you exit the cl-letf. It's like if
you were using 'fset'.

Here is an example that uses cl-letf. Note that the call to
async-shell-command is outside the "local" binding, yet, the cl-letf
breaks it. You should try this in an other Emacs, just in case.

(defun oops ()
  (let ((v (async-shell-command "date" "!sh async")))
(cl-letf
(((symbol-function 'comint-output-filter)
  (lambda (proc string)
(message "async-shell-command is using my binding: %s" string)
(read-string "What's the password?"
  (read-string "what: ")
  )))
(oops)


>
> Here is another version on the same theme, where I don't think you could 
> modify the local
> environment without let-binding at all:
>
> #+begin_src emacs-lisp
> (defun my-read-string (prompt)
>   (let ((delta 20 )
> (minibuffer-mode-map org-mode-map))
> (window-resize (minibuffer-window) delta)
> (cl-letf (((symbol-function 'org-ctrl-c-ctrl-c)
>(lambda ()
>  (interactive)
>  (let ((s (buffer-string)))
>(exit-minibuffer) s)))
>   ((symbol-function 'minibuffer-mode) #'org-mode)
>   ((symbol-function 'minibuffer-complete-and-exit) #'org-return)
>   ((symbol-function 'org-kill-note-or-show-branches) 
> #'keyboard-escape-quit))
>   (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# 
> " prompt "\n\n")
> #+end_src

I hope I've convinced you to not do that. I definitely will not try it,
as Emacs needs a working minibuffer for plenty of things: debugging,
saving, quitting, etc.


> read-string is written in C and creates its own minibuffer, which is deleted 
> by
> the time read-string exits. I don't know of any other way to cutomize exactly
> *that* minibuffer, without installing a hook or advising some functions, 
> which I
> think is way less clean and much more "global" than just running the function 
> in
> a local environment. As I understand, let binding for this purpose is a normal
> technique in lisps, but I am not an expert as said; I am actually 
> experimenting
> with this for the purpose of learning and seeing what is possible.

Yes, let binding is fundamental. But I think it's the first time I see
'cl-letf' with the 'symbol-function' place.


> ...
> but I am not sure if I can do anything here without introducing at-least an
> extra keymap, to not install into the org-capture-mode-map, so I can as well
> create a minor mode, but at this point it is not much different than
> re-invinting the read-string, so I'll terminate my experiment here :).

You can replace the buffer keymap with a keymap that only contain your custom
keys, and inherits everything else from org-capture-mode-map.


>
> But I wouldn't speak in some generic terms like "use hooks" or "advise" 
> instead
> of let-binding.

I didn't mean to say to not use let bindings. I'm trying to say that
using 'fset' (i.e. cl-letf + the symbol-function place) looks like a
really bad idea to me. And, in this case, hooks and adivces are what is
usually used.



> (defun org-project-new-project ()
>   (interactive)
>   (let ((org-capture-templates org-project-templates))
> (org-capture)))
>
> ...

> I don't know what would be the alternative, but let-binding on
> org-capture-templates, let me clearly re-use the functionality without 
> polluting
> the global org-capture-templates variable and without re-implementing pretty
> much anything.

That looks to me like a perfect use of a let binding.  You bind a dynamic
*variable* using *let*, and, that variable is rebound, and used, during, and
only during 'org-capture'.



> I am very interested to hear more on the topic, since I would definitely like 
> to
> learn more about different techniques.

Variables are designed to be overriden (let bounds). Functions are not
(as there is only one binding at any given time).


> Hope that explains a bit more on the background of the experiment :).

I'm still confused about the 

Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-11 Thread Ihor Radchenko
Arthur Miller  writes:

> Based on a Reddit thread:
>
> https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3
>
> I did a small experiment to see if I can re-use org-capture, to just capture a
> string from a buffer, without actually writing to any file.

You can use a template target set to function pointing to temporary
buffer. + org-capture-before-finalize-hook

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at .
Support Org development at ,
or support my work at 



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-11 Thread Arthur Miller
Bruno Barbier  writes:

> Arthur Miller  writes:
>
>>> Bruno Barbier  writes:
>>> If you really want to just get the piece of text, you might be able to
>>> use the hook `org-capture-mode-hook' to replace the key binding to
>>> 'C-c C-c' in the capture buffer, so that it calls your own function that
>>> will take the string and call `org-capture-kill'.
>>
>> In this case you wouldn't like to replace the key binding, it would affect 
>> all
>> org-capture buffers; the point is just to replace it when called in certain
>> context (my-read-line). Let-binding the function in this context achieves
>> exactly the same effect of C-c C-c beng bound to my function but without
>> affecting all org-capture-buffers.
>
> The hook `org-capture-mode-hook' will be run in your special
> capture buffer. You can override the "C-c C-c" binding only there.

Yes and in every other capture buffer, so I would either have to test on some
variable, make another mode, or mode-map or something similar. Just to customize
on the key, instead of the value bound to that key.

>>
>> Yes, I am aware of both hooks and advising; but again, with those I would 
>> affect
>> all uses of the function, and that would lead to checking some global state 
>> or
>> variable to switch on, which is not optimal either. With let-binding we can 
>> have
>> different behaviour only in a certain context.
>
> Even if I could let bind the function at the right time, I would avoid
> that solution, as I can't garantuee that this global hack will not break
> other parts of Emacs (other captures, output filters, threads, timers,
> etc.).

Why do you think it will break other parts? This is not a global hack, on 
contrary it
exactly tries to prevent to be "global" in entire Emacs, by let-binding a name
to a local lambda, which becomes "global" only in that buffer. If that
explains.

Here is another version on the same theme, where I don't think you could modify 
the local
environment without let-binding at all:

#+begin_src emacs-lisp
(defun my-read-string (prompt)
  (let ((delta 20 )
(minibuffer-mode-map org-mode-map))
(window-resize (minibuffer-window) delta)
(cl-letf (((symbol-function 'org-ctrl-c-ctrl-c)
   (lambda ()
 (interactive)
 (let ((s (buffer-string)))
   (exit-minibuffer) s)))
  ((symbol-function 'minibuffer-mode) #'org-mode)
  ((symbol-function 'minibuffer-complete-and-exit) #'org-return)
  ((symbol-function 'org-kill-note-or-show-branches) 
#'keyboard-escape-quit))
  (read-string (concat "# Press C-c C-c to continue, C-c C-k to cancel\n# " 
prompt "\n\n")
#+end_src

read-string is written in C and creates its own minibuffer, which is deleted by
the time read-string exits. I don't know of any other way to cutomize exactly
*that* minibuffer, without installing a hook or advising some functions, which I
think is way less clean and much more "global" than just running the function in
a local environment. As I understand, let binding for this purpose is a normal
technique in lisps, but I am not an expert as said; I am actually experimenting
with this for the purpose of learning and seeing what is possible.

Of course, we can always write our own read-string function and re-implement the
function from scratch, which author of that blog actually did. The experiment
was to test if I can modify the existing functionality to re-use, rather than to
re-invent something. Since read-string functions does not let us specify buffer,
mode, etc, let binding is one way of doing it locally.

Considering how org-capture works, the same technique of just modifying the
local environment is not really applicable; now when you reminded me that
capture buffer lives longer then let-binding, I understand what happens. I can
access the buffer after org-capture exits, in my-read-string:

(with-current-buffer
(try-completion "CAPTURE" (mapcar #'buffer-name (buffer-list)))
 (  do the thng  )

but I am not sure if I can do anything here without introducing at-least an
extra keymap, to not install into the org-capture-mode-map, so I can as well
create a minor mode, but at this point it is not much different than
re-invinting the read-string, so I'll terminate my experiment here :).

But I wouldn't speak in some generic terms like "use hooks" or "advise" instead
of let-binding. Let binding is a powerful and legitimate technique to modify
local environment of functions. I am not really sure where it stands in
abstraction, if it is sort-of template, or interface programming, since I am not
that familiar with lisp (yet), but I do understand it has very good and powerful
uses. Consider this (you can actually eval an run from gnus, or in scartch):

#+begin_src emacs-lisp
 Project folder - org-capture related code
(defvar org-project-root-dir nil)
(defvar org-project-templates nil)
(defvar org-project-finalize-hooks nil)

(setq 

Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-10 Thread Bruno Barbier
Arthur Miller  writes:

>> Bruno Barbier  writes:
>> If you really want to just get the piece of text, you might be able to
>> use the hook `org-capture-mode-hook' to replace the key binding to
>> 'C-c C-c' in the capture buffer, so that it calls your own function that
>> will take the string and call `org-capture-kill'.
>
> In this case you wouldn't like to replace the key binding, it would affect all
> org-capture buffers; the point is just to replace it when called in certain
> context (my-read-line). Let-binding the function in this context achieves
> exactly the same effect of C-c C-c beng bound to my function but without
> affecting all org-capture-buffers.

The hook `org-capture-mode-hook' will be run in your special
capture buffer. You can override the "C-c C-c" binding only there.

>
> Yes, I am aware of both hooks and advising; but again, with those I would 
> affect
> all uses of the function, and that would lead to checking some global state or
> variable to switch on, which is not optimal either. With let-binding we can 
> have
> different behaviour only in a certain context.

Even if I could let bind the function at the right time, I would avoid
that solution, as I can't garantuee that this global hack will not break
other parts of Emacs (other captures, output filters, threads, timers,
etc.).

>
> Anyway, thanks, I needed the reminder above.

You're welcome.

Bruno




Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-10 Thread Arthur Miller
Bruno Barbier  writes:

> Arthur Miller  writes:
>
>> However I see that the binding for the org-capture-finalizer, in capture 
>> buffer,
>> is still the default 'org-capture--default-finalize' and not my lambda.
>>
>> I am really not an expert on emacs lisp; and I do understand that this is
>> somewhat "creative" use of org-capture (to put it nicely :-)), but I would 
>> like
>> to understand what is going on here.
>>
>> I don't understand why let-binding here does not work?
>
> Your bindings probably work. But, as the function `org-capture'
> just *starts* the capture process, they are removed when exiting the
> 'let', before you even begin editing your capture.

Yes of course :) I am quite aware that org-capture just setups the buffer, and
that org-capture-finalize finnishes by writing stuff to files etc, and yet I
have tottally forgott it when writing this. This for opening my eyes.

> I'm not sure I understand your use case:  if you have a piece
> of org text, you can put it anywhere (possibly using refiling).

it is just a fun test. I wouldn't do that myself normally and I have no idea why
the blog author needs it either. If I wanted to input multiline
text into some dokument I would open dokument itself. But this was just a
thought I am testing; you can read in the link I posted in the first mail.

> If you really want to just get the piece of text, you might be able to
> use the hook `org-capture-mode-hook' to replace the key binding to
> 'C-c C-c' in the capture buffer, so that it calls your own function that
> will take the string and call `org-capture-kill'.

In this case you wouldn't like to replace the key binding, it would affect all
org-capture buffers; the point is just to replace it when called in certain
context (my-read-line). Let-binding the function in this context achieves
exactly the same effect of C-c C-c beng bound to my function but without
affecting all org-capture-buffers.

>You can usually use hooks (like `org-capture-mode-hook'):
>   (info "(elisp) Hooks")
>
> or, if it's not possible, you can advise the functions:
>
>   (info "(elisp) Advising Functions")

Yes, I am aware of both hooks and advising; but again, with those I would affect
all uses of the function, and that would lead to checking some global state or
variable to switch on, which is not optimal either. With let-binding we can have
different behaviour only in a certain context.

Anyway, thanks, I needed the reminder above.

cheers
/arthur



Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-10 Thread Bruno Barbier
Arthur Miller  writes:

> However I see that the binding for the org-capture-finalizer, in capture 
> buffer,
> is still the default 'org-capture--default-finalize' and not my lambda.
>
> I am really not an expert on emacs lisp; and I do understand that this is
> somewhat "creative" use of org-capture (to put it nicely :-)), but I would 
> like
> to understand what is going on here.
>
> I don't understand why let-binding here does not work?

Your bindings probably work. But, as the function `org-capture'
just *starts* the capture process, they are removed when exiting the
'let', before you even begin editing your capture.

I'm not sure I understand your use case:  if you have a piece
of org text, you can put it anywhere (possibly using refiling).

If you really want to just get the piece of text, you might be able to
use the hook `org-capture-mode-hook' to replace the key binding to
'C-c C-c' in the capture buffer, so that it calls your own function that
will take the string and call `org-capture-kill'.

Note that they are safer way to modify Emacs behavior than overwriting
the functions. You can usually use hooks (like `org-capture-mode-hook'):

  (info "(elisp) Hooks")

or, if it's not possible, you can advise the functions:

  (info "(elisp) Advising Functions")


Bruno









Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-10 Thread Arthur Miller
Ruijie Yu  writes:

> Hi Arthur,
>
> Please excuse my brevity and semi-random line of thought, as I’m replying on 
> mobile right now.  See below. 
>
>> On Feb 10, 2023, at 23:11, Arthur Miller  wrote:
>> 
>> 
>> Based on a Reddit thread:
>> 
>> https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3
>> 
>> I did a small experiment to see if I can re-use org-capture, to just capture 
>> a
>> string from a buffer, without actually writing to any file.
>> 
>> My plan was to just let-bind org-capture-finalize with cl-letf:
>> 
>> #+begin_src emacs-lisp
>> (defun my-read-string ()
>> (cl-letf (((symbol-function 'org-capture-finalize) ;; C-c C-c
>>   (lambda ( _) (interactive "P") (buffer-string)))
>>  ((symbol-function 'org-kill-note-or-show-branches) #'kill-buffer)) 
>> ;; C-c C-k
>>  (let ((org-capture-templates '(("s" "string" plain (function ignore)
>>(org-capture nil "s"
>> #+end_src
>
> Based on my somewhat-limited experience with CL (and elisp), I have never seen
> this particular type of letf structure.  What I am used to seeing and writing 
> is
> the following:

It uses "place" or "field" to set the symbol binding, as in setf or incf.

You can read more on SX:

https://stackoverflow.com/questions/39550578/in-emacs-what-is-the-difference-between-cl-flet-and-cl-letf

> (cl-letf ((f (x) (1+ x))
>(1+ (f 2)))
> ; => 4
>
> In particular, IIUC, I don’t think you would need symbol-function here.  Maybe
> you can learn more from the docstring of cl-letf than me trying to drain my
> memory on this topic without reference.
>
> Also, in the code snippet you provided, what *should* org-capture-finalize 
> be?  A function that can be called like this:
>
>(org-capture-finalize arg1 arg2)
>
> ? Or a variable containing a function (reference) that can be called like 
> this:
>
>(funcall org-capture-finalize arg1 arg2)
>
> ?  In the former case you might be able to use cl-letf, and in the latter 
> case you should use let with a lambda value. 
>
>> Unfortunately, that does not work. Regardless of binding, and if I used 
>> cl-letf
>> or cl-flet or cl-labels, or old let, or something brewed on the internet, the
>> binding org-capture see for org-capture-finalize, is the original one from
>> org-capture.el.
>> 
>> My second experiment was to abstract the finalize function into a funcallable
>> fariable in org-capture.el (I have patched org-capture.el with this):
>> 
>> #+begin_src emacs-lisp
>> (defvar org-capture-finalizer #'org-capture--default-finalize)
>> 
>> (defun org-capture-finalize ( stay-with-capture)
>> "Finalize the capture process.
>> With prefix argument STAY-WITH-CAPTURE, jump to the location of the
>> captured item after finalizing."
>> (interactive "P")
>> (funcall org-capture-finalizer stay-with-capture))
>> 
>> 
>> (defun org-capture--default-finalize ( stay-with-capture)
>> "Default implementation for org-capture finalizer function."
>> 
>> ;; this is the original org-capture-finalize just renamed to 
>> "default-finalize"
>> )
>> #+end_src
>> 
>> So I could then have something like this (never mind C-c C-k function being
>> removed):
>> 
>> #+begin_src emacs-lisp
>> (defun my-read-string ()
>> (let ((org-capture-templates '(("s" "string" plain (function ignore
>>  (org-capture-finalizer
>>   (lambda ( _) (interactive "P") (buffer-string
>>  (org-capture nil "s")))
>> #+end_src
>> 
>> However I see that the binding for the org-capture-finalizer, in capture 
>> buffer,
>> is still the default 'org-capture--default-finalize' and not my lambda.
>
> I guess this answers part of my question in my previous paragraph.  Is
> org-capture-finalizer defined via defvar?  If so, does it help if you put an
> empty defvar before the let binding?  If not, maybe someone actually using 
> Emacs
> right now can be of more help here.

These were two different examples; one that let-binds the function
'org-caputre-finalize', via cl-letf and the latter one that was completely
different in which I have defvared a symbol so I can let-bind it as a variable.

>   If not, maybe someone actually using 
> Emacs
> right now can be of more help here.

Don't worry; thanks for the help anyway!

/a





Re: Problem with let/cl-letf binding stuff with org-capture

2023-02-10 Thread General discussions about Org-mode.
Hi Arthur,

Please excuse my brevity and semi-random line of thought, as I’m replying on 
mobile right now.  See below. 

> On Feb 10, 2023, at 23:11, Arthur Miller  wrote:
> 
> 
> Based on a Reddit thread:
> 
> https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3
> 
> I did a small experiment to see if I can re-use org-capture, to just capture a
> string from a buffer, without actually writing to any file.
> 
> My plan was to just let-bind org-capture-finalize with cl-letf:
> 
> #+begin_src emacs-lisp
> (defun my-read-string ()
> (cl-letf (((symbol-function 'org-capture-finalize) ;; C-c C-c
>   (lambda ( _) (interactive "P") (buffer-string)))
>  ((symbol-function 'org-kill-note-or-show-branches) #'kill-buffer)) 
> ;; C-c C-k
>  (let ((org-capture-templates '(("s" "string" plain (function ignore)
>(org-capture nil "s"
> #+end_src

Based on my somewhat-limited experience with CL (and elisp), I have never seen 
this particular type of letf structure.  What I am used to seeing and writing 
is the following:

(cl-letf ((f (x) (1+ x))
   (1+ (f 2)))
; => 4

In particular, IIUC, I don’t think you would need symbol-function here.  Maybe 
you can learn more from the docstring of cl-letf than me trying to drain my 
memory on this topic without reference. 

Also, in the code snippet you provided, what *should* org-capture-finalize be?  
A function that can be called like this:

   (org-capture-finalize arg1 arg2)

? Or a variable containing a function (reference) that can be called like this:

   (funcall org-capture-finalize arg1 arg2)

?  In the former case you might be able to use cl-letf, and in the latter case 
you should use let with a lambda value. 

> Unfortunately, that does not work. Regardless of binding, and if I used 
> cl-letf
> or cl-flet or cl-labels, or old let, or something brewed on the internet, the
> binding org-capture see for org-capture-finalize, is the original one from
> org-capture.el.
> 
> My second experiment was to abstract the finalize function into a funcallable
> fariable in org-capture.el (I have patched org-capture.el with this):
> 
> #+begin_src emacs-lisp
> (defvar org-capture-finalizer #'org-capture--default-finalize)
> 
> (defun org-capture-finalize ( stay-with-capture)
> "Finalize the capture process.
> With prefix argument STAY-WITH-CAPTURE, jump to the location of the
> captured item after finalizing."
> (interactive "P")
> (funcall org-capture-finalizer stay-with-capture))
> 
> 
> (defun org-capture--default-finalize ( stay-with-capture)
> "Default implementation for org-capture finalizer function."
> 
> ;; this is the original org-capture-finalize just renamed to 
> "default-finalize"
> )
> #+end_src
> 
> So I could then have something like this (never mind C-c C-k function being
> removed):
> 
> #+begin_src emacs-lisp
> (defun my-read-string ()
> (let ((org-capture-templates '(("s" "string" plain (function ignore
>  (org-capture-finalizer
>   (lambda ( _) (interactive "P") (buffer-string
>  (org-capture nil "s")))
> #+end_src
> 
> However I see that the binding for the org-capture-finalizer, in capture 
> buffer,
> is still the default 'org-capture--default-finalize' and not my lambda.

I guess this answers part of my question in my previous paragraph.  Is 
org-capture-finalizer defined via defvar?  If so, does it help if you put an 
empty defvar before the let binding?  If not, maybe someone actually using 
Emacs right now can be of more help here. 

> I am really not an expert on emacs lisp; and I do understand that this is
> somewhat "creative" use of org-capture (to put it nicely :-)), but I would 
> like
> to understand what is going on here.
> 
> I don't understand why let-binding here does not work? If I take 
> (symbol-functon
> 'org-capture) I see it is a closure. I am not sure if it has something with 
> the
> problem to do? I have tested to disable lexical binding, re-eval things, but
> the let-binding seems rock stable :). Nothing makes org-capture to reconsider
> using my local let-binding.
> 
> I would really like to understand this, so please if someone can explain it, I
> will appreciate to hear.
> 
> Thanks in advance
> /arthur

Best,


RY



Problem with let/cl-letf binding stuff with org-capture

2023-02-10 Thread Arthur Miller


Based on a Reddit thread:

https://www.reddit.com/r/emacs/comments/10xhvd8/a_little_readstring_utility_using_an_org_mode/j7xziao/?context=3

I did a small experiment to see if I can re-use org-capture, to just capture a
string from a buffer, without actually writing to any file.

My plan was to just let-bind org-capture-finalize with cl-letf:

#+begin_src emacs-lisp
(defun my-read-string ()
  (cl-letf (((symbol-function 'org-capture-finalize) ;; C-c C-c
 (lambda ( _) (interactive "P") (buffer-string)))
((symbol-function 'org-kill-note-or-show-branches) #'kill-buffer)) 
;; C-c C-k
(let ((org-capture-templates '(("s" "string" plain (function ignore)
  (org-capture nil "s"
#+end_src

Unfortunately, that does not work. Regardless of binding, and if I used cl-letf
or cl-flet or cl-labels, or old let, or something brewed on the internet, the
binding org-capture see for org-capture-finalize, is the original one from
org-capture.el.

My second experiment was to abstract the finalize function into a funcallable
fariable in org-capture.el (I have patched org-capture.el with this):

#+begin_src emacs-lisp
(defvar org-capture-finalizer #'org-capture--default-finalize)

(defun org-capture-finalize ( stay-with-capture)
  "Finalize the capture process.
With prefix argument STAY-WITH-CAPTURE, jump to the location of the
captured item after finalizing."
  (interactive "P")
  (funcall org-capture-finalizer stay-with-capture))


(defun org-capture--default-finalize ( stay-with-capture)
  "Default implementation for org-capture finalizer function."

;; this is the original org-capture-finalize just renamed to "default-finalize"
)
#+end_src

So I could then have something like this (never mind C-c C-k function being
removed):

#+begin_src emacs-lisp
(defun my-read-string ()
  (let ((org-capture-templates '(("s" "string" plain (function ignore
(org-capture-finalizer
 (lambda ( _) (interactive "P") (buffer-string
(org-capture nil "s")))
#+end_src

However I see that the binding for the org-capture-finalizer, in capture buffer,
is still the default 'org-capture--default-finalize' and not my lambda.

I am really not an expert on emacs lisp; and I do understand that this is
somewhat "creative" use of org-capture (to put it nicely :-)), but I would like
to understand what is going on here.

I don't understand why let-binding here does not work? If I take (symbol-functon
'org-capture) I see it is a closure. I am not sure if it has something with the
problem to do? I have tested to disable lexical binding, re-eval things, but
the let-binding seems rock stable :). Nothing makes org-capture to reconsider
using my local let-binding.

I would really like to understand this, so please if someone can explain it, I
will appreciate to hear.

Thanks in advance
/arthur